From 5454494adbfad3148e75b45653a255004ca989b3 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Fri, 9 Nov 2018 20:13:15 -0500 Subject: [PATCH] qt/applets: Provide Qt frontend implementation of software keyboard Implements all of the features of the keyboard, including length, default text, character validation, and UTF-16 character support. --- src/yuzu/CMakeLists.txt | 2 + src/yuzu/applets/software_keyboard.cpp | 107 +++++++++++++++++++++++++ src/yuzu/applets/software_keyboard.h | 62 ++++++++++++++ 3 files changed, 171 insertions(+) create mode 100644 src/yuzu/applets/software_keyboard.cpp create mode 100644 src/yuzu/applets/software_keyboard.h diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index f9ca2948e..53c7f00d4 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt @@ -7,6 +7,8 @@ add_executable(yuzu Info.plist about_dialog.cpp about_dialog.h + applets/software_keyboard.cpp + applets/software_keyboard.h bootmanager.cpp bootmanager.h compatibility_list.cpp diff --git a/src/yuzu/applets/software_keyboard.cpp b/src/yuzu/applets/software_keyboard.cpp new file mode 100644 index 000000000..9e1c59626 --- /dev/null +++ b/src/yuzu/applets/software_keyboard.cpp @@ -0,0 +1,107 @@ +// Copyright 2018 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include +#include +#include +#include +#include +#include +#include "common/logging/backend.h" +#include "yuzu/applets/software_keyboard.h" + +QtSoftwareKeyboardValidator::QtSoftwareKeyboardValidator( + Frontend::SoftwareKeyboardApplet::Parameters parameters) + : parameters(std::move(parameters)) {} + +QValidator::State QtSoftwareKeyboardValidator::validate(QString& input, int&) const { + if (input.size() > parameters.max_length) + return Invalid; + if (parameters.disable_space && input.contains(' ')) + return Invalid; + if (parameters.disable_address && input.contains('@')) + return Invalid; + if (parameters.disable_percent && input.contains('%')) + return Invalid; + if (parameters.disable_slash && (input.contains('/') || input.contains('\\'))) + return Invalid; + if (parameters.disable_number && + std::any_of(input.begin(), input.end(), [](QChar c) { return c.isDigit(); })) + return Invalid; + + if (parameters.disable_download_code && + std::any_of(input.begin(), input.end(), [](QChar c) { return c == 'O' || c == 'I'; })) + return Invalid; + + return Acceptable; +} + +QtSoftwareKeyboardDialog::QtSoftwareKeyboardDialog( + QWidget* parent, Frontend::SoftwareKeyboardApplet::Parameters 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(), 12, 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()); + + line_edit = new QLineEdit; + line_edit->setValidator(new QtSoftwareKeyboardValidator(parameters)); + line_edit->setMaxLength(static_cast(parameters.max_length)); + line_edit->setText(QString::fromStdU16String(parameters.initial_text)); + line_edit->setCursorPosition( + parameters.cursor_at_beginning ? 0 : static_cast(parameters.initial_text.size())); + line_edit->setEchoMode(parameters.password ? QLineEdit::Password : QLineEdit::Normal); + + buttons = new QDialogButtonBox; + buttons->addButton(tr("Cancel"), QDialogButtonBox::RejectRole); + buttons->addButton(parameters.submit_text.empty() + ? tr("OK") + : QString::fromStdU16String(parameters.submit_text), + QDialogButtonBox::AcceptRole); + + connect(buttons, &QDialogButtonBox::accepted, this, &QtSoftwareKeyboardDialog::Submit); + connect(buttons, &QDialogButtonBox::rejected, this, &QtSoftwareKeyboardDialog::Reject); + layout->addWidget(header_label); + layout->addWidget(sub_label); + layout->addWidget(guide_label); + layout->addWidget(line_edit); + layout->addWidget(buttons); + setLayout(layout); + setWindowTitle("Software Keyboard"); +} + +void QtSoftwareKeyboardDialog::Submit() { + ok = true; + text = line_edit->text().toStdU16String(); + accept(); +} + +void QtSoftwareKeyboardDialog::Reject() { + ok = false; + text = Common::UTF8ToUTF16(""); + accept(); +} + +QtSoftwareKeyboard::QtSoftwareKeyboard(QWidget& parent) : parent(parent) {} + +bool QtSoftwareKeyboard::GetText(Parameters parameters, std::u16string& text) { + QtSoftwareKeyboardDialog dialog(&parent, parameters); + dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint | + Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint); + dialog.setWindowModality(Qt::WindowModal); + dialog.exec(); + + text = dialog.text; + return dialog.ok; +} diff --git a/src/yuzu/applets/software_keyboard.h b/src/yuzu/applets/software_keyboard.h new file mode 100644 index 000000000..2a18419db --- /dev/null +++ b/src/yuzu/applets/software_keyboard.h @@ -0,0 +1,62 @@ +// Copyright 2018 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once +#include +#include +#include "common/assert.h" +#include "core/frontend/applets/software_keyboard.h" + +class QDialogButtonBox; +class QLabel; +class QLineEdit; +class QVBoxLayout; +class QtSoftwareKeyboard; + +class QtSoftwareKeyboardValidator final : public QValidator { +public: + explicit QtSoftwareKeyboardValidator(Frontend::SoftwareKeyboardApplet::Parameters parameters); + State validate(QString&, int&) const override; + +private: + Frontend::SoftwareKeyboardApplet::Parameters parameters; +}; + +class QtSoftwareKeyboardDialog final : public QDialog { + Q_OBJECT + +public: + QtSoftwareKeyboardDialog(QWidget* parent, + Frontend::SoftwareKeyboardApplet::Parameters parameters); + void Submit(); + void Reject(); + +private: + bool ok = false; + std::u16string text; + + QDialogButtonBox* buttons; + QLabel* header_label; + QLabel* sub_label; + QLabel* guide_label; + QLineEdit* line_edit; + QVBoxLayout* layout; + + Frontend::SoftwareKeyboardApplet::Parameters parameters; + + friend class QtSoftwareKeyboard; +}; + +class QtSoftwareKeyboard final : public QObject, public Frontend::SoftwareKeyboardApplet { +public: + explicit QtSoftwareKeyboard(QWidget& parent); + bool GetText(Parameters parameters, std::u16string& text) override; + + ~QtSoftwareKeyboard() { + UNREACHABLE(); + } + +private: + QWidget& parent; +};