Merge pull request #3850 from zhaowenlan1779/swkbd
applets/swkbd: Software Keyboard Implementation
This commit is contained in:
commit
bf6da61da5
16 changed files with 774 additions and 34 deletions
|
@ -7,6 +7,8 @@ add_executable(citra-qt
|
|||
Info.plist
|
||||
aboutdialog.cpp
|
||||
aboutdialog.h
|
||||
applets/swkbd.cpp
|
||||
applets/swkbd.h
|
||||
bootmanager.cpp
|
||||
bootmanager.h
|
||||
camera/camera_util.cpp
|
||||
|
|
129
src/citra_qt/applets/swkbd.cpp
Normal file
129
src/citra_qt/applets/swkbd.cpp
Normal file
|
@ -0,0 +1,129 @@
|
|||
// Copyright 2018 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <QDialogButtonBox>
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QMessageBox>
|
||||
#include <QString>
|
||||
#include <QVBoxLayout>
|
||||
#include "citra_qt/applets/swkbd.h"
|
||||
|
||||
QtKeyboardValidator::QtKeyboardValidator(QtKeyboard* keyboard_) : keyboard(keyboard_) {}
|
||||
|
||||
QtKeyboardValidator::State QtKeyboardValidator::validate(QString& input, int& pos) const {
|
||||
if (keyboard->ValidateFilters(input.toStdString()) == Frontend::ValidationError::None) {
|
||||
if (input.size() > keyboard->config.max_text_length)
|
||||
return State::Invalid;
|
||||
return State::Acceptable;
|
||||
} else {
|
||||
return State::Invalid;
|
||||
}
|
||||
}
|
||||
|
||||
QtKeyboardDialog::QtKeyboardDialog(QWidget* parent, QtKeyboard* keyboard_)
|
||||
: QDialog(parent), keyboard(keyboard_) {
|
||||
using namespace Frontend;
|
||||
KeyboardConfig config = keyboard->config;
|
||||
layout = new QVBoxLayout;
|
||||
label = new QLabel(QString::fromStdString(config.hint_text));
|
||||
line_edit = new QLineEdit;
|
||||
line_edit->setValidator(new QtKeyboardValidator(keyboard));
|
||||
buttons = new QDialogButtonBox;
|
||||
// Initialize buttons
|
||||
switch (config.button_config) {
|
||||
case ButtonConfig::Triple:
|
||||
buttons->addButton(config.has_custom_button_text
|
||||
? QString::fromStdString(config.button_text[2])
|
||||
: tr(BUTTON_OKAY),
|
||||
QDialogButtonBox::ButtonRole::AcceptRole);
|
||||
buttons->addButton(config.has_custom_button_text
|
||||
? QString::fromStdString(config.button_text[1])
|
||||
: tr(BUTTON_FORGOT),
|
||||
QDialogButtonBox::ButtonRole::HelpRole);
|
||||
buttons->addButton(config.has_custom_button_text
|
||||
? QString::fromStdString(config.button_text[0])
|
||||
: tr(BUTTON_CANCEL),
|
||||
QDialogButtonBox::ButtonRole::RejectRole);
|
||||
break;
|
||||
case ButtonConfig::Dual:
|
||||
buttons->addButton(config.has_custom_button_text
|
||||
? QString::fromStdString(config.button_text[1])
|
||||
: tr(BUTTON_OKAY),
|
||||
QDialogButtonBox::ButtonRole::AcceptRole);
|
||||
buttons->addButton(config.has_custom_button_text
|
||||
? QString::fromStdString(config.button_text[0])
|
||||
: tr(BUTTON_CANCEL),
|
||||
QDialogButtonBox::ButtonRole::RejectRole);
|
||||
break;
|
||||
case ButtonConfig::Single:
|
||||
buttons->addButton(config.has_custom_button_text
|
||||
? QString::fromStdString(config.button_text[0])
|
||||
: tr(BUTTON_OKAY),
|
||||
QDialogButtonBox::ButtonRole::AcceptRole);
|
||||
break;
|
||||
case ButtonConfig::None:
|
||||
break;
|
||||
}
|
||||
connect(buttons, &QDialogButtonBox::accepted, this, [=] { Submit(); });
|
||||
connect(buttons, &QDialogButtonBox::rejected, this, [=] {
|
||||
button = QtKeyboard::cancel_id;
|
||||
accept();
|
||||
});
|
||||
connect(buttons, &QDialogButtonBox::helpRequested, this, [=] {
|
||||
button = QtKeyboard::forgot_id;
|
||||
accept();
|
||||
});
|
||||
layout->addWidget(label);
|
||||
layout->addWidget(line_edit);
|
||||
layout->addWidget(buttons);
|
||||
setLayout(layout);
|
||||
}
|
||||
|
||||
void QtKeyboardDialog::Submit() {
|
||||
auto error = keyboard->ValidateInput(line_edit->text().toStdString());
|
||||
if (error != Frontend::ValidationError::None) {
|
||||
HandleValidationError(error);
|
||||
} else {
|
||||
button = keyboard->ok_id;
|
||||
text = line_edit->text();
|
||||
accept();
|
||||
}
|
||||
}
|
||||
|
||||
void QtKeyboardDialog::HandleValidationError(Frontend::ValidationError error) {
|
||||
using namespace Frontend;
|
||||
const std::unordered_map<ValidationError, QString> VALIDATION_ERROR_MESSAGES = {
|
||||
{ValidationError::FixedLengthRequired,
|
||||
tr("Text length is not correct (should be %1 characters)")
|
||||
.arg(keyboard->config.max_text_length)},
|
||||
{ValidationError::MaxLengthExceeded,
|
||||
tr("Text is too long (should be no more than %1 characters)")
|
||||
.arg(keyboard->config.max_text_length)},
|
||||
{ValidationError::BlankInputNotAllowed, tr("Blank input is not allowed")},
|
||||
{ValidationError::EmptyInputNotAllowed, tr("Empty input is not allowed")},
|
||||
};
|
||||
QMessageBox::critical(this, tr("Validation error"), VALIDATION_ERROR_MESSAGES.at(error));
|
||||
}
|
||||
|
||||
QtKeyboard::QtKeyboard(QWidget& parent_) : parent(parent_) {}
|
||||
|
||||
void QtKeyboard::Setup(const Frontend::KeyboardConfig* config) {
|
||||
SoftwareKeyboard::Setup(config);
|
||||
if (this->config.button_config != Frontend::ButtonConfig::None) {
|
||||
ok_id = static_cast<u8>(this->config.button_config);
|
||||
}
|
||||
QMetaObject::invokeMethod(this, "OpenInputDialog", Qt::BlockingQueuedConnection);
|
||||
}
|
||||
|
||||
void QtKeyboard::OpenInputDialog() {
|
||||
QtKeyboardDialog dialog(&parent, this);
|
||||
dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint |
|
||||
Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint);
|
||||
dialog.setWindowModality(Qt::WindowModal);
|
||||
dialog.exec();
|
||||
LOG_INFO(Frontend, "SWKBD input dialog finished, text={}, button={}", dialog.text.toStdString(),
|
||||
dialog.button);
|
||||
Finalize(dialog.text.toStdString(), dialog.button);
|
||||
}
|
65
src/citra_qt/applets/swkbd.h
Normal file
65
src/citra_qt/applets/swkbd.h
Normal file
|
@ -0,0 +1,65 @@
|
|||
// Copyright 2018 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QDialog>
|
||||
#include <QValidator>
|
||||
#include "core/frontend/applets/swkbd.h"
|
||||
|
||||
class QDialogButtonBox;
|
||||
class QLabel;
|
||||
class QLineEdit;
|
||||
class QVBoxLayout;
|
||||
class QtKeyboard;
|
||||
|
||||
class QtKeyboardValidator final : public QValidator {
|
||||
public:
|
||||
explicit QtKeyboardValidator(QtKeyboard* keyboard);
|
||||
State validate(QString& input, int& pos) const override;
|
||||
|
||||
private:
|
||||
QtKeyboard* keyboard;
|
||||
};
|
||||
|
||||
class QtKeyboardDialog final : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QtKeyboardDialog(QWidget* parent, QtKeyboard* keyboard);
|
||||
void Submit();
|
||||
|
||||
private:
|
||||
void HandleValidationError(Frontend::ValidationError error);
|
||||
QDialogButtonBox* buttons;
|
||||
QLabel* label;
|
||||
QLineEdit* line_edit;
|
||||
QVBoxLayout* layout;
|
||||
QtKeyboard* keyboard;
|
||||
QString text;
|
||||
u8 button;
|
||||
|
||||
friend class QtKeyboard;
|
||||
};
|
||||
|
||||
class QtKeyboard final : public QObject, public Frontend::SoftwareKeyboard {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit QtKeyboard(QWidget& parent);
|
||||
void Setup(const Frontend::KeyboardConfig* config) override;
|
||||
|
||||
private:
|
||||
Q_INVOKABLE void OpenInputDialog();
|
||||
|
||||
/// Index of the buttons
|
||||
u8 ok_id;
|
||||
static constexpr u8 forgot_id = 1;
|
||||
static constexpr u8 cancel_id = 0;
|
||||
|
||||
QWidget& parent;
|
||||
|
||||
friend class QtKeyboardDialog;
|
||||
friend class QtKeyboardValidator;
|
||||
};
|
|
@ -16,6 +16,7 @@
|
|||
#include <QtGui>
|
||||
#include <QtWidgets>
|
||||
#include "citra_qt/aboutdialog.h"
|
||||
#include "citra_qt/applets/swkbd.h"
|
||||
#include "citra_qt/bootmanager.h"
|
||||
#include "citra_qt/camera/qt_multimedia_camera.h"
|
||||
#include "citra_qt/camera/still_image_camera.h"
|
||||
|
@ -50,6 +51,7 @@
|
|||
#include "common/string_util.h"
|
||||
#include "core/core.h"
|
||||
#include "core/file_sys/archive_source_sd_savedata.h"
|
||||
#include "core/frontend/applets/default_applets.h"
|
||||
#include "core/gdbstub/gdbstub.h"
|
||||
#include "core/hle/service/fs/archive.h"
|
||||
#include "core/loader/loader.h"
|
||||
|
@ -1468,6 +1470,10 @@ int main(int argc, char* argv[]) {
|
|||
Camera::RegisterFactory("qt", std::make_unique<Camera::QtMultimediaCameraFactory>());
|
||||
Camera::QtMultimediaCameraHandler::Init();
|
||||
|
||||
// Register frontend applets
|
||||
Frontend::RegisterDefaultApplets();
|
||||
Frontend::RegisterSoftwareKeyboard(std::make_shared<QtKeyboard>(main_window));
|
||||
|
||||
main_window.show();
|
||||
return app.exec();
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue