From 5454494adbfad3148e75b45653a255004ca989b3 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Fri, 9 Nov 2018 20:13:15 -0500 Subject: 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/applets/software_keyboard.cpp | 107 +++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 src/yuzu/applets/software_keyboard.cpp (limited to 'src/yuzu/applets/software_keyboard.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; +} -- cgit v1.2.3 From a81645400f9ba40b272163ef6f751ba3428b85a1 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Fri, 9 Nov 2018 20:38:11 -0500 Subject: qt/main: Register Qt Software Keyboard frontend with AM Allows using Qt provider over default. --- src/yuzu/applets/software_keyboard.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/yuzu/applets/software_keyboard.cpp') diff --git a/src/yuzu/applets/software_keyboard.cpp b/src/yuzu/applets/software_keyboard.cpp index 9e1c59626..bd8bd0dd0 100644 --- a/src/yuzu/applets/software_keyboard.cpp +++ b/src/yuzu/applets/software_keyboard.cpp @@ -9,6 +9,7 @@ #include #include #include "common/logging/backend.h" +#include "common/string_util.h" #include "yuzu/applets/software_keyboard.h" QtSoftwareKeyboardValidator::QtSoftwareKeyboardValidator( -- cgit v1.2.3 From e696ed1f4d20f28f8b26c637498962938df7d96f Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Sun, 11 Nov 2018 16:39:25 -0500 Subject: am: Deglobalize software keyboard applet --- src/yuzu/applets/software_keyboard.cpp | 55 ++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 19 deletions(-) (limited to 'src/yuzu/applets/software_keyboard.cpp') diff --git a/src/yuzu/applets/software_keyboard.cpp b/src/yuzu/applets/software_keyboard.cpp index bd8bd0dd0..fad150ec1 100644 --- a/src/yuzu/applets/software_keyboard.cpp +++ b/src/yuzu/applets/software_keyboard.cpp @@ -2,21 +2,20 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include +#include #include #include #include #include #include -#include "common/logging/backend.h" -#include "common/string_util.h" #include "yuzu/applets/software_keyboard.h" +#include "yuzu/main.h" QtSoftwareKeyboardValidator::QtSoftwareKeyboardValidator( - Frontend::SoftwareKeyboardApplet::Parameters parameters) + Core::Frontend::SoftwareKeyboardParameters parameters) : parameters(std::move(parameters)) {} -QValidator::State QtSoftwareKeyboardValidator::validate(QString& input, int&) const { +QValidator::State QtSoftwareKeyboardValidator::validate(QString& input, int& pos) const { if (input.size() > parameters.max_length) return Invalid; if (parameters.disable_space && input.contains(' ')) @@ -28,18 +27,20 @@ QValidator::State QtSoftwareKeyboardValidator::validate(QString& input, int&) co 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(); })) + 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'; })) + 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_) + QWidget* parent, Core::Frontend::SoftwareKeyboardParameters parameters_) : QDialog(parent), parameters(std::move(parameters_)) { layout = new QVBoxLayout; @@ -79,9 +80,11 @@ QtSoftwareKeyboardDialog::QtSoftwareKeyboardDialog( layout->addWidget(line_edit); layout->addWidget(buttons); setLayout(layout); - setWindowTitle("Software Keyboard"); + setWindowTitle(tr("Software Keyboard")); } +QtSoftwareKeyboardDialog::~QtSoftwareKeyboardDialog() = default; + void QtSoftwareKeyboardDialog::Submit() { ok = true; text = line_edit->text().toStdU16String(); @@ -90,19 +93,33 @@ void QtSoftwareKeyboardDialog::Submit() { void QtSoftwareKeyboardDialog::Reject() { ok = false; - text = Common::UTF8ToUTF16(""); + text.clear(); accept(); } -QtSoftwareKeyboard::QtSoftwareKeyboard(QWidget& parent) : parent(parent) {} +std::u16string QtSoftwareKeyboardDialog::GetText() { + return text; +} + +bool QtSoftwareKeyboardDialog::GetStatus() { + return ok; +} -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(); +QtSoftwareKeyboard::QtSoftwareKeyboard(GMainWindow& parent) : main_window(parent) {} + +QtSoftwareKeyboard::~QtSoftwareKeyboard() = default; + +bool QtSoftwareKeyboard::GetText(Core::Frontend::SoftwareKeyboardParameters parameters, + std::u16string& text) const { + bool success; + QMetaObject::invokeMethod(&main_window, "SoftwareKeyboardGetText", Qt::BlockingQueuedConnection, + Q_RETURN_ARG(bool, success), + Q_ARG(Core::Frontend::SoftwareKeyboardParameters, parameters), + Q_ARG(std::u16string&, text)); + return success; +} - text = dialog.text; - return dialog.ok; +void QtSoftwareKeyboard::SendTextCheckDialog(std::u16string error_message) const { + QMetaObject::invokeMethod(&main_window, "SoftwareKeyboardInvokeCheckDialog", + Qt::BlockingQueuedConnection, Q_ARG(std::u16string, error_message)); } -- cgit v1.2.3 From 7cfb29de23836aa1873bbb108e3d25a0e9dcfa6d Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Sun, 11 Nov 2018 20:16:38 -0500 Subject: am: Allow applets to push multiple and different channels of data --- src/yuzu/applets/software_keyboard.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'src/yuzu/applets/software_keyboard.cpp') diff --git a/src/yuzu/applets/software_keyboard.cpp b/src/yuzu/applets/software_keyboard.cpp index fad150ec1..92992ef87 100644 --- a/src/yuzu/applets/software_keyboard.cpp +++ b/src/yuzu/applets/software_keyboard.cpp @@ -97,11 +97,11 @@ void QtSoftwareKeyboardDialog::Reject() { accept(); } -std::u16string QtSoftwareKeyboardDialog::GetText() { +std::u16string QtSoftwareKeyboardDialog::GetText() const { return text; } -bool QtSoftwareKeyboardDialog::GetStatus() { +bool QtSoftwareKeyboardDialog::GetStatus() const { return ok; } @@ -109,13 +109,12 @@ QtSoftwareKeyboard::QtSoftwareKeyboard(GMainWindow& parent) : main_window(parent QtSoftwareKeyboard::~QtSoftwareKeyboard() = default; -bool QtSoftwareKeyboard::GetText(Core::Frontend::SoftwareKeyboardParameters parameters, - std::u16string& text) const { - bool success; +std::optional QtSoftwareKeyboard::GetText( + Core::Frontend::SoftwareKeyboardParameters parameters) const { + std::optional success; QMetaObject::invokeMethod(&main_window, "SoftwareKeyboardGetText", Qt::BlockingQueuedConnection, - Q_RETURN_ARG(bool, success), - Q_ARG(Core::Frontend::SoftwareKeyboardParameters, parameters), - Q_ARG(std::u16string&, text)); + Q_RETURN_ARG(std::optional, success), + Q_ARG(Core::Frontend::SoftwareKeyboardParameters, parameters)); return success; } -- cgit v1.2.3 From 8b433beff34c382e50334bb59c4f71394845558c Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Mon, 12 Nov 2018 11:08:09 -0500 Subject: software_keyboard: Make GetText asynchronous a --- src/yuzu/applets/software_keyboard.cpp | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) (limited to 'src/yuzu/applets/software_keyboard.cpp') diff --git a/src/yuzu/applets/software_keyboard.cpp b/src/yuzu/applets/software_keyboard.cpp index 92992ef87..9fb179f5c 100644 --- a/src/yuzu/applets/software_keyboard.cpp +++ b/src/yuzu/applets/software_keyboard.cpp @@ -105,20 +105,27 @@ bool QtSoftwareKeyboardDialog::GetStatus() const { return ok; } -QtSoftwareKeyboard::QtSoftwareKeyboard(GMainWindow& parent) : main_window(parent) {} +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); +} QtSoftwareKeyboard::~QtSoftwareKeyboard() = default; -std::optional QtSoftwareKeyboard::GetText( - Core::Frontend::SoftwareKeyboardParameters parameters) const { - std::optional success; - QMetaObject::invokeMethod(&main_window, "SoftwareKeyboardGetText", Qt::BlockingQueuedConnection, - Q_RETURN_ARG(std::optional, success), - Q_ARG(Core::Frontend::SoftwareKeyboardParameters, parameters)); - return success; +void QtSoftwareKeyboard::RequestText(std::function)> out, + Core::Frontend::SoftwareKeyboardParameters parameters) const { + text_output = out; + emit MainWindowGetText(parameters); } void QtSoftwareKeyboard::SendTextCheckDialog(std::u16string error_message) const { - QMetaObject::invokeMethod(&main_window, "SoftwareKeyboardInvokeCheckDialog", - Qt::BlockingQueuedConnection, Q_ARG(std::u16string, error_message)); + emit MainWindowTextCheckDialog(error_message); +} + +void QtSoftwareKeyboard::MainWindowFinishedText(std::optional text) { + text_output(text); } -- cgit v1.2.3 From 19b2571aecfff680c7a414c505eafc26264b6f2f Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Sat, 17 Nov 2018 12:18:03 -0500 Subject: applet: Add operation completed callback --- src/yuzu/applets/software_keyboard.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'src/yuzu/applets/software_keyboard.cpp') diff --git a/src/yuzu/applets/software_keyboard.cpp b/src/yuzu/applets/software_keyboard.cpp index 9fb179f5c..83b9c320b 100644 --- a/src/yuzu/applets/software_keyboard.cpp +++ b/src/yuzu/applets/software_keyboard.cpp @@ -3,11 +3,13 @@ // Refer to the license.txt file included. #include +#include #include #include #include #include #include +#include "core/hle/lock.h" #include "yuzu/applets/software_keyboard.h" #include "yuzu/main.h" @@ -122,10 +124,20 @@ void QtSoftwareKeyboard::RequestText(std::function finished_check) const { + this->finished_check = finished_check; emit MainWindowTextCheckDialog(error_message); } void QtSoftwareKeyboard::MainWindowFinishedText(std::optional text) { + // Acquire the HLE mutex + std::lock_guard lock(HLE::g_hle_lock); text_output(text); } + +void QtSoftwareKeyboard::MainWindowFinishedCheckDialog() { + // Acquire the HLE mutex + std::lock_guard lock(HLE::g_hle_lock); + finished_check(); +} -- cgit v1.2.3 From 56cf5b7b17cd87f4a23bd45ae661762ce1fda5d1 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Sat, 17 Nov 2018 14:44:16 -0500 Subject: software_keyboard: Add max and current length display to dialog --- src/yuzu/applets/software_keyboard.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'src/yuzu/applets/software_keyboard.cpp') diff --git a/src/yuzu/applets/software_keyboard.cpp b/src/yuzu/applets/software_keyboard.cpp index 83b9c320b..efefb1f99 100644 --- a/src/yuzu/applets/software_keyboard.cpp +++ b/src/yuzu/applets/software_keyboard.cpp @@ -47,7 +47,7 @@ QtSoftwareKeyboardDialog::QtSoftwareKeyboardDialog( layout = new QVBoxLayout; header_label = new QLabel(QString::fromStdU16String(parameters.header_text)); - header_label->setFont({header_label->font().family(), 12, QFont::Bold}); + header_label->setFont({header_label->font().family(), 11, QFont::Bold}); if (header_label->text().isEmpty()) header_label->setText(tr("Enter text:")); @@ -59,6 +59,10 @@ QtSoftwareKeyboardDialog::QtSoftwareKeyboardDialog( 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(parameters.max_length)); @@ -67,6 +71,10 @@ QtSoftwareKeyboardDialog::QtSoftwareKeyboardDialog( parameters.cursor_at_beginning ? 0 : static_cast(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; buttons->addButton(tr("Cancel"), QDialogButtonBox::RejectRole); buttons->addButton(parameters.submit_text.empty() @@ -79,6 +87,7 @@ QtSoftwareKeyboardDialog::QtSoftwareKeyboardDialog( 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); -- cgit v1.2.3