diff options
Diffstat (limited to 'src/yuzu/applets')
-rw-r--r-- | src/yuzu/applets/qt_amiibo_settings.cpp | 274 | ||||
-rw-r--r-- | src/yuzu/applets/qt_amiibo_settings.h | 85 | ||||
-rw-r--r-- | src/yuzu/applets/qt_amiibo_settings.ui | 494 | ||||
-rw-r--r-- | src/yuzu/applets/qt_controller.cpp | 778 | ||||
-rw-r--r-- | src/yuzu/applets/qt_controller.h | 183 | ||||
-rw-r--r-- | src/yuzu/applets/qt_controller.ui | 2699 | ||||
-rw-r--r-- | src/yuzu/applets/qt_error.cpp | 68 | ||||
-rw-r--r-- | src/yuzu/applets/qt_error.h | 34 | ||||
-rw-r--r-- | src/yuzu/applets/qt_profile_select.cpp | 260 | ||||
-rw-r--r-- | src/yuzu/applets/qt_profile_select.h | 87 | ||||
-rw-r--r-- | src/yuzu/applets/qt_software_keyboard.cpp | 1674 | ||||
-rw-r--r-- | src/yuzu/applets/qt_software_keyboard.h | 287 | ||||
-rw-r--r-- | src/yuzu/applets/qt_software_keyboard.ui | 3541 | ||||
-rw-r--r-- | src/yuzu/applets/qt_web_browser.cpp | 449 | ||||
-rw-r--r-- | src/yuzu/applets/qt_web_browser.h | 220 | ||||
-rw-r--r-- | src/yuzu/applets/qt_web_browser_scripts.h | 198 |
16 files changed, 0 insertions, 11331 deletions
diff --git a/src/yuzu/applets/qt_amiibo_settings.cpp b/src/yuzu/applets/qt_amiibo_settings.cpp deleted file mode 100644 index b91796dde..000000000 --- a/src/yuzu/applets/qt_amiibo_settings.cpp +++ /dev/null @@ -1,274 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include <algorithm> -#include <thread> -#include <fmt/format.h> -#include <nlohmann/json.hpp> - -#include "common/assert.h" -#include "common/string_util.h" -#include "core/hle/service/nfc/common/device.h" -#include "core/hle/service/nfp/nfp_result.h" -#include "input_common/drivers/virtual_amiibo.h" -#include "input_common/main.h" -#include "ui_qt_amiibo_settings.h" -#ifdef ENABLE_WEB_SERVICE -#include "web_service/web_backend.h" -#endif -#include "yuzu/applets/qt_amiibo_settings.h" -#include "yuzu/main.h" - -QtAmiiboSettingsDialog::QtAmiiboSettingsDialog(QWidget* parent, - Core::Frontend::CabinetParameters parameters_, - InputCommon::InputSubsystem* input_subsystem_, - std::shared_ptr<Service::NFC::NfcDevice> nfp_device_) - : QDialog(parent), ui(std::make_unique<Ui::QtAmiiboSettingsDialog>()), - input_subsystem{input_subsystem_}, nfp_device{std::move(nfp_device_)}, - parameters(std::move(parameters_)) { - ui->setupUi(this); - - LoadInfo(); - - resize(0, 0); -} - -QtAmiiboSettingsDialog::~QtAmiiboSettingsDialog() = default; - -int QtAmiiboSettingsDialog::exec() { - if (!is_initialized) { - return QDialog::Rejected; - } - return QDialog::exec(); -} - -std::string QtAmiiboSettingsDialog::GetName() const { - return ui->amiiboCustomNameValue->text().toStdString(); -} - -void QtAmiiboSettingsDialog::LoadInfo() { - if (input_subsystem->GetVirtualAmiibo()->ReloadAmiibo() != - InputCommon::VirtualAmiibo::Info::Success) { - return; - } - - if (nfp_device->GetCurrentState() != Service::NFC::DeviceState::TagFound && - nfp_device->GetCurrentState() != Service::NFC::DeviceState::TagMounted) { - return; - } - nfp_device->Mount(Service::NFP::ModelType::Amiibo, Service::NFP::MountTarget::All); - - LoadAmiiboInfo(); - LoadAmiiboData(); - LoadAmiiboGameInfo(); - - ui->amiiboDirectoryValue->setText( - QString::fromStdString(input_subsystem->GetVirtualAmiibo()->GetLastFilePath())); - - SetSettingsDescription(); - is_initialized = true; -} - -void QtAmiiboSettingsDialog::LoadAmiiboInfo() { - Service::NFP::ModelInfo model_info{}; - const auto model_result = nfp_device->GetModelInfo(model_info); - - if (model_result.IsFailure()) { - ui->amiiboImageLabel->setVisible(false); - ui->amiiboInfoGroup->setVisible(false); - return; - } - - const auto amiibo_id = - fmt::format("{:04x}{:02x}{:02x}{:04x}{:02x}02", Common::swap16(model_info.character_id), - model_info.character_variant, model_info.amiibo_type, model_info.model_number, - model_info.series); - - LOG_DEBUG(Frontend, "Loading amiibo id {}", amiibo_id); - // Note: This function is not being used until we host the images on our server - // LoadAmiiboApiInfo(amiibo_id); - ui->amiiboImageLabel->setVisible(false); - ui->amiiboInfoGroup->setVisible(false); -} - -void QtAmiiboSettingsDialog::LoadAmiiboApiInfo(std::string_view amiibo_id) { -#ifdef ENABLE_WEB_SERVICE - // TODO: Host this data on our website - WebService::Client client{"https://amiiboapi.com", {}, {}}; - WebService::Client image_client{"https://raw.githubusercontent.com", {}, {}}; - const auto url_path = fmt::format("/api/amiibo/?id={}", amiibo_id); - - const auto amiibo_json = client.GetJson(url_path, true).returned_data; - if (amiibo_json.empty()) { - ui->amiiboImageLabel->setVisible(false); - ui->amiiboInfoGroup->setVisible(false); - return; - } - - std::string amiibo_series{}; - std::string amiibo_name{}; - std::string amiibo_image_url{}; - std::string amiibo_type{}; - - const auto parsed_amiibo_json_json = nlohmann::json::parse(amiibo_json).at("amiibo"); - parsed_amiibo_json_json.at("amiiboSeries").get_to(amiibo_series); - parsed_amiibo_json_json.at("name").get_to(amiibo_name); - parsed_amiibo_json_json.at("image").get_to(amiibo_image_url); - parsed_amiibo_json_json.at("type").get_to(amiibo_type); - - ui->amiiboSeriesValue->setText(QString::fromStdString(amiibo_series)); - ui->amiiboNameValue->setText(QString::fromStdString(amiibo_name)); - ui->amiiboTypeValue->setText(QString::fromStdString(amiibo_type)); - - if (amiibo_image_url.size() < 34) { - ui->amiiboImageLabel->setVisible(false); - } - - const auto image_url_path = amiibo_image_url.substr(34, amiibo_image_url.size() - 34); - const auto image_data = image_client.GetImage(image_url_path, true).returned_data; - - if (image_data.empty()) { - ui->amiiboImageLabel->setVisible(false); - } - - QPixmap pixmap; - pixmap.loadFromData(reinterpret_cast<const u8*>(image_data.data()), - static_cast<uint>(image_data.size())); - pixmap = pixmap.scaled(250, 350, Qt::AspectRatioMode::KeepAspectRatio, - Qt::TransformationMode::SmoothTransformation); - ui->amiiboImageLabel->setPixmap(pixmap); -#endif -} - -void QtAmiiboSettingsDialog::LoadAmiiboData() { - Service::NFP::RegisterInfo register_info{}; - Service::NFP::CommonInfo common_info{}; - const auto register_result = nfp_device->GetRegisterInfo(register_info); - const auto common_result = nfp_device->GetCommonInfo(common_info); - - if (register_result.IsFailure()) { - ui->creationDateValue->setDisabled(true); - ui->modificationDateValue->setDisabled(true); - ui->amiiboCustomNameValue->setReadOnly(false); - ui->amiiboOwnerValue->setReadOnly(false); - return; - } - - if (parameters.mode == Service::NFP::CabinetMode::StartNicknameAndOwnerSettings) { - ui->creationDateValue->setDisabled(true); - ui->modificationDateValue->setDisabled(true); - } - - const auto amiibo_name = std::string(register_info.amiibo_name.data()); - const auto owner_name = - Common::UTF16ToUTF8(register_info.mii_char_info.GetNickname().data.data()); - const auto creation_date = - QDate(register_info.creation_date.year, register_info.creation_date.month, - register_info.creation_date.day); - - ui->amiiboCustomNameValue->setText(QString::fromStdString(amiibo_name)); - ui->amiiboOwnerValue->setText(QString::fromStdString(owner_name)); - ui->amiiboCustomNameValue->setReadOnly(true); - ui->amiiboOwnerValue->setReadOnly(true); - ui->creationDateValue->setDate(creation_date); - - if (common_result.IsFailure()) { - ui->modificationDateValue->setDisabled(true); - return; - } - - const auto modification_date = - QDate(common_info.last_write_date.year, common_info.last_write_date.month, - common_info.last_write_date.day); - ui->modificationDateValue->setDate(modification_date); -} - -void QtAmiiboSettingsDialog::LoadAmiiboGameInfo() { - u32 application_area_id{}; - const auto application_result = nfp_device->GetApplicationAreaId(application_area_id); - - if (application_result.IsFailure()) { - ui->gameIdValue->setVisible(false); - ui->gameIdLabel->setText(tr("No game data present")); - return; - } - - SetGameDataName(application_area_id); -} - -void QtAmiiboSettingsDialog::SetGameDataName(u32 application_area_id) { - static constexpr std::array<std::pair<u32, const char*>, 12> game_name_list = { - // 3ds, wii u - std::pair<u32, const char*>{0x10110E00, "Super Smash Bros (3DS/WiiU)"}, - {0x00132600, "Mario & Luigi: Paper Jam"}, - {0x0014F000, "Animal Crossing: Happy Home Designer"}, - {0x00152600, "Chibi-Robo!: Zip Lash"}, - {0x10161f00, "Mario Party 10"}, - {0x1019C800, "The Legend of Zelda: Twilight Princess HD"}, - // switch - {0x10162B00, "Splatoon 2"}, - {0x1016e100, "Shovel Knight: Treasure Trove"}, - {0x1019C800, "The Legend of Zelda: Breath of the Wild"}, - {0x34F80200, "Super Smash Bros. Ultimate"}, - {0x38600500, "Splatoon 3"}, - {0x3B440400, "The Legend of Zelda: Link's Awakening"}, - }; - - for (const auto& [game_id, game_name] : game_name_list) { - if (application_area_id == game_id) { - ui->gameIdValue->setText(QString::fromStdString(game_name)); - return; - } - } - - const auto application_area_string = fmt::format("{:016x}", application_area_id); - ui->gameIdValue->setText(QString::fromStdString(application_area_string)); -} - -void QtAmiiboSettingsDialog::SetSettingsDescription() { - switch (parameters.mode) { - case Service::NFP::CabinetMode::StartFormatter: - ui->cabinetActionDescriptionLabel->setText( - tr("The following amiibo data will be formatted:")); - break; - case Service::NFP::CabinetMode::StartGameDataEraser: - ui->cabinetActionDescriptionLabel->setText(tr("The following game data will removed:")); - break; - case Service::NFP::CabinetMode::StartNicknameAndOwnerSettings: - ui->cabinetActionDescriptionLabel->setText(tr("Set nickname and owner:")); - break; - case Service::NFP::CabinetMode::StartRestorer: - ui->cabinetActionDescriptionLabel->setText(tr("Do you wish to restore this amiibo?")); - break; - } -} - -QtAmiiboSettings::QtAmiiboSettings(GMainWindow& parent) { - connect(this, &QtAmiiboSettings::MainWindowShowAmiiboSettings, &parent, - &GMainWindow::AmiiboSettingsShowDialog, Qt::QueuedConnection); - connect(this, &QtAmiiboSettings::MainWindowRequestExit, &parent, - &GMainWindow::AmiiboSettingsRequestExit, Qt::QueuedConnection); - connect(&parent, &GMainWindow::AmiiboSettingsFinished, this, - &QtAmiiboSettings::MainWindowFinished, Qt::QueuedConnection); -} - -QtAmiiboSettings::~QtAmiiboSettings() = default; - -void QtAmiiboSettings::Close() const { - callback = {}; - emit MainWindowRequestExit(); -} - -void QtAmiiboSettings::ShowCabinetApplet( - const Core::Frontend::CabinetCallback& callback_, - const Core::Frontend::CabinetParameters& parameters, - std::shared_ptr<Service::NFC::NfcDevice> nfp_device) const { - callback = std::move(callback_); - emit MainWindowShowAmiiboSettings(parameters, nfp_device); -} - -void QtAmiiboSettings::MainWindowFinished(bool is_success, const std::string& name) { - if (callback) { - callback(is_success, name); - } -} diff --git a/src/yuzu/applets/qt_amiibo_settings.h b/src/yuzu/applets/qt_amiibo_settings.h deleted file mode 100644 index 3833cf6f2..000000000 --- a/src/yuzu/applets/qt_amiibo_settings.h +++ /dev/null @@ -1,85 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include <array> -#include <memory> -#include <QDialog> -#include "core/frontend/applets/cabinet.h" - -class GMainWindow; -class QCheckBox; -class QComboBox; -class QDialogButtonBox; -class QGroupBox; -class QLabel; - -namespace InputCommon { -class InputSubsystem; -} - -namespace Ui { -class QtAmiiboSettingsDialog; -} - -namespace Service::NFC { -class NfcDevice; -} // namespace Service::NFC - -class QtAmiiboSettingsDialog final : public QDialog { - Q_OBJECT - -public: - explicit QtAmiiboSettingsDialog(QWidget* parent, Core::Frontend::CabinetParameters parameters_, - InputCommon::InputSubsystem* input_subsystem_, - std::shared_ptr<Service::NFC::NfcDevice> nfp_device_); - ~QtAmiiboSettingsDialog() override; - - int exec() override; - - std::string GetName() const; - -private: - void LoadInfo(); - void LoadAmiiboInfo(); - void LoadAmiiboApiInfo(std::string_view amiibo_id); - void LoadAmiiboData(); - void LoadAmiiboGameInfo(); - void SetGameDataName(u32 application_area_id); - void SetSettingsDescription(); - - std::unique_ptr<Ui::QtAmiiboSettingsDialog> ui; - - InputCommon::InputSubsystem* input_subsystem; - std::shared_ptr<Service::NFC::NfcDevice> nfp_device; - - // Parameters sent in from the backend HLE applet. - Core::Frontend::CabinetParameters parameters; - - // If false amiibo settings failed to load - bool is_initialized{}; -}; - -class QtAmiiboSettings final : public QObject, public Core::Frontend::CabinetApplet { - Q_OBJECT - -public: - explicit QtAmiiboSettings(GMainWindow& parent); - ~QtAmiiboSettings() override; - - void Close() const override; - void ShowCabinetApplet(const Core::Frontend::CabinetCallback& callback_, - const Core::Frontend::CabinetParameters& parameters, - std::shared_ptr<Service::NFC::NfcDevice> nfp_device) const override; - -signals: - void MainWindowShowAmiiboSettings(const Core::Frontend::CabinetParameters& parameters, - std::shared_ptr<Service::NFC::NfcDevice> nfp_device) const; - void MainWindowRequestExit() const; - -private: - void MainWindowFinished(bool is_success, const std::string& name); - - mutable Core::Frontend::CabinetCallback callback; -}; diff --git a/src/yuzu/applets/qt_amiibo_settings.ui b/src/yuzu/applets/qt_amiibo_settings.ui deleted file mode 100644 index f377a6e61..000000000 --- a/src/yuzu/applets/qt_amiibo_settings.ui +++ /dev/null @@ -1,494 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>QtAmiiboSettingsDialog</class> - <widget class="QDialog" name="QtAmiiboSettingsDialog"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>839</width> - <height>500</height> - </rect> - </property> - <property name="windowTitle"> - <string>Amiibo Settings</string> - </property> - <property name="styleSheet"> - <string notr="true"/> - </property> - <layout class="QVBoxLayout" name="verticalLayout" stretch="0"> - <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="QWidget" name="mainControllerApplet" native="true"> - <layout class="QVBoxLayout" name="verticalLayout_1" stretch="0,3,0"> - <property name="spacing"> - <number>0</number> - </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="QWidget" name="topControllerApplet" native="true"> - <layout class="QHBoxLayout" name="horizontalLayout"> - <property name="spacing"> - <number>10</number> - </property> - <property name="leftMargin"> - <number>20</number> - </property> - <property name="topMargin"> - <number>15</number> - </property> - <property name="rightMargin"> - <number>0</number> - </property> - <property name="bottomMargin"> - <number>15</number> - </property> - <item> - <widget class="QLabel" name="cabinetActionDescriptionLabel"> - <property name="font"> - <font> - <pointsize>12</pointsize> - <weight>75</weight> - <bold>true</bold> - </font> - </property> - <property name="text"> - <string/> - </property> - <property name="alignment"> - <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> - </property> - <property name="wordWrap"> - <bool>false</bool> - </property> - </widget> - </item> - <item> - <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="QWidget" name="middleControllerApplet" native="true"> - <layout class="QVBoxLayout" name="verticalLayout_3"> - <property name="spacing"> - <number>0</number> - </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> - <layout class="QHBoxLayout" name="horizontalLayout_2"> - <property name="spacing"> - <number>20</number> - </property> - <property name="leftMargin"> - <number>15</number> - </property> - <property name="rightMargin"> - <number>15</number> - </property> - <item> - <widget class="QLabel" name="amiiboImageLabel"> - <property name="minimumSize"> - <size> - <width>250</width> - <height>350</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>236</width> - <height>350</height> - </size> - </property> - <property name="text"> - <string/> - </property> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - </widget> - </item> - <item> - <layout class="QVBoxLayout" name="verticalLayout_4"> - <property name="leftMargin"> - <number>0</number> - </property> - <property name="topMargin"> - <number>8</number> - </property> - <property name="bottomMargin"> - <number>15</number> - </property> - <item> - <widget class="QGroupBox" name="amiiboInfoGroup"> - <property name="title"> - <string>Amiibo Info</string> - </property> - <layout class="QVBoxLayout" name="verticalLayout_5"> - <item> - <layout class="QGridLayout" name="gridLayout_1"> - <item row="0" column="0"> - <widget class="QLabel" name="amiiboSeriesLabel"> - <property name="text"> - <string>Series</string> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QLineEdit" name="amiiboSeriesValue"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="readOnly"> - <bool>true</bool> - </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="amiiboTypeLabel"> - <property name="text"> - <string>Type</string> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QLineEdit" name="amiiboTypeValue"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="readOnly"> - <bool>true</bool> - </property> - </widget> - </item> - <item row="2" column="0"> - <widget class="QLabel" name="amiiboNameLabel"> - <property name="text"> - <string>Name</string> - </property> - </widget> - </item> - <item row="2" column="1"> - <widget class="QLineEdit" name="amiiboNameValue"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="readOnly"> - <bool>true</bool> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QGroupBox" name="amiiboDataGroup"> - <property name="title"> - <string>Amiibo Data</string> - </property> - <layout class="QVBoxLayout" name="verticalLayout_6"> - <item> - <layout class="QGridLayout" name="gridLayout_2"> - <item row="0" column="0"> - <widget class="QLabel" name="amiiboCustomNameLabel"> - <property name="text"> - <string>Custom Name</string> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QLineEdit" name="amiiboCustomNameValue"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="maxLength"> - <number>10</number> - </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="amiiboOwnerLabel"> - <property name="text"> - <string>Owner</string> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QLineEdit" name="amiiboOwnerValue"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="maxLength"> - <number>10</number> - </property> - </widget> - </item> - <item row="2" column="0"> - <widget class="QLabel" name="creationDateLabel"> - <property name="text"> - <string>Creation Date</string> - </property> - </widget> - </item> - <item row="2" column="1"> - <widget class="QDateTimeEdit" name="creationDateValue"> - <property name="readOnly"> - <bool>true</bool> - </property> - <property name="minimumDate"> - <date> - <year>1970</year> - <month>1</month> - <day>1</day> - </date> - </property> - <property name="displayFormat"> - <string>dd/MM/yyyy</string> - </property> - </widget> - </item> - <item row="3" column="0"> - <widget class="QLabel" name="modificationDateLabel"> - <property name="text"> - <string>Modification Date</string> - </property> - </widget> - </item> - <item row="3" column="1"> - <widget class="QDateTimeEdit" name="modificationDateValue"> - <property name="readOnly"> - <bool>true</bool> - </property> - <property name="minimumDate"> - <date> - <year>1970</year> - <month>1</month> - <day>1</day> - </date> - </property> - <property name="displayFormat"> - <string>dd/MM/yyyy </string> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QGroupBox" name="gameDataGroup"> - <property name="minimumSize"> - <size> - <width>500</width> - <height>0</height> - </size> - </property> - <property name="title"> - <string>Game Data</string> - </property> - <layout class="QGridLayout" name="gridLayout_3"> - <item row="0" column="0"> - <widget class="QLabel" name="gameIdLabel"> - <property name="text"> - <string>Game Id</string> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QLineEdit" name="gameIdValue"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="readOnly"> - <bool>true</bool> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QGroupBox" name="MountAmiiboGroup"> - <property name="minimumSize"> - <size> - <width>500</width> - <height>0</height> - </size> - </property> - <property name="title"> - <string>Mount Amiibo</string> - </property> - <layout class="QGridLayout" name="gridLayout_4"> - <item row="0" column="3"> - <widget class="QToolButton" name="amiiboDirectoryButton"> - <property name="text"> - <string>...</string> - </property> - </widget> - </item> - <item row="0" column="1"> - <spacer name="horizontalSpacer"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeType"> - <enum>QSizePolicy::Maximum</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>60</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item row="0" column="0"> - <widget class="QLabel" name="amiiboDirectoryLabel"> - <property name="text"> - <string>File Path</string> - </property> - </widget> - </item> - <item row="0" column="2"> - <widget class="QLineEdit" name="amiiboDirectoryValue"/> - </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> - </layout> - </item> - </layout> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QWidget" name="bottomControllerApplet" native="true"> - <layout class="QHBoxLayout" name="horizontalLayout_6"> - <property name="spacing"> - <number>15</number> - </property> - <property name="leftMargin"> - <number>15</number> - </property> - <property name="topMargin"> - <number>8</number> - </property> - <property name="rightMargin"> - <number>20</number> - </property> - <property name="bottomMargin"> - <number>8</number> - </property> - <item alignment="Qt::AlignBottom"> - <widget class="QDialogButtonBox" name="buttonBox"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="standardButtons"> - <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> - </property> - </widget> - </item> - </layout> - </widget> - </item> - </layout> - </widget> - </item> - </layout> - </widget> - <resources/> - <connections> - <connection> - <sender>buttonBox</sender> - <signal>accepted()</signal> - <receiver>QtAmiiboSettingsDialog</receiver> - <slot>accept()</slot> - </connection> - <connection> - <sender>buttonBox</sender> - <signal>rejected()</signal> - <receiver>QtAmiiboSettingsDialog</receiver> - <slot>reject()</slot> - </connection> - </connections> -</ui> diff --git a/src/yuzu/applets/qt_controller.cpp b/src/yuzu/applets/qt_controller.cpp deleted file mode 100644 index 48ce860ad..000000000 --- a/src/yuzu/applets/qt_controller.cpp +++ /dev/null @@ -1,778 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include <algorithm> -#include <thread> - -#include "common/assert.h" -#include "common/settings.h" -#include "common/settings_enums.h" -#include "common/string_util.h" -#include "core/core.h" -#include "core/hle/service/sm/sm.h" -#include "hid_core/frontend/emulated_controller.h" -#include "hid_core/hid_core.h" -#include "hid_core/hid_types.h" -#include "hid_core/resources/npad/npad.h" -#include "ui_qt_controller.h" -#include "yuzu/applets/qt_controller.h" -#include "yuzu/configuration/configure_input.h" -#include "yuzu/configuration/configure_input_profile_dialog.h" -#include "yuzu/configuration/configure_motion_touch.h" -#include "yuzu/configuration/configure_vibration.h" -#include "yuzu/configuration/input_profiles.h" -#include "yuzu/main.h" -#include "yuzu/util/controller_navigation.h" - -namespace { - -void UpdateController(Core::HID::EmulatedController* controller, - Core::HID::NpadStyleIndex controller_type, bool connected) { - if (controller->IsConnected(true)) { - controller->Disconnect(); - } - controller->SetNpadStyleIndex(controller_type); - if (connected) { - controller->Connect(true); - } -} - -// Returns true if the given controller type is compatible with the given parameters. -bool IsControllerCompatible(Core::HID::NpadStyleIndex controller_type, - Core::Frontend::ControllerParameters parameters) { - switch (controller_type) { - case Core::HID::NpadStyleIndex::Fullkey: - return parameters.allow_pro_controller; - case Core::HID::NpadStyleIndex::JoyconDual: - return parameters.allow_dual_joycons; - case Core::HID::NpadStyleIndex::JoyconLeft: - return parameters.allow_left_joycon; - case Core::HID::NpadStyleIndex::JoyconRight: - return parameters.allow_right_joycon; - case Core::HID::NpadStyleIndex::Handheld: - return parameters.enable_single_mode && parameters.allow_handheld; - case Core::HID::NpadStyleIndex::GameCube: - return parameters.allow_gamecube_controller; - default: - return false; - } -} - -} // namespace - -QtControllerSelectorDialog::QtControllerSelectorDialog( - QWidget* parent, Core::Frontend::ControllerParameters parameters_, - InputCommon::InputSubsystem* input_subsystem_, Core::System& system_) - : QDialog(parent), ui(std::make_unique<Ui::QtControllerSelectorDialog>()), - parameters(std::move(parameters_)), input_subsystem{input_subsystem_}, - input_profiles(std::make_unique<InputProfiles>()), system{system_} { - ui->setupUi(this); - - player_widgets = { - ui->widgetPlayer1, ui->widgetPlayer2, ui->widgetPlayer3, ui->widgetPlayer4, - ui->widgetPlayer5, ui->widgetPlayer6, ui->widgetPlayer7, ui->widgetPlayer8, - }; - - player_groupboxes = { - ui->groupPlayer1Connected, ui->groupPlayer2Connected, ui->groupPlayer3Connected, - ui->groupPlayer4Connected, ui->groupPlayer5Connected, ui->groupPlayer6Connected, - ui->groupPlayer7Connected, ui->groupPlayer8Connected, - }; - - connected_controller_icons = { - ui->controllerPlayer1, ui->controllerPlayer2, ui->controllerPlayer3, ui->controllerPlayer4, - ui->controllerPlayer5, ui->controllerPlayer6, ui->controllerPlayer7, ui->controllerPlayer8, - }; - - led_patterns_boxes = {{ - {ui->checkboxPlayer1LED1, ui->checkboxPlayer1LED2, ui->checkboxPlayer1LED3, - ui->checkboxPlayer1LED4}, - {ui->checkboxPlayer2LED1, ui->checkboxPlayer2LED2, ui->checkboxPlayer2LED3, - ui->checkboxPlayer2LED4}, - {ui->checkboxPlayer3LED1, ui->checkboxPlayer3LED2, ui->checkboxPlayer3LED3, - ui->checkboxPlayer3LED4}, - {ui->checkboxPlayer4LED1, ui->checkboxPlayer4LED2, ui->checkboxPlayer4LED3, - ui->checkboxPlayer4LED4}, - {ui->checkboxPlayer5LED1, ui->checkboxPlayer5LED2, ui->checkboxPlayer5LED3, - ui->checkboxPlayer5LED4}, - {ui->checkboxPlayer6LED1, ui->checkboxPlayer6LED2, ui->checkboxPlayer6LED3, - ui->checkboxPlayer6LED4}, - {ui->checkboxPlayer7LED1, ui->checkboxPlayer7LED2, ui->checkboxPlayer7LED3, - ui->checkboxPlayer7LED4}, - {ui->checkboxPlayer8LED1, ui->checkboxPlayer8LED2, ui->checkboxPlayer8LED3, - ui->checkboxPlayer8LED4}, - }}; - - explain_text_labels = { - ui->labelPlayer1Explain, ui->labelPlayer2Explain, ui->labelPlayer3Explain, - ui->labelPlayer4Explain, ui->labelPlayer5Explain, ui->labelPlayer6Explain, - ui->labelPlayer7Explain, ui->labelPlayer8Explain, - }; - - emulated_controllers = { - ui->comboPlayer1Emulated, ui->comboPlayer2Emulated, ui->comboPlayer3Emulated, - ui->comboPlayer4Emulated, ui->comboPlayer5Emulated, ui->comboPlayer6Emulated, - ui->comboPlayer7Emulated, ui->comboPlayer8Emulated, - }; - - player_labels = { - ui->labelPlayer1, ui->labelPlayer2, ui->labelPlayer3, ui->labelPlayer4, - ui->labelPlayer5, ui->labelPlayer6, ui->labelPlayer7, ui->labelPlayer8, - }; - - connected_controller_labels = { - ui->labelConnectedPlayer1, ui->labelConnectedPlayer2, ui->labelConnectedPlayer3, - ui->labelConnectedPlayer4, ui->labelConnectedPlayer5, ui->labelConnectedPlayer6, - ui->labelConnectedPlayer7, ui->labelConnectedPlayer8, - }; - - connected_controller_checkboxes = { - ui->checkboxPlayer1Connected, ui->checkboxPlayer2Connected, ui->checkboxPlayer3Connected, - ui->checkboxPlayer4Connected, ui->checkboxPlayer5Connected, ui->checkboxPlayer6Connected, - ui->checkboxPlayer7Connected, ui->checkboxPlayer8Connected, - }; - - ui->labelError->setVisible(false); - - // Setup/load everything prior to setting up connections. - // This avoids unintentionally changing the states of elements while loading them in. - SetSupportedControllers(); - DisableUnsupportedPlayers(); - - for (std::size_t player_index = 0; player_index < NUM_PLAYERS; ++player_index) { - SetEmulatedControllers(player_index); - } - - LoadConfiguration(); - - controller_navigation = new ControllerNavigation(system.HIDCore(), this); - - for (std::size_t i = 0; i < NUM_PLAYERS; ++i) { - SetExplainText(i); - UpdateControllerIcon(i); - UpdateLEDPattern(i); - UpdateBorderColor(i); - - connect(player_groupboxes[i], &QGroupBox::toggled, [this, i](bool checked) { - // Reconnect current controller if it was the last one checked - // (player number was reduced by more than one) - const bool reconnect_first = !checked && i < player_groupboxes.size() - 1 && - player_groupboxes[i + 1]->isChecked(); - - // Ensures that connecting a controller changes the number of players - if (connected_controller_checkboxes[i]->isChecked() != checked) { - // Ensures that the players are always connected in sequential order - PropagatePlayerNumberChanged(i, checked, reconnect_first); - } - }); - connect(connected_controller_checkboxes[i], &QCheckBox::clicked, [this, i](bool checked) { - // Reconnect current controller if it was the last one checked - // (player number was reduced by more than one) - const bool reconnect_first = !checked && - i < connected_controller_checkboxes.size() - 1 && - connected_controller_checkboxes[i + 1]->isChecked(); - - // Ensures that the players are always connected in sequential order - PropagatePlayerNumberChanged(i, checked, reconnect_first); - }); - - connect(emulated_controllers[i], qOverload<int>(&QComboBox::currentIndexChanged), - [this, i](int) { - UpdateControllerIcon(i); - UpdateControllerState(i); - UpdateLEDPattern(i); - CheckIfParametersMet(); - }); - - connect(connected_controller_checkboxes[i], &QCheckBox::stateChanged, [this, i](int state) { - player_groupboxes[i]->setChecked(state == Qt::Checked); - UpdateControllerIcon(i); - UpdateControllerState(i); - UpdateLEDPattern(i); - UpdateBorderColor(i); - CheckIfParametersMet(); - }); - - if (i == 0) { - connect(emulated_controllers[i], qOverload<int>(&QComboBox::currentIndexChanged), - [this, i](int index) { - UpdateDockedState(GetControllerTypeFromIndex(index, i) == - Core::HID::NpadStyleIndex::Handheld); - }); - } - } - - connect(ui->vibrationButton, &QPushButton::clicked, this, - &QtControllerSelectorDialog::CallConfigureVibrationDialog); - - connect(ui->motionButton, &QPushButton::clicked, this, - &QtControllerSelectorDialog::CallConfigureMotionTouchDialog); - - connect(ui->inputConfigButton, &QPushButton::clicked, this, - &QtControllerSelectorDialog::CallConfigureInputProfileDialog); - - connect(ui->buttonBox, &QDialogButtonBox::accepted, this, - &QtControllerSelectorDialog::ApplyConfiguration); - - connect(controller_navigation, &ControllerNavigation::TriggerKeyboardEvent, - [this](Qt::Key key) { - QKeyEvent* event = new QKeyEvent(QEvent::KeyPress, key, Qt::NoModifier); - QCoreApplication::postEvent(this, event); - }); - - // Enhancement: Check if the parameters have already been met before disconnecting controllers. - // If all the parameters are met AND only allows a single player, - // stop the constructor here as we do not need to continue. - if (CheckIfParametersMet() && parameters.enable_single_mode) { - return; - } - - // If keep_controllers_connected is false, forcefully disconnect all controllers - if (!parameters.keep_controllers_connected) { - for (auto player : player_groupboxes) { - player->setChecked(false); - } - } - - resize(0, 0); -} - -QtControllerSelectorDialog::~QtControllerSelectorDialog() { - controller_navigation->UnloadController(); - system.HIDCore().DisableAllControllerConfiguration(); -} - -int QtControllerSelectorDialog::exec() { - if (parameters_met && parameters.enable_single_mode) { - return QDialog::Accepted; - } - return QDialog::exec(); -} - -void QtControllerSelectorDialog::ApplyConfiguration() { - const bool pre_docked_mode = Settings::IsDockedMode(); - const bool docked_mode_selected = ui->radioDocked->isChecked(); - Settings::values.use_docked_mode.SetValue( - docked_mode_selected ? Settings::ConsoleMode::Docked : Settings::ConsoleMode::Handheld); - OnDockedModeChanged(pre_docked_mode, docked_mode_selected, system); - - Settings::values.vibration_enabled.SetValue(ui->vibrationGroup->isChecked()); - Settings::values.motion_enabled.SetValue(ui->motionGroup->isChecked()); -} - -void QtControllerSelectorDialog::LoadConfiguration() { - system.HIDCore().EnableAllControllerConfiguration(); - - const auto* handheld = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld); - for (std::size_t index = 0; index < NUM_PLAYERS; ++index) { - const auto* controller = system.HIDCore().GetEmulatedControllerByIndex(index); - const auto connected = - controller->IsConnected(true) || (index == 0 && handheld->IsConnected(true)); - player_groupboxes[index]->setChecked(connected); - connected_controller_checkboxes[index]->setChecked(connected); - emulated_controllers[index]->setCurrentIndex( - GetIndexFromControllerType(controller->GetNpadStyleIndex(true), index)); - } - - UpdateDockedState(handheld->IsConnected(true)); - - ui->vibrationGroup->setChecked(Settings::values.vibration_enabled.GetValue()); - ui->motionGroup->setChecked(Settings::values.motion_enabled.GetValue()); -} - -void QtControllerSelectorDialog::CallConfigureVibrationDialog() { - ConfigureVibration dialog(this, system.HIDCore()); - - dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint | - Qt::WindowSystemMenuHint); - dialog.setWindowModality(Qt::WindowModal); - - if (dialog.exec() == QDialog::Accepted) { - dialog.ApplyConfiguration(); - } -} - -void QtControllerSelectorDialog::CallConfigureMotionTouchDialog() { - ConfigureMotionTouch dialog(this, input_subsystem); - - dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint | - Qt::WindowSystemMenuHint); - dialog.setWindowModality(Qt::WindowModal); - - if (dialog.exec() == QDialog::Accepted) { - dialog.ApplyConfiguration(); - } -} - -void QtControllerSelectorDialog::CallConfigureInputProfileDialog() { - ConfigureInputProfileDialog dialog(this, input_subsystem, input_profiles.get(), system); - - dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint | - Qt::WindowSystemMenuHint); - dialog.setWindowModality(Qt::WindowModal); - dialog.exec(); -} - -void QtControllerSelectorDialog::keyPressEvent(QKeyEvent* evt) { - const auto num_connected_players = static_cast<int>( - std::count_if(player_groupboxes.begin(), player_groupboxes.end(), - [](const QGroupBox* player) { return player->isChecked(); })); - - const auto min_supported_players = parameters.enable_single_mode ? 1 : parameters.min_players; - const auto max_supported_players = parameters.enable_single_mode ? 1 : parameters.max_players; - - if ((evt->key() == Qt::Key_Enter || evt->key() == Qt::Key_Return) && !parameters_met) { - // Display error message when trying to validate using "Enter" and "OK" button is disabled - ui->labelError->setVisible(true); - return; - } else if (evt->key() == Qt::Key_Left && num_connected_players > min_supported_players) { - // Remove a player if possible - connected_controller_checkboxes[num_connected_players - 1]->setChecked(false); - return; - } else if (evt->key() == Qt::Key_Right && num_connected_players < max_supported_players) { - // Add a player, if possible - ui->labelError->setVisible(false); - connected_controller_checkboxes[num_connected_players]->setChecked(true); - return; - } - QDialog::keyPressEvent(evt); -} - -bool QtControllerSelectorDialog::CheckIfParametersMet() { - // Here, we check and validate the current configuration against all applicable parameters. - const auto num_connected_players = static_cast<int>( - std::count_if(player_groupboxes.begin(), player_groupboxes.end(), - [](const QGroupBox* player) { return player->isChecked(); })); - - const auto min_supported_players = parameters.enable_single_mode ? 1 : parameters.min_players; - const auto max_supported_players = parameters.enable_single_mode ? 1 : parameters.max_players; - - // First, check against the number of connected players. - if (num_connected_players < min_supported_players || - num_connected_players > max_supported_players) { - parameters_met = false; - ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(parameters_met); - return parameters_met; - } - - // Next, check against all connected controllers. - const auto all_controllers_compatible = [this] { - for (std::size_t index = 0; index < NUM_PLAYERS; ++index) { - // Skip controllers that are not used, we only care about the currently connected ones. - if (!player_groupboxes[index]->isChecked() || !player_groupboxes[index]->isEnabled()) { - continue; - } - - const auto compatible = IsControllerCompatible( - GetControllerTypeFromIndex(emulated_controllers[index]->currentIndex(), index), - parameters); - - // If any controller is found to be incompatible, return false early. - if (!compatible) { - return false; - } - } - - // Reaching here means all currently connected controllers are compatible. - return true; - }(); - - parameters_met = all_controllers_compatible; - ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(parameters_met); - return parameters_met; -} - -void QtControllerSelectorDialog::SetSupportedControllers() { - const QString theme = [] { - if (QIcon::themeName().contains(QStringLiteral("dark"))) { - return QStringLiteral("_dark"); - } else if (QIcon::themeName().contains(QStringLiteral("midnight"))) { - return QStringLiteral("_midnight"); - } else { - return QString{}; - } - }(); - - if (parameters.enable_single_mode && parameters.allow_handheld) { - ui->controllerSupported1->setStyleSheet( - QStringLiteral("image: url(:/controller/applet_handheld%0); ").arg(theme)); - } else { - ui->controllerSupported1->setStyleSheet( - QStringLiteral("image: url(:/controller/applet_handheld%0_disabled); ").arg(theme)); - } - - if (parameters.allow_dual_joycons) { - ui->controllerSupported2->setStyleSheet( - QStringLiteral("image: url(:/controller/applet_dual_joycon%0); ").arg(theme)); - } else { - ui->controllerSupported2->setStyleSheet( - QStringLiteral("image: url(:/controller/applet_dual_joycon%0_disabled); ").arg(theme)); - } - - if (parameters.allow_left_joycon) { - ui->controllerSupported3->setStyleSheet( - QStringLiteral("image: url(:/controller/applet_joycon_left%0); ").arg(theme)); - } else { - ui->controllerSupported3->setStyleSheet( - QStringLiteral("image: url(:/controller/applet_joycon_left%0_disabled); ").arg(theme)); - } - - if (parameters.allow_right_joycon) { - ui->controllerSupported4->setStyleSheet( - QStringLiteral("image: url(:/controller/applet_joycon_right%0); ").arg(theme)); - } else { - ui->controllerSupported4->setStyleSheet( - QStringLiteral("image: url(:/controller/applet_joycon_right%0_disabled); ").arg(theme)); - } - - if (parameters.allow_pro_controller || parameters.allow_gamecube_controller) { - ui->controllerSupported5->setStyleSheet( - QStringLiteral("image: url(:/controller/applet_pro_controller%0); ").arg(theme)); - } else { - ui->controllerSupported5->setStyleSheet( - QStringLiteral("image: url(:/controller/applet_pro_controller%0_disabled); ") - .arg(theme)); - } - - // enable_single_mode overrides min_players and max_players. - if (parameters.enable_single_mode) { - ui->numberSupportedLabel->setText(QStringLiteral("1")); - return; - } - - if (parameters.min_players == parameters.max_players) { - ui->numberSupportedLabel->setText(QStringLiteral("%1").arg(parameters.max_players)); - } else { - ui->numberSupportedLabel->setText( - QStringLiteral("%1 - %2").arg(parameters.min_players).arg(parameters.max_players)); - } -} - -void QtControllerSelectorDialog::SetEmulatedControllers(std::size_t player_index) { - const auto npad_style_set = system.HIDCore().GetSupportedStyleTag(); - auto& pairs = index_controller_type_pairs[player_index]; - - pairs.clear(); - emulated_controllers[player_index]->clear(); - - const auto add_item = [&](Core::HID::NpadStyleIndex controller_type, - const QString& controller_name) { - pairs.emplace_back(emulated_controllers[player_index]->count(), controller_type); - emulated_controllers[player_index]->addItem(controller_name); - }; - - if (npad_style_set.fullkey == 1) { - add_item(Core::HID::NpadStyleIndex::Fullkey, tr("Pro Controller")); - } - - if (npad_style_set.joycon_dual == 1) { - add_item(Core::HID::NpadStyleIndex::JoyconDual, tr("Dual Joycons")); - } - - if (npad_style_set.joycon_left == 1) { - add_item(Core::HID::NpadStyleIndex::JoyconLeft, tr("Left Joycon")); - } - - if (npad_style_set.joycon_right == 1) { - add_item(Core::HID::NpadStyleIndex::JoyconRight, tr("Right Joycon")); - } - - if (player_index == 0 && npad_style_set.handheld == 1) { - add_item(Core::HID::NpadStyleIndex::Handheld, tr("Handheld")); - } - - if (npad_style_set.gamecube == 1) { - add_item(Core::HID::NpadStyleIndex::GameCube, tr("GameCube Controller")); - } - - // Disable all unsupported controllers - if (!Settings::values.enable_all_controllers) { - return; - } - - if (npad_style_set.palma == 1) { - add_item(Core::HID::NpadStyleIndex::Pokeball, tr("Poke Ball Plus")); - } - - if (npad_style_set.lark == 1) { - add_item(Core::HID::NpadStyleIndex::NES, tr("NES Controller")); - } - - if (npad_style_set.lucia == 1) { - add_item(Core::HID::NpadStyleIndex::SNES, tr("SNES Controller")); - } - - if (npad_style_set.lagoon == 1) { - add_item(Core::HID::NpadStyleIndex::N64, tr("N64 Controller")); - } - - if (npad_style_set.lager == 1) { - add_item(Core::HID::NpadStyleIndex::SegaGenesis, tr("Sega Genesis")); - } -} - -Core::HID::NpadStyleIndex QtControllerSelectorDialog::GetControllerTypeFromIndex( - int index, std::size_t player_index) const { - const auto& pairs = index_controller_type_pairs[player_index]; - - const auto it = std::find_if(pairs.begin(), pairs.end(), - [index](const auto& pair) { return pair.first == index; }); - - if (it == pairs.end()) { - return Core::HID::NpadStyleIndex::Fullkey; - } - - return it->second; -} - -int QtControllerSelectorDialog::GetIndexFromControllerType(Core::HID::NpadStyleIndex type, - std::size_t player_index) const { - const auto& pairs = index_controller_type_pairs[player_index]; - - const auto it = std::find_if(pairs.begin(), pairs.end(), - [type](const auto& pair) { return pair.second == type; }); - - if (it == pairs.end()) { - return 0; - } - - return it->first; -} - -void QtControllerSelectorDialog::UpdateControllerIcon(std::size_t player_index) { - if (!player_groupboxes[player_index]->isChecked()) { - connected_controller_icons[player_index]->setStyleSheet(QString{}); - player_labels[player_index]->show(); - return; - } - - const QString stylesheet = [this, player_index] { - switch (GetControllerTypeFromIndex(emulated_controllers[player_index]->currentIndex(), - player_index)) { - case Core::HID::NpadStyleIndex::Fullkey: - case Core::HID::NpadStyleIndex::GameCube: - return QStringLiteral("image: url(:/controller/applet_pro_controller%0); "); - case Core::HID::NpadStyleIndex::JoyconDual: - return QStringLiteral("image: url(:/controller/applet_dual_joycon%0); "); - case Core::HID::NpadStyleIndex::JoyconLeft: - return QStringLiteral("image: url(:/controller/applet_joycon_left%0); "); - case Core::HID::NpadStyleIndex::JoyconRight: - return QStringLiteral("image: url(:/controller/applet_joycon_right%0); "); - case Core::HID::NpadStyleIndex::Handheld: - return QStringLiteral("image: url(:/controller/applet_handheld%0); "); - default: - return QString{}; - } - }(); - - if (stylesheet.isEmpty()) { - connected_controller_icons[player_index]->setStyleSheet(QString{}); - player_labels[player_index]->show(); - return; - } - - const QString theme = [] { - if (QIcon::themeName().contains(QStringLiteral("dark"))) { - return QStringLiteral("_dark"); - } else if (QIcon::themeName().contains(QStringLiteral("midnight"))) { - return QStringLiteral("_midnight"); - } else { - return QString{}; - } - }(); - - connected_controller_icons[player_index]->setStyleSheet(stylesheet.arg(theme)); - player_labels[player_index]->hide(); -} - -void QtControllerSelectorDialog::UpdateControllerState(std::size_t player_index) { - auto* controller = system.HIDCore().GetEmulatedControllerByIndex(player_index); - - const auto controller_type = GetControllerTypeFromIndex( - emulated_controllers[player_index]->currentIndex(), player_index); - const auto player_connected = player_groupboxes[player_index]->isChecked() && - controller_type != Core::HID::NpadStyleIndex::Handheld; - - if (controller->GetNpadStyleIndex(true) == controller_type && - controller->IsConnected(true) == player_connected) { - return; - } - - // Disconnect the controller first. - UpdateController(controller, controller_type, false); - - // Handheld - if (player_index == 0) { - if (controller_type == Core::HID::NpadStyleIndex::Handheld) { - auto* handheld = - system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld); - UpdateController(handheld, Core::HID::NpadStyleIndex::Handheld, - player_groupboxes[player_index]->isChecked()); - } - } - - UpdateController(controller, controller_type, player_connected); -} - -void QtControllerSelectorDialog::UpdateLEDPattern(std::size_t player_index) { - if (!player_groupboxes[player_index]->isChecked() || - GetControllerTypeFromIndex(emulated_controllers[player_index]->currentIndex(), - player_index) == Core::HID::NpadStyleIndex::Handheld) { - led_patterns_boxes[player_index][0]->setChecked(false); - led_patterns_boxes[player_index][1]->setChecked(false); - led_patterns_boxes[player_index][2]->setChecked(false); - led_patterns_boxes[player_index][3]->setChecked(false); - return; - } - - const auto* controller = system.HIDCore().GetEmulatedControllerByIndex(player_index); - const auto led_pattern = controller->GetLedPattern(); - led_patterns_boxes[player_index][0]->setChecked(led_pattern.position1); - led_patterns_boxes[player_index][1]->setChecked(led_pattern.position2); - led_patterns_boxes[player_index][2]->setChecked(led_pattern.position3); - led_patterns_boxes[player_index][3]->setChecked(led_pattern.position4); -} - -void QtControllerSelectorDialog::UpdateBorderColor(std::size_t player_index) { - if (!parameters.enable_border_color || - player_index >= static_cast<std::size_t>(parameters.max_players) || - player_groupboxes[player_index]->styleSheet().contains(QStringLiteral("QGroupBox"))) { - return; - } - - player_groupboxes[player_index]->setStyleSheet( - player_groupboxes[player_index]->styleSheet().append( - QStringLiteral("QGroupBox#groupPlayer%1Connected:checked " - "{ border: 1px solid rgba(%2, %3, %4, %5); }") - .arg(player_index + 1) - .arg(parameters.border_colors[player_index][0]) - .arg(parameters.border_colors[player_index][1]) - .arg(parameters.border_colors[player_index][2]) - .arg(parameters.border_colors[player_index][3]))); -} - -void QtControllerSelectorDialog::SetExplainText(std::size_t player_index) { - if (!parameters.enable_explain_text || - player_index >= static_cast<std::size_t>(parameters.max_players)) { - return; - } - - explain_text_labels[player_index]->setText(QString::fromStdString( - Common::StringFromFixedZeroTerminatedBuffer(parameters.explain_text[player_index].data(), - parameters.explain_text[player_index].size()))); -} - -void QtControllerSelectorDialog::UpdateDockedState(bool is_handheld) { - // Disallow changing the console mode if the controller type is handheld. - ui->radioDocked->setEnabled(!is_handheld); - ui->radioUndocked->setEnabled(!is_handheld); - - ui->radioDocked->setChecked(Settings::IsDockedMode()); - ui->radioUndocked->setChecked(!Settings::IsDockedMode()); - - // Also force into undocked mode if the controller type is handheld. - if (is_handheld) { - ui->radioUndocked->setChecked(true); - } -} - -void QtControllerSelectorDialog::PropagatePlayerNumberChanged(size_t player_index, bool checked, - bool reconnect_current) { - connected_controller_checkboxes[player_index]->setChecked(checked); - // Hide eventual error message about number of controllers - ui->labelError->setVisible(false); - - if (checked) { - // Check all previous buttons when checked - if (player_index > 0) { - PropagatePlayerNumberChanged(player_index - 1, checked); - } - } else { - // Unchecked all following buttons when unchecked - if (player_index < connected_controller_checkboxes.size() - 1) { - PropagatePlayerNumberChanged(player_index + 1, checked); - } - } - - if (reconnect_current) { - connected_controller_checkboxes[player_index]->setCheckState(Qt::Checked); - } -} - -void QtControllerSelectorDialog::DisableUnsupportedPlayers() { - const auto max_supported_players = parameters.enable_single_mode ? 1 : parameters.max_players; - - switch (max_supported_players) { - case 0: - default: - ASSERT(false); - return; - case 1: - ui->widgetSpacer->hide(); - ui->widgetSpacer2->hide(); - ui->widgetSpacer3->hide(); - ui->widgetSpacer4->hide(); - break; - case 2: - ui->widgetSpacer->hide(); - ui->widgetSpacer2->hide(); - ui->widgetSpacer3->hide(); - break; - case 3: - ui->widgetSpacer->hide(); - ui->widgetSpacer2->hide(); - break; - case 4: - ui->widgetSpacer->hide(); - break; - case 5: - case 6: - case 7: - case 8: - break; - } - - for (std::size_t index = max_supported_players; index < NUM_PLAYERS; ++index) { - auto* controller = system.HIDCore().GetEmulatedControllerByIndex(index); - // Disconnect any unsupported players here and disable or hide them if applicable. - UpdateController(controller, controller->GetNpadStyleIndex(true), false); - // Hide the player widgets when max_supported_controllers is less than or equal to 4. - if (max_supported_players <= 4) { - player_widgets[index]->hide(); - } - - // Disable and hide the following to prevent these from interaction. - player_widgets[index]->setDisabled(true); - connected_controller_checkboxes[index]->setDisabled(true); - connected_controller_labels[index]->hide(); - connected_controller_checkboxes[index]->hide(); - } -} - -QtControllerSelector::QtControllerSelector(GMainWindow& parent) { - connect(this, &QtControllerSelector::MainWindowReconfigureControllers, &parent, - &GMainWindow::ControllerSelectorReconfigureControllers, Qt::QueuedConnection); - connect(this, &QtControllerSelector::MainWindowRequestExit, &parent, - &GMainWindow::ControllerSelectorRequestExit, Qt::QueuedConnection); - connect(&parent, &GMainWindow::ControllerSelectorReconfigureFinished, this, - &QtControllerSelector::MainWindowReconfigureFinished, Qt::QueuedConnection); -} - -QtControllerSelector::~QtControllerSelector() = default; - -void QtControllerSelector::Close() const { - callback = {}; - emit MainWindowRequestExit(); -} - -void QtControllerSelector::ReconfigureControllers( - ReconfigureCallback callback_, const Core::Frontend::ControllerParameters& parameters) const { - callback = std::move(callback_); - emit MainWindowReconfigureControllers(parameters); -} - -void QtControllerSelector::MainWindowReconfigureFinished(bool is_success) { - if (callback) { - callback(is_success); - } -} diff --git a/src/yuzu/applets/qt_controller.h b/src/yuzu/applets/qt_controller.h deleted file mode 100644 index e5372495d..000000000 --- a/src/yuzu/applets/qt_controller.h +++ /dev/null @@ -1,183 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include <array> -#include <memory> -#include <QDialog> -#include "core/frontend/applets/controller.h" - -class GMainWindow; -class QCheckBox; -class QComboBox; -class QDialogButtonBox; -class QGroupBox; -class QLabel; - -class InputProfiles; - -namespace InputCommon { -class InputSubsystem; -} - -namespace Ui { -class QtControllerSelectorDialog; -} - -namespace Core { -class System; -} - -namespace Core::HID { -class HIDCore; -enum class NpadStyleIndex : u8; -} // namespace Core::HID - -class ControllerNavigation; - -class QtControllerSelectorDialog final : public QDialog { - Q_OBJECT - -public: - explicit QtControllerSelectorDialog(QWidget* parent, - Core::Frontend::ControllerParameters parameters_, - InputCommon::InputSubsystem* input_subsystem_, - Core::System& system_); - ~QtControllerSelectorDialog() override; - - int exec() override; - - void keyPressEvent(QKeyEvent* evt) override; - -private: - // Applies the current configuration. - void ApplyConfiguration(); - - // Loads the current input configuration into the frontend applet. - void LoadConfiguration(); - - // Initializes the "Configure Vibration" Dialog. - void CallConfigureVibrationDialog(); - - // Initializes the "Configure Motion / Touch" Dialog. - void CallConfigureMotionTouchDialog(); - - // Initializes the "Create Input Profile" Dialog. - void CallConfigureInputProfileDialog(); - - // Checks the current configuration against the given parameters. - // This sets and returns the value of parameters_met. - bool CheckIfParametersMet(); - - // Sets the controller icons for "Supported Controller Types". - void SetSupportedControllers(); - - // Sets the emulated controllers per player. - void SetEmulatedControllers(std::size_t player_index); - - // Gets the Controller Type for a given controller combobox index per player. - Core::HID::NpadStyleIndex GetControllerTypeFromIndex(int index, std::size_t player_index) const; - - // Gets the controller combobox index for a given Controller Type per player. - int GetIndexFromControllerType(Core::HID::NpadStyleIndex type, std::size_t player_index) const; - - // Updates the controller icons per player. - void UpdateControllerIcon(std::size_t player_index); - - // Updates the controller state (type and connection status) per player. - void UpdateControllerState(std::size_t player_index); - - // Updates the LED pattern per player. - void UpdateLEDPattern(std::size_t player_index); - - // Updates the border color per player. - void UpdateBorderColor(std::size_t player_index); - - // Sets the "Explain Text" per player. - void SetExplainText(std::size_t player_index); - - // Updates the console mode. - void UpdateDockedState(bool is_handheld); - - // Enable preceding controllers or disable following ones - void PropagatePlayerNumberChanged(size_t player_index, bool checked, - bool reconnect_current = false); - - // Disables and disconnects unsupported players based on the given parameters. - void DisableUnsupportedPlayers(); - - std::unique_ptr<Ui::QtControllerSelectorDialog> ui; - - // Parameters sent in from the backend HLE applet. - Core::Frontend::ControllerParameters parameters; - - InputCommon::InputSubsystem* input_subsystem; - - std::unique_ptr<InputProfiles> input_profiles; - - Core::System& system; - - ControllerNavigation* controller_navigation = nullptr; - - // This is true if and only if all parameters are met. Otherwise, this is false. - // This determines whether the "OK" button can be clicked to exit the applet. - bool parameters_met{false}; - - static constexpr std::size_t NUM_PLAYERS = 8; - - // Widgets encapsulating the groupboxes and comboboxes per player. - std::array<QWidget*, NUM_PLAYERS> player_widgets; - - // Groupboxes encapsulating the controller icons and LED patterns per player. - std::array<QGroupBox*, NUM_PLAYERS> player_groupboxes; - - // Icons for currently connected controllers/players. - std::array<QWidget*, NUM_PLAYERS> connected_controller_icons; - - // Labels that represent the player numbers in place of the controller icons. - std::array<QLabel*, NUM_PLAYERS> player_labels; - - // LED patterns for currently connected controllers/players. - std::array<std::array<QCheckBox*, 4>, NUM_PLAYERS> led_patterns_boxes; - - // Labels representing additional information known as "Explain Text" per player. - std::array<QLabel*, NUM_PLAYERS> explain_text_labels; - - // Comboboxes with a list of emulated controllers per player. - std::array<QComboBox*, NUM_PLAYERS> emulated_controllers; - - /// Pairs of emulated controller index and Controller Type enum per player. - std::array<std::vector<std::pair<int, Core::HID::NpadStyleIndex>>, NUM_PLAYERS> - index_controller_type_pairs; - - // Labels representing the number of connected controllers - // above the "Connected Controllers" checkboxes. - std::array<QLabel*, NUM_PLAYERS> connected_controller_labels; - - // Checkboxes representing the "Connected Controllers". - std::array<QCheckBox*, NUM_PLAYERS> connected_controller_checkboxes; -}; - -class QtControllerSelector final : public QObject, public Core::Frontend::ControllerApplet { - Q_OBJECT - -public: - explicit QtControllerSelector(GMainWindow& parent); - ~QtControllerSelector() override; - - void Close() const override; - void ReconfigureControllers( - ReconfigureCallback callback_, - const Core::Frontend::ControllerParameters& parameters) const override; - -signals: - void MainWindowReconfigureControllers( - const Core::Frontend::ControllerParameters& parameters) const; - void MainWindowRequestExit() const; - -private: - void MainWindowReconfigureFinished(bool is_success); - - mutable ReconfigureCallback callback; -}; diff --git a/src/yuzu/applets/qt_controller.ui b/src/yuzu/applets/qt_controller.ui deleted file mode 100644 index 6f7cb3c13..000000000 --- a/src/yuzu/applets/qt_controller.ui +++ /dev/null @@ -1,2699 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>QtControllerSelectorDialog</class> - <widget class="QDialog" name="QtControllerSelectorDialog"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>839</width> - <height>630</height> - </rect> - </property> - <property name="windowTitle"> - <string>Controller Applet</string> - </property> - <property name="styleSheet"> - <string notr="true"/> - </property> - <layout class="QVBoxLayout" name="verticalLayout" stretch="0"> - <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="QWidget" name="mainControllerApplet" native="true"> - <layout class="QVBoxLayout" name="verticalLayout_2" stretch="0,3,0"> - <property name="spacing"> - <number>0</number> - </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="QWidget" name="topControllerApplet" native="true"> - <layout class="QHBoxLayout" name="horizontalLayout"> - <property name="spacing"> - <number>10</number> - </property> - <property name="leftMargin"> - <number>0</number> - </property> - <property name="topMargin"> - <number>10</number> - </property> - <property name="rightMargin"> - <number>0</number> - </property> - <property name="bottomMargin"> - <number>10</number> - </property> - <item> - <spacer name="controllerAppletHorizontalSpacer2"> - <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> - <widget class="QWidget" name="controllersSupported" native="true"> - <property name="minimumSize"> - <size> - <width>70</width> - <height>70</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>70</width> - <height>70</height> - </size> - </property> - <layout class="QVBoxLayout" name="verticalLayout_21"> - <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="controllersSupportedLabel"> - <property name="minimumSize"> - <size> - <width>70</width> - <height>70</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>70</width> - <height>70</height> - </size> - </property> - <property name="font"> - <font> - <weight>75</weight> - <bold>true</bold> - </font> - </property> - <property name="text"> - <string>Supported Controller Types:</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - <property name="wordWrap"> - <bool>true</bool> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QWidget" name="controllerSupported1" native="true"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>70</width> - <height>70</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>70</width> - <height>70</height> - </size> - </property> - <property name="styleSheet"> - <string notr="true"/> - </property> - </widget> - </item> - <item> - <widget class="QWidget" name="controllerSupported2" native="true"> - <property name="minimumSize"> - <size> - <width>70</width> - <height>70</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>70</width> - <height>70</height> - </size> - </property> - <property name="styleSheet"> - <string notr="true"/> - </property> - </widget> - </item> - <item> - <widget class="QWidget" name="controllerSupported3" native="true"> - <property name="minimumSize"> - <size> - <width>70</width> - <height>70</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>70</width> - <height>70</height> - </size> - </property> - <property name="styleSheet"> - <string notr="true"/> - </property> - </widget> - </item> - <item> - <widget class="QWidget" name="controllerSupported4" native="true"> - <property name="minimumSize"> - <size> - <width>70</width> - <height>70</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>70</width> - <height>70</height> - </size> - </property> - <property name="styleSheet"> - <string notr="true"/> - </property> - </widget> - </item> - <item> - <widget class="QWidget" name="controllerSupported5" native="true"> - <property name="minimumSize"> - <size> - <width>70</width> - <height>70</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>70</width> - <height>70</height> - </size> - </property> - <property name="styleSheet"> - <string notr="true"/> - </property> - </widget> - </item> - <item> - <widget class="QWidget" name="playersSupported" native="true"> - <property name="minimumSize"> - <size> - <width>70</width> - <height>70</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>70</width> - <height>70</height> - </size> - </property> - <layout class="QVBoxLayout" name="verticalLayout_20"> - <property name="spacing"> - <number>0</number> - </property> - <property name="leftMargin"> - <number>0</number> - </property> - <property name="topMargin"> - <number>16</number> - </property> - <property name="rightMargin"> - <number>14</number> - </property> - <property name="bottomMargin"> - <number>16</number> - </property> - <item> - <widget class="QLabel" name="maxSupportedLabel"> - <property name="font"> - <font> - <weight>75</weight> - <bold>true</bold> - </font> - </property> - <property name="text"> - <string>Players:</string> - </property> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - <property name="wordWrap"> - <bool>false</bool> - </property> - </widget> - </item> - <item> - <widget class="QLabel" name="numberSupportedLabel"> - <property name="font"> - <font> - <pointsize>14</pointsize> - </font> - </property> - <property name="text"> - <string>1 - 8</string> - </property> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <spacer name="controllerAppletHorizontalSpacer3"> - <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="QWidget" name="middleControllerApplet" native="true"> - <layout class="QVBoxLayout" name="verticalLayout_3"> - <property name="spacing"> - <number>0</number> - </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> - <layout class="QGridLayout" name="gridLayout"> - <property name="spacing"> - <number>5</number> - </property> - <item row="1" column="7"> - <widget class="QWidget" name="widgetPlayer4" native="true"> - <layout class="QVBoxLayout" name="verticalLayout_27"> - <property name="spacing"> - <number>5</number> - </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 alignment="Qt::AlignHCenter"> - <widget class="QGroupBox" name="groupPlayer4Connected"> - <property name="minimumSize"> - <size> - <width>100</width> - <height>100</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>100</width> - <height>100</height> - </size> - </property> - <property name="title"> - <string/> - </property> - <property name="checkable"> - <bool>true</bool> - </property> - <property name="checked"> - <bool>false</bool> - </property> - <layout class="QVBoxLayout" name="verticalLayout_7" stretch="1,0"> - <property name="spacing"> - <number>7</number> - </property> - <property name="leftMargin"> - <number>14</number> - </property> - <property name="topMargin"> - <number>7</number> - </property> - <property name="rightMargin"> - <number>14</number> - </property> - <property name="bottomMargin"> - <number>4</number> - </property> - <item> - <widget class="QWidget" name="controllerPlayer4" native="true"> - <property name="styleSheet"> - <string notr="true"/> - </property> - <layout class="QVBoxLayout" name="verticalLayout_15"> - <property name="topMargin"> - <number>16</number> - </property> - <item alignment="Qt::AlignHCenter|Qt::AlignVCenter"> - <widget class="QLabel" name="labelPlayer4"> - <property name="text"> - <string>P4</string> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item alignment="Qt::AlignHCenter"> - <widget class="QWidget" name="Player4LEDs" native="true"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="minimumSize"> - <size> - <width>0</width> - <height>10</height> - </size> - </property> - <layout class="QHBoxLayout" name="horizontalLayout_10"> - <property name="spacing"> - <number>4</number> - </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="checkboxPlayer4LED1"/> - </item> - <item> - <widget class="QCheckBox" name="checkboxPlayer4LED2"/> - </item> - <item> - <widget class="QCheckBox" name="checkboxPlayer4LED3"/> - </item> - <item> - <widget class="QCheckBox" name="checkboxPlayer4LED4"/> - </item> - </layout> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QWidget" name="Player4Explain" native="true"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>10</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>150</width> - <height>16777215</height> - </size> - </property> - <layout class="QVBoxLayout" name="verticalLayout_39"> - <property name="spacing"> - <number>0</number> - </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="QLabel" name="labelPlayer4Explain"> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QComboBox" name="comboPlayer4Emulated"> - <item> - <property name="text"> - <string>Pro Controller</string> - </property> - </item> - <item> - <property name="text"> - <string>Dual Joycons</string> - </property> - </item> - <item> - <property name="text"> - <string>Left Joycon</string> - </property> - </item> - <item> - <property name="text"> - <string>Right Joycon</string> - </property> - </item> - </widget> - </item> - <item> - <widget class="QComboBox" name="comboPlayer4Profile"> - <item> - <property name="text"> - <string>Use Current Config</string> - </property> - </item> - </widget> - </item> - </layout> - </widget> - </item> - <item row="1" column="3"> - <widget class="QWidget" name="widgetPlayer2" native="true"> - <layout class="QVBoxLayout" name="verticalLayout_29"> - <property name="spacing"> - <number>5</number> - </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 alignment="Qt::AlignHCenter"> - <widget class="QGroupBox" name="groupPlayer2Connected"> - <property name="minimumSize"> - <size> - <width>100</width> - <height>100</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>100</width> - <height>100</height> - </size> - </property> - <property name="title"> - <string/> - </property> - <property name="checkable"> - <bool>true</bool> - </property> - <property name="checked"> - <bool>false</bool> - </property> - <layout class="QVBoxLayout" name="verticalLayout_5" stretch="1,0"> - <property name="spacing"> - <number>7</number> - </property> - <property name="leftMargin"> - <number>14</number> - </property> - <property name="topMargin"> - <number>7</number> - </property> - <property name="rightMargin"> - <number>14</number> - </property> - <property name="bottomMargin"> - <number>4</number> - </property> - <item> - <widget class="QWidget" name="controllerPlayer2" native="true"> - <property name="styleSheet"> - <string notr="true"/> - </property> - <layout class="QVBoxLayout" name="verticalLayout_13"> - <property name="topMargin"> - <number>16</number> - </property> - <item alignment="Qt::AlignHCenter|Qt::AlignVCenter"> - <widget class="QLabel" name="labelPlayer2"> - <property name="text"> - <string>P2</string> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item alignment="Qt::AlignHCenter"> - <widget class="QWidget" name="Player2LEDs" native="true"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="minimumSize"> - <size> - <width>0</width> - <height>10</height> - </size> - </property> - <layout class="QHBoxLayout" name="horizontalLayout_8"> - <property name="spacing"> - <number>4</number> - </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="checkboxPlayer2LED1"/> - </item> - <item> - <widget class="QCheckBox" name="checkboxPlayer2LED2"/> - </item> - <item> - <widget class="QCheckBox" name="checkboxPlayer2LED3"/> - </item> - <item> - <widget class="QCheckBox" name="checkboxPlayer2LED4"/> - </item> - </layout> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QWidget" name="Player2Explain" native="true"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>10</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>150</width> - <height>16777215</height> - </size> - </property> - <layout class="QVBoxLayout" name="verticalLayout_37"> - <property name="spacing"> - <number>0</number> - </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="QLabel" name="labelPlayer2Explain"> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QComboBox" name="comboPlayer2Emulated"> - <item> - <property name="text"> - <string>Pro Controller</string> - </property> - </item> - <item> - <property name="text"> - <string>Dual Joycons</string> - </property> - </item> - <item> - <property name="text"> - <string>Left Joycon</string> - </property> - </item> - <item> - <property name="text"> - <string>Right Joycon</string> - </property> - </item> - </widget> - </item> - <item> - <widget class="QComboBox" name="comboPlayer2Profile"> - <item> - <property name="text"> - <string>Use Current Config</string> - </property> - </item> - </widget> - </item> - </layout> - </widget> - </item> - <item row="1" column="1"> - <widget class="QWidget" name="widgetPlayer1" native="true"> - <layout class="QVBoxLayout" name="verticalLayout_30"> - <property name="spacing"> - <number>5</number> - </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 alignment="Qt::AlignHCenter"> - <widget class="QGroupBox" name="groupPlayer1Connected"> - <property name="minimumSize"> - <size> - <width>100</width> - <height>100</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>100</width> - <height>100</height> - </size> - </property> - <property name="title"> - <string/> - </property> - <property name="checkable"> - <bool>true</bool> - </property> - <property name="checked"> - <bool>false</bool> - </property> - <layout class="QVBoxLayout" name="verticalLayout_4" stretch="1,0"> - <property name="spacing"> - <number>7</number> - </property> - <property name="leftMargin"> - <number>14</number> - </property> - <property name="topMargin"> - <number>7</number> - </property> - <property name="rightMargin"> - <number>14</number> - </property> - <property name="bottomMargin"> - <number>4</number> - </property> - <item> - <widget class="QWidget" name="controllerPlayer1" native="true"> - <property name="styleSheet"> - <string notr="true"/> - </property> - <layout class="QVBoxLayout" name="verticalLayout_12"> - <property name="topMargin"> - <number>16</number> - </property> - <item alignment="Qt::AlignHCenter|Qt::AlignVCenter"> - <widget class="QLabel" name="labelPlayer1"> - <property name="text"> - <string>P1</string> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item alignment="Qt::AlignHCenter"> - <widget class="QWidget" name="Player1LEDs" native="true"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="minimumSize"> - <size> - <width>0</width> - <height>10</height> - </size> - </property> - <layout class="QHBoxLayout" name="horizontalLayout_2"> - <property name="spacing"> - <number>4</number> - </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="checkboxPlayer1LED1"> - <property name="layoutDirection"> - <enum>Qt::LeftToRight</enum> - </property> - </widget> - </item> - <item> - <widget class="QCheckBox" name="checkboxPlayer1LED2"/> - </item> - <item> - <widget class="QCheckBox" name="checkboxPlayer1LED3"/> - </item> - <item> - <widget class="QCheckBox" name="checkboxPlayer1LED4"/> - </item> - </layout> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QWidget" name="Player1Explain" native="true"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>10</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>150</width> - <height>16777215</height> - </size> - </property> - <layout class="QVBoxLayout" name="verticalLayout_36"> - <property name="spacing"> - <number>0</number> - </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="QLabel" name="labelPlayer1Explain"> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QComboBox" name="comboPlayer1Emulated"> - <item> - <property name="text"> - <string>Pro Controller</string> - </property> - </item> - <item> - <property name="text"> - <string>Dual Joycons</string> - </property> - </item> - <item> - <property name="text"> - <string>Left Joycon</string> - </property> - </item> - <item> - <property name="text"> - <string>Right Joycon</string> - </property> - </item> - <item> - <property name="text"> - <string>Handheld</string> - </property> - </item> - </widget> - </item> - <item> - <widget class="QComboBox" name="comboPlayer1Profile"> - <item> - <property name="text"> - <string>Use Current Config</string> - </property> - </item> - </widget> - </item> - </layout> - </widget> - </item> - <item row="1" column="8"> - <widget class="QWidget" name="widgetSpacer2" native="true"> - <property name="minimumSize"> - <size> - <width>25</width> - <height>0</height> - </size> - </property> - <layout class="QVBoxLayout" name="verticalLayout_31"> - <property name="spacing"> - <number>0</number> - </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> - <spacer name="controllerAppletHorizontalSpacer8"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>25</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - </layout> - </widget> - </item> - <item row="1" column="4"> - <widget class="QWidget" name="widgetSpacer4" native="true"> - <layout class="QVBoxLayout" name="verticalLayout_33"> - <property name="spacing"> - <number>0</number> - </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> - <spacer name="controllerAppletHorizontalSpacer6"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>0</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - </layout> - </widget> - </item> - <item row="1" column="6"> - <widget class="QWidget" name="widgetSpacer3" native="true"> - <layout class="QVBoxLayout" name="verticalLayout_32"> - <property name="spacing"> - <number>0</number> - </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> - <spacer name="controllerAppletHorizontalSpacer7"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>0</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - </layout> - </widget> - </item> - <item row="1" column="5"> - <widget class="QWidget" name="widgetPlayer3" native="true"> - <layout class="QVBoxLayout" name="verticalLayout_28"> - <property name="spacing"> - <number>5</number> - </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 alignment="Qt::AlignHCenter"> - <widget class="QGroupBox" name="groupPlayer3Connected"> - <property name="minimumSize"> - <size> - <width>100</width> - <height>100</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>100</width> - <height>100</height> - </size> - </property> - <property name="title"> - <string/> - </property> - <property name="checkable"> - <bool>true</bool> - </property> - <property name="checked"> - <bool>false</bool> - </property> - <layout class="QVBoxLayout" name="verticalLayout_6" stretch="1,0"> - <property name="spacing"> - <number>7</number> - </property> - <property name="leftMargin"> - <number>14</number> - </property> - <property name="topMargin"> - <number>7</number> - </property> - <property name="rightMargin"> - <number>14</number> - </property> - <property name="bottomMargin"> - <number>4</number> - </property> - <item> - <widget class="QWidget" name="controllerPlayer3" native="true"> - <property name="styleSheet"> - <string notr="true"/> - </property> - <layout class="QVBoxLayout" name="verticalLayout_14"> - <property name="topMargin"> - <number>16</number> - </property> - <item alignment="Qt::AlignHCenter|Qt::AlignVCenter"> - <widget class="QLabel" name="labelPlayer3"> - <property name="text"> - <string>P3</string> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item alignment="Qt::AlignHCenter"> - <widget class="QWidget" name="Player3LEDs" native="true"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="minimumSize"> - <size> - <width>0</width> - <height>10</height> - </size> - </property> - <layout class="QHBoxLayout" name="horizontalLayout_9"> - <property name="spacing"> - <number>4</number> - </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="checkboxPlayer3LED1"/> - </item> - <item> - <widget class="QCheckBox" name="checkboxPlayer3LED2"/> - </item> - <item> - <widget class="QCheckBox" name="checkboxPlayer3LED3"/> - </item> - <item> - <widget class="QCheckBox" name="checkboxPlayer3LED4"/> - </item> - </layout> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QWidget" name="Player3Explain" native="true"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>10</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>150</width> - <height>16777215</height> - </size> - </property> - <layout class="QVBoxLayout" name="verticalLayout_38"> - <property name="spacing"> - <number>0</number> - </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="QLabel" name="labelPlayer3Explain"> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QComboBox" name="comboPlayer3Emulated"> - <item> - <property name="text"> - <string>Pro Controller</string> - </property> - </item> - <item> - <property name="text"> - <string>Dual Joycons</string> - </property> - </item> - <item> - <property name="text"> - <string>Left Joycon</string> - </property> - </item> - <item> - <property name="text"> - <string>Right Joycon</string> - </property> - </item> - </widget> - </item> - <item> - <widget class="QComboBox" name="comboPlayer3Profile"> - <item> - <property name="text"> - <string>Use Current Config</string> - </property> - </item> - </widget> - </item> - </layout> - </widget> - </item> - <item row="0" column="1"> - <widget class="QWidget" name="widgetSpacer5" native="true"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>25</height> - </size> - </property> - <layout class="QVBoxLayout" name="verticalLayout_34"> - <property name="spacing"> - <number>0</number> - </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> - <spacer name="controllerAppletVerticalSpacer3"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>25</height> - </size> - </property> - </spacer> - </item> - </layout> - </widget> - </item> - <item row="6" column="5"> - <widget class="QWidget" name="widgetPlayer7" native="true"> - <layout class="QVBoxLayout" name="verticalLayout_25"> - <property name="spacing"> - <number>5</number> - </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 alignment="Qt::AlignHCenter"> - <widget class="QGroupBox" name="groupPlayer7Connected"> - <property name="minimumSize"> - <size> - <width>100</width> - <height>100</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>100</width> - <height>100</height> - </size> - </property> - <property name="title"> - <string/> - </property> - <property name="checkable"> - <bool>true</bool> - </property> - <property name="checked"> - <bool>false</bool> - </property> - <layout class="QVBoxLayout" name="verticalLayout_10" stretch="1,0"> - <property name="spacing"> - <number>7</number> - </property> - <property name="leftMargin"> - <number>14</number> - </property> - <property name="topMargin"> - <number>7</number> - </property> - <property name="rightMargin"> - <number>14</number> - </property> - <property name="bottomMargin"> - <number>4</number> - </property> - <item> - <widget class="QWidget" name="controllerPlayer7" native="true"> - <property name="styleSheet"> - <string notr="true"/> - </property> - <layout class="QVBoxLayout" name="verticalLayout_18"> - <property name="topMargin"> - <number>16</number> - </property> - <item alignment="Qt::AlignHCenter|Qt::AlignVCenter"> - <widget class="QLabel" name="labelPlayer7"> - <property name="text"> - <string>P7</string> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item alignment="Qt::AlignHCenter"> - <widget class="QWidget" name="Player7LEDs" native="true"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="minimumSize"> - <size> - <width>0</width> - <height>10</height> - </size> - </property> - <layout class="QHBoxLayout" name="horizontalLayout_13"> - <property name="spacing"> - <number>4</number> - </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="checkboxPlayer7LED1"/> - </item> - <item> - <widget class="QCheckBox" name="checkboxPlayer7LED2"/> - </item> - <item> - <widget class="QCheckBox" name="checkboxPlayer7LED3"/> - </item> - <item> - <widget class="QCheckBox" name="checkboxPlayer7LED4"/> - </item> - </layout> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QWidget" name="Player7Explain" native="true"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>10</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>150</width> - <height>16777215</height> - </size> - </property> - <layout class="QVBoxLayout" name="verticalLayout_42"> - <property name="spacing"> - <number>0</number> - </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="QLabel" name="labelPlayer7Explain"> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QComboBox" name="comboPlayer7Emulated"> - <item> - <property name="text"> - <string>Pro Controller</string> - </property> - </item> - <item> - <property name="text"> - <string>Dual Joycons</string> - </property> - </item> - <item> - <property name="text"> - <string>Left Joycon</string> - </property> - </item> - <item> - <property name="text"> - <string>Right Joycon</string> - </property> - </item> - </widget> - </item> - <item> - <widget class="QComboBox" name="comboPlayer7Profile"> - <item> - <property name="text"> - <string>Use Current Config</string> - </property> - </item> - </widget> - </item> - </layout> - </widget> - </item> - <item row="6" column="7"> - <widget class="QWidget" name="widgetPlayer8" native="true"> - <layout class="QVBoxLayout" name="verticalLayout_26"> - <property name="spacing"> - <number>5</number> - </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 alignment="Qt::AlignHCenter"> - <widget class="QGroupBox" name="groupPlayer8Connected"> - <property name="minimumSize"> - <size> - <width>100</width> - <height>100</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>100</width> - <height>100</height> - </size> - </property> - <property name="title"> - <string/> - </property> - <property name="checkable"> - <bool>true</bool> - </property> - <property name="checked"> - <bool>false</bool> - </property> - <layout class="QVBoxLayout" name="verticalLayout_11" stretch="1,0"> - <property name="spacing"> - <number>7</number> - </property> - <property name="leftMargin"> - <number>14</number> - </property> - <property name="topMargin"> - <number>7</number> - </property> - <property name="rightMargin"> - <number>14</number> - </property> - <property name="bottomMargin"> - <number>4</number> - </property> - <item> - <widget class="QWidget" name="controllerPlayer8" native="true"> - <property name="styleSheet"> - <string notr="true"/> - </property> - <layout class="QVBoxLayout" name="verticalLayout_19"> - <property name="topMargin"> - <number>16</number> - </property> - <item alignment="Qt::AlignHCenter|Qt::AlignVCenter"> - <widget class="QLabel" name="labelPlayer8"> - <property name="text"> - <string>P8</string> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item alignment="Qt::AlignHCenter"> - <widget class="QWidget" name="Player8LEDs" native="true"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="minimumSize"> - <size> - <width>0</width> - <height>10</height> - </size> - </property> - <layout class="QHBoxLayout" name="horizontalLayout_14"> - <property name="spacing"> - <number>4</number> - </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="checkboxPlayer8LED1"/> - </item> - <item> - <widget class="QCheckBox" name="checkboxPlayer8LED2"/> - </item> - <item> - <widget class="QCheckBox" name="checkboxPlayer8LED3"/> - </item> - <item> - <widget class="QCheckBox" name="checkboxPlayer8LED4"/> - </item> - </layout> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QWidget" name="Player8Explain" native="true"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>10</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>150</width> - <height>16777215</height> - </size> - </property> - <layout class="QVBoxLayout" name="verticalLayout_35"> - <property name="spacing"> - <number>0</number> - </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="QLabel" name="labelPlayer8Explain"> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QComboBox" name="comboPlayer8Emulated"> - <item> - <property name="text"> - <string>Pro Controller</string> - </property> - </item> - <item> - <property name="text"> - <string>Dual Joycons</string> - </property> - </item> - <item> - <property name="text"> - <string>Left Joycon</string> - </property> - </item> - <item> - <property name="text"> - <string>Right Joycon</string> - </property> - </item> - </widget> - </item> - <item> - <widget class="QComboBox" name="comboPlayer8Profile"> - <item> - <property name="text"> - <string>Use Current Config</string> - </property> - </item> - </widget> - </item> - </layout> - </widget> - </item> - <item row="6" column="1"> - <widget class="QWidget" name="widgetPlayer5" native="true"> - <layout class="QVBoxLayout" name="verticalLayout_23"> - <property name="spacing"> - <number>5</number> - </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 alignment="Qt::AlignHCenter"> - <widget class="QGroupBox" name="groupPlayer5Connected"> - <property name="minimumSize"> - <size> - <width>100</width> - <height>100</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>100</width> - <height>100</height> - </size> - </property> - <property name="title"> - <string/> - </property> - <property name="checkable"> - <bool>true</bool> - </property> - <property name="checked"> - <bool>false</bool> - </property> - <layout class="QVBoxLayout" name="verticalLayout_8" stretch="1,0"> - <property name="spacing"> - <number>7</number> - </property> - <property name="leftMargin"> - <number>14</number> - </property> - <property name="topMargin"> - <number>7</number> - </property> - <property name="rightMargin"> - <number>14</number> - </property> - <property name="bottomMargin"> - <number>4</number> - </property> - <item> - <widget class="QWidget" name="controllerPlayer5" native="true"> - <property name="styleSheet"> - <string notr="true"/> - </property> - <layout class="QVBoxLayout" name="verticalLayout_16"> - <property name="topMargin"> - <number>16</number> - </property> - <item alignment="Qt::AlignHCenter|Qt::AlignVCenter"> - <widget class="QLabel" name="labelPlayer5"> - <property name="text"> - <string>P5</string> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item alignment="Qt::AlignHCenter"> - <widget class="QWidget" name="Player5LEDs" native="true"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="minimumSize"> - <size> - <width>0</width> - <height>10</height> - </size> - </property> - <layout class="QHBoxLayout" name="horizontalLayout_11"> - <property name="spacing"> - <number>4</number> - </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="checkboxPlayer5LED1"> - <property name="layoutDirection"> - <enum>Qt::LeftToRight</enum> - </property> - </widget> - </item> - <item> - <widget class="QCheckBox" name="checkboxPlayer5LED2"/> - </item> - <item> - <widget class="QCheckBox" name="checkboxPlayer5LED3"/> - </item> - <item> - <widget class="QCheckBox" name="checkboxPlayer5LED4"/> - </item> - </layout> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QWidget" name="Player5Explain" native="true"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>10</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>150</width> - <height>16777215</height> - </size> - </property> - <layout class="QVBoxLayout" name="verticalLayout_40"> - <property name="spacing"> - <number>0</number> - </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="QLabel" name="labelPlayer5Explain"> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QComboBox" name="comboPlayer5Emulated"> - <item> - <property name="text"> - <string>Pro Controller</string> - </property> - </item> - <item> - <property name="text"> - <string>Dual Joycons</string> - </property> - </item> - <item> - <property name="text"> - <string>Left Joycon</string> - </property> - </item> - <item> - <property name="text"> - <string>Right Joycon</string> - </property> - </item> - </widget> - </item> - <item> - <widget class="QComboBox" name="comboPlayer5Profile"> - <item> - <property name="text"> - <string>Use Current Config</string> - </property> - </item> - </widget> - </item> - </layout> - </widget> - </item> - <item row="6" column="3"> - <widget class="QWidget" name="widgetPlayer6" native="true"> - <layout class="QVBoxLayout" name="verticalLayout_24"> - <property name="spacing"> - <number>5</number> - </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 alignment="Qt::AlignHCenter"> - <widget class="QGroupBox" name="groupPlayer6Connected"> - <property name="minimumSize"> - <size> - <width>100</width> - <height>100</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>100</width> - <height>100</height> - </size> - </property> - <property name="title"> - <string/> - </property> - <property name="checkable"> - <bool>true</bool> - </property> - <property name="checked"> - <bool>false</bool> - </property> - <layout class="QVBoxLayout" name="verticalLayout_9" stretch="1,0"> - <property name="spacing"> - <number>7</number> - </property> - <property name="leftMargin"> - <number>14</number> - </property> - <property name="topMargin"> - <number>7</number> - </property> - <property name="rightMargin"> - <number>14</number> - </property> - <property name="bottomMargin"> - <number>4</number> - </property> - <item> - <widget class="QWidget" name="controllerPlayer6" native="true"> - <property name="styleSheet"> - <string notr="true"/> - </property> - <layout class="QVBoxLayout" name="verticalLayout_17"> - <property name="topMargin"> - <number>16</number> - </property> - <item alignment="Qt::AlignHCenter|Qt::AlignVCenter"> - <widget class="QLabel" name="labelPlayer6"> - <property name="text"> - <string>P6</string> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item alignment="Qt::AlignHCenter"> - <widget class="QWidget" name="Player6LEDs" native="true"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="minimumSize"> - <size> - <width>0</width> - <height>10</height> - </size> - </property> - <layout class="QHBoxLayout" name="horizontalLayout_12"> - <property name="spacing"> - <number>4</number> - </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="checkboxPlayer6LED1"/> - </item> - <item> - <widget class="QCheckBox" name="checkboxPlayer6LED2"/> - </item> - <item> - <widget class="QCheckBox" name="checkboxPlayer6LED3"/> - </item> - <item> - <widget class="QCheckBox" name="checkboxPlayer6LED4"/> - </item> - </layout> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QWidget" name="Player6Explain" native="true"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>10</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>150</width> - <height>16777215</height> - </size> - </property> - <layout class="QVBoxLayout" name="verticalLayout_41"> - <property name="spacing"> - <number>0</number> - </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="QLabel" name="labelPlayer6Explain"> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QComboBox" name="comboPlayer6Emulated"> - <item> - <property name="text"> - <string>Pro Controller</string> - </property> - </item> - <item> - <property name="text"> - <string>Dual Joycons</string> - </property> - </item> - <item> - <property name="text"> - <string>Left Joycon</string> - </property> - </item> - <item> - <property name="text"> - <string>Right Joycon</string> - </property> - </item> - </widget> - </item> - <item> - <widget class="QComboBox" name="comboPlayer6Profile"> - <item> - <property name="text"> - <string>Use Current Config</string> - </property> - </item> - </widget> - </item> - </layout> - </widget> - </item> - <item row="10" column="1"> - <widget class="QWidget" name="widgetSpacer" native="true"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>25</height> - </size> - </property> - <layout class="QVBoxLayout" name="verticalLayout_22"> - <property name="spacing"> - <number>0</number> - </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> - <spacer name="controllerAppletVerticalSpacer"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>25</height> - </size> - </property> - </spacer> - </item> - </layout> - </widget> - </item> - <item row="1" column="2"> - <widget class="QWidget" name="widgetSpacer6" native="true"> - <layout class="QHBoxLayout" name="horizontalLayout_15"> - <property name="spacing"> - <number>0</number> - </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> - <spacer name="controllerAppletHorizontalSpacer5"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>0</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - </layout> - </widget> - </item> - <item row="1" column="0"> - <widget class="QWidget" name="widgetSpacer7" native="true"> - <property name="minimumSize"> - <size> - <width>25</width> - <height>0</height> - </size> - </property> - <layout class="QHBoxLayout" name="horizontalLayout_16"> - <property name="spacing"> - <number>0</number> - </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> - <spacer name="controllerAppletHorizontalSpacer4"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>25</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - </layout> - </widget> - </item> - <item row="2" column="1"> - <widget class="QWidget" name="widgetSpacer9" native="true"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>25</height> - </size> - </property> - <layout class="QHBoxLayout" name="horizontalLayout_17"> - <property name="spacing"> - <number>0</number> - </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> - <spacer name="controllerAppletVerticalSpacer2"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>25</height> - </size> - </property> - </spacer> - </item> - </layout> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QWidget" name="bottomControllerApplet" native="true"> - <layout class="QHBoxLayout" name="horizontalLayout_6"> - <property name="spacing"> - <number>15</number> - </property> - <property name="leftMargin"> - <number>15</number> - </property> - <property name="topMargin"> - <number>8</number> - </property> - <property name="rightMargin"> - <number>15</number> - </property> - <property name="bottomMargin"> - <number>15</number> - </property> - <item> - <widget class="QGroupBox" name="handheldGroup"> - <property name="maximumSize"> - <size> - <width>16777215</width> - <height>16777215</height> - </size> - </property> - <property name="title"> - <string>Console Mode</string> - </property> - <layout class="QHBoxLayout" name="horizontalLayout_3"> - <property name="spacing"> - <number>6</number> - </property> - <property name="leftMargin"> - <number>8</number> - </property> - <property name="topMargin"> - <number>6</number> - </property> - <property name="rightMargin"> - <number>3</number> - </property> - <property name="bottomMargin"> - <number>6</number> - </property> - <item> - <widget class="QRadioButton" name="radioDocked"> - <property name="text"> - <string>Docked</string> - </property> - <property name="checked"> - <bool>true</bool> - </property> - </widget> - </item> - <item> - <widget class="QRadioButton" name="radioUndocked"> - <property name="text"> - <string>Handheld</string> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QGroupBox" name="vibrationGroup"> - <property name="title"> - <string>Vibration</string> - </property> - <property name="checkable"> - <bool>true</bool> - </property> - <layout class="QHBoxLayout" name="horizontalLayout_5"> - <property name="leftMargin"> - <number>3</number> - </property> - <property name="topMargin"> - <number>3</number> - </property> - <property name="rightMargin"> - <number>3</number> - </property> - <property name="bottomMargin"> - <number>3</number> - </property> - <item> - <widget class="QPushButton" name="vibrationButton"> - <property name="minimumSize"> - <size> - <width>68</width> - <height>0</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>68</width> - <height>16777215</height> - </size> - </property> - <property name="styleSheet"> - <string notr="true">min-width: 68px;</string> - </property> - <property name="text"> - <string>Configure</string> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QGroupBox" name="motionGroup"> - <property name="title"> - <string>Motion</string> - </property> - <property name="checkable"> - <bool>true</bool> - </property> - <layout class="QHBoxLayout" name="horizontalLayout_4"> - <property name="leftMargin"> - <number>3</number> - </property> - <property name="topMargin"> - <number>3</number> - </property> - <property name="rightMargin"> - <number>3</number> - </property> - <property name="bottomMargin"> - <number>3</number> - </property> - <item> - <widget class="QPushButton" name="motionButton"> - <property name="minimumSize"> - <size> - <width>68</width> - <height>0</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>68</width> - <height>16777215</height> - </size> - </property> - <property name="styleSheet"> - <string notr="true">min-width: 68px;</string> - </property> - <property name="text"> - <string>Configure</string> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QGroupBox" name="inputConfigGroup"> - <property name="title"> - <string>Profiles</string> - </property> - <layout class="QHBoxLayout" name="horizontalLayout_7"> - <property name="leftMargin"> - <number>3</number> - </property> - <property name="topMargin"> - <number>3</number> - </property> - <property name="rightMargin"> - <number>3</number> - </property> - <property name="bottomMargin"> - <number>3</number> - </property> - <item> - <widget class="QPushButton" name="inputConfigButton"> - <property name="maximumSize"> - <size> - <width>68</width> - <height>16777215</height> - </size> - </property> - <property name="styleSheet"> - <string notr="true">min-width: 68px;</string> - </property> - <property name="text"> - <string>Create</string> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QWidget" name="connectedControllers" native="true"> - <layout class="QGridLayout" name="gridLayout_2"> - <property name="leftMargin"> - <number>5</number> - </property> - <property name="topMargin"> - <number>0</number> - </property> - <property name="rightMargin"> - <number>0</number> - </property> - <property name="bottomMargin"> - <number>0</number> - </property> - <property name="spacing"> - <number>3</number> - </property> - <item row="1" column="4"> - <widget class="QCheckBox" name="checkboxPlayer4Connected"> - <property name="text"> - <string/> - </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="labelControllers"> - <property name="text"> - <string>Controllers</string> - </property> - </widget> - </item> - <item row="1" column="2"> - <widget class="QCheckBox" name="checkboxPlayer2Connected"> - <property name="text"> - <string/> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QLabel" name="labelConnectedPlayer1"> - <property name="text"> - <string>1</string> - </property> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - </widget> - </item> - <item row="1" column="3"> - <widget class="QCheckBox" name="checkboxPlayer3Connected"> - <property name="text"> - <string/> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QCheckBox" name="checkboxPlayer1Connected"> - <property name="layoutDirection"> - <enum>Qt::LeftToRight</enum> - </property> - <property name="checked"> - <bool>false</bool> - </property> - </widget> - </item> - <item row="0" column="2"> - <widget class="QLabel" name="labelConnectedPlayer2"> - <property name="text"> - <string>2</string> - </property> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - </widget> - </item> - <item row="0" column="4"> - <widget class="QLabel" name="labelConnectedPlayer4"> - <property name="text"> - <string>4</string> - </property> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - </widget> - </item> - <item row="0" column="3"> - <widget class="QLabel" name="labelConnectedPlayer3"> - <property name="text"> - <string>3</string> - </property> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - </widget> - </item> - <item row="0" column="0"> - <widget class="QLabel" name="labelConnected"> - <property name="text"> - <string>Connected</string> - </property> - </widget> - </item> - <item row="1" column="7"> - <widget class="QCheckBox" name="checkboxPlayer7Connected"> - <property name="text"> - <string/> - </property> - </widget> - </item> - <item row="0" column="5"> - <widget class="QLabel" name="labelConnectedPlayer5"> - <property name="text"> - <string>5</string> - </property> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - </widget> - </item> - <item row="1" column="6"> - <widget class="QCheckBox" name="checkboxPlayer6Connected"> - <property name="text"> - <string/> - </property> - </widget> - </item> - <item row="0" column="7"> - <widget class="QLabel" name="labelConnectedPlayer7"> - <property name="text"> - <string>7</string> - </property> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - </widget> - </item> - <item row="1" column="5"> - <widget class="QCheckBox" name="checkboxPlayer5Connected"> - <property name="text"> - <string/> - </property> - </widget> - </item> - <item row="0" column="6"> - <widget class="QLabel" name="labelConnectedPlayer6"> - <property name="text"> - <string>6</string> - </property> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - </widget> - </item> - <item row="0" column="8"> - <widget class="QLabel" name="labelConnectedPlayer8"> - <property name="text"> - <string>8</string> - </property> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - </widget> - </item> - <item row="1" column="8"> - <widget class="QCheckBox" name="checkboxPlayer8Connected"> - <property name="text"> - <string/> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <spacer name="controllerAppletHorizontalSpacer"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>0</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item alignment="Qt::AlignBottom"> - <widget class="QWidget" name="closeButtons" native="true"> - <layout class="QVBoxLayout" name="verticalLayout_46"> - <property name="spacing"> - <number>7</number> - </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="QLabel" name="labelError"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="styleSheet"> - <string notr="true">QLabel { color : red; }</string> - </property> - <property name="text"> - <string>Not enough controllers</string> - </property> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - <property name="margin"> - <number>0</number> - </property> - </widget> - </item> - <item> - <widget class="QDialogButtonBox" name="buttonBox"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="standardButtons"> - <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> - </property> - </widget> - </item> - </layout> - </widget> - </item> - </layout> - </widget> - </item> - </layout> - </widget> - </item> - </layout> - </widget> - <resources/> - <connections> - <connection> - <sender>buttonBox</sender> - <signal>accepted()</signal> - <receiver>QtControllerSelectorDialog</receiver> - <slot>accept()</slot> - </connection> - <connection> - <sender>buttonBox</sender> - <signal>rejected()</signal> - <receiver>QtControllerSelectorDialog</receiver> - <slot>reject()</slot> - </connection> - </connections> -</ui> diff --git a/src/yuzu/applets/qt_error.cpp b/src/yuzu/applets/qt_error.cpp deleted file mode 100644 index ad35f4126..000000000 --- a/src/yuzu/applets/qt_error.cpp +++ /dev/null @@ -1,68 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include <QDateTime> -#include "yuzu/applets/qt_error.h" -#include "yuzu/main.h" - -QtErrorDisplay::QtErrorDisplay(GMainWindow& parent) { - connect(this, &QtErrorDisplay::MainWindowDisplayError, &parent, - &GMainWindow::ErrorDisplayDisplayError, Qt::QueuedConnection); - connect(this, &QtErrorDisplay::MainWindowRequestExit, &parent, - &GMainWindow::ErrorDisplayRequestExit, Qt::QueuedConnection); - connect(&parent, &GMainWindow::ErrorDisplayFinished, this, - &QtErrorDisplay::MainWindowFinishedError, Qt::DirectConnection); -} - -QtErrorDisplay::~QtErrorDisplay() = default; - -void QtErrorDisplay::Close() const { - callback = {}; - emit MainWindowRequestExit(); -} - -void QtErrorDisplay::ShowError(Result error, FinishedCallback finished) const { - callback = std::move(finished); - emit MainWindowDisplayError( - tr("Error Code: %1-%2 (0x%3)") - .arg(static_cast<u32>(error.GetModule()) + 2000, 4, 10, QChar::fromLatin1('0')) - .arg(error.GetDescription(), 4, 10, QChar::fromLatin1('0')) - .arg(error.raw, 8, 16, QChar::fromLatin1('0')), - tr("An error has occurred.\nPlease try again or contact the developer of the software.")); -} - -void QtErrorDisplay::ShowErrorWithTimestamp(Result error, std::chrono::seconds time, - FinishedCallback finished) const { - callback = std::move(finished); - - const QDateTime date_time = QDateTime::fromSecsSinceEpoch(time.count()); - emit MainWindowDisplayError( - tr("Error Code: %1-%2 (0x%3)") - .arg(static_cast<u32>(error.GetModule()) + 2000, 4, 10, QChar::fromLatin1('0')) - .arg(error.GetDescription(), 4, 10, QChar::fromLatin1('0')) - .arg(error.raw, 8, 16, QChar::fromLatin1('0')), - tr("An error occurred on %1 at %2.\nPlease try again or contact the developer of the " - "software.") - .arg(date_time.toString(QStringLiteral("dddd, MMMM d, yyyy"))) - .arg(date_time.toString(QStringLiteral("h:mm:ss A")))); -} - -void QtErrorDisplay::ShowCustomErrorText(Result error, std::string dialog_text, - std::string fullscreen_text, - FinishedCallback finished) const { - callback = std::move(finished); - emit MainWindowDisplayError( - tr("Error Code: %1-%2 (0x%3)") - .arg(static_cast<u32>(error.GetModule()) + 2000, 4, 10, QChar::fromLatin1('0')) - .arg(error.GetDescription(), 4, 10, QChar::fromLatin1('0')) - .arg(error.raw, 8, 16, QChar::fromLatin1('0')), - tr("An error has occurred.\n\n%1\n\n%2") - .arg(QString::fromStdString(dialog_text)) - .arg(QString::fromStdString(fullscreen_text))); -} - -void QtErrorDisplay::MainWindowFinishedError() { - if (callback) { - callback(); - } -} diff --git a/src/yuzu/applets/qt_error.h b/src/yuzu/applets/qt_error.h deleted file mode 100644 index 957f170ad..000000000 --- a/src/yuzu/applets/qt_error.h +++ /dev/null @@ -1,34 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include <QObject> - -#include "core/frontend/applets/error.h" - -class GMainWindow; - -class QtErrorDisplay final : public QObject, public Core::Frontend::ErrorApplet { - Q_OBJECT - -public: - explicit QtErrorDisplay(GMainWindow& parent); - ~QtErrorDisplay() override; - - void Close() const override; - void ShowError(Result error, FinishedCallback finished) const override; - void ShowErrorWithTimestamp(Result error, std::chrono::seconds time, - FinishedCallback finished) const override; - void ShowCustomErrorText(Result error, std::string dialog_text, std::string fullscreen_text, - FinishedCallback finished) const override; - -signals: - void MainWindowDisplayError(QString error_code, QString error_text) const; - void MainWindowRequestExit() const; - -private: - void MainWindowFinishedError(); - - mutable FinishedCallback callback; -}; diff --git a/src/yuzu/applets/qt_profile_select.cpp b/src/yuzu/applets/qt_profile_select.cpp deleted file mode 100644 index 66edd6acd..000000000 --- a/src/yuzu/applets/qt_profile_select.cpp +++ /dev/null @@ -1,260 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include <mutex> -#include <QApplication> -#include <QDialogButtonBox> -#include <QHeaderView> -#include <QLabel> -#include <QLineEdit> -#include <QScrollArea> -#include <QStandardItemModel> -#include <QTreeView> -#include <QVBoxLayout> -#include "common/fs/path_util.h" -#include "common/string_util.h" -#include "core/constants.h" -#include "core/core.h" -#include "core/hle/service/acc/profile_manager.h" -#include "yuzu/applets/qt_profile_select.h" -#include "yuzu/main.h" -#include "yuzu/util/controller_navigation.h" - -namespace { -QString FormatUserEntryText(const QString& username, Common::UUID uuid) { - return QtProfileSelectionDialog::tr( - "%1\n%2", "%1 is the profile username, %2 is the formatted UUID (e.g. " - "00112233-4455-6677-8899-AABBCCDDEEFF))") - .arg(username, QString::fromStdString(uuid.FormattedString())); -} - -QString GetImagePath(Common::UUID uuid) { - const auto path = - Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir) / - fmt::format("system/save/8000000000000010/su/avators/{}.jpg", uuid.FormattedString()); - return QString::fromStdString(Common::FS::PathToUTF8String(path)); -} - -QPixmap GetIcon(Common::UUID uuid) { - QPixmap icon{GetImagePath(uuid)}; - - if (!icon) { - icon.fill(Qt::black); - icon.loadFromData(Core::Constants::ACCOUNT_BACKUP_JPEG.data(), - static_cast<u32>(Core::Constants::ACCOUNT_BACKUP_JPEG.size())); - } - - return icon.scaled(64, 64, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); -} -} // Anonymous namespace - -QtProfileSelectionDialog::QtProfileSelectionDialog( - Core::System& system, QWidget* parent, - const Core::Frontend::ProfileSelectParameters& parameters) - : QDialog(parent), profile_manager{system.GetProfileManager()} { - outer_layout = new QVBoxLayout; - - instruction_label = new QLabel(); - - scroll_area = new QScrollArea; - - buttons = new QDialogButtonBox(QDialogButtonBox::Cancel | QDialogButtonBox::Ok); - connect(buttons, &QDialogButtonBox::accepted, this, &QtProfileSelectionDialog::accept); - connect(buttons, &QDialogButtonBox::rejected, this, &QtProfileSelectionDialog::reject); - - outer_layout->addWidget(instruction_label); - outer_layout->addWidget(scroll_area); - outer_layout->addWidget(buttons); - - layout = new QVBoxLayout; - tree_view = new QTreeView; - item_model = new QStandardItemModel(tree_view); - tree_view->setModel(item_model); - controller_navigation = new ControllerNavigation(system.HIDCore(), this); - - tree_view->setAlternatingRowColors(true); - tree_view->setSelectionMode(QHeaderView::SingleSelection); - tree_view->setSelectionBehavior(QHeaderView::SelectRows); - tree_view->setVerticalScrollMode(QHeaderView::ScrollPerPixel); - tree_view->setHorizontalScrollMode(QHeaderView::ScrollPerPixel); - tree_view->setSortingEnabled(true); - tree_view->setEditTriggers(QHeaderView::NoEditTriggers); - tree_view->setUniformRowHeights(true); - tree_view->setIconSize({64, 64}); - tree_view->setContextMenuPolicy(Qt::NoContextMenu); - - item_model->insertColumns(0, 1); - item_model->setHeaderData(0, Qt::Horizontal, tr("Users")); - - // We must register all custom types with the Qt Automoc system so that we are able to use it - // with signals/slots. In this case, QList falls under the umbrella of custom types. - qRegisterMetaType<QList<QStandardItem*>>("QList<QStandardItem*>"); - - layout->setContentsMargins(0, 0, 0, 0); - layout->setSpacing(0); - layout->addWidget(tree_view); - - scroll_area->setLayout(layout); - - connect(tree_view, &QTreeView::clicked, this, &QtProfileSelectionDialog::SelectUser); - connect(tree_view, &QTreeView::doubleClicked, this, &QtProfileSelectionDialog::accept); - connect(controller_navigation, &ControllerNavigation::TriggerKeyboardEvent, - [this](Qt::Key key) { - if (!this->isActiveWindow()) { - return; - } - QKeyEvent* event = new QKeyEvent(QEvent::KeyPress, key, Qt::NoModifier); - QCoreApplication::postEvent(tree_view, event); - SelectUser(tree_view->currentIndex()); - }); - - const auto& profiles = profile_manager.GetAllUsers(); - for (const auto& user : profiles) { - Service::Account::ProfileBase profile{}; - if (!profile_manager.GetProfileBase(user, profile)) - continue; - - const auto username = Common::StringFromFixedZeroTerminatedBuffer( - reinterpret_cast<const char*>(profile.username.data()), profile.username.size()); - - list_items.push_back(QList<QStandardItem*>{new QStandardItem{ - GetIcon(user), FormatUserEntryText(QString::fromStdString(username), user)}}); - } - - for (const auto& item : list_items) - item_model->appendRow(item); - - setLayout(outer_layout); - SetWindowTitle(parameters); - SetDialogPurpose(parameters); - resize(550, 400); -} - -QtProfileSelectionDialog::~QtProfileSelectionDialog() { - controller_navigation->UnloadController(); -}; - -int QtProfileSelectionDialog::exec() { - // Skip profile selection when there's only one. - if (profile_manager.GetUserCount() == 1) { - user_index = 0; - return QDialog::Accepted; - } - return QDialog::exec(); -} - -void QtProfileSelectionDialog::accept() { - QDialog::accept(); -} - -void QtProfileSelectionDialog::reject() { - user_index = 0; - QDialog::reject(); -} - -int QtProfileSelectionDialog::GetIndex() const { - return user_index; -} - -void QtProfileSelectionDialog::SelectUser(const QModelIndex& index) { - user_index = index.row(); -} - -void QtProfileSelectionDialog::SetWindowTitle( - const Core::Frontend::ProfileSelectParameters& parameters) { - using Service::AM::Frontend::UiMode; - switch (parameters.mode) { - case UiMode::UserCreator: - case UiMode::UserCreatorForStarter: - setWindowTitle(tr("Profile Creator")); - return; - case UiMode::EnsureNetworkServiceAccountAvailable: - setWindowTitle(tr("Profile Selector")); - return; - case UiMode::UserIconEditor: - setWindowTitle(tr("Profile Icon Editor")); - return; - case UiMode::UserNicknameEditor: - setWindowTitle(tr("Profile Nickname Editor")); - return; - case UiMode::NintendoAccountAuthorizationRequestContext: - case UiMode::IntroduceExternalNetworkServiceAccount: - case UiMode::IntroduceExternalNetworkServiceAccountForRegistration: - case UiMode::NintendoAccountNnidLinker: - case UiMode::LicenseRequirementsForNetworkService: - case UiMode::LicenseRequirementsForNetworkServiceWithUserContextImpl: - case UiMode::UserCreatorForImmediateNaLoginTest: - case UiMode::UserQualificationPromoter: - case UiMode::UserSelector: - default: - setWindowTitle(tr("Profile Selector")); - } -} - -void QtProfileSelectionDialog::SetDialogPurpose( - const Core::Frontend::ProfileSelectParameters& parameters) { - using Service::AM::Frontend::UserSelectionPurpose; - - switch (parameters.purpose) { - case UserSelectionPurpose::GameCardRegistration: - instruction_label->setText(tr("Who will receive the points?")); - return; - case UserSelectionPurpose::EShopLaunch: - instruction_label->setText(tr("Who is using Nintendo eShop?")); - return; - case UserSelectionPurpose::EShopItemShow: - instruction_label->setText(tr("Who is making this purchase?")); - return; - case UserSelectionPurpose::PicturePost: - instruction_label->setText(tr("Who is posting?")); - return; - case UserSelectionPurpose::NintendoAccountLinkage: - instruction_label->setText(tr("Select a user to link to a Nintendo Account.")); - return; - case UserSelectionPurpose::SettingsUpdate: - instruction_label->setText(tr("Change settings for which user?")); - return; - case UserSelectionPurpose::SaveDataDeletion: - instruction_label->setText(tr("Format data for which user?")); - return; - case UserSelectionPurpose::UserMigration: - instruction_label->setText(tr("Which user will be transferred to another console?")); - return; - case UserSelectionPurpose::SaveDataTransfer: - instruction_label->setText(tr("Send save data for which user?")); - return; - case UserSelectionPurpose::General: - default: - instruction_label->setText(tr("Select a user:")); - return; - } -} - -QtProfileSelector::QtProfileSelector(GMainWindow& parent) { - connect(this, &QtProfileSelector::MainWindowSelectProfile, &parent, - &GMainWindow::ProfileSelectorSelectProfile, Qt::QueuedConnection); - connect(this, &QtProfileSelector::MainWindowRequestExit, &parent, - &GMainWindow::ProfileSelectorRequestExit, Qt::QueuedConnection); - connect(&parent, &GMainWindow::ProfileSelectorFinishedSelection, this, - &QtProfileSelector::MainWindowFinishedSelection, Qt::DirectConnection); -} - -QtProfileSelector::~QtProfileSelector() = default; - -void QtProfileSelector::Close() const { - callback = {}; - emit MainWindowRequestExit(); -} - -void QtProfileSelector::SelectProfile( - SelectProfileCallback callback_, - const Core::Frontend::ProfileSelectParameters& parameters) const { - callback = std::move(callback_); - emit MainWindowSelectProfile(parameters); -} - -void QtProfileSelector::MainWindowFinishedSelection(std::optional<Common::UUID> uuid) { - if (callback) { - callback(uuid); - } -} diff --git a/src/yuzu/applets/qt_profile_select.h b/src/yuzu/applets/qt_profile_select.h deleted file mode 100644 index 607f1777c..000000000 --- a/src/yuzu/applets/qt_profile_select.h +++ /dev/null @@ -1,87 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include <vector> -#include <QDialog> -#include <QList> -#include "core/frontend/applets/profile_select.h" - -class ControllerNavigation; -class GMainWindow; -class QDialogButtonBox; -class QGraphicsScene; -class QLabel; -class QScrollArea; -class QStandardItem; -class QStandardItemModel; -class QTreeView; -class QVBoxLayout; - -namespace Core { -class System; -} - -namespace Service::Account { -class ProfileManager; -} - -class QtProfileSelectionDialog final : public QDialog { - Q_OBJECT - -public: - explicit QtProfileSelectionDialog(Core::System& system, QWidget* parent, - const Core::Frontend::ProfileSelectParameters& parameters); - ~QtProfileSelectionDialog() override; - - int exec() override; - void accept() override; - void reject() override; - - int GetIndex() const; - -private: - void SelectUser(const QModelIndex& index); - - void SetWindowTitle(const Core::Frontend::ProfileSelectParameters& parameters); - void SetDialogPurpose(const Core::Frontend::ProfileSelectParameters& parameters); - - int user_index = 0; - - QVBoxLayout* layout; - QTreeView* tree_view; - QStandardItemModel* item_model; - QGraphicsScene* scene; - - std::vector<QList<QStandardItem*>> list_items; - - QVBoxLayout* outer_layout; - QLabel* instruction_label; - QScrollArea* scroll_area; - QDialogButtonBox* buttons; - - Service::Account::ProfileManager& profile_manager; - ControllerNavigation* controller_navigation = nullptr; -}; - -class QtProfileSelector final : public QObject, public Core::Frontend::ProfileSelectApplet { - Q_OBJECT - -public: - explicit QtProfileSelector(GMainWindow& parent); - ~QtProfileSelector() override; - - void Close() const override; - void SelectProfile(SelectProfileCallback callback_, - const Core::Frontend::ProfileSelectParameters& parameters) const override; - -signals: - void MainWindowSelectProfile(const Core::Frontend::ProfileSelectParameters& parameters) const; - void MainWindowRequestExit() const; - -private: - void MainWindowFinishedSelection(std::optional<Common::UUID> uuid); - - mutable SelectProfileCallback callback; -}; diff --git a/src/yuzu/applets/qt_software_keyboard.cpp b/src/yuzu/applets/qt_software_keyboard.cpp deleted file mode 100644 index 2749e6ed3..000000000 --- a/src/yuzu/applets/qt_software_keyboard.cpp +++ /dev/null @@ -1,1674 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include <QCursor> -#include <QKeyEvent> -#include <QScreen> - -#include "common/logging/log.h" -#include "common/settings.h" -#include "common/string_util.h" -#include "core/core.h" -#include "hid_core/frontend/emulated_controller.h" -#include "hid_core/frontend/input_interpreter.h" -#include "hid_core/hid_core.h" -#include "hid_core/hid_types.h" -#include "ui_qt_software_keyboard.h" -#include "yuzu/applets/qt_software_keyboard.h" -#include "yuzu/main.h" -#include "yuzu/util/overlay_dialog.h" - -namespace { - -using namespace Service::AM::Frontend; - -constexpr float BASE_HEADER_FONT_SIZE = 23.0f; -constexpr float BASE_SUB_FONT_SIZE = 17.0f; -constexpr float BASE_EDITOR_FONT_SIZE = 26.0f; -constexpr float BASE_CHAR_BUTTON_FONT_SIZE = 28.0f; -constexpr float BASE_LABEL_BUTTON_FONT_SIZE = 18.0f; -constexpr float BASE_ICON_BUTTON_SIZE = 36.0f; -[[maybe_unused]] constexpr float BASE_WIDTH = 1280.0f; -constexpr float BASE_HEIGHT = 720.0f; - -} // Anonymous namespace - -QtSoftwareKeyboardDialog::QtSoftwareKeyboardDialog( - QWidget* parent, Core::System& system_, bool is_inline_, - Core::Frontend::KeyboardInitializeParameters initialize_parameters_) - : QDialog(parent), ui{std::make_unique<Ui::QtSoftwareKeyboardDialog>()}, system{system_}, - is_inline{is_inline_}, initialize_parameters{std::move(initialize_parameters_)} { - ui->setupUi(this); - - setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint | Qt::WindowTitleHint | - Qt::WindowSystemMenuHint | Qt::CustomizeWindowHint); - setWindowModality(Qt::WindowModal); - setAttribute(Qt::WA_DeleteOnClose); - setAttribute(Qt::WA_TranslucentBackground); - - keyboard_buttons = {{ - {{ - { - ui->button_1, - ui->button_2, - ui->button_3, - ui->button_4, - ui->button_5, - ui->button_6, - ui->button_7, - ui->button_8, - ui->button_9, - ui->button_0, - ui->button_minus, - ui->button_backspace, - }, - { - ui->button_q, - ui->button_w, - ui->button_e, - ui->button_r, - ui->button_t, - ui->button_y, - ui->button_u, - ui->button_i, - ui->button_o, - ui->button_p, - ui->button_slash, - ui->button_return, - }, - { - ui->button_a, - ui->button_s, - ui->button_d, - ui->button_f, - ui->button_g, - ui->button_h, - ui->button_j, - ui->button_k, - ui->button_l, - ui->button_colon, - ui->button_apostrophe, - ui->button_return, - }, - { - ui->button_z, - ui->button_x, - ui->button_c, - ui->button_v, - ui->button_b, - ui->button_n, - ui->button_m, - ui->button_comma, - ui->button_dot, - ui->button_question, - ui->button_exclamation, - ui->button_ok, - }, - { - ui->button_shift, - ui->button_shift, - ui->button_space, - ui->button_space, - ui->button_space, - ui->button_space, - ui->button_space, - ui->button_space, - ui->button_space, - ui->button_space, - ui->button_space, - ui->button_ok, - }, - }}, - {{ - { - ui->button_hash, - ui->button_left_bracket, - ui->button_right_bracket, - ui->button_dollar, - ui->button_percent, - ui->button_circumflex, - ui->button_ampersand, - ui->button_asterisk, - ui->button_left_parenthesis, - ui->button_right_parenthesis, - ui->button_underscore, - ui->button_backspace_shift, - }, - { - ui->button_q_shift, - ui->button_w_shift, - ui->button_e_shift, - ui->button_r_shift, - ui->button_t_shift, - ui->button_y_shift, - ui->button_u_shift, - ui->button_i_shift, - ui->button_o_shift, - ui->button_p_shift, - ui->button_at, - ui->button_return_shift, - }, - { - ui->button_a_shift, - ui->button_s_shift, - ui->button_d_shift, - ui->button_f_shift, - ui->button_g_shift, - ui->button_h_shift, - ui->button_j_shift, - ui->button_k_shift, - ui->button_l_shift, - ui->button_semicolon, - ui->button_quotation, - ui->button_return_shift, - }, - { - ui->button_z_shift, - ui->button_x_shift, - ui->button_c_shift, - ui->button_v_shift, - ui->button_b_shift, - ui->button_n_shift, - ui->button_m_shift, - ui->button_less_than, - ui->button_greater_than, - ui->button_plus, - ui->button_equal, - ui->button_ok_shift, - }, - { - ui->button_shift_shift, - ui->button_shift_shift, - ui->button_space_shift, - ui->button_space_shift, - ui->button_space_shift, - ui->button_space_shift, - ui->button_space_shift, - ui->button_space_shift, - ui->button_space_shift, - ui->button_space_shift, - ui->button_space_shift, - ui->button_ok_shift, - }, - }}, - }}; - - numberpad_buttons = {{ - { - ui->button_1_num, - ui->button_2_num, - ui->button_3_num, - ui->button_backspace_num, - }, - { - ui->button_4_num, - ui->button_5_num, - ui->button_6_num, - ui->button_ok_num, - }, - { - ui->button_7_num, - ui->button_8_num, - ui->button_9_num, - ui->button_ok_num, - }, - { - ui->button_left_optional_num, - ui->button_0_num, - ui->button_right_optional_num, - ui->button_ok_num, - }, - }}; - - all_buttons = { - ui->button_1, - ui->button_2, - ui->button_3, - ui->button_4, - ui->button_5, - ui->button_6, - ui->button_7, - ui->button_8, - ui->button_9, - ui->button_0, - ui->button_minus, - ui->button_backspace, - ui->button_q, - ui->button_w, - ui->button_e, - ui->button_r, - ui->button_t, - ui->button_y, - ui->button_u, - ui->button_i, - ui->button_o, - ui->button_p, - ui->button_slash, - ui->button_return, - ui->button_a, - ui->button_s, - ui->button_d, - ui->button_f, - ui->button_g, - ui->button_h, - ui->button_j, - ui->button_k, - ui->button_l, - ui->button_colon, - ui->button_apostrophe, - ui->button_z, - ui->button_x, - ui->button_c, - ui->button_v, - ui->button_b, - ui->button_n, - ui->button_m, - ui->button_comma, - ui->button_dot, - ui->button_question, - ui->button_exclamation, - ui->button_ok, - ui->button_shift, - ui->button_space, - ui->button_hash, - ui->button_left_bracket, - ui->button_right_bracket, - ui->button_dollar, - ui->button_percent, - ui->button_circumflex, - ui->button_ampersand, - ui->button_asterisk, - ui->button_left_parenthesis, - ui->button_right_parenthesis, - ui->button_underscore, - ui->button_backspace_shift, - ui->button_q_shift, - ui->button_w_shift, - ui->button_e_shift, - ui->button_r_shift, - ui->button_t_shift, - ui->button_y_shift, - ui->button_u_shift, - ui->button_i_shift, - ui->button_o_shift, - ui->button_p_shift, - ui->button_at, - ui->button_return_shift, - ui->button_a_shift, - ui->button_s_shift, - ui->button_d_shift, - ui->button_f_shift, - ui->button_g_shift, - ui->button_h_shift, - ui->button_j_shift, - ui->button_k_shift, - ui->button_l_shift, - ui->button_semicolon, - ui->button_quotation, - ui->button_z_shift, - ui->button_x_shift, - ui->button_c_shift, - ui->button_v_shift, - ui->button_b_shift, - ui->button_n_shift, - ui->button_m_shift, - ui->button_less_than, - ui->button_greater_than, - ui->button_plus, - ui->button_equal, - ui->button_ok_shift, - ui->button_shift_shift, - ui->button_space_shift, - ui->button_1_num, - ui->button_2_num, - ui->button_3_num, - ui->button_backspace_num, - ui->button_4_num, - ui->button_5_num, - ui->button_6_num, - ui->button_ok_num, - ui->button_7_num, - ui->button_8_num, - ui->button_9_num, - ui->button_left_optional_num, - ui->button_0_num, - ui->button_right_optional_num, - }; - - SetupMouseHover(); - - if (!initialize_parameters.ok_text.empty()) { - ui->button_ok->setText(QString::fromStdU16String(initialize_parameters.ok_text)); - } - - ui->label_header->setText(QString::fromStdU16String(initialize_parameters.header_text)); - ui->label_sub->setText(QString::fromStdU16String(initialize_parameters.sub_text)); - - ui->button_left_optional_num->setText(QChar{initialize_parameters.left_optional_symbol_key}); - ui->button_right_optional_num->setText(QChar{initialize_parameters.right_optional_symbol_key}); - - current_text = initialize_parameters.initial_text; - cursor_position = initialize_parameters.initial_cursor_position; - - SetTextDrawType(); - - for (auto* button : all_buttons) { - connect(button, &QPushButton::clicked, this, [this, button](bool) { - if (is_inline) { - InlineKeyboardButtonClicked(button); - } else { - NormalKeyboardButtonClicked(button); - } - }); - } - - // TODO (Morph): Remove this when InputInterpreter no longer relies on the HID backend - if (system.IsPoweredOn()) { - input_interpreter = std::make_unique<InputInterpreter>(system); - } -} - -QtSoftwareKeyboardDialog::~QtSoftwareKeyboardDialog() { - StopInputThread(); -} - -void QtSoftwareKeyboardDialog::ShowNormalKeyboard(QPoint pos, QSize size) { - if (isVisible()) { - return; - } - - MoveAndResizeWindow(pos, size); - - SetKeyboardType(); - SetPasswordMode(); - SetControllerImage(); - DisableKeyboardButtons(); - SetBackspaceOkEnabled(); - - open(); -} - -void QtSoftwareKeyboardDialog::ShowTextCheckDialog( - Service::AM::Frontend::SwkbdTextCheckResult text_check_result, - std::u16string text_check_message) { - switch (text_check_result) { - case SwkbdTextCheckResult::Success: - case SwkbdTextCheckResult::Silent: - default: - break; - case SwkbdTextCheckResult::Failure: { - StopInputThread(); - - OverlayDialog dialog(this, system, QString{}, QString::fromStdU16String(text_check_message), - QString{}, tr("OK"), Qt::AlignCenter); - dialog.exec(); - - StartInputThread(); - break; - } - case SwkbdTextCheckResult::Confirm: { - StopInputThread(); - - OverlayDialog dialog(this, system, QString{}, QString::fromStdU16String(text_check_message), - tr("Cancel"), tr("OK"), Qt::AlignCenter); - if (dialog.exec() != QDialog::Accepted) { - StartInputThread(); - break; - } - - const auto text = ui->topOSK->currentIndex() == 1 ? ui->text_edit_osk->toPlainText() - : ui->line_edit_osk->text(); - auto text_str = Common::U16StringFromBuffer(text.utf16(), text.size()); - - emit SubmitNormalText(SwkbdResult::Ok, std::move(text_str), true); - break; - } - } -} - -void QtSoftwareKeyboardDialog::ShowInlineKeyboard( - Core::Frontend::InlineAppearParameters appear_parameters, QPoint pos, QSize size) { - MoveAndResizeWindow(pos, size); - - ui->topOSK->setStyleSheet(QStringLiteral("background: rgba(0, 0, 0, 0);")); - - ui->headerOSK->hide(); - ui->subOSK->hide(); - ui->inputOSK->hide(); - ui->charactersOSK->hide(); - ui->inputBoxOSK->hide(); - ui->charactersBoxOSK->hide(); - - initialize_parameters.max_text_length = appear_parameters.max_text_length; - initialize_parameters.min_text_length = appear_parameters.min_text_length; - initialize_parameters.type = appear_parameters.type; - initialize_parameters.key_disable_flags = appear_parameters.key_disable_flags; - initialize_parameters.enable_backspace_button = appear_parameters.enable_backspace_button; - initialize_parameters.enable_return_button = appear_parameters.enable_return_button; - initialize_parameters.disable_cancel_button = appear_parameters.disable_cancel_button; - - SetKeyboardType(); - SetControllerImage(); - DisableKeyboardButtons(); - SetBackspaceOkEnabled(); - - open(); -} - -void QtSoftwareKeyboardDialog::HideInlineKeyboard() { - StopInputThread(); - QDialog::hide(); -} - -void QtSoftwareKeyboardDialog::InlineTextChanged( - Core::Frontend::InlineTextParameters text_parameters) { - current_text = text_parameters.input_text; - cursor_position = text_parameters.cursor_position; - - SetBackspaceOkEnabled(); -} - -void QtSoftwareKeyboardDialog::ExitKeyboard() { - StopInputThread(); - QDialog::done(QDialog::Accepted); -} - -void QtSoftwareKeyboardDialog::open() { - QDialog::open(); - - row = 0; - column = 0; - - switch (bottom_osk_index) { - case BottomOSKIndex::LowerCase: - case BottomOSKIndex::UpperCase: { - const auto* const curr_button = - keyboard_buttons[static_cast<std::size_t>(bottom_osk_index)][row][column]; - - // This is a workaround for setFocus() randomly not showing focus in the UI - QCursor::setPos(curr_button->mapToGlobal(curr_button->rect().center())); - break; - } - case BottomOSKIndex::NumberPad: { - const auto* const curr_button = numberpad_buttons[row][column]; - - // This is a workaround for setFocus() randomly not showing focus in the UI - QCursor::setPos(curr_button->mapToGlobal(curr_button->rect().center())); - break; - } - default: - break; - } - - StartInputThread(); -} - -void QtSoftwareKeyboardDialog::reject() { - // Pressing the ESC key in a dialog calls QDialog::reject(). - // We will override this behavior to the "Cancel" action on the software keyboard. - TranslateButtonPress(Core::HID::NpadButton::X); -} - -void QtSoftwareKeyboardDialog::keyPressEvent(QKeyEvent* event) { - if (!is_inline) { - QDialog::keyPressEvent(event); - return; - } - - const auto entered_key = event->key(); - - switch (entered_key) { - case Qt::Key_Escape: - QDialog::keyPressEvent(event); - return; - case Qt::Key_Backspace: - switch (bottom_osk_index) { - case BottomOSKIndex::LowerCase: - ui->button_backspace->click(); - break; - case BottomOSKIndex::UpperCase: - ui->button_backspace_shift->click(); - break; - case BottomOSKIndex::NumberPad: - ui->button_backspace_num->click(); - break; - default: - break; - } - return; - case Qt::Key_Return: - switch (bottom_osk_index) { - case BottomOSKIndex::LowerCase: - ui->button_ok->click(); - break; - case BottomOSKIndex::UpperCase: - ui->button_ok_shift->click(); - break; - case BottomOSKIndex::NumberPad: - ui->button_ok_num->click(); - break; - default: - break; - } - return; - case Qt::Key_Left: - MoveTextCursorDirection(Direction::Left); - return; - case Qt::Key_Right: - MoveTextCursorDirection(Direction::Right); - return; - default: - break; - } - - const auto entered_text = event->text(); - - if (entered_text.isEmpty()) { - return; - } - - InlineTextInsertString(Common::U16StringFromBuffer(entered_text.utf16(), entered_text.size())); -} - -void QtSoftwareKeyboardDialog::MoveAndResizeWindow(QPoint pos, QSize size) { - QDialog::move(pos); - QDialog::resize(size); - - // High DPI - const float dpi_scale = screen()->logicalDotsPerInch() / 96.0f; - - RescaleKeyboardElements(size.width(), size.height(), dpi_scale); -} - -void QtSoftwareKeyboardDialog::RescaleKeyboardElements(float width, float height, float dpi_scale) { - const auto header_font_size = BASE_HEADER_FONT_SIZE * (height / BASE_HEIGHT) / dpi_scale; - const auto sub_font_size = BASE_SUB_FONT_SIZE * (height / BASE_HEIGHT) / dpi_scale; - const auto editor_font_size = BASE_EDITOR_FONT_SIZE * (height / BASE_HEIGHT) / dpi_scale; - const auto char_button_font_size = - BASE_CHAR_BUTTON_FONT_SIZE * (height / BASE_HEIGHT) / dpi_scale; - const auto label_button_font_size = - BASE_LABEL_BUTTON_FONT_SIZE * (height / BASE_HEIGHT) / dpi_scale; - - QFont header_font(QStringLiteral("MS Shell Dlg 2"), header_font_size, QFont::Normal); - QFont sub_font(QStringLiteral("MS Shell Dlg 2"), sub_font_size, QFont::Normal); - QFont editor_font(QStringLiteral("MS Shell Dlg 2"), editor_font_size, QFont::Normal); - QFont char_button_font(QStringLiteral("MS Shell Dlg 2"), char_button_font_size, QFont::Normal); - QFont label_button_font(QStringLiteral("MS Shell Dlg 2"), label_button_font_size, - QFont::Normal); - - ui->label_header->setFont(header_font); - ui->label_sub->setFont(sub_font); - ui->line_edit_osk->setFont(editor_font); - ui->text_edit_osk->setFont(editor_font); - ui->label_characters->setFont(sub_font); - ui->label_characters_box->setFont(sub_font); - - ui->label_shift->setFont(label_button_font); - ui->label_shift_shift->setFont(label_button_font); - ui->label_cancel->setFont(label_button_font); - ui->label_cancel_shift->setFont(label_button_font); - ui->label_cancel_num->setFont(label_button_font); - ui->label_enter->setFont(label_button_font); - ui->label_enter_shift->setFont(label_button_font); - ui->label_enter_num->setFont(label_button_font); - - for (auto* button : all_buttons) { - if (button == ui->button_return || button == ui->button_return_shift) { - button->setFont(label_button_font); - continue; - } - - if (button == ui->button_space || button == ui->button_space_shift) { - button->setFont(label_button_font); - continue; - } - - if (button == ui->button_shift || button == ui->button_shift_shift) { - button->setFont(label_button_font); - button->setIconSize(QSize(BASE_ICON_BUTTON_SIZE, BASE_ICON_BUTTON_SIZE) * - (height / BASE_HEIGHT)); - continue; - } - - if (button == ui->button_backspace || button == ui->button_backspace_shift || - button == ui->button_backspace_num) { - button->setFont(label_button_font); - button->setIconSize(QSize(BASE_ICON_BUTTON_SIZE, BASE_ICON_BUTTON_SIZE) * - (height / BASE_HEIGHT)); - continue; - } - - if (button == ui->button_ok || button == ui->button_ok_shift || - button == ui->button_ok_num) { - button->setFont(label_button_font); - continue; - } - - button->setFont(char_button_font); - } -} - -void QtSoftwareKeyboardDialog::SetKeyboardType() { - switch (initialize_parameters.type) { - case SwkbdType::Normal: - case SwkbdType::Qwerty: - case SwkbdType::Unknown3: - case SwkbdType::Latin: - case SwkbdType::SimplifiedChinese: - case SwkbdType::TraditionalChinese: - case SwkbdType::Korean: - default: { - bottom_osk_index = BottomOSKIndex::LowerCase; - ui->bottomOSK->setCurrentIndex(static_cast<int>(bottom_osk_index)); - - ui->verticalLayout_2->setStretch(0, 320); - ui->verticalLayout_2->setStretch(1, 400); - - ui->gridLineOSK->setRowStretch(5, 94); - ui->gridBoxOSK->setRowStretch(2, 81); - break; - } - case SwkbdType::NumberPad: { - bottom_osk_index = BottomOSKIndex::NumberPad; - ui->bottomOSK->setCurrentIndex(static_cast<int>(bottom_osk_index)); - - ui->verticalLayout_2->setStretch(0, 370); - ui->verticalLayout_2->setStretch(1, 350); - - ui->gridLineOSK->setRowStretch(5, 144); - ui->gridBoxOSK->setRowStretch(2, 131); - break; - } - } -} - -void QtSoftwareKeyboardDialog::SetPasswordMode() { - switch (initialize_parameters.password_mode) { - case SwkbdPasswordMode::Disabled: - default: - ui->line_edit_osk->setEchoMode(QLineEdit::Normal); - break; - case SwkbdPasswordMode::Enabled: - ui->line_edit_osk->setEchoMode(QLineEdit::Password); - break; - } -} - -void QtSoftwareKeyboardDialog::SetTextDrawType() { - switch (initialize_parameters.text_draw_type) { - case SwkbdTextDrawType::Line: - case SwkbdTextDrawType::DownloadCode: { - ui->topOSK->setCurrentIndex(0); - - if (initialize_parameters.max_text_length <= 10) { - ui->gridLineOSK->setColumnStretch(0, 390); - ui->gridLineOSK->setColumnStretch(1, 500); - ui->gridLineOSK->setColumnStretch(2, 390); - } else { - ui->gridLineOSK->setColumnStretch(0, 130); - ui->gridLineOSK->setColumnStretch(1, 1020); - ui->gridLineOSK->setColumnStretch(2, 130); - } - - if (is_inline) { - return; - } - - connect(ui->line_edit_osk, &QLineEdit::textChanged, [this](const QString& changed_string) { - const auto is_valid = ValidateInputText(changed_string); - - const auto text_length = static_cast<u32>(changed_string.length()); - - ui->label_characters->setText(QStringLiteral("%1/%2") - .arg(text_length) - .arg(initialize_parameters.max_text_length)); - - ui->button_ok->setEnabled(is_valid); - ui->button_ok_shift->setEnabled(is_valid); - ui->button_ok_num->setEnabled(is_valid); - - ui->line_edit_osk->setFocus(); - }); - - connect(ui->line_edit_osk, &QLineEdit::cursorPositionChanged, - [this](int old_cursor_position, int new_cursor_position) { - ui->button_backspace->setEnabled( - initialize_parameters.enable_backspace_button && new_cursor_position > 0); - ui->button_backspace_shift->setEnabled( - initialize_parameters.enable_backspace_button && new_cursor_position > 0); - ui->button_backspace_num->setEnabled( - initialize_parameters.enable_backspace_button && new_cursor_position > 0); - - ui->line_edit_osk->setFocus(); - }); - - connect( - ui->line_edit_osk, &QLineEdit::returnPressed, this, - [this] { TranslateButtonPress(Core::HID::NpadButton::Plus); }, Qt::QueuedConnection); - - ui->line_edit_osk->setPlaceholderText( - QString::fromStdU16String(initialize_parameters.guide_text)); - ui->line_edit_osk->setText(QString::fromStdU16String(initialize_parameters.initial_text)); - ui->line_edit_osk->setMaxLength(initialize_parameters.max_text_length); - ui->line_edit_osk->setCursorPosition(initialize_parameters.initial_cursor_position); - - ui->label_characters->setText(QStringLiteral("%1/%2") - .arg(initialize_parameters.initial_text.size()) - .arg(initialize_parameters.max_text_length)); - break; - } - case SwkbdTextDrawType::Box: - default: { - ui->topOSK->setCurrentIndex(1); - - if (is_inline) { - return; - } - - connect(ui->text_edit_osk, &QTextEdit::textChanged, [this] { - if (static_cast<u32>(ui->text_edit_osk->toPlainText().length()) > - initialize_parameters.max_text_length) { - auto text_cursor = ui->text_edit_osk->textCursor(); - ui->text_edit_osk->setTextCursor(text_cursor); - text_cursor.deletePreviousChar(); - } - - const auto is_valid = ValidateInputText(ui->text_edit_osk->toPlainText()); - - const auto text_length = static_cast<u32>(ui->text_edit_osk->toPlainText().length()); - - ui->label_characters_box->setText(QStringLiteral("%1/%2") - .arg(text_length) - .arg(initialize_parameters.max_text_length)); - - ui->button_ok->setEnabled(is_valid); - ui->button_ok_shift->setEnabled(is_valid); - ui->button_ok_num->setEnabled(is_valid); - - ui->text_edit_osk->setFocus(); - }); - - connect(ui->text_edit_osk, &QTextEdit::cursorPositionChanged, [this] { - const auto new_cursor_position = ui->text_edit_osk->textCursor().position(); - - ui->button_backspace->setEnabled(initialize_parameters.enable_backspace_button && - new_cursor_position > 0); - ui->button_backspace_shift->setEnabled(initialize_parameters.enable_backspace_button && - new_cursor_position > 0); - ui->button_backspace_num->setEnabled(initialize_parameters.enable_backspace_button && - new_cursor_position > 0); - - ui->text_edit_osk->setFocus(); - }); - - ui->text_edit_osk->setPlaceholderText( - QString::fromStdU16String(initialize_parameters.guide_text)); - ui->text_edit_osk->setText(QString::fromStdU16String(initialize_parameters.initial_text)); - ui->text_edit_osk->moveCursor(initialize_parameters.initial_cursor_position == 0 - ? QTextCursor::Start - : QTextCursor::End); - - ui->label_characters_box->setText(QStringLiteral("%1/%2") - .arg(initialize_parameters.initial_text.size()) - .arg(initialize_parameters.max_text_length)); - break; - } - } -} - -void QtSoftwareKeyboardDialog::SetControllerImage() { - const auto* handheld = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld); - const auto* player_1 = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1); - const auto controller_type = - handheld->IsConnected() ? handheld->GetNpadStyleIndex() : player_1->GetNpadStyleIndex(); - - const QString theme = [] { - if (QIcon::themeName().contains(QStringLiteral("dark")) || - QIcon::themeName().contains(QStringLiteral("midnight"))) { - return QStringLiteral("_dark"); - } else { - return QString{}; - } - }(); - - switch (controller_type) { - case Core::HID::NpadStyleIndex::Fullkey: - case Core::HID::NpadStyleIndex::GameCube: - ui->icon_controller->setStyleSheet( - QStringLiteral("image: url(:/overlay/controller_pro%1.png);").arg(theme)); - ui->icon_controller_shift->setStyleSheet( - QStringLiteral("image: url(:/overlay/controller_pro%1.png);").arg(theme)); - ui->icon_controller_num->setStyleSheet( - QStringLiteral("image: url(:/overlay/controller_pro%1.png);").arg(theme)); - break; - case Core::HID::NpadStyleIndex::JoyconDual: - ui->icon_controller->setStyleSheet( - QStringLiteral("image: url(:/overlay/controller_dual_joycon%1.png);").arg(theme)); - ui->icon_controller_shift->setStyleSheet( - QStringLiteral("image: url(:/overlay/controller_dual_joycon%1.png);").arg(theme)); - ui->icon_controller_num->setStyleSheet( - QStringLiteral("image: url(:/overlay/controller_dual_joycon%1.png);").arg(theme)); - break; - case Core::HID::NpadStyleIndex::JoyconLeft: - ui->icon_controller->setStyleSheet( - QStringLiteral("image: url(:/overlay/controller_single_joycon_left%1.png);") - .arg(theme)); - ui->icon_controller_shift->setStyleSheet( - QStringLiteral("image: url(:/overlay/controller_single_joycon_left%1.png);") - .arg(theme)); - ui->icon_controller_num->setStyleSheet( - QStringLiteral("image: url(:/overlay/controller_single_joycon_left%1.png);") - .arg(theme)); - break; - case Core::HID::NpadStyleIndex::JoyconRight: - ui->icon_controller->setStyleSheet( - QStringLiteral("image: url(:/overlay/controller_single_joycon_right%1.png);") - .arg(theme)); - ui->icon_controller_shift->setStyleSheet( - QStringLiteral("image: url(:/overlay/controller_single_joycon_right%1.png);") - .arg(theme)); - ui->icon_controller_num->setStyleSheet( - QStringLiteral("image: url(:/overlay/controller_single_joycon_right%1.png);") - .arg(theme)); - break; - case Core::HID::NpadStyleIndex::Handheld: - ui->icon_controller->setStyleSheet( - QStringLiteral("image: url(:/overlay/controller_handheld%1.png);").arg(theme)); - ui->icon_controller_shift->setStyleSheet( - QStringLiteral("image: url(:/overlay/controller_handheld%1.png);").arg(theme)); - ui->icon_controller_num->setStyleSheet( - QStringLiteral("image: url(:/overlay/controller_handheld%1.png);").arg(theme)); - break; - default: - break; - } -} - -void QtSoftwareKeyboardDialog::DisableKeyboardButtons() { - switch (bottom_osk_index) { - case BottomOSKIndex::LowerCase: - case BottomOSKIndex::UpperCase: - default: { - for (const auto& keys : keyboard_buttons) { - for (const auto& rows : keys) { - for (auto* button : rows) { - if (!button) { - continue; - } - - button->setEnabled(true); - } - } - } - - const auto& key_disable_flags = initialize_parameters.key_disable_flags; - - ui->button_space->setDisabled(key_disable_flags.space); - ui->button_space_shift->setDisabled(key_disable_flags.space); - - ui->button_at->setDisabled(key_disable_flags.at || key_disable_flags.username); - - ui->button_percent->setDisabled(key_disable_flags.percent || key_disable_flags.username); - - ui->button_slash->setDisabled(key_disable_flags.slash); - - ui->button_1->setDisabled(key_disable_flags.numbers); - ui->button_2->setDisabled(key_disable_flags.numbers); - ui->button_3->setDisabled(key_disable_flags.numbers); - ui->button_4->setDisabled(key_disable_flags.numbers); - ui->button_5->setDisabled(key_disable_flags.numbers); - ui->button_6->setDisabled(key_disable_flags.numbers); - ui->button_7->setDisabled(key_disable_flags.numbers); - ui->button_8->setDisabled(key_disable_flags.numbers); - ui->button_9->setDisabled(key_disable_flags.numbers); - ui->button_0->setDisabled(key_disable_flags.numbers); - - ui->button_return->setEnabled(initialize_parameters.enable_return_button); - ui->button_return_shift->setEnabled(initialize_parameters.enable_return_button); - break; - } - case BottomOSKIndex::NumberPad: { - for (const auto& rows : numberpad_buttons) { - for (auto* button : rows) { - if (!button) { - continue; - } - - button->setEnabled(true); - } - } - - const auto enable_left_optional = initialize_parameters.left_optional_symbol_key != '\0'; - const auto enable_right_optional = initialize_parameters.right_optional_symbol_key != '\0'; - - ui->button_left_optional_num->setEnabled(enable_left_optional); - ui->button_left_optional_num->setVisible(enable_left_optional); - - ui->button_right_optional_num->setEnabled(enable_right_optional); - ui->button_right_optional_num->setVisible(enable_right_optional); - break; - } - } -} - -void QtSoftwareKeyboardDialog::SetBackspaceOkEnabled() { - if (is_inline) { - ui->button_ok->setEnabled(current_text.size() >= initialize_parameters.min_text_length); - ui->button_ok_shift->setEnabled(current_text.size() >= - initialize_parameters.min_text_length); - ui->button_ok_num->setEnabled(current_text.size() >= initialize_parameters.min_text_length); - - ui->button_backspace->setEnabled(initialize_parameters.enable_backspace_button && - cursor_position > 0); - ui->button_backspace_shift->setEnabled(initialize_parameters.enable_backspace_button && - cursor_position > 0); - ui->button_backspace_num->setEnabled(initialize_parameters.enable_backspace_button && - cursor_position > 0); - } else { - const auto text_length = [this] { - if (ui->topOSK->currentIndex() == 1) { - return static_cast<u32>(ui->text_edit_osk->toPlainText().length()); - } else { - return static_cast<u32>(ui->line_edit_osk->text().length()); - } - }(); - - const auto normal_cursor_position = [this] { - if (ui->topOSK->currentIndex() == 1) { - return ui->text_edit_osk->textCursor().position(); - } else { - return ui->line_edit_osk->cursorPosition(); - } - }(); - - ui->button_ok->setEnabled(text_length >= initialize_parameters.min_text_length); - ui->button_ok_shift->setEnabled(text_length >= initialize_parameters.min_text_length); - ui->button_ok_num->setEnabled(text_length >= initialize_parameters.min_text_length); - - ui->button_backspace->setEnabled(initialize_parameters.enable_backspace_button && - normal_cursor_position > 0); - ui->button_backspace_shift->setEnabled(initialize_parameters.enable_backspace_button && - normal_cursor_position > 0); - ui->button_backspace_num->setEnabled(initialize_parameters.enable_backspace_button && - normal_cursor_position > 0); - } -} - -bool QtSoftwareKeyboardDialog::ValidateInputText(const QString& input_text) { - const auto& key_disable_flags = initialize_parameters.key_disable_flags; - - const auto input_text_length = static_cast<u32>(input_text.length()); - - if (input_text_length < initialize_parameters.min_text_length || - input_text_length > initialize_parameters.max_text_length) { - return false; - } - - if (key_disable_flags.space && input_text.contains(QLatin1Char{' '})) { - return false; - } - - if ((key_disable_flags.at || key_disable_flags.username) && - input_text.contains(QLatin1Char{'@'})) { - return false; - } - - if ((key_disable_flags.percent || key_disable_flags.username) && - input_text.contains(QLatin1Char{'%'})) { - return false; - } - - if (key_disable_flags.slash && input_text.contains(QLatin1Char{'/'})) { - return false; - } - - if ((key_disable_flags.backslash || key_disable_flags.username) && - input_text.contains(QLatin1Char('\\'))) { - return false; - } - - if (key_disable_flags.numbers && - std::any_of(input_text.begin(), input_text.end(), [](QChar c) { return c.isDigit(); })) { - return false; - } - - if (bottom_osk_index == BottomOSKIndex::NumberPad && - std::any_of(input_text.begin(), input_text.end(), [this](QChar c) { - return !c.isDigit() && c != QChar{initialize_parameters.left_optional_symbol_key} && - c != QChar{initialize_parameters.right_optional_symbol_key}; - })) { - return false; - } - - return true; -} - -void QtSoftwareKeyboardDialog::ChangeBottomOSKIndex() { - switch (bottom_osk_index) { - case BottomOSKIndex::LowerCase: - bottom_osk_index = BottomOSKIndex::UpperCase; - ui->bottomOSK->setCurrentIndex(static_cast<int>(bottom_osk_index)); - - ui->button_shift_shift->setStyleSheet( - QStringLiteral("image: url(:/overlay/osk_button_shift_lock_off.png);" - "\nimage-position: left;")); - - ui->button_shift_shift->setIconSize(ui->button_shift->iconSize()); - ui->button_backspace_shift->setIconSize(ui->button_backspace->iconSize()); - break; - case BottomOSKIndex::UpperCase: - if (caps_lock_enabled) { - caps_lock_enabled = false; - - ui->button_shift_shift->setStyleSheet( - QStringLiteral("image: url(:/overlay/osk_button_shift_lock_off.png);" - "\nimage-position: left;")); - - ui->button_shift_shift->setIconSize(ui->button_shift->iconSize()); - ui->button_backspace_shift->setIconSize(ui->button_backspace->iconSize()); - - ui->label_shift_shift->setText(QStringLiteral("Caps Lock")); - - bottom_osk_index = BottomOSKIndex::LowerCase; - ui->bottomOSK->setCurrentIndex(static_cast<int>(bottom_osk_index)); - } else { - caps_lock_enabled = true; - - ui->button_shift_shift->setStyleSheet( - QStringLiteral("image: url(:/overlay/osk_button_shift_lock_on.png);" - "\nimage-position: left;")); - - ui->button_shift_shift->setIconSize(ui->button_shift->iconSize()); - ui->button_backspace_shift->setIconSize(ui->button_backspace->iconSize()); - - ui->label_shift_shift->setText(QStringLiteral("Caps Lock Off")); - } - break; - case BottomOSKIndex::NumberPad: - default: - break; - } -} - -void QtSoftwareKeyboardDialog::NormalKeyboardButtonClicked(QPushButton* button) { - if (button == ui->button_ampersand) { - if (ui->topOSK->currentIndex() == 1) { - ui->text_edit_osk->insertPlainText(QStringLiteral("&")); - } else { - ui->line_edit_osk->insert(QStringLiteral("&")); - } - return; - } - - if (button == ui->button_return || button == ui->button_return_shift) { - if (ui->topOSK->currentIndex() == 1) { - ui->text_edit_osk->insertPlainText(QStringLiteral("\n")); - } else { - ui->line_edit_osk->insert(QStringLiteral("\n")); - } - return; - } - - if (button == ui->button_space || button == ui->button_space_shift) { - if (ui->topOSK->currentIndex() == 1) { - ui->text_edit_osk->insertPlainText(QStringLiteral(" ")); - } else { - ui->line_edit_osk->insert(QStringLiteral(" ")); - } - return; - } - - if (button == ui->button_shift || button == ui->button_shift_shift) { - ChangeBottomOSKIndex(); - return; - } - - if (button == ui->button_backspace || button == ui->button_backspace_shift || - button == ui->button_backspace_num) { - if (ui->topOSK->currentIndex() == 1) { - auto text_cursor = ui->text_edit_osk->textCursor(); - ui->text_edit_osk->setTextCursor(text_cursor); - text_cursor.deletePreviousChar(); - } else { - ui->line_edit_osk->backspace(); - } - return; - } - - if (button == ui->button_ok || button == ui->button_ok_shift || button == ui->button_ok_num) { - const auto text = ui->topOSK->currentIndex() == 1 ? ui->text_edit_osk->toPlainText() - : ui->line_edit_osk->text(); - auto text_str = Common::U16StringFromBuffer(text.utf16(), text.size()); - - emit SubmitNormalText(SwkbdResult::Ok, std::move(text_str)); - return; - } - - if (ui->topOSK->currentIndex() == 1) { - ui->text_edit_osk->insertPlainText(button->text()); - } else { - ui->line_edit_osk->insert(button->text()); - } - - // Revert the keyboard to lowercase if the shift key is active. - if (bottom_osk_index == BottomOSKIndex::UpperCase && !caps_lock_enabled) { - // This is set to true since ChangeBottomOSKIndex will change bottom_osk_index to LowerCase - // if bottom_osk_index is UpperCase and caps_lock_enabled is true. - caps_lock_enabled = true; - ChangeBottomOSKIndex(); - } -} - -void QtSoftwareKeyboardDialog::InlineKeyboardButtonClicked(QPushButton* button) { - if (!button->isEnabled()) { - return; - } - - if (button == ui->button_ampersand) { - InlineTextInsertString(u"&"); - return; - } - - if (button == ui->button_return || button == ui->button_return_shift) { - InlineTextInsertString(u"\n"); - return; - } - - if (button == ui->button_space || button == ui->button_space_shift) { - InlineTextInsertString(u" "); - return; - } - - if (button == ui->button_shift || button == ui->button_shift_shift) { - ChangeBottomOSKIndex(); - return; - } - - if (button == ui->button_backspace || button == ui->button_backspace_shift || - button == ui->button_backspace_num) { - if (cursor_position <= 0 || current_text.empty()) { - cursor_position = 0; - return; - } - - --cursor_position; - - current_text.erase(cursor_position, 1); - - SetBackspaceOkEnabled(); - - emit SubmitInlineText(SwkbdReplyType::ChangedString, current_text, cursor_position); - return; - } - - if (button == ui->button_ok || button == ui->button_ok_shift || button == ui->button_ok_num) { - emit SubmitInlineText(SwkbdReplyType::DecidedEnter, current_text, cursor_position); - return; - } - - const auto button_text = button->text(); - InlineTextInsertString(Common::U16StringFromBuffer(button_text.utf16(), button_text.size())); - - // Revert the keyboard to lowercase if the shift key is active. - if (bottom_osk_index == BottomOSKIndex::UpperCase && !caps_lock_enabled) { - // This is set to true since ChangeBottomOSKIndex will change bottom_osk_index to LowerCase - // if bottom_osk_index is UpperCase and caps_lock_enabled is true. - caps_lock_enabled = true; - ChangeBottomOSKIndex(); - } -} - -void QtSoftwareKeyboardDialog::InlineTextInsertString(std::u16string_view string) { - if ((current_text.size() + string.size()) > initialize_parameters.max_text_length) { - return; - } - - current_text.insert(cursor_position, string); - - cursor_position += static_cast<s32>(string.size()); - - SetBackspaceOkEnabled(); - - emit SubmitInlineText(SwkbdReplyType::ChangedString, current_text, cursor_position); -} - -void QtSoftwareKeyboardDialog::SetupMouseHover() { - // setFocus() has a bug where continuously changing focus will cause the focus UI to - // mysteriously disappear. A workaround we have found is using the mouse to hover over - // the buttons to act in place of the button focus. As a result, we will have to set - // a blank cursor when hovering over all the buttons and set a no focus policy so the - // buttons do not stay in focus in addition to the mouse hover. - for (auto* button : all_buttons) { - button->setCursor(QCursor(Qt::BlankCursor)); - button->setFocusPolicy(Qt::NoFocus); - } -} - -template <Core::HID::NpadButton... T> -void QtSoftwareKeyboardDialog::HandleButtonPressedOnce() { - const auto f = [this](Core::HID::NpadButton button) { - if (input_interpreter->IsButtonPressedOnce(button)) { - TranslateButtonPress(button); - } - }; - - (f(T), ...); -} - -template <Core::HID::NpadButton... T> -void QtSoftwareKeyboardDialog::HandleButtonHold() { - const auto f = [this](Core::HID::NpadButton button) { - if (input_interpreter->IsButtonHeld(button)) { - TranslateButtonPress(button); - } - }; - - (f(T), ...); -} - -void QtSoftwareKeyboardDialog::TranslateButtonPress(Core::HID::NpadButton button) { - switch (button) { - case Core::HID::NpadButton::A: - switch (bottom_osk_index) { - case BottomOSKIndex::LowerCase: - case BottomOSKIndex::UpperCase: - keyboard_buttons[static_cast<std::size_t>(bottom_osk_index)][row][column]->click(); - break; - case BottomOSKIndex::NumberPad: - numberpad_buttons[row][column]->click(); - break; - default: - break; - } - break; - case Core::HID::NpadButton::B: - switch (bottom_osk_index) { - case BottomOSKIndex::LowerCase: - ui->button_backspace->click(); - break; - case BottomOSKIndex::UpperCase: - ui->button_backspace_shift->click(); - break; - case BottomOSKIndex::NumberPad: - ui->button_backspace_num->click(); - break; - default: - break; - } - break; - case Core::HID::NpadButton::X: - if (is_inline) { - emit SubmitInlineText(SwkbdReplyType::DecidedCancel, current_text, cursor_position); - } else { - const auto text = ui->topOSK->currentIndex() == 1 ? ui->text_edit_osk->toPlainText() - : ui->line_edit_osk->text(); - auto text_str = Common::U16StringFromBuffer(text.utf16(), text.size()); - - emit SubmitNormalText(SwkbdResult::Cancel, std::move(text_str)); - } - break; - case Core::HID::NpadButton::Y: - switch (bottom_osk_index) { - case BottomOSKIndex::LowerCase: - ui->button_space->click(); - break; - case BottomOSKIndex::UpperCase: - ui->button_space_shift->click(); - break; - case BottomOSKIndex::NumberPad: - default: - break; - } - break; - case Core::HID::NpadButton::StickL: - case Core::HID::NpadButton::StickR: - switch (bottom_osk_index) { - case BottomOSKIndex::LowerCase: - ui->button_shift->click(); - break; - case BottomOSKIndex::UpperCase: - ui->button_shift_shift->click(); - break; - case BottomOSKIndex::NumberPad: - default: - break; - } - break; - case Core::HID::NpadButton::L: - MoveTextCursorDirection(Direction::Left); - break; - case Core::HID::NpadButton::R: - MoveTextCursorDirection(Direction::Right); - break; - case Core::HID::NpadButton::Plus: - switch (bottom_osk_index) { - case BottomOSKIndex::LowerCase: - ui->button_ok->click(); - break; - case BottomOSKIndex::UpperCase: - ui->button_ok_shift->click(); - break; - case BottomOSKIndex::NumberPad: - ui->button_ok_num->click(); - break; - default: - break; - } - break; - case Core::HID::NpadButton::Left: - case Core::HID::NpadButton::StickLLeft: - case Core::HID::NpadButton::StickRLeft: - MoveButtonDirection(Direction::Left); - break; - case Core::HID::NpadButton::Up: - case Core::HID::NpadButton::StickLUp: - case Core::HID::NpadButton::StickRUp: - MoveButtonDirection(Direction::Up); - break; - case Core::HID::NpadButton::Right: - case Core::HID::NpadButton::StickLRight: - case Core::HID::NpadButton::StickRRight: - MoveButtonDirection(Direction::Right); - break; - case Core::HID::NpadButton::Down: - case Core::HID::NpadButton::StickLDown: - case Core::HID::NpadButton::StickRDown: - MoveButtonDirection(Direction::Down); - break; - default: - break; - } -} - -void QtSoftwareKeyboardDialog::MoveButtonDirection(Direction direction) { - // Changes the row or column index depending on the direction. - auto move_direction = [this, direction](std::size_t max_rows, std::size_t max_columns) { - switch (direction) { - case Direction::Left: - column = (column + max_columns - 1) % max_columns; - break; - case Direction::Up: - row = (row + max_rows - 1) % max_rows; - break; - case Direction::Right: - column = (column + 1) % max_columns; - break; - case Direction::Down: - row = (row + 1) % max_rows; - break; - default: - break; - } - }; - - // Store the initial row and column. - const auto initial_row = row; - const auto initial_column = column; - - switch (bottom_osk_index) { - case BottomOSKIndex::LowerCase: - case BottomOSKIndex::UpperCase: { - const auto index = static_cast<std::size_t>(bottom_osk_index); - - const auto* const prev_button = keyboard_buttons[index][row][column]; - move_direction(NUM_ROWS_NORMAL, NUM_COLUMNS_NORMAL); - auto* curr_button = keyboard_buttons[index][row][column]; - - while (!curr_button || !curr_button->isEnabled() || curr_button == prev_button) { - // If we returned back to where we started from, break the loop. - if (row == initial_row && column == initial_column) { - break; - } - - move_direction(NUM_ROWS_NORMAL, NUM_COLUMNS_NORMAL); - curr_button = keyboard_buttons[index][row][column]; - } - - // This is a workaround for setFocus() randomly not showing focus in the UI - QCursor::setPos(curr_button->mapToGlobal(curr_button->rect().center())); - break; - } - case BottomOSKIndex::NumberPad: { - const auto* const prev_button = numberpad_buttons[row][column]; - move_direction(NUM_ROWS_NUMPAD, NUM_COLUMNS_NUMPAD); - auto* curr_button = numberpad_buttons[row][column]; - - while (!curr_button || !curr_button->isEnabled() || curr_button == prev_button) { - // If we returned back to where we started from, break the loop. - if (row == initial_row && column == initial_column) { - break; - } - - move_direction(NUM_ROWS_NUMPAD, NUM_COLUMNS_NUMPAD); - curr_button = numberpad_buttons[row][column]; - } - - // This is a workaround for setFocus() randomly not showing focus in the UI - QCursor::setPos(curr_button->mapToGlobal(curr_button->rect().center())); - break; - } - default: - break; - } -} - -void QtSoftwareKeyboardDialog::MoveTextCursorDirection(Direction direction) { - switch (direction) { - case Direction::Left: - if (is_inline) { - if (cursor_position <= 0) { - cursor_position = 0; - } else { - --cursor_position; - emit SubmitInlineText(SwkbdReplyType::MovedCursor, current_text, cursor_position); - } - } else { - if (ui->topOSK->currentIndex() == 1) { - ui->text_edit_osk->moveCursor(QTextCursor::Left); - } else { - ui->line_edit_osk->setCursorPosition(ui->line_edit_osk->cursorPosition() - 1); - } - } - break; - case Direction::Right: - if (is_inline) { - if (cursor_position >= static_cast<s32>(current_text.size())) { - cursor_position = static_cast<s32>(current_text.size()); - } else { - ++cursor_position; - emit SubmitInlineText(SwkbdReplyType::MovedCursor, current_text, cursor_position); - } - } else { - if (ui->topOSK->currentIndex() == 1) { - ui->text_edit_osk->moveCursor(QTextCursor::Right); - } else { - ui->line_edit_osk->setCursorPosition(ui->line_edit_osk->cursorPosition() + 1); - } - } - break; - default: - break; - } -} - -void QtSoftwareKeyboardDialog::StartInputThread() { - if (input_thread_running) { - return; - } - - input_thread_running = true; - - input_thread = std::thread(&QtSoftwareKeyboardDialog::InputThread, this); -} - -void QtSoftwareKeyboardDialog::StopInputThread() { - input_thread_running = false; - - if (input_thread.joinable()) { - input_thread.join(); - } - - if (input_interpreter) { - input_interpreter->ResetButtonStates(); - } -} - -void QtSoftwareKeyboardDialog::InputThread() { - while (input_thread_running) { - input_interpreter->PollInput(); - - HandleButtonPressedOnce< - Core::HID::NpadButton::A, Core::HID::NpadButton::B, Core::HID::NpadButton::X, - Core::HID::NpadButton::Y, Core::HID::NpadButton::StickL, Core::HID::NpadButton::StickR, - Core::HID::NpadButton::L, Core::HID::NpadButton::R, Core::HID::NpadButton::Plus, - Core::HID::NpadButton::Left, Core::HID::NpadButton::Up, Core::HID::NpadButton::Right, - Core::HID::NpadButton::Down, Core::HID::NpadButton::StickLLeft, - Core::HID::NpadButton::StickLUp, Core::HID::NpadButton::StickLRight, - Core::HID::NpadButton::StickLDown, Core::HID::NpadButton::StickRLeft, - Core::HID::NpadButton::StickRUp, Core::HID::NpadButton::StickRRight, - Core::HID::NpadButton::StickRDown>(); - - HandleButtonHold<Core::HID::NpadButton::B, Core::HID::NpadButton::L, - Core::HID::NpadButton::R, Core::HID::NpadButton::Left, - Core::HID::NpadButton::Up, Core::HID::NpadButton::Right, - Core::HID::NpadButton::Down, Core::HID::NpadButton::StickLLeft, - Core::HID::NpadButton::StickLUp, Core::HID::NpadButton::StickLRight, - Core::HID::NpadButton::StickLDown, Core::HID::NpadButton::StickRLeft, - Core::HID::NpadButton::StickRUp, Core::HID::NpadButton::StickRRight, - Core::HID::NpadButton::StickRDown>(); - - std::this_thread::sleep_for(std::chrono::milliseconds(50)); - } -} - -QtSoftwareKeyboard::QtSoftwareKeyboard(GMainWindow& main_window) { - connect(this, &QtSoftwareKeyboard::MainWindowInitializeKeyboard, &main_window, - &GMainWindow::SoftwareKeyboardInitialize, Qt::QueuedConnection); - connect(this, &QtSoftwareKeyboard::MainWindowShowNormalKeyboard, &main_window, - &GMainWindow::SoftwareKeyboardShowNormal, Qt::QueuedConnection); - connect(this, &QtSoftwareKeyboard::MainWindowShowTextCheckDialog, &main_window, - &GMainWindow::SoftwareKeyboardShowTextCheck, Qt::QueuedConnection); - connect(this, &QtSoftwareKeyboard::MainWindowShowInlineKeyboard, &main_window, - &GMainWindow::SoftwareKeyboardShowInline, Qt::QueuedConnection); - connect(this, &QtSoftwareKeyboard::MainWindowHideInlineKeyboard, &main_window, - &GMainWindow::SoftwareKeyboardHideInline, Qt::QueuedConnection); - connect(this, &QtSoftwareKeyboard::MainWindowInlineTextChanged, &main_window, - &GMainWindow::SoftwareKeyboardInlineTextChanged, Qt::QueuedConnection); - connect(this, &QtSoftwareKeyboard::MainWindowExitKeyboard, &main_window, - &GMainWindow::SoftwareKeyboardExit, Qt::QueuedConnection); - connect(&main_window, &GMainWindow::SoftwareKeyboardSubmitNormalText, this, - &QtSoftwareKeyboard::SubmitNormalText, Qt::QueuedConnection); - connect(&main_window, &GMainWindow::SoftwareKeyboardSubmitInlineText, this, - &QtSoftwareKeyboard::SubmitInlineText, Qt::QueuedConnection); -} - -QtSoftwareKeyboard::~QtSoftwareKeyboard() = default; - -void QtSoftwareKeyboard::InitializeKeyboard( - bool is_inline, Core::Frontend::KeyboardInitializeParameters initialize_parameters, - SubmitNormalCallback submit_normal_callback_, SubmitInlineCallback submit_inline_callback_) { - if (is_inline) { - submit_inline_callback = std::move(submit_inline_callback_); - } else { - submit_normal_callback = std::move(submit_normal_callback_); - } - - LOG_INFO(Service_AM, - "\nKeyboardInitializeParameters:" - "\nok_text={}" - "\nheader_text={}" - "\nsub_text={}" - "\nguide_text={}" - "\ninitial_text={}" - "\nmax_text_length={}" - "\nmin_text_length={}" - "\ninitial_cursor_position={}" - "\ntype={}" - "\npassword_mode={}" - "\ntext_draw_type={}" - "\nkey_disable_flags={}" - "\nuse_blur_background={}" - "\nenable_backspace_button={}" - "\nenable_return_button={}" - "\ndisable_cancel_button={}", - Common::UTF16ToUTF8(initialize_parameters.ok_text), - Common::UTF16ToUTF8(initialize_parameters.header_text), - Common::UTF16ToUTF8(initialize_parameters.sub_text), - Common::UTF16ToUTF8(initialize_parameters.guide_text), - Common::UTF16ToUTF8(initialize_parameters.initial_text), - initialize_parameters.max_text_length, initialize_parameters.min_text_length, - initialize_parameters.initial_cursor_position, initialize_parameters.type, - initialize_parameters.password_mode, initialize_parameters.text_draw_type, - initialize_parameters.key_disable_flags.raw, initialize_parameters.use_blur_background, - initialize_parameters.enable_backspace_button, - initialize_parameters.enable_return_button, - initialize_parameters.disable_cancel_button); - - emit MainWindowInitializeKeyboard(is_inline, std::move(initialize_parameters)); -} - -void QtSoftwareKeyboard::ShowNormalKeyboard() const { - emit MainWindowShowNormalKeyboard(); -} - -void QtSoftwareKeyboard::ShowTextCheckDialog( - Service::AM::Frontend::SwkbdTextCheckResult text_check_result, - std::u16string text_check_message) const { - emit MainWindowShowTextCheckDialog(text_check_result, std::move(text_check_message)); -} - -void QtSoftwareKeyboard::ShowInlineKeyboard( - Core::Frontend::InlineAppearParameters appear_parameters) const { - LOG_INFO(Service_AM, - "\nInlineAppearParameters:" - "\nmax_text_length={}" - "\nmin_text_length={}" - "\nkey_top_scale_x={}" - "\nkey_top_scale_y={}" - "\nkey_top_translate_x={}" - "\nkey_top_translate_y={}" - "\ntype={}" - "\nkey_disable_flags={}" - "\nkey_top_as_floating={}" - "\nenable_backspace_button={}" - "\nenable_return_button={}" - "\ndisable_cancel_button={}", - appear_parameters.max_text_length, appear_parameters.min_text_length, - appear_parameters.key_top_scale_x, appear_parameters.key_top_scale_y, - appear_parameters.key_top_translate_x, appear_parameters.key_top_translate_y, - appear_parameters.type, appear_parameters.key_disable_flags.raw, - appear_parameters.key_top_as_floating, appear_parameters.enable_backspace_button, - appear_parameters.enable_return_button, appear_parameters.disable_cancel_button); - - emit MainWindowShowInlineKeyboard(std::move(appear_parameters)); -} - -void QtSoftwareKeyboard::HideInlineKeyboard() const { - emit MainWindowHideInlineKeyboard(); -} - -void QtSoftwareKeyboard::InlineTextChanged( - Core::Frontend::InlineTextParameters text_parameters) const { - LOG_INFO(Service_AM, - "\nInlineTextParameters:" - "\ninput_text={}" - "\ncursor_position={}", - Common::UTF16ToUTF8(text_parameters.input_text), text_parameters.cursor_position); - - emit MainWindowInlineTextChanged(std::move(text_parameters)); -} - -void QtSoftwareKeyboard::ExitKeyboard() const { - emit MainWindowExitKeyboard(); -} - -void QtSoftwareKeyboard::SubmitNormalText(Service::AM::Frontend::SwkbdResult result, - std::u16string submitted_text, bool confirmed) const { - submit_normal_callback(result, submitted_text, confirmed); -} - -void QtSoftwareKeyboard::SubmitInlineText(Service::AM::Frontend::SwkbdReplyType reply_type, - std::u16string submitted_text, - s32 cursor_position) const { - submit_inline_callback(reply_type, submitted_text, cursor_position); -} diff --git a/src/yuzu/applets/qt_software_keyboard.h b/src/yuzu/applets/qt_software_keyboard.h deleted file mode 100644 index 7e2fdf09e..000000000 --- a/src/yuzu/applets/qt_software_keyboard.h +++ /dev/null @@ -1,287 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include <array> -#include <atomic> -#include <memory> -#include <thread> - -#include <QDialog> -#include <QValidator> - -#include "core/frontend/applets/software_keyboard.h" - -class InputInterpreter; - -namespace Core { -class System; -} - -namespace Core::HID { -enum class NpadButton : u64; -} - -namespace Ui { -class QtSoftwareKeyboardDialog; -} - -class GMainWindow; - -class QtSoftwareKeyboardDialog final : public QDialog { - Q_OBJECT - -public: - QtSoftwareKeyboardDialog(QWidget* parent, Core::System& system_, bool is_inline_, - Core::Frontend::KeyboardInitializeParameters initialize_parameters_); - ~QtSoftwareKeyboardDialog() override; - - void ShowNormalKeyboard(QPoint pos, QSize size); - - void ShowTextCheckDialog(Service::AM::Frontend::SwkbdTextCheckResult text_check_result, - std::u16string text_check_message); - - void ShowInlineKeyboard(Core::Frontend::InlineAppearParameters appear_parameters, QPoint pos, - QSize size); - - void HideInlineKeyboard(); - - void InlineTextChanged(Core::Frontend::InlineTextParameters text_parameters); - - void ExitKeyboard(); - -signals: - void SubmitNormalText(Service::AM::Frontend::SwkbdResult result, std::u16string submitted_text, - bool confirmed = false) const; - - void SubmitInlineText(Service::AM::Frontend::SwkbdReplyType reply_type, - std::u16string submitted_text, s32 cursor_position) const; - -public slots: - void open() override; - void reject() override; - -protected: - /// We override the keyPressEvent for inputting text into the inline software keyboard. - void keyPressEvent(QKeyEvent* event) override; - -private: - enum class Direction { - Left, - Up, - Right, - Down, - }; - - enum class BottomOSKIndex { - LowerCase, - UpperCase, - NumberPad, - }; - - /** - * Moves and resizes the window to a specified position and size. - * - * @param pos Top-left window position - * @param size Window size - */ - void MoveAndResizeWindow(QPoint pos, QSize size); - - /** - * Rescales all keyboard elements to account for High DPI displays. - * - * @param width Window width - * @param height Window height - * @param dpi_scale Display scaling factor - */ - void RescaleKeyboardElements(float width, float height, float dpi_scale); - - /// Sets the keyboard type based on initialize_parameters. - void SetKeyboardType(); - - /// Sets the password mode based on initialize_parameters. - void SetPasswordMode(); - - /// Sets the text draw type based on initialize_parameters. - void SetTextDrawType(); - - /// Sets the controller image at the bottom left of the software keyboard. - void SetControllerImage(); - - /// Disables buttons based on initialize_parameters. - void DisableKeyboardButtons(); - - /// Changes whether the backspace or/and ok buttons should be enabled or disabled. - void SetBackspaceOkEnabled(); - - /** - * Validates the input text sent in based on the parameters in initialize_parameters. - * - * @param input_text Input text - * - * @returns True if the input text is valid, false otherwise. - */ - bool ValidateInputText(const QString& input_text); - - /// Switches between LowerCase and UpperCase (Shift and Caps Lock) - void ChangeBottomOSKIndex(); - - /// Processes a keyboard button click from the UI as normal keyboard input. - void NormalKeyboardButtonClicked(QPushButton* button); - - /// Processes a keyboard button click from the UI as inline keyboard input. - void InlineKeyboardButtonClicked(QPushButton* button); - - /** - * Inserts a string of arbitrary length into the current_text at the current cursor position. - * This is only used for the inline software keyboard. - */ - void InlineTextInsertString(std::u16string_view string); - - /// Setup the mouse hover workaround for "focusing" buttons. This should only be called once. - void SetupMouseHover(); - - /** - * Handles button presses and converts them into keyboard input. - * - * @tparam HIDButton The list of buttons that can be converted into keyboard input. - */ - template <Core::HID::NpadButton... T> - void HandleButtonPressedOnce(); - - /** - * Handles button holds and converts them into keyboard input. - * - * @tparam HIDButton The list of buttons that can be converted into keyboard input. - */ - template <Core::HID::NpadButton... T> - void HandleButtonHold(); - - /** - * Translates a button press to focus or click a keyboard button. - * - * @param button The button press to process. - */ - void TranslateButtonPress(Core::HID::NpadButton button); - - /** - * Moves the focus of a button in a certain direction. - * - * @param direction The direction to move. - */ - void MoveButtonDirection(Direction direction); - - /** - * Moves the text cursor in a certain direction. - * - * @param direction The direction to move. - */ - void MoveTextCursorDirection(Direction direction); - - void StartInputThread(); - void StopInputThread(); - - /// The thread where input is being polled and processed. - void InputThread(); - - std::unique_ptr<Ui::QtSoftwareKeyboardDialog> ui; - - Core::System& system; - - // True if it is the inline software keyboard. - bool is_inline; - - // Common software keyboard initialize parameters. - Core::Frontend::KeyboardInitializeParameters initialize_parameters; - - // Used only by the inline software keyboard since the QLineEdit or QTextEdit is hidden. - std::u16string current_text; - s32 cursor_position{0}; - - static constexpr std::size_t NUM_ROWS_NORMAL = 5; - static constexpr std::size_t NUM_COLUMNS_NORMAL = 12; - static constexpr std::size_t NUM_ROWS_NUMPAD = 4; - static constexpr std::size_t NUM_COLUMNS_NUMPAD = 4; - - // Stores the normal keyboard layout. - std::array<std::array<std::array<QPushButton*, NUM_COLUMNS_NORMAL>, NUM_ROWS_NORMAL>, 2> - keyboard_buttons; - // Stores the numberpad keyboard layout. - std::array<std::array<QPushButton*, NUM_COLUMNS_NUMPAD>, NUM_ROWS_NUMPAD> numberpad_buttons; - - // Contains a set of all buttons used in keyboard_buttons and numberpad_buttons. - std::array<QPushButton*, 112> all_buttons; - - std::size_t row{0}; - std::size_t column{0}; - - BottomOSKIndex bottom_osk_index{BottomOSKIndex::LowerCase}; - std::atomic<bool> caps_lock_enabled{false}; - - std::unique_ptr<InputInterpreter> input_interpreter; - - std::thread input_thread; - - std::atomic<bool> input_thread_running{}; -}; - -class QtSoftwareKeyboard final : public QObject, public Core::Frontend::SoftwareKeyboardApplet { - Q_OBJECT - -public: - explicit QtSoftwareKeyboard(GMainWindow& parent); - ~QtSoftwareKeyboard() override; - - void Close() const override { - ExitKeyboard(); - } - - void InitializeKeyboard(bool is_inline, - Core::Frontend::KeyboardInitializeParameters initialize_parameters, - SubmitNormalCallback submit_normal_callback_, - SubmitInlineCallback submit_inline_callback_) override; - - void ShowNormalKeyboard() const override; - - void ShowTextCheckDialog(Service::AM::Frontend::SwkbdTextCheckResult text_check_result, - std::u16string text_check_message) const override; - - void ShowInlineKeyboard( - Core::Frontend::InlineAppearParameters appear_parameters) const override; - - void HideInlineKeyboard() const override; - - void InlineTextChanged(Core::Frontend::InlineTextParameters text_parameters) const override; - - void ExitKeyboard() const override; - -signals: - void MainWindowInitializeKeyboard( - bool is_inline, Core::Frontend::KeyboardInitializeParameters initialize_parameters) const; - - void MainWindowShowNormalKeyboard() const; - - void MainWindowShowTextCheckDialog( - Service::AM::Frontend::SwkbdTextCheckResult text_check_result, - std::u16string text_check_message) const; - - void MainWindowShowInlineKeyboard( - Core::Frontend::InlineAppearParameters appear_parameters) const; - - void MainWindowHideInlineKeyboard() const; - - void MainWindowInlineTextChanged(Core::Frontend::InlineTextParameters text_parameters) const; - - void MainWindowExitKeyboard() const; - -private: - void SubmitNormalText(Service::AM::Frontend::SwkbdResult result, std::u16string submitted_text, - bool confirmed) const; - - void SubmitInlineText(Service::AM::Frontend::SwkbdReplyType reply_type, - std::u16string submitted_text, s32 cursor_position) const; - - mutable SubmitNormalCallback submit_normal_callback; - mutable SubmitInlineCallback submit_inline_callback; -}; diff --git a/src/yuzu/applets/qt_software_keyboard.ui b/src/yuzu/applets/qt_software_keyboard.ui deleted file mode 100644 index 9661cb260..000000000 --- a/src/yuzu/applets/qt_software_keyboard.ui +++ /dev/null @@ -1,3541 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>QtSoftwareKeyboardDialog</class> - <widget class="QDialog" name="QtSoftwareKeyboardDialog"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>1280</width> - <height>720</height> - </rect> - </property> - <property name="windowTitle"> - <string>Software Keyboard</string> - </property> - <property name="styleSheet"> - <string notr="true"/> - </property> - <layout class="QVBoxLayout" name="verticalLayout"> - <property name="spacing"> - <number>0</number> - </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="QWidget" name="mainOSK" native="true"> - <layout class="QVBoxLayout" name="verticalLayout_2" stretch="320,400"> - <property name="spacing"> - <number>0</number> - </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="QStackedWidget" name="topOSK"> - <property name="currentIndex"> - <number>0</number> - </property> - <widget class="QWidget" name="lineOSK"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>100</height> - </size> - </property> - <layout class="QVBoxLayout" name="lineOSKVerticalLayout"> - <property name="spacing"> - <number>0</number> - </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> - <layout class="QGridLayout" name="gridLineOSK" rowstretch="40,50,23,48,65,94" columnstretch="130,1020,130"> - <property name="topMargin"> - <number>0</number> - </property> - <property name="spacing"> - <number>0</number> - </property> - <item row="4" column="2"> - <spacer name="horizontalSpacer_3"> - <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="4" column="0"> - <spacer name="horizontalSpacer_4"> - <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="5" column="1"> - <widget class="QWidget" name="charactersOSK" native="true"> - <layout class="QVBoxLayout" name="verticalLayout_5"> - <property name="spacing"> - <number>0</number> - </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 alignment="Qt::AlignRight|Qt::AlignTop"> - <widget class="QLabel" name="label_characters"> - <property name="font"> - <font> - <pointsize>17</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">0/32</string> - </property> - <property name="alignment"> - <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item row="3" column="1"> - <spacer name="verticalSpacer_2"> - <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 row="5" column="0"> - <spacer name="verticalSpacer_3"> - <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 row="4" column="1"> - <widget class="QWidget" name="inputOSK" native="true"> - <layout class="QVBoxLayout" name="verticalLayout_3"> - <item> - <widget class="QLineEdit" name="line_edit_osk"> - <property name="font"> - <font> - <pointsize>26</pointsize> - <weight>50</weight> - <bold>false</bold> - </font> - </property> - <property name="focusPolicy"> - <enum>Qt::StrongFocus</enum> - </property> - <property name="text"> - <string/> - </property> - <property name="maxLength"> - <number>32</number> - </property> - <property name="placeholderText"> - <string>Enter Text</string> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item row="0" column="1"> - <spacer name="verticalSpacer_4"> - <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 row="1" column="0" colspan="3"> - <widget class="QWidget" name="headerOSK" native="true"> - <layout class="QHBoxLayout" name="horizontalLayout_4" stretch="130,1020,130"> - <property name="spacing"> - <number>0</number> - </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> - <spacer name="horizontalSpacer_18"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>127</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QLabel" name="label_header"> - <property name="font"> - <font> - <pointsize>23</pointsize> - </font> - </property> - <property name="text"> - <string/> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer_19"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>127</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - </layout> - </widget> - </item> - <item row="2" column="0" colspan="3"> - <widget class="QWidget" name="subOSK" native="true"> - <layout class="QHBoxLayout" name="horizontalLayout_3" stretch="130,1020,130"> - <property name="spacing"> - <number>0</number> - </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> - <spacer name="horizontalSpacer_16"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>127</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QLabel" name="label_sub"> - <property name="font"> - <font> - <pointsize>17</pointsize> - </font> - </property> - <property name="text"> - <string/> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer_17"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>127</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - </layout> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - <widget class="QWidget" name="boxOSK"> - <layout class="QVBoxLayout" name="boxOSKVerticalLayout"> - <property name="spacing"> - <number>0</number> - </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> - <layout class="QGridLayout" name="gridBoxOSK" rowstretch="61,178,81" columnstretch="120,1040,120"> - <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> - <property name="spacing"> - <number>0</number> - </property> - <item row="0" column="1"> - <spacer name="verticalSpacer_5"> - <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 row="1" column="0"> - <spacer name="horizontalSpacer_20"> - <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="1" column="2"> - <spacer name="horizontalSpacer_21"> - <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="2" column="1" alignment="Qt::AlignRight|Qt::AlignTop"> - <widget class="QWidget" name="charactersBoxOSK" native="true"> - <layout class="QVBoxLayout" name="verticalLayout_4"> - <property name="spacing"> - <number>0</number> - </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="QLabel" name="label_characters_box"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="font"> - <font> - <pointsize>17</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">0/500</string> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item row="1" column="1"> - <widget class="QWidget" name="inputBoxOSK" native="true"> - <layout class="QVBoxLayout" name="verticalLayout_6"> - <property name="spacing"> - <number>0</number> - </property> - <property name="leftMargin"> - <number>14</number> - </property> - <property name="topMargin"> - <number>9</number> - </property> - <property name="rightMargin"> - <number>14</number> - </property> - <property name="bottomMargin"> - <number>9</number> - </property> - <item> - <widget class="QTextEdit" name="text_edit_osk"> - <property name="font"> - <font> - <pointsize>26</pointsize> - </font> - </property> - <property name="focusPolicy"> - <enum>Qt::StrongFocus</enum> - </property> - <property name="html"> - <string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:26pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html></string> - </property> - </widget> - </item> - </layout> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - </widget> - </item> - <item> - <widget class="QStackedWidget" name="bottomOSK"> - <property name="currentIndex"> - <number>0</number> - </property> - <widget class="QWidget" name="normalOSK"> - <layout class="QVBoxLayout" name="normalPageVerticalLayout"> - <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> - <layout class="QGridLayout" name="kbOSKnormal" rowstretch="15,63,63,63,63,63,70" columnstretch="54,96,96,96,96,96,96,96,96,96,96,96,116,54"> - <property name="spacing"> - <number>0</number> - </property> - <item row="6" column="1" colspan="12"> - <widget class="QWidget" name="legendOSK" native="true"> - <layout class="QHBoxLayout" name="horizontalLayout_2" stretch="70,525,25,12,22,41,25,12,22,41,25,12,47,37,29,12,69,37,29,12,56,8"> - <property name="spacing"> - <number>0</number> - </property> - <property name="leftMargin"> - <number>2</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="QWidget" name="icon_controller" native="true"> - <property name="styleSheet"> - <string notr="true"/> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer_5"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>0</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QWidget" name="button_L" native="true"/> - </item> - <item> - <spacer name="horizontalSpacer_14"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>0</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QWidget" name="arrow_left" native="true"/> - </item> - <item> - <spacer name="horizontalSpacer_13"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>0</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QWidget" name="button_R" native="true"/> - </item> - <item> - <spacer name="horizontalSpacer_12"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>0</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QWidget" name="arrow_right" native="true"/> - </item> - <item> - <spacer name="horizontalSpacer_11"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>0</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QWidget" name="button_press_stick" native="true"/> - </item> - <item> - <spacer name="horizontalSpacer_10"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>0</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QLabel" name="label_shift"> - <property name="font"> - <font> - <pointsize>18</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">Shift</string> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer_15"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>0</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QWidget" name="button_X" native="true"/> - </item> - <item> - <spacer name="horizontalSpacer_9"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>0</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QLabel" name="label_cancel"> - <property name="font"> - <font> - <pointsize>18</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">Cancel</string> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer_8"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>0</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QWidget" name="button_A" native="true"/> - </item> - <item> - <spacer name="horizontalSpacer_7"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>0</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QLabel" name="label_enter"> - <property name="font"> - <font> - <pointsize>18</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">Enter</string> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer_6"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>0</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - </layout> - </widget> - </item> - <item row="1" column="11"> - <widget class="QPushButton" name="button_minus"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">-</string> - </property> - </widget> - </item> - <item row="3" column="11"> - <widget class="QPushButton" name="button_apostrophe"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">'</string> - </property> - </widget> - </item> - <item row="2" column="11"> - <widget class="QPushButton" name="button_slash"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">/</string> - </property> - </widget> - </item> - <item row="4" column="11"> - <widget class="QPushButton" name="button_exclamation"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">!</string> - </property> - </widget> - </item> - <item row="1" column="7"> - <widget class="QPushButton" name="button_7"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">7</string> - </property> - </widget> - </item> - <item row="1" column="8"> - <widget class="QPushButton" name="button_8"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">8</string> - </property> - </widget> - </item> - <item row="1" column="10"> - <widget class="QPushButton" name="button_0"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">0</string> - </property> - </widget> - </item> - <item row="1" column="9"> - <widget class="QPushButton" name="button_9"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">9</string> - </property> - </widget> - </item> - <item row="2" column="2"> - <widget class="QPushButton" name="button_w"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">w</string> - </property> - </widget> - </item> - <item row="2" column="4"> - <widget class="QPushButton" name="button_r"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">r</string> - </property> - </widget> - </item> - <item row="2" column="3"> - <widget class="QPushButton" name="button_e"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">e</string> - </property> - </widget> - </item> - <item row="2" column="1"> - <widget class="QPushButton" name="button_q"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">q</string> - </property> - </widget> - </item> - <item row="2" column="7"> - <widget class="QPushButton" name="button_u"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">u</string> - </property> - </widget> - </item> - <item row="2" column="6"> - <widget class="QPushButton" name="button_y"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">y</string> - </property> - </widget> - </item> - <item row="2" column="5"> - <widget class="QPushButton" name="button_t"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">t</string> - </property> - </widget> - </item> - <item row="2" column="9"> - <widget class="QPushButton" name="button_o"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">o</string> - </property> - </widget> - </item> - <item row="2" column="10"> - <widget class="QPushButton" name="button_p"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">p</string> - </property> - </widget> - </item> - <item row="2" column="8"> - <widget class="QPushButton" name="button_i"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">i</string> - </property> - </widget> - </item> - <item row="3" column="1"> - <widget class="QPushButton" name="button_a"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">a</string> - </property> - </widget> - </item> - <item row="3" column="2"> - <widget class="QPushButton" name="button_s"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">s</string> - </property> - </widget> - </item> - <item row="3" column="3"> - <widget class="QPushButton" name="button_d"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">d</string> - </property> - </widget> - </item> - <item row="3" column="4"> - <widget class="QPushButton" name="button_f"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">f</string> - </property> - </widget> - </item> - <item row="3" column="6"> - <widget class="QPushButton" name="button_h"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">h</string> - </property> - </widget> - </item> - <item row="3" column="7"> - <widget class="QPushButton" name="button_j"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">j</string> - </property> - </widget> - </item> - <item row="3" column="5"> - <widget class="QPushButton" name="button_g"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">g</string> - </property> - </widget> - </item> - <item row="3" column="8"> - <widget class="QPushButton" name="button_k"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">k</string> - </property> - </widget> - </item> - <item row="3" column="9"> - <widget class="QPushButton" name="button_l"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">l</string> - </property> - </widget> - </item> - <item row="3" column="10"> - <widget class="QPushButton" name="button_colon"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">:</string> - </property> - </widget> - </item> - <item row="2" column="12" rowspan="2"> - <widget class="QPushButton" name="button_return"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>18</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">Return</string> - </property> - </widget> - </item> - <item row="4" column="12" rowspan="2"> - <widget class="QPushButton" name="button_ok"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>18</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">OK</string> - </property> - </widget> - </item> - <item row="4" column="1"> - <widget class="QPushButton" name="button_z"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">z</string> - </property> - </widget> - </item> - <item row="4" column="3"> - <widget class="QPushButton" name="button_c"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">c</string> - </property> - </widget> - </item> - <item row="4" column="2"> - <widget class="QPushButton" name="button_x"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">x</string> - </property> - </widget> - </item> - <item row="4" column="4"> - <widget class="QPushButton" name="button_v"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">v</string> - </property> - </widget> - </item> - <item row="4" column="7"> - <widget class="QPushButton" name="button_m"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">m</string> - </property> - </widget> - </item> - <item row="4" column="8"> - <widget class="QPushButton" name="button_comma"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">,</string> - </property> - </widget> - </item> - <item row="4" column="6"> - <widget class="QPushButton" name="button_n"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">n</string> - </property> - </widget> - </item> - <item row="4" column="5"> - <widget class="QPushButton" name="button_b"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">b</string> - </property> - </widget> - </item> - <item row="5" column="1" colspan="2"> - <widget class="QPushButton" name="button_shift"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>18</pointsize> - </font> - </property> - <property name="text"> - <string notr="true"/> - </property> - <property name="checkable"> - <bool>true</bool> - </property> - <property name="checked"> - <bool>false</bool> - </property> - </widget> - </item> - <item row="4" column="10"> - <widget class="QPushButton" name="button_question"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">?</string> - </property> - </widget> - </item> - <item row="4" column="9"> - <widget class="QPushButton" name="button_dot"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">.</string> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QPushButton" name="button_1"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">1</string> - </property> - </widget> - </item> - <item row="1" column="3"> - <widget class="QPushButton" name="button_3"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">3</string> - </property> - </widget> - </item> - <item row="1" column="4"> - <widget class="QPushButton" name="button_4"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">4</string> - </property> - </widget> - </item> - <item row="1" column="2"> - <widget class="QPushButton" name="button_2"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">2</string> - </property> - </widget> - </item> - <item row="1" column="6"> - <widget class="QPushButton" name="button_6"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">6</string> - </property> - </widget> - </item> - <item row="1" column="5"> - <widget class="QPushButton" name="button_5"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">5</string> - </property> - </widget> - </item> - <item row="5" column="3" colspan="9"> - <widget class="QPushButton" name="button_space"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>18</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">Space</string> - </property> - </widget> - </item> - <item row="1" column="12"> - <widget class="QPushButton" name="button_backspace"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>18</pointsize> - </font> - </property> - <property name="text"> - <string notr="true"/> - </property> - </widget> - </item> - <item row="1" 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"> - <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 row="1" column="13"> - <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> - </item> - </layout> - </widget> - <widget class="QWidget" name="shiftOSK"> - <layout class="QVBoxLayout" name="shiftPageVerticalLayout"> - <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> - <layout class="QGridLayout" name="kbOSKshift" rowstretch="15,63,63,63,63,63,70" columnstretch="54,96,96,96,96,96,96,96,96,96,96,96,116,54"> - <property name="spacing"> - <number>0</number> - </property> - <item row="6" column="1" colspan="12"> - <widget class="QWidget" name="legendOSKshift" native="true"> - <layout class="QHBoxLayout" name="horizontalLayout_5" stretch="70,464,25,12,22,41,25,12,22,41,25,12,95,37,29,12,69,37,29,12,56,8"> - <property name="spacing"> - <number>0</number> - </property> - <property name="leftMargin"> - <number>2</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="QWidget" name="icon_controller_shift" native="true"> - <property name="styleSheet"> - <string notr="true"/> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer_22"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>0</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QWidget" name="button_L_shift" native="true"/> - </item> - <item> - <spacer name="horizontalSpacer_23"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>0</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QWidget" name="arrow_left_shift" native="true"/> - </item> - <item> - <spacer name="horizontalSpacer_24"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>0</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QWidget" name="button_R_shift" native="true"/> - </item> - <item> - <spacer name="horizontalSpacer_25"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>0</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QWidget" name="arrow_right_shift" native="true"/> - </item> - <item> - <spacer name="horizontalSpacer_26"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>0</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QWidget" name="button_press_stick_shift" native="true"/> - </item> - <item> - <spacer name="horizontalSpacer_27"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>0</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QLabel" name="label_shift_shift"> - <property name="font"> - <font> - <pointsize>18</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">Caps Lock</string> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer_28"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>0</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QWidget" name="button_X_shift" native="true"/> - </item> - <item> - <spacer name="horizontalSpacer_29"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>0</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QLabel" name="label_cancel_shift"> - <property name="font"> - <font> - <pointsize>18</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">Cancel</string> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer_30"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>0</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QWidget" name="button_A_shift" native="true"/> - </item> - <item> - <spacer name="horizontalSpacer_31"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>0</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QLabel" name="label_enter_shift"> - <property name="font"> - <font> - <pointsize>18</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">Enter</string> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer_32"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>0</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - </layout> - </widget> - </item> - <item row="1" column="11"> - <widget class="QPushButton" name="button_underscore"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">_</string> - </property> - </widget> - </item> - <item row="3" column="11"> - <widget class="QPushButton" name="button_quotation"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">"</string> - </property> - </widget> - </item> - <item row="2" column="11"> - <widget class="QPushButton" name="button_at"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">@</string> - </property> - </widget> - </item> - <item row="4" column="11"> - <widget class="QPushButton" name="button_equal"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">=</string> - </property> - </widget> - </item> - <item row="1" column="7"> - <widget class="QPushButton" name="button_ampersand"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">&&</string> - </property> - </widget> - </item> - <item row="1" column="8"> - <widget class="QPushButton" name="button_asterisk"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">*</string> - </property> - </widget> - </item> - <item row="1" column="10"> - <widget class="QPushButton" name="button_right_parenthesis"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">)</string> - </property> - </widget> - </item> - <item row="1" column="9"> - <widget class="QPushButton" name="button_left_parenthesis"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">(</string> - </property> - </widget> - </item> - <item row="2" column="2"> - <widget class="QPushButton" name="button_w_shift"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">W</string> - </property> - </widget> - </item> - <item row="2" column="4"> - <widget class="QPushButton" name="button_r_shift"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">R</string> - </property> - </widget> - </item> - <item row="2" column="3"> - <widget class="QPushButton" name="button_e_shift"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">E</string> - </property> - </widget> - </item> - <item row="2" column="1"> - <widget class="QPushButton" name="button_q_shift"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">Q</string> - </property> - </widget> - </item> - <item row="2" column="7"> - <widget class="QPushButton" name="button_u_shift"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">U</string> - </property> - </widget> - </item> - <item row="2" column="6"> - <widget class="QPushButton" name="button_y_shift"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">Y</string> - </property> - </widget> - </item> - <item row="2" column="5"> - <widget class="QPushButton" name="button_t_shift"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">T</string> - </property> - </widget> - </item> - <item row="2" column="9"> - <widget class="QPushButton" name="button_o_shift"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">O</string> - </property> - </widget> - </item> - <item row="2" column="10"> - <widget class="QPushButton" name="button_p_shift"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">P</string> - </property> - </widget> - </item> - <item row="2" column="8"> - <widget class="QPushButton" name="button_i_shift"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">I</string> - </property> - </widget> - </item> - <item row="3" column="1"> - <widget class="QPushButton" name="button_a_shift"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">A</string> - </property> - </widget> - </item> - <item row="3" column="2"> - <widget class="QPushButton" name="button_s_shift"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">S</string> - </property> - </widget> - </item> - <item row="3" column="3"> - <widget class="QPushButton" name="button_d_shift"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">D</string> - </property> - </widget> - </item> - <item row="3" column="4"> - <widget class="QPushButton" name="button_f_shift"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">F</string> - </property> - </widget> - </item> - <item row="3" column="6"> - <widget class="QPushButton" name="button_h_shift"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">H</string> - </property> - </widget> - </item> - <item row="3" column="7"> - <widget class="QPushButton" name="button_j_shift"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">J</string> - </property> - </widget> - </item> - <item row="3" column="5"> - <widget class="QPushButton" name="button_g_shift"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">G</string> - </property> - </widget> - </item> - <item row="3" column="8"> - <widget class="QPushButton" name="button_k_shift"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">K</string> - </property> - </widget> - </item> - <item row="3" column="9"> - <widget class="QPushButton" name="button_l_shift"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">L</string> - </property> - </widget> - </item> - <item row="3" column="10"> - <widget class="QPushButton" name="button_semicolon"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">;</string> - </property> - </widget> - </item> - <item row="2" column="12" rowspan="2"> - <widget class="QPushButton" name="button_return_shift"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>18</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">Return</string> - </property> - </widget> - </item> - <item row="4" column="12" rowspan="2"> - <widget class="QPushButton" name="button_ok_shift"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>18</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">OK</string> - </property> - </widget> - </item> - <item row="4" column="1"> - <widget class="QPushButton" name="button_z_shift"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">Z</string> - </property> - </widget> - </item> - <item row="4" column="3"> - <widget class="QPushButton" name="button_c_shift"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">C</string> - </property> - </widget> - </item> - <item row="4" column="2"> - <widget class="QPushButton" name="button_x_shift"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">X</string> - </property> - </widget> - </item> - <item row="4" column="4"> - <widget class="QPushButton" name="button_v_shift"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">V</string> - </property> - </widget> - </item> - <item row="4" column="7"> - <widget class="QPushButton" name="button_m_shift"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">M</string> - </property> - </widget> - </item> - <item row="4" column="8"> - <widget class="QPushButton" name="button_less_than"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true"><</string> - </property> - </widget> - </item> - <item row="4" column="6"> - <widget class="QPushButton" name="button_n_shift"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">N</string> - </property> - </widget> - </item> - <item row="4" column="5"> - <widget class="QPushButton" name="button_b_shift"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">B</string> - </property> - </widget> - </item> - <item row="5" column="1" colspan="2"> - <widget class="QPushButton" name="button_shift_shift"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>18</pointsize> - </font> - </property> - <property name="text"> - <string notr="true"/> - </property> - <property name="checkable"> - <bool>true</bool> - </property> - <property name="checked"> - <bool>false</bool> - </property> - </widget> - </item> - <item row="4" column="10"> - <widget class="QPushButton" name="button_plus"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">+</string> - </property> - </widget> - </item> - <item row="4" column="9"> - <widget class="QPushButton" name="button_greater_than"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">></string> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QPushButton" name="button_hash"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">#</string> - </property> - </widget> - </item> - <item row="1" column="3"> - <widget class="QPushButton" name="button_right_bracket"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">]</string> - </property> - </widget> - </item> - <item row="1" column="4"> - <widget class="QPushButton" name="button_dollar"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">$</string> - </property> - </widget> - </item> - <item row="1" column="2"> - <widget class="QPushButton" name="button_left_bracket"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">[</string> - </property> - </widget> - </item> - <item row="1" column="6"> - <widget class="QPushButton" name="button_circumflex"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">^</string> - </property> - </widget> - </item> - <item row="1" column="5"> - <widget class="QPushButton" name="button_percent"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">%</string> - </property> - </widget> - </item> - <item row="5" column="3" colspan="9"> - <widget class="QPushButton" name="button_space_shift"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>18</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">Space</string> - </property> - </widget> - </item> - <item row="1" column="12"> - <widget class="QPushButton" name="button_backspace_shift"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>18</pointsize> - </font> - </property> - <property name="text"> - <string notr="true"/> - </property> - </widget> - </item> - <item row="1" column="0"> - <spacer name="horizontalSpacer_33"> - <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"> - <spacer name="verticalSpacer_6"> - <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 row="1" column="13"> - <spacer name="horizontalSpacer_34"> - <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> - </item> - </layout> - </widget> - <widget class="QWidget" name="numOSK"> - <layout class="QVBoxLayout" name="graphicsTabVerticalLayout"> - <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> - <layout class="QGridLayout" name="kbOSKnum" rowstretch="18,63,63,63,63,10,70" columnstretch="54,307,186,186,186,120,187,54"> - <property name="leftMargin"> - <number>0</number> - </property> - <property name="rightMargin"> - <number>0</number> - </property> - <property name="spacing"> - <number>0</number> - </property> - <item row="1" column="5"> - <widget class="QPushButton" name="button_backspace_num"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>18</pointsize> - </font> - </property> - <property name="text"> - <string notr="true"/> - </property> - </widget> - </item> - <item row="1" column="6"> - <spacer name="horizontalSpacer_35"> - <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="1" column="1"> - <spacer name="horizontalSpacer_36"> - <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="2"> - <spacer name="verticalSpacer_7"> - <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 row="6" column="1" colspan="6"> - <widget class="QWidget" name="legendOSKnum" native="true"> - <layout class="QHBoxLayout" name="horizontalLayout_6" stretch="25,70,601,25,12,22,41,25,12,22,41,29,12,69,37,29,12,56,30"> - <property name="spacing"> - <number>0</number> - </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> - <spacer name="horizontalSpacer_48"> - <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> - <widget class="QWidget" name="icon_controller_num" native="true"> - <property name="styleSheet"> - <string notr="true"/> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer_38"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>0</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QWidget" name="button_L_num" native="true"/> - </item> - <item> - <spacer name="horizontalSpacer_39"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>0</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QWidget" name="arrow_left_num" native="true"/> - </item> - <item> - <spacer name="horizontalSpacer_40"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>0</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QWidget" name="button_R_num" native="true"/> - </item> - <item> - <spacer name="horizontalSpacer_41"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>0</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QWidget" name="arrow_right_num" native="true"/> - </item> - <item> - <spacer name="horizontalSpacer_42"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>0</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QWidget" name="button_X_num" native="true"/> - </item> - <item> - <spacer name="horizontalSpacer_43"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>0</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QLabel" name="label_cancel_num"> - <property name="font"> - <font> - <pointsize>18</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">Cancel</string> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer_44"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>0</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QWidget" name="button_A_num" native="true"/> - </item> - <item> - <spacer name="horizontalSpacer_45"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>0</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QLabel" name="label_enter_num"> - <property name="font"> - <font> - <pointsize>18</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">Enter</string> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer_46"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>0</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - </layout> - </widget> - </item> - <item row="2" column="4"> - <widget class="QPushButton" name="button_6_num"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">6</string> - </property> - </widget> - </item> - <item row="2" column="2"> - <widget class="QPushButton" name="button_4_num"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">4</string> - </property> - </widget> - </item> - <item row="3" column="4"> - <widget class="QPushButton" name="button_9_num"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">9</string> - </property> - </widget> - </item> - <item row="2" column="3"> - <widget class="QPushButton" name="button_5_num"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">5</string> - </property> - </widget> - </item> - <item row="2" column="5" rowspan="3"> - <widget class="QPushButton" name="button_ok_num"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>18</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">OK</string> - </property> - </widget> - </item> - <item row="3" column="2"> - <widget class="QPushButton" name="button_7_num"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">7</string> - </property> - </widget> - </item> - <item row="3" column="3"> - <widget class="QPushButton" name="button_8_num"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">8</string> - </property> - </widget> - </item> - <item row="1" column="3"> - <widget class="QPushButton" name="button_2_num"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">2</string> - </property> - </widget> - </item> - <item row="1" column="2"> - <widget class="QPushButton" name="button_1_num"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">1</string> - </property> - </widget> - </item> - <item row="4" column="2"> - <widget class="QPushButton" name="button_left_optional_num"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true"></string> - </property> - </widget> - </item> - <item row="4" column="3"> - <widget class="QPushButton" name="button_0_num"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">0</string> - </property> - </widget> - </item> - <item row="4" column="4"> - <widget class="QPushButton" name="button_right_optional_num"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true"></string> - </property> - </widget> - </item> - <item row="1" column="4"> - <widget class="QPushButton" name="button_3_num"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>28</pointsize> - </font> - </property> - <property name="text"> - <string notr="true">3</string> - </property> - </widget> - </item> - <item row="1" column="0"> - <spacer name="horizontalSpacer_37"> - <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="1" column="7"> - <spacer name="horizontalSpacer_47"> - <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="5" column="3"> - <spacer name="verticalSpacer_8"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>0</height> - </size> - </property> - </spacer> - </item> - </layout> - </item> - </layout> - </widget> - </widget> - </item> - </layout> - </widget> - </item> - </layout> - </widget> - <tabstops> - <tabstop>button_1</tabstop> - <tabstop>button_2</tabstop> - <tabstop>button_3</tabstop> - <tabstop>button_4</tabstop> - <tabstop>button_5</tabstop> - <tabstop>button_6</tabstop> - <tabstop>button_7</tabstop> - <tabstop>button_8</tabstop> - <tabstop>button_9</tabstop> - <tabstop>button_0</tabstop> - <tabstop>button_minus</tabstop> - <tabstop>button_backspace</tabstop> - <tabstop>button_q</tabstop> - <tabstop>button_w</tabstop> - <tabstop>button_e</tabstop> - <tabstop>button_r</tabstop> - <tabstop>button_t</tabstop> - <tabstop>button_y</tabstop> - <tabstop>button_u</tabstop> - <tabstop>button_i</tabstop> - <tabstop>button_o</tabstop> - <tabstop>button_p</tabstop> - <tabstop>button_slash</tabstop> - <tabstop>button_return</tabstop> - <tabstop>button_a</tabstop> - <tabstop>button_s</tabstop> - <tabstop>button_d</tabstop> - <tabstop>button_f</tabstop> - <tabstop>button_g</tabstop> - <tabstop>button_h</tabstop> - <tabstop>button_j</tabstop> - <tabstop>button_k</tabstop> - <tabstop>button_l</tabstop> - <tabstop>button_colon</tabstop> - <tabstop>button_apostrophe</tabstop> - <tabstop>button_z</tabstop> - <tabstop>button_x</tabstop> - <tabstop>button_c</tabstop> - <tabstop>button_v</tabstop> - <tabstop>button_b</tabstop> - <tabstop>button_n</tabstop> - <tabstop>button_m</tabstop> - <tabstop>button_comma</tabstop> - <tabstop>button_dot</tabstop> - <tabstop>button_question</tabstop> - <tabstop>button_exclamation</tabstop> - <tabstop>button_ok</tabstop> - <tabstop>button_shift</tabstop> - <tabstop>button_space</tabstop> - <tabstop>button_hash</tabstop> - <tabstop>button_left_bracket</tabstop> - <tabstop>button_right_bracket</tabstop> - <tabstop>button_dollar</tabstop> - <tabstop>button_percent</tabstop> - <tabstop>button_circumflex</tabstop> - <tabstop>button_ampersand</tabstop> - <tabstop>button_asterisk</tabstop> - <tabstop>button_left_parenthesis</tabstop> - <tabstop>button_right_parenthesis</tabstop> - <tabstop>button_underscore</tabstop> - <tabstop>button_backspace_shift</tabstop> - <tabstop>button_q_shift</tabstop> - <tabstop>button_w_shift</tabstop> - <tabstop>button_e_shift</tabstop> - <tabstop>button_r_shift</tabstop> - <tabstop>button_t_shift</tabstop> - <tabstop>button_y_shift</tabstop> - <tabstop>button_u_shift</tabstop> - <tabstop>button_i_shift</tabstop> - <tabstop>button_o_shift</tabstop> - <tabstop>button_p_shift</tabstop> - <tabstop>button_at</tabstop> - <tabstop>button_return_shift</tabstop> - <tabstop>button_a_shift</tabstop> - <tabstop>button_s_shift</tabstop> - <tabstop>button_d_shift</tabstop> - <tabstop>button_f_shift</tabstop> - <tabstop>button_g_shift</tabstop> - <tabstop>button_h_shift</tabstop> - <tabstop>button_j_shift</tabstop> - <tabstop>button_k_shift</tabstop> - <tabstop>button_l_shift</tabstop> - <tabstop>button_semicolon</tabstop> - <tabstop>button_quotation</tabstop> - <tabstop>button_z_shift</tabstop> - <tabstop>button_x_shift</tabstop> - <tabstop>button_c_shift</tabstop> - <tabstop>button_v_shift</tabstop> - <tabstop>button_b_shift</tabstop> - <tabstop>button_n_shift</tabstop> - <tabstop>button_m_shift</tabstop> - <tabstop>button_less_than</tabstop> - <tabstop>button_greater_than</tabstop> - <tabstop>button_plus</tabstop> - <tabstop>button_equal</tabstop> - <tabstop>button_ok_shift</tabstop> - <tabstop>button_shift_shift</tabstop> - <tabstop>button_space_shift</tabstop> - <tabstop>button_1_num</tabstop> - <tabstop>button_2_num</tabstop> - <tabstop>button_3_num</tabstop> - <tabstop>button_backspace_num</tabstop> - <tabstop>button_4_num</tabstop> - <tabstop>button_5_num</tabstop> - <tabstop>button_6_num</tabstop> - <tabstop>button_ok_num</tabstop> - <tabstop>button_7_num</tabstop> - <tabstop>button_8_num</tabstop> - <tabstop>button_9_num</tabstop> - <tabstop>button_left_optional_num</tabstop> - <tabstop>button_0_num</tabstop> - <tabstop>button_right_optional_num</tabstop> - </tabstops> - <resources> - <include location="../../../dist/icons/overlay/overlay.qrc"/> - </resources> - <connections/> -</ui> diff --git a/src/yuzu/applets/qt_web_browser.cpp b/src/yuzu/applets/qt_web_browser.cpp deleted file mode 100644 index cce9b2efb..000000000 --- a/src/yuzu/applets/qt_web_browser.cpp +++ /dev/null @@ -1,449 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#ifdef YUZU_USE_QT_WEB_ENGINE -#include <bit> - -#include <QApplication> -#include <QKeyEvent> - -#include <QWebEngineProfile> -#include <QWebEngineScript> -#include <QWebEngineScriptCollection> -#include <QWebEngineSettings> -#include <QWebEngineUrlScheme> - -#include "hid_core/frontend/input_interpreter.h" -#include "yuzu/applets/qt_web_browser_scripts.h" -#endif - -#include "common/fs/path_util.h" -#include "core/core.h" -#include "input_common/drivers/keyboard.h" -#include "yuzu/applets/qt_web_browser.h" -#include "yuzu/main.h" -#include "yuzu/util/url_request_interceptor.h" - -#ifdef YUZU_USE_QT_WEB_ENGINE - -namespace { - -constexpr int HIDButtonToKey(Core::HID::NpadButton button) { - switch (button) { - case Core::HID::NpadButton::Left: - case Core::HID::NpadButton::StickLLeft: - return Qt::Key_Left; - case Core::HID::NpadButton::Up: - case Core::HID::NpadButton::StickLUp: - return Qt::Key_Up; - case Core::HID::NpadButton::Right: - case Core::HID::NpadButton::StickLRight: - return Qt::Key_Right; - case Core::HID::NpadButton::Down: - case Core::HID::NpadButton::StickLDown: - return Qt::Key_Down; - default: - return 0; - } -} - -} // Anonymous namespace - -QtNXWebEngineView::QtNXWebEngineView(QWidget* parent, Core::System& system, - InputCommon::InputSubsystem* input_subsystem_) - : QWebEngineView(parent), input_subsystem{input_subsystem_}, - url_interceptor(std::make_unique<UrlRequestInterceptor>()), - input_interpreter(std::make_unique<InputInterpreter>(system)), - default_profile{QWebEngineProfile::defaultProfile()}, global_settings{ - default_profile->settings()} { - default_profile->setPersistentStoragePath(QString::fromStdString(Common::FS::PathToUTF8String( - Common::FS::GetYuzuPath(Common::FS::YuzuPath::YuzuDir) / "qtwebengine"))); - - QWebEngineScript gamepad; - QWebEngineScript window_nx; - - gamepad.setName(QStringLiteral("gamepad_script.js")); - window_nx.setName(QStringLiteral("window_nx_script.js")); - - gamepad.setSourceCode(QString::fromStdString(GAMEPAD_SCRIPT)); - window_nx.setSourceCode(QString::fromStdString(WINDOW_NX_SCRIPT)); - - gamepad.setInjectionPoint(QWebEngineScript::DocumentCreation); - window_nx.setInjectionPoint(QWebEngineScript::DocumentCreation); - - gamepad.setWorldId(QWebEngineScript::MainWorld); - window_nx.setWorldId(QWebEngineScript::MainWorld); - - gamepad.setRunsOnSubFrames(true); - window_nx.setRunsOnSubFrames(true); - - default_profile->scripts()->insert(gamepad); - default_profile->scripts()->insert(window_nx); - - default_profile->setUrlRequestInterceptor(url_interceptor.get()); - - global_settings->setAttribute(QWebEngineSettings::LocalContentCanAccessRemoteUrls, true); - global_settings->setAttribute(QWebEngineSettings::FullScreenSupportEnabled, true); - global_settings->setAttribute(QWebEngineSettings::AllowRunningInsecureContent, true); - global_settings->setAttribute(QWebEngineSettings::FocusOnNavigationEnabled, true); - global_settings->setAttribute(QWebEngineSettings::AllowWindowActivationFromJavaScript, true); - global_settings->setAttribute(QWebEngineSettings::ShowScrollBars, false); - - global_settings->setFontFamily(QWebEngineSettings::StandardFont, QStringLiteral("Roboto")); - - connect( - page(), &QWebEnginePage::windowCloseRequested, page(), - [this] { - if (page()->url() == url_interceptor->GetRequestedURL()) { - SetFinished(true); - SetExitReason(Service::AM::Frontend::WebExitReason::WindowClosed); - } - }, - Qt::QueuedConnection); -} - -QtNXWebEngineView::~QtNXWebEngineView() { - SetFinished(true); - StopInputThread(); -} - -void QtNXWebEngineView::LoadLocalWebPage(const std::string& main_url, - const std::string& additional_args) { - is_local = true; - - LoadExtractedFonts(); - FocusFirstLinkElement(); - SetUserAgent(UserAgent::WebApplet); - SetFinished(false); - SetExitReason(Service::AM::Frontend::WebExitReason::EndButtonPressed); - SetLastURL("http://localhost/"); - StartInputThread(); - - load(QUrl(QUrl::fromLocalFile(QString::fromStdString(main_url)).toString() + - QString::fromStdString(additional_args))); -} - -void QtNXWebEngineView::LoadExternalWebPage(const std::string& main_url, - const std::string& additional_args) { - is_local = false; - - FocusFirstLinkElement(); - SetUserAgent(UserAgent::WebApplet); - SetFinished(false); - SetExitReason(Service::AM::Frontend::WebExitReason::EndButtonPressed); - SetLastURL("http://localhost/"); - StartInputThread(); - - load(QUrl(QString::fromStdString(main_url) + QString::fromStdString(additional_args))); -} - -void QtNXWebEngineView::SetUserAgent(UserAgent user_agent) { - const QString user_agent_str = [user_agent] { - switch (user_agent) { - case UserAgent::WebApplet: - default: - return QStringLiteral("WebApplet"); - case UserAgent::ShopN: - return QStringLiteral("ShopN"); - case UserAgent::LoginApplet: - return QStringLiteral("LoginApplet"); - case UserAgent::ShareApplet: - return QStringLiteral("ShareApplet"); - case UserAgent::LobbyApplet: - return QStringLiteral("LobbyApplet"); - case UserAgent::WifiWebAuthApplet: - return QStringLiteral("WifiWebAuthApplet"); - } - }(); - - QWebEngineProfile::defaultProfile()->setHttpUserAgent( - QStringLiteral("Mozilla/5.0 (Nintendo Switch; %1) AppleWebKit/606.4 " - "(KHTML, like Gecko) NF/6.0.1.15.4 NintendoBrowser/5.1.0.20389") - .arg(user_agent_str)); -} - -bool QtNXWebEngineView::IsFinished() const { - return finished; -} - -void QtNXWebEngineView::SetFinished(bool finished_) { - finished = finished_; -} - -Service::AM::Frontend::WebExitReason QtNXWebEngineView::GetExitReason() const { - return exit_reason; -} - -void QtNXWebEngineView::SetExitReason(Service::AM::Frontend::WebExitReason exit_reason_) { - exit_reason = exit_reason_; -} - -const std::string& QtNXWebEngineView::GetLastURL() const { - return last_url; -} - -void QtNXWebEngineView::SetLastURL(std::string last_url_) { - last_url = std::move(last_url_); -} - -QString QtNXWebEngineView::GetCurrentURL() const { - return url_interceptor->GetRequestedURL().toString(); -} - -void QtNXWebEngineView::hide() { - SetFinished(true); - StopInputThread(); - - QWidget::hide(); -} - -void QtNXWebEngineView::keyPressEvent(QKeyEvent* event) { - if (is_local) { - input_subsystem->GetKeyboard()->PressKey(event->key()); - } -} - -void QtNXWebEngineView::keyReleaseEvent(QKeyEvent* event) { - if (is_local) { - input_subsystem->GetKeyboard()->ReleaseKey(event->key()); - } -} - -template <Core::HID::NpadButton... T> -void QtNXWebEngineView::HandleWindowFooterButtonPressedOnce() { - const auto f = [this](Core::HID::NpadButton button) { - if (input_interpreter->IsButtonPressedOnce(button)) { - const auto button_index = std::countr_zero(static_cast<u64>(button)); - - page()->runJavaScript( - QStringLiteral("yuzu_key_callbacks[%1] == null;").arg(button_index), - [this, button](const QVariant& variant) { - if (variant.toBool()) { - switch (button) { - case Core::HID::NpadButton::A: - SendMultipleKeyPressEvents<Qt::Key_A, Qt::Key_Space, Qt::Key_Return>(); - break; - case Core::HID::NpadButton::B: - SendKeyPressEvent(Qt::Key_B); - break; - case Core::HID::NpadButton::X: - SendKeyPressEvent(Qt::Key_X); - break; - case Core::HID::NpadButton::Y: - SendKeyPressEvent(Qt::Key_Y); - break; - default: - break; - } - } - }); - - page()->runJavaScript( - QStringLiteral("if (yuzu_key_callbacks[%1] != null) { yuzu_key_callbacks[%1](); }") - .arg(button_index)); - } - }; - - (f(T), ...); -} - -template <Core::HID::NpadButton... T> -void QtNXWebEngineView::HandleWindowKeyButtonPressedOnce() { - const auto f = [this](Core::HID::NpadButton button) { - if (input_interpreter->IsButtonPressedOnce(button)) { - SendKeyPressEvent(HIDButtonToKey(button)); - } - }; - - (f(T), ...); -} - -template <Core::HID::NpadButton... T> -void QtNXWebEngineView::HandleWindowKeyButtonHold() { - const auto f = [this](Core::HID::NpadButton button) { - if (input_interpreter->IsButtonHeld(button)) { - SendKeyPressEvent(HIDButtonToKey(button)); - } - }; - - (f(T), ...); -} - -void QtNXWebEngineView::SendKeyPressEvent(int key) { - if (key == 0) { - return; - } - - QCoreApplication::postEvent(focusProxy(), - new QKeyEvent(QKeyEvent::KeyPress, key, Qt::NoModifier)); - QCoreApplication::postEvent(focusProxy(), - new QKeyEvent(QKeyEvent::KeyRelease, key, Qt::NoModifier)); -} - -void QtNXWebEngineView::StartInputThread() { - if (input_thread_running) { - return; - } - - input_thread_running = true; - input_thread = std::thread(&QtNXWebEngineView::InputThread, this); -} - -void QtNXWebEngineView::StopInputThread() { - if (is_local) { - QWidget::releaseKeyboard(); - } - - input_thread_running = false; - if (input_thread.joinable()) { - input_thread.join(); - } -} - -void QtNXWebEngineView::InputThread() { - // Wait for 1 second before allowing any inputs to be processed. - std::this_thread::sleep_for(std::chrono::seconds(1)); - - if (is_local) { - QWidget::grabKeyboard(); - } - - while (input_thread_running) { - input_interpreter->PollInput(); - - HandleWindowFooterButtonPressedOnce<Core::HID::NpadButton::A, Core::HID::NpadButton::B, - Core::HID::NpadButton::X, Core::HID::NpadButton::Y, - Core::HID::NpadButton::L, Core::HID::NpadButton::R>(); - - HandleWindowKeyButtonPressedOnce< - Core::HID::NpadButton::Left, Core::HID::NpadButton::Up, Core::HID::NpadButton::Right, - Core::HID::NpadButton::Down, Core::HID::NpadButton::StickLLeft, - Core::HID::NpadButton::StickLUp, Core::HID::NpadButton::StickLRight, - Core::HID::NpadButton::StickLDown>(); - - HandleWindowKeyButtonHold< - Core::HID::NpadButton::Left, Core::HID::NpadButton::Up, Core::HID::NpadButton::Right, - Core::HID::NpadButton::Down, Core::HID::NpadButton::StickLLeft, - Core::HID::NpadButton::StickLUp, Core::HID::NpadButton::StickLRight, - Core::HID::NpadButton::StickLDown>(); - - std::this_thread::sleep_for(std::chrono::milliseconds(50)); - } -} - -void QtNXWebEngineView::LoadExtractedFonts() { - QWebEngineScript nx_font_css; - QWebEngineScript load_nx_font; - - auto fonts_dir_str = Common::FS::PathToUTF8String( - Common::FS::GetYuzuPath(Common::FS::YuzuPath::CacheDir) / "fonts/"); - - std::replace(fonts_dir_str.begin(), fonts_dir_str.end(), '\\', '/'); - - const auto fonts_dir = QString::fromStdString(fonts_dir_str); - - nx_font_css.setName(QStringLiteral("nx_font_css.js")); - load_nx_font.setName(QStringLiteral("load_nx_font.js")); - - nx_font_css.setSourceCode( - QString::fromStdString(NX_FONT_CSS) - .arg(fonts_dir + QStringLiteral("FontStandard.ttf")) - .arg(fonts_dir + QStringLiteral("FontChineseSimplified.ttf")) - .arg(fonts_dir + QStringLiteral("FontExtendedChineseSimplified.ttf")) - .arg(fonts_dir + QStringLiteral("FontChineseTraditional.ttf")) - .arg(fonts_dir + QStringLiteral("FontKorean.ttf")) - .arg(fonts_dir + QStringLiteral("FontNintendoExtended.ttf")) - .arg(fonts_dir + QStringLiteral("FontNintendoExtended2.ttf"))); - load_nx_font.setSourceCode(QString::fromStdString(LOAD_NX_FONT)); - - nx_font_css.setInjectionPoint(QWebEngineScript::DocumentReady); - load_nx_font.setInjectionPoint(QWebEngineScript::Deferred); - - nx_font_css.setWorldId(QWebEngineScript::MainWorld); - load_nx_font.setWorldId(QWebEngineScript::MainWorld); - - nx_font_css.setRunsOnSubFrames(true); - load_nx_font.setRunsOnSubFrames(true); - - default_profile->scripts()->insert(nx_font_css); - default_profile->scripts()->insert(load_nx_font); - - connect( - url_interceptor.get(), &UrlRequestInterceptor::FrameChanged, url_interceptor.get(), - [this] { - std::this_thread::sleep_for(std::chrono::milliseconds(50)); - page()->runJavaScript(QString::fromStdString(LOAD_NX_FONT)); - }, - Qt::QueuedConnection); -} - -void QtNXWebEngineView::FocusFirstLinkElement() { - QWebEngineScript focus_link_element; - - focus_link_element.setName(QStringLiteral("focus_link_element.js")); - focus_link_element.setSourceCode(QString::fromStdString(FOCUS_LINK_ELEMENT_SCRIPT)); - focus_link_element.setWorldId(QWebEngineScript::MainWorld); - focus_link_element.setInjectionPoint(QWebEngineScript::Deferred); - focus_link_element.setRunsOnSubFrames(true); - default_profile->scripts()->insert(focus_link_element); -} - -#endif - -QtWebBrowser::QtWebBrowser(GMainWindow& main_window) { - connect(this, &QtWebBrowser::MainWindowOpenWebPage, &main_window, - &GMainWindow::WebBrowserOpenWebPage, Qt::QueuedConnection); - connect(this, &QtWebBrowser::MainWindowRequestExit, &main_window, - &GMainWindow::WebBrowserRequestExit, Qt::QueuedConnection); - connect(&main_window, &GMainWindow::WebBrowserExtractOfflineRomFS, this, - &QtWebBrowser::MainWindowExtractOfflineRomFS, Qt::QueuedConnection); - connect(&main_window, &GMainWindow::WebBrowserClosed, this, - &QtWebBrowser::MainWindowWebBrowserClosed, Qt::QueuedConnection); -} - -QtWebBrowser::~QtWebBrowser() = default; - -void QtWebBrowser::Close() const { - callback = {}; - emit MainWindowRequestExit(); -} - -void QtWebBrowser::OpenLocalWebPage(const std::string& local_url, - ExtractROMFSCallback extract_romfs_callback_, - OpenWebPageCallback callback_) const { - extract_romfs_callback = std::move(extract_romfs_callback_); - callback = std::move(callback_); - - const auto index = local_url.find('?'); - - if (index == std::string::npos) { - emit MainWindowOpenWebPage(local_url, "", true); - } else { - emit MainWindowOpenWebPage(local_url.substr(0, index), local_url.substr(index), true); - } -} - -void QtWebBrowser::OpenExternalWebPage(const std::string& external_url, - OpenWebPageCallback callback_) const { - callback = std::move(callback_); - - const auto index = external_url.find('?'); - - if (index == std::string::npos) { - emit MainWindowOpenWebPage(external_url, "", false); - } else { - emit MainWindowOpenWebPage(external_url.substr(0, index), external_url.substr(index), - false); - } -} - -void QtWebBrowser::MainWindowExtractOfflineRomFS() { - extract_romfs_callback(); -} - -void QtWebBrowser::MainWindowWebBrowserClosed(Service::AM::Frontend::WebExitReason exit_reason, - std::string last_url) { - if (callback) { - callback(exit_reason, last_url); - } -} diff --git a/src/yuzu/applets/qt_web_browser.h b/src/yuzu/applets/qt_web_browser.h deleted file mode 100644 index e8a0b6931..000000000 --- a/src/yuzu/applets/qt_web_browser.h +++ /dev/null @@ -1,220 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include <atomic> -#include <thread> - -#include <QObject> - -#ifdef YUZU_USE_QT_WEB_ENGINE -#include <QWebEngineView> -#endif - -#include "core/frontend/applets/web_browser.h" - -class GMainWindow; -class InputInterpreter; -class UrlRequestInterceptor; - -namespace Core { -class System; -} - -namespace Core::HID { -enum class NpadButton : u64; -} - -namespace InputCommon { -class InputSubsystem; -} - -#ifdef YUZU_USE_QT_WEB_ENGINE - -enum class UserAgent { - WebApplet, - ShopN, - LoginApplet, - ShareApplet, - LobbyApplet, - WifiWebAuthApplet, -}; - -class QWebEngineProfile; -class QWebEngineSettings; - -class QtNXWebEngineView : public QWebEngineView { - Q_OBJECT - -public: - explicit QtNXWebEngineView(QWidget* parent, Core::System& system, - InputCommon::InputSubsystem* input_subsystem_); - ~QtNXWebEngineView() override; - - /** - * Loads a HTML document that exists locally. Cannot be used to load external websites. - * - * @param main_url The url to the file. - * @param additional_args Additional arguments appended to the main url. - */ - void LoadLocalWebPage(const std::string& main_url, const std::string& additional_args); - - /** - * Loads an external website. Cannot be used to load local urls. - * - * @param main_url The url to the website. - * @param additional_args Additional arguments appended to the main url. - */ - void LoadExternalWebPage(const std::string& main_url, const std::string& additional_args); - - /** - * Sets the background color of the web page. - * - * @param color The color to set. - */ - void SetBackgroundColor(QColor color); - - /** - * Sets the user agent of the web browser. - * - * @param user_agent The user agent enum. - */ - void SetUserAgent(UserAgent user_agent); - - [[nodiscard]] bool IsFinished() const; - void SetFinished(bool finished_); - - [[nodiscard]] Service::AM::Frontend::WebExitReason GetExitReason() const; - void SetExitReason(Service::AM::Frontend::WebExitReason exit_reason_); - - [[nodiscard]] const std::string& GetLastURL() const; - void SetLastURL(std::string last_url_); - - /** - * This gets the current URL that has been requested by the webpage. - * This only applies to the main frame. Sub frames and other resources are ignored. - * - * @return Currently requested URL - */ - [[nodiscard]] QString GetCurrentURL() const; - -public slots: - void hide(); - -protected: - void keyPressEvent(QKeyEvent* event) override; - void keyReleaseEvent(QKeyEvent* event) override; - -private: - /** - * Handles button presses to execute functions assigned in yuzu_key_callbacks. - * yuzu_key_callbacks contains specialized functions for the buttons in the window footer - * that can be overridden by games to achieve desired functionality. - * - * @tparam HIDButton The list of buttons contained in yuzu_key_callbacks - */ - template <Core::HID::NpadButton... T> - void HandleWindowFooterButtonPressedOnce(); - - /** - * Handles button presses and converts them into keyboard input. - * This should only be used to convert D-Pad or Analog Stick input into arrow keys. - * - * @tparam HIDButton The list of buttons that can be converted into keyboard input. - */ - template <Core::HID::NpadButton... T> - void HandleWindowKeyButtonPressedOnce(); - - /** - * Handles button holds and converts them into keyboard input. - * This should only be used to convert D-Pad or Analog Stick input into arrow keys. - * - * @tparam HIDButton The list of buttons that can be converted into keyboard input. - */ - template <Core::HID::NpadButton... T> - void HandleWindowKeyButtonHold(); - - /** - * Sends a key press event to QWebEngineView. - * - * @param key Qt key code. - */ - void SendKeyPressEvent(int key); - - /** - * Sends multiple key press events to QWebEngineView. - * - * @tparam int Qt key code. - */ - template <int... T> - void SendMultipleKeyPressEvents() { - (SendKeyPressEvent(T), ...); - } - - void StartInputThread(); - void StopInputThread(); - - /// The thread where input is being polled and processed. - void InputThread(); - - /// Loads the extracted fonts using JavaScript. - void LoadExtractedFonts(); - - /// Brings focus to the first available link element. - void FocusFirstLinkElement(); - - InputCommon::InputSubsystem* input_subsystem; - - std::unique_ptr<UrlRequestInterceptor> url_interceptor; - - std::unique_ptr<InputInterpreter> input_interpreter; - - std::thread input_thread; - - std::atomic<bool> input_thread_running{}; - - std::atomic<bool> finished{}; - - Service::AM::Frontend::WebExitReason exit_reason{ - Service::AM::Frontend::WebExitReason::EndButtonPressed}; - - std::string last_url{"http://localhost/"}; - - bool is_local{}; - - QWebEngineProfile* default_profile; - QWebEngineSettings* global_settings; -}; - -#endif - -class QtWebBrowser final : public QObject, public Core::Frontend::WebBrowserApplet { - Q_OBJECT - -public: - explicit QtWebBrowser(GMainWindow& parent); - ~QtWebBrowser() override; - - void Close() const override; - void OpenLocalWebPage(const std::string& local_url, - ExtractROMFSCallback extract_romfs_callback_, - OpenWebPageCallback callback_) const override; - - void OpenExternalWebPage(const std::string& external_url, - OpenWebPageCallback callback_) const override; - -signals: - void MainWindowOpenWebPage(const std::string& main_url, const std::string& additional_args, - bool is_local) const; - void MainWindowRequestExit() const; - -private: - void MainWindowExtractOfflineRomFS(); - - void MainWindowWebBrowserClosed(Service::AM::Frontend::WebExitReason exit_reason, - std::string last_url); - - mutable ExtractROMFSCallback extract_romfs_callback; - mutable OpenWebPageCallback callback; -}; diff --git a/src/yuzu/applets/qt_web_browser_scripts.h b/src/yuzu/applets/qt_web_browser_scripts.h deleted file mode 100644 index f5530c38f..000000000 --- a/src/yuzu/applets/qt_web_browser_scripts.h +++ /dev/null @@ -1,198 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -constexpr char NX_FONT_CSS[] = R"( -(function() { - css = document.createElement('style'); - css.type = 'text/css'; - css.id = 'nx_font'; - css.innerText = ` -/* FontStandard */ -@font-face { - font-family: 'FontStandard'; - src: url('%1') format('truetype'); -} - -/* FontChineseSimplified */ -@font-face { - font-family: 'FontChineseSimplified'; - src: url('%2') format('truetype'); -} - -/* FontExtendedChineseSimplified */ -@font-face { - font-family: 'FontExtendedChineseSimplified'; - src: url('%3') format('truetype'); -} - -/* FontChineseTraditional */ -@font-face { - font-family: 'FontChineseTraditional'; - src: url('%4') format('truetype'); -} - -/* FontKorean */ -@font-face { - font-family: 'FontKorean'; - src: url('%5') format('truetype'); -} - -/* FontNintendoExtended */ -@font-face { - font-family: 'NintendoExt003'; - src: url('%6') format('truetype'); -} - -/* FontNintendoExtended2 */ -@font-face { - font-family: 'NintendoExt003'; - src: url('%7') format('truetype'); -} -`; - - document.head.appendChild(css); -})(); -)"; - -constexpr char LOAD_NX_FONT[] = R"( -(function() { - var elements = document.querySelectorAll("*"); - - for (var i = 0; i < elements.length; i++) { - var style = window.getComputedStyle(elements[i], null); - if (style.fontFamily.includes("Arial") || style.fontFamily.includes("Calibri") || - style.fontFamily.includes("Century") || style.fontFamily.includes("Times New Roman")) { - elements[i].style.fontFamily = "FontStandard, FontChineseSimplified, FontExtendedChineseSimplified, FontChineseTraditional, FontKorean, NintendoExt003"; - } else { - elements[i].style.fontFamily = style.fontFamily + ", FontStandard, FontChineseSimplified, FontExtendedChineseSimplified, FontChineseTraditional, FontKorean, NintendoExt003"; - } - } -})(); -)"; - -constexpr char FOCUS_LINK_ELEMENT_SCRIPT[] = R"( -if (document.getElementsByTagName("a").length > 0) { - document.getElementsByTagName("a")[0].focus(); -} -)"; - -constexpr char GAMEPAD_SCRIPT[] = R"( -window.addEventListener("gamepadconnected", function(e) { - console.log("Gamepad connected at index %d: %s. %d buttons, %d axes.", - e.gamepad.index, e.gamepad.id, e.gamepad.buttons.length, e.gamepad.axes.length); -}); - -window.addEventListener("gamepaddisconnected", function(e) { - console.log("Gamepad disconnected from index %d: %s", e.gamepad.index, e.gamepad.id); -}); -)"; - -constexpr char WINDOW_NX_SCRIPT[] = R"( -var end_applet = false; -var yuzu_key_callbacks = []; - -(function() { - class WindowNX { - constructor() { - yuzu_key_callbacks[1] = function() { window.history.back(); }; - yuzu_key_callbacks[2] = function() { window.nx.endApplet(); }; - } - - addEventListener(type, listener, options) { - console.log("nx.addEventListener called, type=%s", type); - - window.addEventListener(type, listener, options); - } - - endApplet() { - console.log("nx.endApplet called"); - - end_applet = true; - } - - playSystemSe(system_se) { - console.log("nx.playSystemSe is not implemented, system_se=%s", system_se); - } - - sendMessage(message) { - console.log("nx.sendMessage is not implemented, message=%s", message); - } - - setCursorScrollSpeed(scroll_speed) { - console.log("nx.setCursorScrollSpeed is not implemented, scroll_speed=%d", scroll_speed); - } - } - - class WindowNXFooter { - setAssign(key, label, func, option) { - console.log("nx.footer.setAssign called, key=%s", key); - - switch (key) { - case "A": - yuzu_key_callbacks[0] = func; - break; - case "B": - yuzu_key_callbacks[1] = func; - break; - case "X": - yuzu_key_callbacks[2] = func; - break; - case "Y": - yuzu_key_callbacks[3] = func; - break; - case "L": - yuzu_key_callbacks[6] = func; - break; - case "R": - yuzu_key_callbacks[7] = func; - break; - } - } - - setFixed(kind) { - console.log("nx.footer.setFixed is not implemented, kind=%s", kind); - } - - unsetAssign(key) { - console.log("nx.footer.unsetAssign called, key=%s", key); - - switch (key) { - case "A": - yuzu_key_callbacks[0] = function() {}; - break; - case "B": - yuzu_key_callbacks[1] = function() {}; - break; - case "X": - yuzu_key_callbacks[2] = function() {}; - break; - case "Y": - yuzu_key_callbacks[3] = function() {}; - break; - case "L": - yuzu_key_callbacks[6] = function() {}; - break; - case "R": - yuzu_key_callbacks[7] = function() {}; - break; - } - } - } - - class WindowNXPlayReport { - incrementCounter(counter_id) { - console.log("nx.playReport.incrementCounter is not implemented, counter_id=%d", counter_id); - } - - setCounterSetIdentifier(counter_id) { - console.log("nx.playReport.setCounterSetIdentifier is not implemented, counter_id=%d", counter_id); - } - } - - window.nx = new WindowNX(); - window.nx.footer = new WindowNXFooter(); - window.nx.playReport = new WindowNXPlayReport(); -})(); -)"; |