diff options
Diffstat (limited to 'src/yuzu/applets')
| -rw-r--r-- | src/yuzu/applets/controller.cpp | 16 | ||||
| -rw-r--r-- | src/yuzu/applets/controller.h | 3 | ||||
| -rw-r--r-- | src/yuzu/applets/error.cpp | 22 | ||||
| -rw-r--r-- | src/yuzu/applets/error.h | 2 | ||||
| -rw-r--r-- | src/yuzu/applets/software_keyboard.cpp | 1712 | ||||
| -rw-r--r-- | src/yuzu/applets/software_keyboard.h | 283 | ||||
| -rw-r--r-- | src/yuzu/applets/software_keyboard.ui | 3503 | 
7 files changed, 5381 insertions, 160 deletions
| diff --git a/src/yuzu/applets/controller.cpp b/src/yuzu/applets/controller.cpp index b92cd6886..836d90fda 100644 --- a/src/yuzu/applets/controller.cpp +++ b/src/yuzu/applets/controller.cpp @@ -16,6 +16,7 @@  #include "yuzu/applets/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" @@ -206,6 +207,9 @@ QtControllerSelectorDialog::QtControllerSelectorDialog(      connect(ui->vibrationButton, &QPushButton::clicked, this,              &QtControllerSelectorDialog::CallConfigureVibrationDialog); +    connect(ui->motionButton, &QPushButton::clicked, this, +            &QtControllerSelectorDialog::CallConfigureMotionTouchDialog); +      connect(ui->inputConfigButton, &QPushButton::clicked, this,              &QtControllerSelectorDialog::CallConfigureInputProfileDialog); @@ -276,6 +280,18 @@ void QtControllerSelectorDialog::CallConfigureVibrationDialog() {      }  } +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()); diff --git a/src/yuzu/applets/controller.h b/src/yuzu/applets/controller.h index 3518eed56..9b57aea1a 100644 --- a/src/yuzu/applets/controller.h +++ b/src/yuzu/applets/controller.h @@ -51,6 +51,9 @@ private:      // Initializes the "Configure Vibration" Dialog.      void CallConfigureVibrationDialog(); +    // Initializes the "Configure Motion / Touch" Dialog. +    void CallConfigureMotionTouchDialog(); +      // Initializes the "Create Input Profile" Dialog.      void CallConfigureInputProfileDialog(); diff --git a/src/yuzu/applets/error.cpp b/src/yuzu/applets/error.cpp index 8ee03ddb3..085688cd4 100644 --- a/src/yuzu/applets/error.cpp +++ b/src/yuzu/applets/error.cpp @@ -19,11 +19,11 @@ QtErrorDisplay::~QtErrorDisplay() = default;  void QtErrorDisplay::ShowError(ResultCode error, std::function<void()> finished) const {      callback = std::move(finished);      emit MainWindowDisplayError( -        tr("An error has occurred.\nPlease try again or contact the developer of the " -           "software.\n\nError Code: %1-%2 (0x%3)") +        tr("Error Code: %1-%2 (0x%3)")              .arg(static_cast<u32>(error.module.Value()) + 2000, 4, 10, QChar::fromLatin1('0'))              .arg(error.description, 4, 10, QChar::fromLatin1('0')) -            .arg(error.raw, 8, 16, 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(ResultCode error, std::chrono::seconds time, @@ -32,13 +32,14 @@ void QtErrorDisplay::ShowErrorWithTimestamp(ResultCode error, std::chrono::secon      const QDateTime date_time = QDateTime::fromSecsSinceEpoch(time.count());      emit MainWindowDisplayError( -        tr("An error occurred on %1 at %2.\nPlease try again or contact the " -           "developer of the software.\n\nError Code: %3-%4 (0x%5)") -            .arg(date_time.toString(QStringLiteral("dddd, MMMM d, yyyy"))) -            .arg(date_time.toString(QStringLiteral("h:mm:ss A"))) +        tr("Error Code: %1-%2 (0x%3)")              .arg(static_cast<u32>(error.module.Value()) + 2000, 4, 10, QChar::fromLatin1('0'))              .arg(error.description, 4, 10, QChar::fromLatin1('0')) -            .arg(error.raw, 8, 16, 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(ResultCode error, std::string dialog_text, @@ -46,10 +47,11 @@ void QtErrorDisplay::ShowCustomErrorText(ResultCode error, std::string dialog_te                                           std::function<void()> finished) const {      callback = std::move(finished);      emit MainWindowDisplayError( -        tr("An error has occurred.\nError Code: %1-%2 (0x%3)\n\n%4\n\n%5") +        tr("Error Code: %1-%2 (0x%3)")              .arg(static_cast<u32>(error.module.Value()) + 2000, 4, 10, QChar::fromLatin1('0'))              .arg(error.description, 4, 10, QChar::fromLatin1('0')) -            .arg(error.raw, 8, 16, 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)));  } diff --git a/src/yuzu/applets/error.h b/src/yuzu/applets/error.h index b0932d895..8bd895a32 100644 --- a/src/yuzu/applets/error.h +++ b/src/yuzu/applets/error.h @@ -24,7 +24,7 @@ public:                               std::function<void()> finished) const override;  signals: -    void MainWindowDisplayError(QString error) const; +    void MainWindowDisplayError(QString error_code, QString error_text) const;  private:      void MainWindowFinishedError(); diff --git a/src/yuzu/applets/software_keyboard.cpp b/src/yuzu/applets/software_keyboard.cpp index ab8cfd8ee..fd3368479 100644 --- a/src/yuzu/applets/software_keyboard.cpp +++ b/src/yuzu/applets/software_keyboard.cpp @@ -1,153 +1,1641 @@ -// Copyright 2018 yuzu Emulator Project +// Copyright 2021 yuzu Emulator Project  // Licensed under GPLv2 or any later version  // Refer to the license.txt file included. -#include <algorithm> -#include <mutex> -#include <QDialogButtonBox> -#include <QFont> -#include <QLabel> -#include <QLineEdit> -#include <QVBoxLayout> -#include "core/hle/lock.h" +#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 "core/frontend/input_interpreter.h" +#include "ui_software_keyboard.h"  #include "yuzu/applets/software_keyboard.h"  #include "yuzu/main.h" +#include "yuzu/util/overlay_dialog.h" + +namespace { + +using namespace Service::AM::Applets; + +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, +            }, +        }}, +    }}; -QtSoftwareKeyboardValidator::QtSoftwareKeyboardValidator( -    Core::Frontend::SoftwareKeyboardParameters parameters) -    : parameters(std::move(parameters)) {} +    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, +        }, +        { +            nullptr, +            ui->button_0_num, +            nullptr, +            ui->button_ok_num, +        }, +    }}; -QValidator::State QtSoftwareKeyboardValidator::validate(QString& input, int& pos) const { -    if (input.size() > static_cast<s64>(parameters.max_length)) { -        return Invalid; +    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_0_num, +    }; + +    SetupMouseHover(); + +    if (!initialize_parameters.ok_text.empty()) { +        ui->button_ok->setText(QString::fromStdU16String(initialize_parameters.ok_text));      } -    if (parameters.disable_space && input.contains(QLatin1Char{' '})) { -        return Invalid; + +    ui->label_header->setText(QString::fromStdU16String(initialize_parameters.header_text)); +    ui->label_sub->setText(QString::fromStdU16String(initialize_parameters.sub_text)); + +    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); +            } +        });      } -    if (parameters.disable_address && input.contains(QLatin1Char{'@'})) { -        return Invalid; + +    // TODO (Morph): Remove this when InputInterpreter no longer relies on the HID backend +    if (system.IsPoweredOn()) { +        input_interpreter = std::make_unique<InputInterpreter>(system);      } -    if (parameters.disable_percent && input.contains(QLatin1Char{'%'})) { -        return Invalid; +} + +QtSoftwareKeyboardDialog::~QtSoftwareKeyboardDialog() { +    StopInputThread(); +} + +void QtSoftwareKeyboardDialog::ShowNormalKeyboard(QPoint pos, QSize size) { +    if (isVisible()) { +        return;      } -    if (parameters.disable_slash && -        (input.contains(QLatin1Char{'/'}) || input.contains(QLatin1Char{'\\'}))) { -        return Invalid; + +    MoveAndResizeWindow(pos, size); + +    SetKeyboardType(); +    SetPasswordMode(); +    SetControllerImage(); +    DisableKeyboardButtons(); +    SetBackspaceOkEnabled(); + +    open(); +} + +void QtSoftwareKeyboardDialog::ShowTextCheckDialog( +    Service::AM::Applets::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;      } -    if (parameters.disable_number && -        std::any_of(input.begin(), input.end(), [](QChar c) { return c.isDigit(); })) { -        return Invalid; +    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) { +            emit SubmitNormalText(SwkbdResult::Ok, current_text); +            break; +        } + +        StartInputThread(); +        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 = initialize_parameters.disable_cancel_button; -    if (parameters.disable_download_code && std::any_of(input.begin(), input.end(), [](QChar c) { -            return c == QLatin1Char{'O'} || c == QLatin1Char{'I'}; -        })) { -        return Invalid; +    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; + +    const auto* const curr_button = +        keyboard_buttons[static_cast<int>(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())); + +    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. +    if (is_inline) { +        emit SubmitInlineText(SwkbdReplyType::DecidedCancel, current_text, cursor_position); +    } else { +        emit SubmitNormalText(SwkbdResult::Cancel, current_text);      } +} + +void QtSoftwareKeyboardDialog::keyPressEvent(QKeyEvent* event) { +    if (!is_inline) { +        QDialog::keyPressEvent(event); +        return; +    } + +    const auto entered_key = event->key(); -    return Acceptable; +    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(entered_text.toStdU16String());  } -QtSoftwareKeyboardDialog::QtSoftwareKeyboardDialog( -    QWidget* parent, Core::Frontend::SoftwareKeyboardParameters parameters_) -    : QDialog(parent), parameters(std::move(parameters_)) { -    layout = new QVBoxLayout; - -    header_label = new QLabel(QString::fromStdU16String(parameters.header_text)); -    header_label->setFont({header_label->font().family(), 11, QFont::Bold}); -    if (header_label->text().isEmpty()) -        header_label->setText(tr("Enter text:")); - -    sub_label = new QLabel(QString::fromStdU16String(parameters.sub_text)); -    sub_label->setFont({sub_label->font().family(), sub_label->font().pointSize(), -                        sub_label->font().weight(), true}); -    sub_label->setHidden(parameters.sub_text.empty()); - -    guide_label = new QLabel(QString::fromStdU16String(parameters.guide_text)); -    guide_label->setHidden(parameters.guide_text.empty()); - -    length_label = new QLabel(QStringLiteral("0/%1").arg(parameters.max_length)); -    length_label->setAlignment(Qt::AlignRight); -    length_label->setFont({length_label->font().family(), 8}); - -    line_edit = new QLineEdit; -    line_edit->setValidator(new QtSoftwareKeyboardValidator(parameters)); -    line_edit->setMaxLength(static_cast<int>(parameters.max_length)); -    line_edit->setText(QString::fromStdU16String(parameters.initial_text)); -    line_edit->setCursorPosition( -        parameters.cursor_at_beginning ? 0 : static_cast<int>(parameters.initial_text.size())); -    line_edit->setEchoMode(parameters.password ? QLineEdit::Password : QLineEdit::Normal); - -    connect(line_edit, &QLineEdit::textChanged, this, [this](const QString& text) { -        length_label->setText(QStringLiteral("%1/%2").arg(text.size()).arg(parameters.max_length)); -    }); - -    buttons = new QDialogButtonBox(QDialogButtonBox::Cancel); -    if (parameters.submit_text.empty()) { -        buttons->addButton(QDialogButtonBox::Ok); +void QtSoftwareKeyboardDialog::MoveAndResizeWindow(QPoint pos, QSize size) { +    QDialog::move(pos); +    QDialog::resize(size); + +    // High DPI +    const float dpi_scale = qApp->screenAt(pos)->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] { +            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; +            } +        }); + +        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 controller_type = Settings::values.players.GetValue()[8].connected +                                     ? Settings::values.players.GetValue()[8].controller_type +                                     : Settings::values.players.GetValue()[0].controller_type; + +    const QString theme = [] { +        if (QIcon::themeName().contains(QStringLiteral("dark")) || +            QIcon::themeName().contains(QStringLiteral("midnight"))) { +            return QStringLiteral("_dark"); +        } else { +            return QString{}; +        } +    }(); + +    switch (controller_type) { +    case Settings::ControllerType::ProController: +    case Settings::ControllerType::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 Settings::ControllerType::DualJoyconDetached: +        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 Settings::ControllerType::LeftJoycon: +        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 Settings::ControllerType::RightJoycon: +        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 Settings::ControllerType::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); +            } +        } +        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 { -        buttons->addButton(QString::fromStdU16String(parameters.submit_text), -                           QDialogButtonBox::AcceptRole); +        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);      } -    connect(buttons, &QDialogButtonBox::accepted, this, &QtSoftwareKeyboardDialog::accept); -    connect(buttons, &QDialogButtonBox::rejected, this, &QtSoftwareKeyboardDialog::reject); -    layout->addWidget(header_label); -    layout->addWidget(sub_label); -    layout->addWidget(guide_label); -    layout->addWidget(length_label); -    layout->addWidget(line_edit); -    layout->addWidget(buttons); -    setLayout(layout); -    setWindowTitle(tr("Software Keyboard"));  } -QtSoftwareKeyboardDialog::~QtSoftwareKeyboardDialog() = default; +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; +    } -void QtSoftwareKeyboardDialog::accept() { -    text = line_edit->text().toStdU16String(); -    QDialog::accept(); +    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(), [](QChar c) { return !c.isDigit(); })) { +        return false; +    } + +    return true;  } -void QtSoftwareKeyboardDialog::reject() { -    text.clear(); -    QDialog::reject(); +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("background-image: url(:/overlay/osk_button_shift_lock_off.png);" +                           "\nbackground-position: left top;" +                           "\nbackground-repeat: no-repeat;" +                           "\nbackground-origin: content;")); + +        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("background-image: url(:/overlay/osk_button_shift_lock_off.png);" +                               "\nbackground-position: left top;" +                               "\nbackground-repeat: no-repeat;" +                               "\nbackground-origin: content;")); + +            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("background-image: url(:/overlay/osk_button_shift_lock_on.png);" +                               "\nbackground-position: left top;" +                               "\nbackground-repeat: no-repeat;" +                               "\nbackground-origin: content;")); + +            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; +    }  } -std::u16string QtSoftwareKeyboardDialog::GetText() const { -    return text; +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) { +        if (ui->topOSK->currentIndex() == 1) { +            emit SubmitNormalText(SwkbdResult::Ok, +                                  ui->text_edit_osk->toPlainText().toStdU16String()); +        } else { +            emit SubmitNormalText(SwkbdResult::Ok, ui->line_edit_osk->text().toStdU16String()); +        } +        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; +    } + +    InlineTextInsertString(button->text().toStdU16String()); + +    // 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 <HIDButton... T> +void QtSoftwareKeyboardDialog::HandleButtonPressedOnce() { +    const auto f = [this](HIDButton button) { +        if (input_interpreter->IsButtonPressedOnce(button)) { +            TranslateButtonPress(button); +        } +    }; + +    (f(T), ...); +} + +template <HIDButton... T> +void QtSoftwareKeyboardDialog::HandleButtonHold() { +    const auto f = [this](HIDButton button) { +        if (input_interpreter->IsButtonHeld(button)) { +            TranslateButtonPress(button); +        } +    }; + +    (f(T), ...); +} + +void QtSoftwareKeyboardDialog::TranslateButtonPress(HIDButton button) { +    switch (button) { +    case HIDButton::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 HIDButton::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 HIDButton::X: +        if (is_inline) { +            emit SubmitInlineText(SwkbdReplyType::DecidedCancel, current_text, cursor_position); +        } else { +            if (ui->topOSK->currentIndex() == 1) { +                emit SubmitNormalText(SwkbdResult::Cancel, +                                      ui->text_edit_osk->toPlainText().toStdU16String()); +            } else { +                emit SubmitNormalText(SwkbdResult::Cancel, +                                      ui->line_edit_osk->text().toStdU16String()); +            } +        } +        break; +    case HIDButton::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 HIDButton::LStick: +    case HIDButton::RStick: +        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 HIDButton::L: +        MoveTextCursorDirection(Direction::Left); +        break; +    case HIDButton::R: +        MoveTextCursorDirection(Direction::Right); +        break; +    case HIDButton::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 HIDButton::DLeft: +    case HIDButton::LStickLeft: +    case HIDButton::RStickLeft: +        MoveButtonDirection(Direction::Left); +        break; +    case HIDButton::DUp: +    case HIDButton::LStickUp: +    case HIDButton::RStickUp: +        MoveButtonDirection(Direction::Up); +        break; +    case HIDButton::DRight: +    case HIDButton::LStickRight: +    case HIDButton::RStickRight: +        MoveButtonDirection(Direction::Right); +        break; +    case HIDButton::DDown: +    case HIDButton::LStickDown: +    case HIDButton::RStickDown: +        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; +        } +    }; + +    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) { +            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) { +            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<HIDButton::A, HIDButton::B, HIDButton::X, HIDButton::Y, +                                HIDButton::LStick, HIDButton::RStick, HIDButton::L, HIDButton::R, +                                HIDButton::Plus, HIDButton::DLeft, HIDButton::DUp, +                                HIDButton::DRight, HIDButton::DDown, HIDButton::LStickLeft, +                                HIDButton::LStickUp, HIDButton::LStickRight, HIDButton::LStickDown, +                                HIDButton::RStickLeft, HIDButton::RStickUp, HIDButton::RStickRight, +                                HIDButton::RStickDown>(); + +        HandleButtonHold<HIDButton::B, HIDButton::L, HIDButton::R, HIDButton::DLeft, HIDButton::DUp, +                         HIDButton::DRight, HIDButton::DDown, HIDButton::LStickLeft, +                         HIDButton::LStickUp, HIDButton::LStickRight, HIDButton::LStickDown, +                         HIDButton::RStickLeft, HIDButton::RStickUp, HIDButton::RStickRight, +                         HIDButton::RStickDown>(); + +        std::this_thread::sleep_for(std::chrono::milliseconds(50)); +    }  }  QtSoftwareKeyboard::QtSoftwareKeyboard(GMainWindow& main_window) { -    connect(this, &QtSoftwareKeyboard::MainWindowGetText, &main_window, -            &GMainWindow::SoftwareKeyboardGetText, Qt::QueuedConnection); -    connect(this, &QtSoftwareKeyboard::MainWindowTextCheckDialog, &main_window, -            &GMainWindow::SoftwareKeyboardInvokeCheckDialog, Qt::BlockingQueuedConnection); -    connect(&main_window, &GMainWindow::SoftwareKeyboardFinishedText, this, -            &QtSoftwareKeyboard::MainWindowFinishedText, Qt::QueuedConnection); +    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::RequestText(std::function<void(std::optional<std::u16string>)> out, -                                     Core::Frontend::SoftwareKeyboardParameters parameters) const { -    text_output = std::move(out); -    emit MainWindowGetText(parameters); +void QtSoftwareKeyboard::InitializeKeyboard( +    bool is_inline, Core::Frontend::KeyboardInitializeParameters initialize_parameters, +    std::function<void(Service::AM::Applets::SwkbdResult, std::u16string)> submit_normal_callback_, +    std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)> +        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::Applets::SwkbdTextCheckResult text_check_result, +    std::u16string text_check_message) const { +    emit MainWindowShowTextCheckDialog(text_check_result, 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::SendTextCheckDialog(std::u16string error_message, -                                             std::function<void()> finished_check_) const { -    finished_check = std::move(finished_check_); -    emit MainWindowTextCheckDialog(error_message); +void QtSoftwareKeyboard::ExitKeyboard() const { +    emit MainWindowExitKeyboard();  } -void QtSoftwareKeyboard::MainWindowFinishedText(std::optional<std::u16string> text) { -    // Acquire the HLE mutex -    std::lock_guard lock{HLE::g_hle_lock}; -    text_output(std::move(text)); +void QtSoftwareKeyboard::SubmitNormalText(Service::AM::Applets::SwkbdResult result, +                                          std::u16string submitted_text) const { +    submit_normal_callback(result, submitted_text);  } -void QtSoftwareKeyboard::MainWindowFinishedCheckDialog() { -    // Acquire the HLE mutex -    std::lock_guard lock{HLE::g_hle_lock}; -    finished_check(); +void QtSoftwareKeyboard::SubmitInlineText(Service::AM::Applets::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/software_keyboard.h b/src/yuzu/applets/software_keyboard.h index 9e1094cce..1a03c098c 100644 --- a/src/yuzu/applets/software_keyboard.h +++ b/src/yuzu/applets/software_keyboard.h @@ -1,54 +1,228 @@ -// Copyright 2018 yuzu Emulator Project +// Copyright 2021 yuzu Emulator Project  // Licensed under GPLv2 or any later version  // Refer to the license.txt file included.  #pragma once +#include <array> +#include <atomic> +#include <memory> +#include <thread> +  #include <QDialog>  #include <QValidator> +  #include "core/frontend/applets/software_keyboard.h" -class GMainWindow; -class QDialogButtonBox; -class QLabel; -class QLineEdit; -class QVBoxLayout; -class QtSoftwareKeyboard; +enum class HIDButton : u8; -class QtSoftwareKeyboardValidator final : public QValidator { -public: -    explicit QtSoftwareKeyboardValidator(Core::Frontend::SoftwareKeyboardParameters parameters); -    State validate(QString& input, int& pos) const override; +class InputInterpreter; -private: -    Core::Frontend::SoftwareKeyboardParameters parameters; -}; +namespace Core { +class System; +} + +namespace Ui { +class QtSoftwareKeyboardDialog; +} + +class GMainWindow;  class QtSoftwareKeyboardDialog final : public QDialog {      Q_OBJECT  public: -    QtSoftwareKeyboardDialog(QWidget* parent, -                             Core::Frontend::SoftwareKeyboardParameters parameters); +    QtSoftwareKeyboardDialog(QWidget* parent, Core::System& system_, bool is_inline_, +                             Core::Frontend::KeyboardInitializeParameters initialize_parameters_);      ~QtSoftwareKeyboardDialog() override; -    void accept() override; +    void ShowNormalKeyboard(QPoint pos, QSize size); + +    void ShowTextCheckDialog(Service::AM::Applets::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::Applets::SwkbdResult result, +                          std::u16string submitted_text) const; + +    void SubmitInlineText(Service::AM::Applets::SwkbdReplyType reply_type, +                          std::u16string submitted_text, s32 cursor_position) const; + +public slots: +    void open() override;      void reject() override; -    std::u16string GetText() const; +protected: +    /// We override the keyPressEvent for inputting text into the inline software keyboard. +    void keyPressEvent(QKeyEvent* event) override;  private: -    std::u16string text; +    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); -    QDialogButtonBox* buttons; -    QLabel* header_label; -    QLabel* sub_label; -    QLabel* guide_label; -    QLabel* length_label; -    QLineEdit* line_edit; -    QVBoxLayout* layout; +    /// Setup the mouse hover workaround for "focusing" buttons. This should only be called once. +    void SetupMouseHover(); -    Core::Frontend::SoftwareKeyboardParameters parameters; +    /** +     * Handles button presses and converts them into keyboard input. +     * +     * @tparam HIDButton The list of buttons that can be converted into keyboard input. +     */ +    template <HIDButton... 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 <HIDButton... T> +    void HandleButtonHold(); + +    /** +     * Translates a button press to focus or click a keyboard button. +     * +     * @param button The button press to process. +     */ +    void TranslateButtonPress(HIDButton 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*, 110> 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 { @@ -58,19 +232,54 @@ public:      explicit QtSoftwareKeyboard(GMainWindow& parent);      ~QtSoftwareKeyboard() override; -    void RequestText(std::function<void(std::optional<std::u16string>)> out, -                     Core::Frontend::SoftwareKeyboardParameters parameters) const override; -    void SendTextCheckDialog(std::u16string error_message, -                             std::function<void()> finished_check_) const override; +    void InitializeKeyboard( +        bool is_inline, Core::Frontend::KeyboardInitializeParameters initialize_parameters, +        std::function<void(Service::AM::Applets::SwkbdResult, std::u16string)> +            submit_normal_callback_, +        std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)> +            submit_inline_callback_) override; + +    void ShowNormalKeyboard() const override; + +    void ShowTextCheckDialog(Service::AM::Applets::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 MainWindowGetText(Core::Frontend::SoftwareKeyboardParameters parameters) const; -    void MainWindowTextCheckDialog(std::u16string error_message) const; +    void MainWindowInitializeKeyboard( +        bool is_inline, Core::Frontend::KeyboardInitializeParameters initialize_parameters) const; + +    void MainWindowShowNormalKeyboard() const; + +    void MainWindowShowTextCheckDialog(Service::AM::Applets::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 MainWindowFinishedText(std::optional<std::u16string> text); -    void MainWindowFinishedCheckDialog(); +    void SubmitNormalText(Service::AM::Applets::SwkbdResult result, +                          std::u16string submitted_text) const; + +    void SubmitInlineText(Service::AM::Applets::SwkbdReplyType reply_type, +                          std::u16string submitted_text, s32 cursor_position) const; -    mutable std::function<void(std::optional<std::u16string>)> text_output; -    mutable std::function<void()> finished_check; +    mutable std::function<void(Service::AM::Applets::SwkbdResult, std::u16string)> +        submit_normal_callback; +    mutable std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)> +        submit_inline_callback;  }; diff --git a/src/yuzu/applets/software_keyboard.ui b/src/yuzu/applets/software_keyboard.ui new file mode 100644 index 000000000..b0a1fcde9 --- /dev/null +++ b/src/yuzu/applets/software_keyboard.ui @@ -0,0 +1,3503 @@ +<?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="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="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_0_num</tabstop> + </tabstops> + <resources> +  <include location="../../../dist/icons/overlay/overlay.qrc"/> + </resources> + <connections/> +</ui> | 
