2020-12-05 13:08:24 +01:00
|
|
|
#include "osk_dialog_frame.h"
|
2020-02-22 20:42:49 +01:00
|
|
|
#include "custom_dialog.h"
|
2019-01-04 22:28:52 +01:00
|
|
|
#include "Emu/Cell/Modules/cellMsgDialog.h"
|
|
|
|
|
|
2021-03-13 16:02:37 +01:00
|
|
|
#include "util/asm.hpp"
|
|
|
|
|
|
2021-01-12 10:59:50 +01:00
|
|
|
#include <QDialogButtonBox>
|
2019-01-04 22:28:52 +01:00
|
|
|
#include <QLabel>
|
|
|
|
|
#include <QLineEdit>
|
2019-01-05 18:11:43 +01:00
|
|
|
#include <QTextEdit>
|
2019-01-04 22:28:52 +01:00
|
|
|
#include <QHBoxLayout>
|
|
|
|
|
#include <QFormLayout>
|
2022-04-21 20:54:02 +02:00
|
|
|
#include <QRegularExpressionValidator>
|
2019-01-04 22:28:52 +01:00
|
|
|
|
|
|
|
|
constexpr auto qstr = QString::fromStdString;
|
|
|
|
|
|
|
|
|
|
osk_dialog_frame::~osk_dialog_frame()
|
|
|
|
|
{
|
|
|
|
|
if (m_dialog)
|
|
|
|
|
{
|
|
|
|
|
m_dialog->deleteLater();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-18 20:14:42 +01:00
|
|
|
void osk_dialog_frame::Create(const osk_params& params)
|
2019-01-04 22:28:52 +01:00
|
|
|
{
|
|
|
|
|
state = OskDialogState::Open;
|
|
|
|
|
|
|
|
|
|
static const auto& lineEditWidth = []() {return QLabel("This is the very length of the lineedit due to hidpi reasons.").sizeHint().width(); };
|
|
|
|
|
|
|
|
|
|
if (m_dialog)
|
|
|
|
|
{
|
|
|
|
|
m_dialog->close();
|
|
|
|
|
delete m_dialog;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_dialog = new custom_dialog(false);
|
|
|
|
|
m_dialog->setModal(true);
|
|
|
|
|
|
|
|
|
|
// Title
|
2023-01-18 20:14:42 +01:00
|
|
|
m_dialog->setWindowTitle(qstr(params.title));
|
2019-01-04 22:28:52 +01:00
|
|
|
|
|
|
|
|
// Message
|
2023-01-18 20:14:42 +01:00
|
|
|
QLabel* message_label = new QLabel(QString::fromStdU16String(params.message));
|
2019-01-04 22:28:52 +01:00
|
|
|
|
|
|
|
|
// Text Input Counter
|
2023-01-18 20:14:42 +01:00
|
|
|
const QString input_text = QString::fromStdU16String(std::u16string(params.init_text));
|
|
|
|
|
QLabel* input_count_label = new QLabel(QString("%1/%2").arg(input_text.length()).arg(params.charlimit));
|
2019-01-04 22:28:52 +01:00
|
|
|
|
|
|
|
|
// Button Layout
|
2021-01-12 10:59:50 +01:00
|
|
|
QDialogButtonBox* button_box = new QDialogButtonBox(QDialogButtonBox::Ok);
|
2019-01-04 22:28:52 +01:00
|
|
|
|
|
|
|
|
// Input Layout
|
|
|
|
|
QHBoxLayout* inputLayout = new QHBoxLayout;
|
|
|
|
|
inputLayout->setAlignment(Qt::AlignHCenter);
|
2019-01-05 18:11:43 +01:00
|
|
|
|
|
|
|
|
// Text Input
|
2023-01-18 20:14:42 +01:00
|
|
|
if (params.prohibit_flags & CELL_OSKDIALOG_NO_RETURN)
|
2019-01-05 18:11:43 +01:00
|
|
|
{
|
|
|
|
|
QLineEdit* input = new QLineEdit(m_dialog);
|
|
|
|
|
input->setFixedWidth(lineEditWidth());
|
2023-01-18 20:14:42 +01:00
|
|
|
input->setMaxLength(params.charlimit);
|
2021-04-07 23:05:18 +02:00
|
|
|
input->setText(input_text);
|
2019-01-05 18:11:43 +01:00
|
|
|
input->setFocus();
|
|
|
|
|
|
2023-01-18 20:14:42 +01:00
|
|
|
if (params.panel_flag & CELL_OSKDIALOG_PANELMODE_PASSWORD)
|
2021-04-12 19:28:39 +02:00
|
|
|
{
|
|
|
|
|
input->setEchoMode(QLineEdit::Password); // Let's assume that games only use the password mode with single-line edit fields
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-18 20:14:42 +01:00
|
|
|
if (params.prohibit_flags & CELL_OSKDIALOG_NO_SPACE)
|
2019-01-05 18:11:43 +01:00
|
|
|
{
|
2022-04-21 20:54:02 +02:00
|
|
|
input->setValidator(new QRegularExpressionValidator(QRegularExpression("^\\S*$"), this));
|
2019-01-05 18:11:43 +01:00
|
|
|
}
|
|
|
|
|
|
2023-01-18 20:14:42 +01:00
|
|
|
connect(input, &QLineEdit::textChanged, input_count_label, [input_count_label, charlimit = params.charlimit, this](const QString& text)
|
2019-01-05 18:11:43 +01:00
|
|
|
{
|
2021-01-12 10:59:50 +01:00
|
|
|
input_count_label->setText(QString("%1/%2").arg(text.length()).arg(charlimit));
|
2019-01-05 18:11:43 +01:00
|
|
|
SetOskText(text);
|
2022-04-19 23:36:18 +02:00
|
|
|
// if (on_osk_key_input_entered) on_osk_key_input_entered({}); // Not applicable
|
2019-01-05 18:11:43 +01:00
|
|
|
});
|
|
|
|
|
connect(input, &QLineEdit::returnPressed, m_dialog, &QDialog::accept);
|
|
|
|
|
|
|
|
|
|
inputLayout->addWidget(input);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
QTextEdit* input = new QTextEdit(m_dialog);
|
|
|
|
|
input->setFixedWidth(lineEditWidth());
|
2021-04-07 23:05:18 +02:00
|
|
|
input->setText(input_text);
|
2019-01-05 18:11:43 +01:00
|
|
|
input->setFocus();
|
2019-01-08 19:14:58 +01:00
|
|
|
input->moveCursor(QTextCursor::End);
|
2021-04-07 23:05:18 +02:00
|
|
|
m_text_old = input_text;
|
2019-01-05 18:11:43 +01:00
|
|
|
|
2020-02-10 09:55:53 +01:00
|
|
|
connect(input, &QTextEdit::textChanged, [=, this]()
|
2019-01-05 18:11:43 +01:00
|
|
|
{
|
|
|
|
|
QString text = input->toPlainText();
|
|
|
|
|
|
2019-01-08 19:14:58 +01:00
|
|
|
if (text == m_text_old)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QTextCursor cursor = input->textCursor();
|
|
|
|
|
const int cursor_pos_new = cursor.position();
|
|
|
|
|
const int cursor_pos_old = cursor_pos_new + m_text_old.length() - text.length();
|
|
|
|
|
|
|
|
|
|
// Reset to old state if character limit was reached
|
2023-01-18 20:14:42 +01:00
|
|
|
if (m_text_old.length() >= static_cast<int>(params.charlimit) && text.length() > static_cast<int>(params.charlimit))
|
2019-01-08 19:14:58 +01:00
|
|
|
{
|
|
|
|
|
input->blockSignals(true);
|
|
|
|
|
input->setPlainText(m_text_old);
|
|
|
|
|
cursor.setPosition(cursor_pos_old);
|
|
|
|
|
input->setTextCursor(cursor);
|
|
|
|
|
input->blockSignals(false);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int cursor_pos = cursor.position();
|
|
|
|
|
|
|
|
|
|
// Clear text of spaces if necessary
|
2023-01-18 20:14:42 +01:00
|
|
|
if (params.prohibit_flags & CELL_OSKDIALOG_NO_SPACE)
|
2019-01-05 18:11:43 +01:00
|
|
|
{
|
2019-01-08 19:14:58 +01:00
|
|
|
int trim_len = text.length();
|
2022-04-21 20:54:02 +02:00
|
|
|
text.remove(QRegularExpression("\\s+"));
|
2019-01-08 19:14:58 +01:00
|
|
|
trim_len -= text.length();
|
|
|
|
|
cursor_pos -= trim_len;
|
2019-01-05 18:11:43 +01:00
|
|
|
}
|
|
|
|
|
|
2019-01-08 19:14:58 +01:00
|
|
|
// Crop if more than one character was pasted and the character limit was exceeded
|
2023-01-18 20:14:42 +01:00
|
|
|
text.chop(text.length() - params.charlimit);
|
2019-01-05 18:11:43 +01:00
|
|
|
|
2019-01-08 19:14:58 +01:00
|
|
|
// Set new text and block signals to prevent infinite loop
|
|
|
|
|
input->blockSignals(true);
|
|
|
|
|
input->setPlainText(text);
|
|
|
|
|
cursor.setPosition(cursor_pos);
|
2019-01-05 18:11:43 +01:00
|
|
|
input->setTextCursor(cursor);
|
2019-01-08 19:14:58 +01:00
|
|
|
input->blockSignals(false);
|
|
|
|
|
|
|
|
|
|
m_text_old = text;
|
2019-01-05 18:11:43 +01:00
|
|
|
|
2023-01-18 20:14:42 +01:00
|
|
|
input_count_label->setText(QString("%1/%2").arg(text.length()).arg(params.charlimit));
|
2019-01-05 18:11:43 +01:00
|
|
|
SetOskText(text);
|
2022-04-19 23:36:18 +02:00
|
|
|
// if (on_osk_key_input_entered) on_osk_key_input_entered({}); // Not applicable
|
2019-01-05 18:11:43 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
inputLayout->addWidget(input);
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-12 10:59:50 +01:00
|
|
|
inputLayout->addWidget(input_count_label);
|
2019-01-04 22:28:52 +01:00
|
|
|
|
|
|
|
|
QFormLayout* layout = new QFormLayout(m_dialog);
|
|
|
|
|
layout->setFormAlignment(Qt::AlignHCenter);
|
|
|
|
|
layout->addRow(message_label);
|
|
|
|
|
layout->addRow(inputLayout);
|
2021-01-12 10:59:50 +01:00
|
|
|
layout->addWidget(button_box);
|
2019-01-04 22:28:52 +01:00
|
|
|
m_dialog->setLayout(layout);
|
|
|
|
|
|
|
|
|
|
// Events
|
2021-01-12 10:59:50 +01:00
|
|
|
connect(button_box, &QDialogButtonBox::accepted, m_dialog, &QDialog::accept);
|
2019-01-04 22:28:52 +01:00
|
|
|
|
2021-09-19 21:12:42 +02:00
|
|
|
connect(m_dialog, &QDialog::finished, [this](int result)
|
2019-01-04 22:28:52 +01:00
|
|
|
{
|
2021-09-19 21:12:42 +02:00
|
|
|
switch (result)
|
|
|
|
|
{
|
|
|
|
|
case QDialog::Accepted:
|
|
|
|
|
on_osk_close(CELL_OSKDIALOG_CLOSE_CONFIRM);
|
|
|
|
|
break;
|
|
|
|
|
case QDialog::Rejected:
|
|
|
|
|
on_osk_close(CELL_OSKDIALOG_CLOSE_CANCEL);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
2021-09-21 00:59:11 +02:00
|
|
|
on_osk_close(result);
|
2021-09-19 21:12:42 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2019-01-04 22:28:52 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Fix size
|
|
|
|
|
m_dialog->layout()->setSizeConstraint(QLayout::SetFixedSize);
|
|
|
|
|
m_dialog->show();
|
|
|
|
|
}
|
2019-01-05 18:11:43 +01:00
|
|
|
|
|
|
|
|
void osk_dialog_frame::SetOskText(const QString& text)
|
|
|
|
|
{
|
2021-05-22 10:42:05 +02:00
|
|
|
std::memcpy(osk_text.data(), utils::bless<char16_t>(text.constData()), std::min<usz>(osk_text.size(), text.size() + usz{1}) * sizeof(char16_t));
|
2019-01-05 18:11:43 +01:00
|
|
|
}
|
|
|
|
|
|
2021-09-19 21:12:42 +02:00
|
|
|
void osk_dialog_frame::Close(s32 status)
|
2019-01-05 18:11:43 +01:00
|
|
|
{
|
|
|
|
|
if (m_dialog)
|
|
|
|
|
{
|
2021-09-19 21:12:42 +02:00
|
|
|
switch (status)
|
|
|
|
|
{
|
|
|
|
|
case CELL_OSKDIALOG_CLOSE_CONFIRM:
|
|
|
|
|
m_dialog->done(QDialog::Accepted);
|
|
|
|
|
break;
|
|
|
|
|
case CELL_OSKDIALOG_CLOSE_CANCEL:
|
|
|
|
|
m_dialog->done(QDialog::Rejected);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
2021-09-21 00:59:11 +02:00
|
|
|
m_dialog->done(status);
|
2021-09-19 21:12:42 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2019-01-05 18:11:43 +01:00
|
|
|
}
|
|
|
|
|
}
|
2023-01-24 00:13:14 +01:00
|
|
|
|
2023-01-24 01:15:35 +01:00
|
|
|
void osk_dialog_frame::Clear(bool clear_all_data)
|
2023-01-24 00:13:14 +01:00
|
|
|
{
|
2023-01-24 01:15:35 +01:00
|
|
|
if (m_dialog && clear_all_data)
|
2023-01-24 00:13:14 +01:00
|
|
|
{
|
|
|
|
|
SetOskText("");
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-01-24 19:38:14 +01:00
|
|
|
|
|
|
|
|
void osk_dialog_frame::SetText(const std::u16string& text)
|
|
|
|
|
{
|
|
|
|
|
if (m_dialog)
|
|
|
|
|
{
|
|
|
|
|
SetOskText(QString::fromStdU16String(text));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void osk_dialog_frame::Insert(const std::u16string& text)
|
|
|
|
|
{
|
|
|
|
|
if (m_dialog)
|
|
|
|
|
{
|
|
|
|
|
// TODO: Correct position (will probably never get implemented because this dialog is just a fallback)
|
|
|
|
|
SetOskText(QString::fromStdU16String(text));
|
|
|
|
|
}
|
|
|
|
|
}
|