2018-11-10 01:13:15 +00:00
|
|
|
// Copyright 2018 yuzu Emulator Project
|
|
|
|
// Licensed under GPLv2 or any later version
|
|
|
|
// Refer to the license.txt file included.
|
|
|
|
|
2018-11-11 21:39:25 +00:00
|
|
|
#include <algorithm>
|
2018-11-17 17:18:03 +00:00
|
|
|
#include <mutex>
|
2018-11-10 01:13:15 +00:00
|
|
|
#include <QDialogButtonBox>
|
|
|
|
#include <QFont>
|
|
|
|
#include <QLabel>
|
|
|
|
#include <QLineEdit>
|
|
|
|
#include <QVBoxLayout>
|
2018-11-17 17:18:03 +00:00
|
|
|
#include "core/hle/lock.h"
|
2018-11-10 01:13:15 +00:00
|
|
|
#include "yuzu/applets/software_keyboard.h"
|
2018-11-11 21:39:25 +00:00
|
|
|
#include "yuzu/main.h"
|
2018-11-10 01:13:15 +00:00
|
|
|
|
|
|
|
QtSoftwareKeyboardValidator::QtSoftwareKeyboardValidator(
|
2018-11-11 21:39:25 +00:00
|
|
|
Core::Frontend::SoftwareKeyboardParameters parameters)
|
2018-11-10 01:13:15 +00:00
|
|
|
: parameters(std::move(parameters)) {}
|
|
|
|
|
2018-11-11 21:39:25 +00:00
|
|
|
QValidator::State QtSoftwareKeyboardValidator::validate(QString& input, int& pos) const {
|
2019-05-25 01:00:26 +00:00
|
|
|
if (input.size() > static_cast<s64>(parameters.max_length)) {
|
2018-11-10 01:13:15 +00:00
|
|
|
return Invalid;
|
2019-05-25 00:56:58 +00:00
|
|
|
}
|
|
|
|
if (parameters.disable_space && input.contains(QLatin1Char{' '})) {
|
2018-11-10 01:13:15 +00:00
|
|
|
return Invalid;
|
2019-05-25 00:56:58 +00:00
|
|
|
}
|
|
|
|
if (parameters.disable_address && input.contains(QLatin1Char{'@'})) {
|
2018-11-10 01:13:15 +00:00
|
|
|
return Invalid;
|
2019-05-25 00:56:58 +00:00
|
|
|
}
|
|
|
|
if (parameters.disable_percent && input.contains(QLatin1Char{'%'})) {
|
2018-11-10 01:13:15 +00:00
|
|
|
return Invalid;
|
2019-05-25 00:56:58 +00:00
|
|
|
}
|
|
|
|
if (parameters.disable_slash &&
|
|
|
|
(input.contains(QLatin1Char{'/'}) || input.contains(QLatin1Char{'\\'}))) {
|
2018-11-10 01:13:15 +00:00
|
|
|
return Invalid;
|
2019-05-25 00:56:58 +00:00
|
|
|
}
|
2018-11-10 01:13:15 +00:00
|
|
|
if (parameters.disable_number &&
|
2018-11-11 21:39:25 +00:00
|
|
|
std::any_of(input.begin(), input.end(), [](QChar c) { return c.isDigit(); })) {
|
2018-11-10 01:13:15 +00:00
|
|
|
return Invalid;
|
2018-11-11 21:39:25 +00:00
|
|
|
}
|
2018-11-10 01:13:15 +00:00
|
|
|
|
2019-05-25 00:56:58 +00:00
|
|
|
if (parameters.disable_download_code && std::any_of(input.begin(), input.end(), [](QChar c) {
|
|
|
|
return c == QLatin1Char{'O'} || c == QLatin1Char{'I'};
|
|
|
|
})) {
|
2018-11-10 01:13:15 +00:00
|
|
|
return Invalid;
|
2018-11-11 21:39:25 +00:00
|
|
|
}
|
2018-11-10 01:13:15 +00:00
|
|
|
|
|
|
|
return Acceptable;
|
|
|
|
}
|
|
|
|
|
|
|
|
QtSoftwareKeyboardDialog::QtSoftwareKeyboardDialog(
|
2018-11-11 21:39:25 +00:00
|
|
|
QWidget* parent, Core::Frontend::SoftwareKeyboardParameters parameters_)
|
2018-11-10 01:13:15 +00:00
|
|
|
: QDialog(parent), parameters(std::move(parameters_)) {
|
|
|
|
layout = new QVBoxLayout;
|
|
|
|
|
|
|
|
header_label = new QLabel(QString::fromStdU16String(parameters.header_text));
|
2018-11-17 19:44:16 +00:00
|
|
|
header_label->setFont({header_label->font().family(), 11, QFont::Bold});
|
2018-11-10 01:13:15 +00:00
|
|
|
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());
|
|
|
|
|
2018-11-17 19:44:16 +00:00
|
|
|
length_label = new QLabel(QStringLiteral("0/%1").arg(parameters.max_length));
|
|
|
|
length_label->setAlignment(Qt::AlignRight);
|
|
|
|
length_label->setFont({length_label->font().family(), 8});
|
|
|
|
|
2018-11-10 01:13:15 +00:00
|
|
|
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);
|
|
|
|
|
2018-11-17 19:44:16 +00:00
|
|
|
connect(line_edit, &QLineEdit::textChanged, this, [this](const QString& text) {
|
|
|
|
length_label->setText(QStringLiteral("%1/%2").arg(text.size()).arg(parameters.max_length));
|
|
|
|
});
|
|
|
|
|
2019-04-03 15:13:07 +00:00
|
|
|
buttons = new QDialogButtonBox(QDialogButtonBox::Cancel);
|
|
|
|
if (parameters.submit_text.empty()) {
|
|
|
|
buttons->addButton(QDialogButtonBox::Ok);
|
|
|
|
} else {
|
|
|
|
buttons->addButton(QString::fromStdU16String(parameters.submit_text),
|
|
|
|
QDialogButtonBox::AcceptRole);
|
|
|
|
}
|
2018-11-20 16:36:47 +00:00
|
|
|
connect(buttons, &QDialogButtonBox::accepted, this, &QtSoftwareKeyboardDialog::accept);
|
|
|
|
connect(buttons, &QDialogButtonBox::rejected, this, &QtSoftwareKeyboardDialog::reject);
|
2018-11-10 01:13:15 +00:00
|
|
|
layout->addWidget(header_label);
|
|
|
|
layout->addWidget(sub_label);
|
|
|
|
layout->addWidget(guide_label);
|
2018-11-17 19:44:16 +00:00
|
|
|
layout->addWidget(length_label);
|
2018-11-10 01:13:15 +00:00
|
|
|
layout->addWidget(line_edit);
|
|
|
|
layout->addWidget(buttons);
|
|
|
|
setLayout(layout);
|
2018-11-11 21:39:25 +00:00
|
|
|
setWindowTitle(tr("Software Keyboard"));
|
2018-11-10 01:13:15 +00:00
|
|
|
}
|
|
|
|
|
2018-11-11 21:39:25 +00:00
|
|
|
QtSoftwareKeyboardDialog::~QtSoftwareKeyboardDialog() = default;
|
|
|
|
|
2018-11-20 16:36:47 +00:00
|
|
|
void QtSoftwareKeyboardDialog::accept() {
|
2018-11-10 01:13:15 +00:00
|
|
|
ok = true;
|
|
|
|
text = line_edit->text().toStdU16String();
|
2018-11-20 16:36:47 +00:00
|
|
|
QDialog::accept();
|
2018-11-10 01:13:15 +00:00
|
|
|
}
|
|
|
|
|
2018-11-20 16:36:47 +00:00
|
|
|
void QtSoftwareKeyboardDialog::reject() {
|
2018-11-10 01:13:15 +00:00
|
|
|
ok = false;
|
2018-11-11 21:39:25 +00:00
|
|
|
text.clear();
|
2018-11-20 16:36:47 +00:00
|
|
|
QDialog::reject();
|
2018-11-10 01:13:15 +00:00
|
|
|
}
|
|
|
|
|
2018-11-12 01:16:38 +00:00
|
|
|
std::u16string QtSoftwareKeyboardDialog::GetText() const {
|
2018-11-11 21:39:25 +00:00
|
|
|
return text;
|
|
|
|
}
|
|
|
|
|
2018-11-12 01:16:38 +00:00
|
|
|
bool QtSoftwareKeyboardDialog::GetStatus() const {
|
2018-11-11 21:39:25 +00:00
|
|
|
return ok;
|
|
|
|
}
|
2018-11-10 01:13:15 +00:00
|
|
|
|
2018-11-12 16:08:09 +00:00
|
|
|
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);
|
|
|
|
}
|
2018-11-11 21:39:25 +00:00
|
|
|
|
|
|
|
QtSoftwareKeyboard::~QtSoftwareKeyboard() = default;
|
|
|
|
|
2018-11-12 16:08:09 +00:00
|
|
|
void QtSoftwareKeyboard::RequestText(std::function<void(std::optional<std::u16string>)> out,
|
|
|
|
Core::Frontend::SoftwareKeyboardParameters parameters) const {
|
2018-11-20 16:30:51 +00:00
|
|
|
text_output = std::move(out);
|
2018-11-12 16:08:09 +00:00
|
|
|
emit MainWindowGetText(parameters);
|
2018-11-11 21:39:25 +00:00
|
|
|
}
|
2018-11-10 01:13:15 +00:00
|
|
|
|
2018-11-17 17:18:03 +00:00
|
|
|
void QtSoftwareKeyboard::SendTextCheckDialog(std::u16string error_message,
|
|
|
|
std::function<void()> finished_check) const {
|
2018-11-20 16:30:51 +00:00
|
|
|
this->finished_check = std::move(finished_check);
|
2018-11-12 16:08:09 +00:00
|
|
|
emit MainWindowTextCheckDialog(error_message);
|
|
|
|
}
|
|
|
|
|
|
|
|
void QtSoftwareKeyboard::MainWindowFinishedText(std::optional<std::u16string> text) {
|
2018-11-17 17:18:03 +00:00
|
|
|
// Acquire the HLE mutex
|
2019-04-01 16:29:59 +00:00
|
|
|
std::lock_guard lock{HLE::g_hle_lock};
|
2018-11-12 16:08:09 +00:00
|
|
|
text_output(text);
|
2018-11-10 01:13:15 +00:00
|
|
|
}
|
2018-11-17 17:18:03 +00:00
|
|
|
|
|
|
|
void QtSoftwareKeyboard::MainWindowFinishedCheckDialog() {
|
|
|
|
// Acquire the HLE mutex
|
2019-04-01 16:29:59 +00:00
|
|
|
std::lock_guard lock{HLE::g_hle_lock};
|
2018-11-17 17:18:03 +00:00
|
|
|
finished_check();
|
|
|
|
}
|