configure_system: Contrain profile usernames to 32 characters
Previously, we would let a user enter an unbounded name and then silently truncate away characters that went over the 32-character limit. This is kind of bad from the UX point of view, because we're essentially not doing what the user intended in certain scenarios. Instead, we clamp it to 32 characters and make that visually apparent in the dialog box to provide a name for a user.
This commit is contained in:
parent
b5f8a5f0a3
commit
a6830e61b8
|
@ -57,7 +57,8 @@ struct UUID {
|
||||||
};
|
};
|
||||||
static_assert(sizeof(UUID) == 16, "UUID is an invalid size!");
|
static_assert(sizeof(UUID) == 16, "UUID is an invalid size!");
|
||||||
|
|
||||||
using ProfileUsername = std::array<u8, 0x20>;
|
constexpr std::size_t profile_username_size = 32;
|
||||||
|
using ProfileUsername = std::array<u8, profile_username_size>;
|
||||||
using ProfileData = std::array<u8, MAX_DATA>;
|
using ProfileData = std::array<u8, MAX_DATA>;
|
||||||
using UserIDArray = std::array<UUID, MAX_USERS>;
|
using UserIDArray = std::array<UUID, MAX_USERS>;
|
||||||
|
|
||||||
|
|
|
@ -56,6 +56,8 @@ add_executable(yuzu
|
||||||
main.h
|
main.h
|
||||||
ui_settings.cpp
|
ui_settings.cpp
|
||||||
ui_settings.h
|
ui_settings.h
|
||||||
|
util/limitable_input_dialog.cpp
|
||||||
|
util/limitable_input_dialog.h
|
||||||
util/spinbox.cpp
|
util/spinbox.cpp
|
||||||
util/spinbox.h
|
util/spinbox.h
|
||||||
util/util.cpp
|
util/util.cpp
|
||||||
|
|
|
@ -6,20 +6,20 @@
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
#include <QGraphicsItem>
|
#include <QGraphicsItem>
|
||||||
#include <QGraphicsScene>
|
#include <QGraphicsScene>
|
||||||
#include <QInputDialog>
|
#include <QHeaderView>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QStandardItemModel>
|
#include <QStandardItemModel>
|
||||||
#include <QTreeView>
|
#include <QTreeView>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
#include "common/common_paths.h"
|
#include "common/assert.h"
|
||||||
#include "common/logging/backend.h"
|
#include "common/file_util.h"
|
||||||
#include "common/string_util.h"
|
#include "common/string_util.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/hle/service/acc/profile_manager.h"
|
#include "core/hle/service/acc/profile_manager.h"
|
||||||
#include "core/settings.h"
|
#include "core/settings.h"
|
||||||
#include "ui_configure_system.h"
|
#include "ui_configure_system.h"
|
||||||
#include "yuzu/configuration/configure_system.h"
|
#include "yuzu/configuration/configure_system.h"
|
||||||
#include "yuzu/main.h"
|
#include "yuzu/util/limitable_input_dialog.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
constexpr std::array<int, 12> days_in_month = {{
|
constexpr std::array<int, 12> days_in_month = {{
|
||||||
|
@ -83,6 +83,12 @@ QPixmap GetIcon(Service::Account::UUID uuid) {
|
||||||
|
|
||||||
return icon.scaled(64, 64, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
|
return icon.scaled(64, 64, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString GetProfileUsernameFromUser(QWidget* parent, const QString& description_text) {
|
||||||
|
return LimitableInputDialog::GetText(parent, ConfigureSystem::tr("Enter Username"),
|
||||||
|
description_text, 1,
|
||||||
|
static_cast<int>(Service::Account::profile_username_size));
|
||||||
|
}
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
||||||
ConfigureSystem::ConfigureSystem(QWidget* parent)
|
ConfigureSystem::ConfigureSystem(QWidget* parent)
|
||||||
|
@ -244,15 +250,13 @@ void ConfigureSystem::SelectUser(const QModelIndex& index) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureSystem::AddUser() {
|
void ConfigureSystem::AddUser() {
|
||||||
const auto uuid = Service::Account::UUID::Generate();
|
|
||||||
|
|
||||||
bool ok = false;
|
|
||||||
const auto username =
|
const auto username =
|
||||||
QInputDialog::getText(this, tr("Enter Username"), tr("Enter a username for the new user:"),
|
GetProfileUsernameFromUser(this, tr("Enter a username for the new user:"));
|
||||||
QLineEdit::Normal, QString(), &ok);
|
if (username.isEmpty()) {
|
||||||
if (!ok)
|
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto uuid = Service::Account::UUID::Generate();
|
||||||
profile_manager->CreateNewUser(uuid, username.toStdString());
|
profile_manager->CreateNewUser(uuid, username.toStdString());
|
||||||
|
|
||||||
item_model->appendRow(new QStandardItem{GetIcon(uuid), FormatUserEntryText(username, uuid)});
|
item_model->appendRow(new QStandardItem{GetIcon(uuid), FormatUserEntryText(username, uuid)});
|
||||||
|
@ -267,24 +271,15 @@ void ConfigureSystem::RenameUser() {
|
||||||
if (!profile_manager->GetProfileBase(*uuid, profile))
|
if (!profile_manager->GetProfileBase(*uuid, profile))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
bool ok = false;
|
const auto new_username = GetProfileUsernameFromUser(this, tr("Enter a new username:"));
|
||||||
const auto old_username = GetAccountUsername(*profile_manager, *uuid);
|
if (new_username.isEmpty()) {
|
||||||
const auto new_username =
|
|
||||||
QInputDialog::getText(this, tr("Enter Username"), tr("Enter a new username:"),
|
|
||||||
QLineEdit::Normal, old_username, &ok);
|
|
||||||
|
|
||||||
if (!ok)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::fill(profile.username.begin(), profile.username.end(), '\0');
|
|
||||||
const auto username_std = new_username.toStdString();
|
|
||||||
if (username_std.size() > profile.username.size()) {
|
|
||||||
std::copy_n(username_std.begin(), std::min(profile.username.size(), username_std.size()),
|
|
||||||
profile.username.begin());
|
|
||||||
} else {
|
|
||||||
std::copy(username_std.begin(), username_std.end(), profile.username.begin());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto username_std = new_username.toStdString();
|
||||||
|
std::fill(profile.username.begin(), profile.username.end(), '\0');
|
||||||
|
std::copy(username_std.begin(), username_std.end(), profile.username.begin());
|
||||||
|
|
||||||
profile_manager->SetProfileBase(*uuid, profile);
|
profile_manager->SetProfileBase(*uuid, profile);
|
||||||
|
|
||||||
item_model->setItem(
|
item_model->setItem(
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
// Copyright 2018 yuzu Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include <QDialogButtonBox>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QLineEdit>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include "yuzu/util/limitable_input_dialog.h"
|
||||||
|
|
||||||
|
LimitableInputDialog::LimitableInputDialog(QWidget* parent) : QDialog{parent} {
|
||||||
|
CreateUI();
|
||||||
|
ConnectEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
LimitableInputDialog::~LimitableInputDialog() = default;
|
||||||
|
|
||||||
|
void LimitableInputDialog::CreateUI() {
|
||||||
|
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||||
|
|
||||||
|
text_label = new QLabel(this);
|
||||||
|
text_entry = new QLineEdit(this);
|
||||||
|
buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
|
||||||
|
|
||||||
|
auto* const layout = new QVBoxLayout;
|
||||||
|
layout->addWidget(text_label);
|
||||||
|
layout->addWidget(text_entry);
|
||||||
|
layout->addWidget(buttons);
|
||||||
|
|
||||||
|
setLayout(layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LimitableInputDialog::ConnectEvents() {
|
||||||
|
connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept);
|
||||||
|
connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString LimitableInputDialog::GetText(QWidget* parent, const QString& title, const QString& text,
|
||||||
|
int min_character_limit, int max_character_limit) {
|
||||||
|
Q_ASSERT(min_character_limit <= max_character_limit);
|
||||||
|
|
||||||
|
LimitableInputDialog dialog{parent};
|
||||||
|
dialog.setWindowTitle(title);
|
||||||
|
dialog.text_label->setText(text);
|
||||||
|
dialog.text_entry->setMaxLength(max_character_limit);
|
||||||
|
|
||||||
|
auto* const ok_button = dialog.buttons->button(QDialogButtonBox::Ok);
|
||||||
|
ok_button->setEnabled(false);
|
||||||
|
connect(dialog.text_entry, &QLineEdit::textEdited, [&](const QString& new_text) {
|
||||||
|
ok_button->setEnabled(new_text.length() >= min_character_limit);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (dialog.exec() != QDialog::Accepted) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return dialog.text_entry->text();
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
// Copyright 2018 yuzu Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
|
||||||
|
class QDialogButtonBox;
|
||||||
|
class QLabel;
|
||||||
|
class QLineEdit;
|
||||||
|
|
||||||
|
/// A QDialog that functions similarly to QInputDialog, however, it allows
|
||||||
|
/// restricting the minimum and total number of characters that can be entered.
|
||||||
|
class LimitableInputDialog final : public QDialog {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit LimitableInputDialog(QWidget* parent = nullptr);
|
||||||
|
~LimitableInputDialog() override;
|
||||||
|
|
||||||
|
static QString GetText(QWidget* parent, const QString& title, const QString& text,
|
||||||
|
int min_character_limit, int max_character_limit);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void CreateUI();
|
||||||
|
void ConnectEvents();
|
||||||
|
|
||||||
|
QLabel* text_label;
|
||||||
|
QLineEdit* text_entry;
|
||||||
|
QDialogButtonBox* buttons;
|
||||||
|
};
|
Reference in New Issue