software_keyboard.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. // Copyright 2018 yuzu Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <algorithm>
  5. #include <mutex>
  6. #include <QDialogButtonBox>
  7. #include <QFont>
  8. #include <QLabel>
  9. #include <QLineEdit>
  10. #include <QVBoxLayout>
  11. #include "core/hle/lock.h"
  12. #include "yuzu/applets/software_keyboard.h"
  13. #include "yuzu/main.h"
  14. QtSoftwareKeyboardValidator::QtSoftwareKeyboardValidator(
  15. Core::Frontend::SoftwareKeyboardParameters parameters)
  16. : parameters(std::move(parameters)) {}
  17. QValidator::State QtSoftwareKeyboardValidator::validate(QString& input, int& pos) const {
  18. if (input.size() > static_cast<s64>(parameters.max_length)) {
  19. return Invalid;
  20. }
  21. if (parameters.disable_space && input.contains(QLatin1Char{' '})) {
  22. return Invalid;
  23. }
  24. if (parameters.disable_address && input.contains(QLatin1Char{'@'})) {
  25. return Invalid;
  26. }
  27. if (parameters.disable_percent && input.contains(QLatin1Char{'%'})) {
  28. return Invalid;
  29. }
  30. if (parameters.disable_slash &&
  31. (input.contains(QLatin1Char{'/'}) || input.contains(QLatin1Char{'\\'}))) {
  32. return Invalid;
  33. }
  34. if (parameters.disable_number &&
  35. std::any_of(input.begin(), input.end(), [](QChar c) { return c.isDigit(); })) {
  36. return Invalid;
  37. }
  38. if (parameters.disable_download_code && std::any_of(input.begin(), input.end(), [](QChar c) {
  39. return c == QLatin1Char{'O'} || c == QLatin1Char{'I'};
  40. })) {
  41. return Invalid;
  42. }
  43. return Acceptable;
  44. }
  45. QtSoftwareKeyboardDialog::QtSoftwareKeyboardDialog(
  46. QWidget* parent, Core::Frontend::SoftwareKeyboardParameters parameters_)
  47. : QDialog(parent), parameters(std::move(parameters_)) {
  48. layout = new QVBoxLayout;
  49. header_label = new QLabel(QString::fromStdU16String(parameters.header_text));
  50. header_label->setFont({header_label->font().family(), 11, QFont::Bold});
  51. if (header_label->text().isEmpty())
  52. header_label->setText(tr("Enter text:"));
  53. sub_label = new QLabel(QString::fromStdU16String(parameters.sub_text));
  54. sub_label->setFont({sub_label->font().family(), sub_label->font().pointSize(),
  55. sub_label->font().weight(), true});
  56. sub_label->setHidden(parameters.sub_text.empty());
  57. guide_label = new QLabel(QString::fromStdU16String(parameters.guide_text));
  58. guide_label->setHidden(parameters.guide_text.empty());
  59. length_label = new QLabel(QStringLiteral("0/%1").arg(parameters.max_length));
  60. length_label->setAlignment(Qt::AlignRight);
  61. length_label->setFont({length_label->font().family(), 8});
  62. line_edit = new QLineEdit;
  63. line_edit->setValidator(new QtSoftwareKeyboardValidator(parameters));
  64. line_edit->setMaxLength(static_cast<int>(parameters.max_length));
  65. line_edit->setText(QString::fromStdU16String(parameters.initial_text));
  66. line_edit->setCursorPosition(
  67. parameters.cursor_at_beginning ? 0 : static_cast<int>(parameters.initial_text.size()));
  68. line_edit->setEchoMode(parameters.password ? QLineEdit::Password : QLineEdit::Normal);
  69. connect(line_edit, &QLineEdit::textChanged, this, [this](const QString& text) {
  70. length_label->setText(QStringLiteral("%1/%2").arg(text.size()).arg(parameters.max_length));
  71. });
  72. buttons = new QDialogButtonBox(QDialogButtonBox::Cancel);
  73. if (parameters.submit_text.empty()) {
  74. buttons->addButton(QDialogButtonBox::Ok);
  75. } else {
  76. buttons->addButton(QString::fromStdU16String(parameters.submit_text),
  77. QDialogButtonBox::AcceptRole);
  78. }
  79. connect(buttons, &QDialogButtonBox::accepted, this, &QtSoftwareKeyboardDialog::accept);
  80. connect(buttons, &QDialogButtonBox::rejected, this, &QtSoftwareKeyboardDialog::reject);
  81. layout->addWidget(header_label);
  82. layout->addWidget(sub_label);
  83. layout->addWidget(guide_label);
  84. layout->addWidget(length_label);
  85. layout->addWidget(line_edit);
  86. layout->addWidget(buttons);
  87. setLayout(layout);
  88. setWindowTitle(tr("Software Keyboard"));
  89. }
  90. QtSoftwareKeyboardDialog::~QtSoftwareKeyboardDialog() = default;
  91. void QtSoftwareKeyboardDialog::accept() {
  92. ok = true;
  93. text = line_edit->text().toStdU16String();
  94. QDialog::accept();
  95. }
  96. void QtSoftwareKeyboardDialog::reject() {
  97. ok = false;
  98. text.clear();
  99. QDialog::reject();
  100. }
  101. std::u16string QtSoftwareKeyboardDialog::GetText() const {
  102. return text;
  103. }
  104. bool QtSoftwareKeyboardDialog::GetStatus() const {
  105. return ok;
  106. }
  107. QtSoftwareKeyboard::QtSoftwareKeyboard(GMainWindow& main_window) {
  108. connect(this, &QtSoftwareKeyboard::MainWindowGetText, &main_window,
  109. &GMainWindow::SoftwareKeyboardGetText, Qt::QueuedConnection);
  110. connect(this, &QtSoftwareKeyboard::MainWindowTextCheckDialog, &main_window,
  111. &GMainWindow::SoftwareKeyboardInvokeCheckDialog, Qt::BlockingQueuedConnection);
  112. connect(&main_window, &GMainWindow::SoftwareKeyboardFinishedText, this,
  113. &QtSoftwareKeyboard::MainWindowFinishedText, Qt::QueuedConnection);
  114. }
  115. QtSoftwareKeyboard::~QtSoftwareKeyboard() = default;
  116. void QtSoftwareKeyboard::RequestText(std::function<void(std::optional<std::u16string>)> out,
  117. Core::Frontend::SoftwareKeyboardParameters parameters) const {
  118. text_output = std::move(out);
  119. emit MainWindowGetText(parameters);
  120. }
  121. void QtSoftwareKeyboard::SendTextCheckDialog(std::u16string error_message,
  122. std::function<void()> finished_check) const {
  123. this->finished_check = std::move(finished_check);
  124. emit MainWindowTextCheckDialog(error_message);
  125. }
  126. void QtSoftwareKeyboard::MainWindowFinishedText(std::optional<std::u16string> text) {
  127. // Acquire the HLE mutex
  128. std::lock_guard lock{HLE::g_hle_lock};
  129. text_output(std::move(text));
  130. }
  131. void QtSoftwareKeyboard::MainWindowFinishedCheckDialog() {
  132. // Acquire the HLE mutex
  133. std::lock_guard lock{HLE::g_hle_lock};
  134. finished_check();
  135. }