From 8eaf857d0605117350dfef13cbd68d53d7f76234 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Fri, 26 Oct 2018 19:28:47 -0400 Subject: [PATCH 1/3] configure_system: Display errors to the user if file operations fail when setting user images We should display an error to the user if setting a user image for an account fails, rather than continuing onwards. --- src/yuzu/configuration/configure_system.cpp | 70 ++++++++++++++------- 1 file changed, 46 insertions(+), 24 deletions(-) diff --git a/src/yuzu/configuration/configure_system.cpp b/src/yuzu/configuration/configure_system.cpp index 20ffb0a9a3..adb16de8ad 100644 --- a/src/yuzu/configuration/configure_system.cpp +++ b/src/yuzu/configuration/configure_system.cpp @@ -48,9 +48,10 @@ constexpr std::array backup_jpeg{ 0x01, 0x01, 0x00, 0x00, 0x3f, 0x00, 0xd2, 0xcf, 0x20, 0xff, 0xd9, }; -std::string GetImagePath(Service::Account::UUID uuid) { - return FileUtil::GetUserPath(FileUtil::UserPath::NANDDir) + - "/system/save/8000000000000010/su/avators/" + uuid.FormatSwitch() + ".jpg"; +QString GetImagePath(Service::Account::UUID uuid) { + const auto path = FileUtil::GetUserPath(FileUtil::UserPath::NANDDir) + + "/system/save/8000000000000010/su/avators/" + uuid.FormatSwitch() + ".jpg"; + return QString::fromStdString(path); } std::string GetAccountUsername(const Service::Account::ProfileManager& manager, @@ -63,6 +64,17 @@ std::string GetAccountUsername(const Service::Account::ProfileManager& manager, return Common::StringFromFixedZeroTerminatedBuffer( reinterpret_cast(profile.username.data()), profile.username.size()); } + +QPixmap GetIcon(Service::Account::UUID uuid) { + QPixmap icon{GetImagePath(uuid)}; + + if (!icon) { + icon.fill(Qt::black); + icon.loadFromData(backup_jpeg.data(), backup_jpeg.size()); + } + + return icon; +} } // Anonymous namespace ConfigureSystem::ConfigureSystem(QWidget* parent) @@ -131,18 +143,6 @@ void ConfigureSystem::setConfiguration() { UpdateCurrentUser(); } -static QPixmap GetIcon(Service::Account::UUID uuid) { - const auto icon_url = QString::fromStdString(GetImagePath(uuid)); - QPixmap icon{icon_url}; - - if (!icon) { - icon.fill(Qt::black); - icon.loadFromData(backup_jpeg.data(), backup_jpeg.size()); - } - - return icon; -} - void ConfigureSystem::PopulateUserList() { const auto& profiles = profile_manager->GetAllUsers(); for (const auto& user : profiles) { @@ -325,24 +325,46 @@ void ConfigureSystem::SetUserImage() { const auto index = tree_view->currentIndex().row(); const auto uuid = profile_manager->GetUser(index); ASSERT(uuid != std::nullopt); - const auto username = GetAccountUsername(*profile_manager, *uuid); const auto file = QFileDialog::getOpenFileName(this, tr("Select User Image"), QString(), tr("JPEG Images (*.jpg *.jpeg)")); - if (file.isEmpty()) + if (file.isEmpty()) { return; + } - FileUtil::Delete(GetImagePath(*uuid)); + const auto image_path = GetImagePath(*uuid); + if (QFile::exists(image_path) && !QFile::remove(image_path)) { + QMessageBox::warning( + this, tr("Error deleting image"), + tr("Error occurred attempting to overwrite previous image at: %1.").arg(image_path)); + return; + } - const auto raw_path = - FileUtil::GetUserPath(FileUtil::UserPath::NANDDir) + "/system/save/8000000000000010"; - if (FileUtil::Exists(raw_path) && !FileUtil::IsDirectory(raw_path)) - FileUtil::Delete(raw_path); + const auto raw_path = QString::fromStdString( + FileUtil::GetUserPath(FileUtil::UserPath::NANDDir) + "/system/save/8000000000000010"); + const QFileInfo raw_info{raw_path}; + if (raw_info.exists() && !raw_info.isDir() && !QFile::remove(raw_path)) { + QMessageBox::warning(this, tr("Error deleting file"), + tr("Unable to delete existing file: %1.").arg(raw_path)); + return; + } - FileUtil::CreateFullPath(GetImagePath(*uuid)); - FileUtil::Copy(file.toStdString(), GetImagePath(*uuid)); + const QString absolute_dst_path = QFileInfo{image_path}.absolutePath(); + if (!QDir{raw_path}.mkpath(absolute_dst_path)) { + QMessageBox::warning( + this, tr("Error creating user image directory"), + tr("Unable to create directory %1 for storing user images.").arg(absolute_dst_path)); + return; + } + if (!QFile::copy(file, image_path)) { + QMessageBox::warning(this, tr("Error copying user image"), + tr("Unable to copy image from %1 to %2").arg(file, image_path)); + return; + } + + const auto username = GetAccountUsername(*profile_manager, *uuid); item_model->setItem( index, 0, new QStandardItem{ From 85ed0af84eeff3d2a7acf1104180a87a4d468a2e Mon Sep 17 00:00:00 2001 From: Lioncash Date: Fri, 26 Oct 2018 19:36:41 -0400 Subject: [PATCH 2/3] configure_system: Move entry formatting for the user account list entries to its own function Avoids the need to duplicate this all over the place, and makes it translator-friendly across the board. --- src/yuzu/configuration/configure_system.cpp | 40 +++++++++++---------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/src/yuzu/configuration/configure_system.cpp b/src/yuzu/configuration/configure_system.cpp index adb16de8ad..f4e892a21b 100644 --- a/src/yuzu/configuration/configure_system.cpp +++ b/src/yuzu/configuration/configure_system.cpp @@ -54,15 +54,23 @@ QString GetImagePath(Service::Account::UUID uuid) { return QString::fromStdString(path); } -std::string GetAccountUsername(const Service::Account::ProfileManager& manager, - Service::Account::UUID uuid) { +QString GetAccountUsername(const Service::Account::ProfileManager& manager, + Service::Account::UUID uuid) { Service::Account::ProfileBase profile; if (!manager.GetProfileBase(uuid, profile)) { - return ""; + return {}; } - return Common::StringFromFixedZeroTerminatedBuffer( + const auto text = Common::StringFromFixedZeroTerminatedBuffer( reinterpret_cast(profile.username.data()), profile.username.size()); + return QString::fromStdString(text); +} + +QString FormatUserEntryText(const QString& username, Service::Account::UUID uuid) { + return ConfigureSystem::tr("%1\n%2", + "%1 is the profile username, %2 is the formatted UUID (e.g. " + "00112233-4455-6677-8899-AABBCCDDEEFF))") + .arg(username, QString::fromStdString(uuid.FormatSwitch())); } QPixmap GetIcon(Service::Account::UUID uuid) { @@ -155,7 +163,7 @@ void ConfigureSystem::PopulateUserList() { list_items.push_back(QList{new QStandardItem{ GetIcon(user).scaled(64, 64, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), - QString::fromStdString(username + '\n' + user.FormatSwitch())}}); + FormatUserEntryText(QString::fromStdString(username), user)}}); } for (const auto& item : list_items) @@ -172,7 +180,7 @@ void ConfigureSystem::UpdateCurrentUser() { scene->clear(); scene->addPixmap( GetIcon(*current_user).scaled(48, 48, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); - ui->current_user_username->setText(QString::fromStdString(username)); + ui->current_user_username->setText(username); } void ConfigureSystem::ReadSystemSettings() {} @@ -250,23 +258,23 @@ void ConfigureSystem::AddUser() { item_model->appendRow(new QStandardItem{ GetIcon(uuid).scaled(64, 64, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), - QString::fromStdString(username.toStdString() + '\n' + uuid.FormatSwitch())}); + FormatUserEntryText(username, uuid)}); } void ConfigureSystem::RenameUser() { const auto user = tree_view->currentIndex().row(); const auto uuid = profile_manager->GetUser(user); ASSERT(uuid != std::nullopt); - const auto username = GetAccountUsername(*profile_manager, *uuid); Service::Account::ProfileBase profile; if (!profile_manager->GetProfileBase(*uuid, profile)) return; bool ok = false; + const auto old_username = GetAccountUsername(*profile_manager, *uuid); const auto new_username = QInputDialog::getText(this, tr("Enter Username"), tr("Enter a new username:"), - QLineEdit::Normal, QString::fromStdString(username), &ok); + QLineEdit::Normal, old_username, &ok); if (!ok) return; @@ -286,10 +294,7 @@ void ConfigureSystem::RenameUser() { user, 0, new QStandardItem{ GetIcon(*uuid).scaled(64, 64, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), - tr("%1\n%2", "%1 is the profile username, %2 is the formatted UUID (e.g. " - "00112233-4455-6677-8899-AABBCCDDEEFF))") - .arg(QString::fromStdString(username_std), - QString::fromStdString(uuid->FormatSwitch()))}); + FormatUserEntryText(QString::fromStdString(username_std), *uuid)}); UpdateCurrentUser(); } @@ -299,10 +304,9 @@ void ConfigureSystem::DeleteUser() { ASSERT(uuid != std::nullopt); const auto username = GetAccountUsername(*profile_manager, *uuid); - const auto confirm = - QMessageBox::question(this, tr("Confirm Delete"), - tr("You are about to delete user with name %1. Are you sure?") - .arg(QString::fromStdString(username))); + const auto confirm = QMessageBox::question( + this, tr("Confirm Delete"), + tr("You are about to delete user with name \"%1\". Are you sure?").arg(username)); if (confirm == QMessageBox::No) return; @@ -369,6 +373,6 @@ void ConfigureSystem::SetUserImage() { index, 0, new QStandardItem{ GetIcon(*uuid).scaled(64, 64, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), - QString::fromStdString(username + '\n' + uuid->FormatSwitch())}); + FormatUserEntryText(username, *uuid)}); UpdateCurrentUser(); } From 9024cbb5b8462df113526f5027b88723f4765fdf Mon Sep 17 00:00:00 2001 From: Lioncash Date: Fri, 26 Oct 2018 19:46:38 -0400 Subject: [PATCH 3/3] configure_system: Make GetIcon() return the scaled 64x64 icon Avoids the need to put the scaling parameters all over the place for the common case. The only other time scaling is done is to generate the smaller 48x48 image, so this is fine. --- src/yuzu/configuration/configure_system.cpp | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/src/yuzu/configuration/configure_system.cpp b/src/yuzu/configuration/configure_system.cpp index f4e892a21b..4b34c1e28a 100644 --- a/src/yuzu/configuration/configure_system.cpp +++ b/src/yuzu/configuration/configure_system.cpp @@ -81,7 +81,7 @@ QPixmap GetIcon(Service::Account::UUID uuid) { icon.loadFromData(backup_jpeg.data(), backup_jpeg.size()); } - return icon; + return icon.scaled(64, 64, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); } } // Anonymous namespace @@ -162,8 +162,7 @@ void ConfigureSystem::PopulateUserList() { reinterpret_cast(profile.username.data()), profile.username.size()); list_items.push_back(QList{new QStandardItem{ - GetIcon(user).scaled(64, 64, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), - FormatUserEntryText(QString::fromStdString(username), user)}}); + GetIcon(user), FormatUserEntryText(QString::fromStdString(username), user)}}); } for (const auto& item : list_items) @@ -256,9 +255,7 @@ void ConfigureSystem::AddUser() { profile_manager->CreateNewUser(uuid, username.toStdString()); - item_model->appendRow(new QStandardItem{ - GetIcon(uuid).scaled(64, 64, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), - FormatUserEntryText(username, uuid)}); + item_model->appendRow(new QStandardItem{GetIcon(uuid), FormatUserEntryText(username, uuid)}); } void ConfigureSystem::RenameUser() { @@ -292,9 +289,8 @@ void ConfigureSystem::RenameUser() { item_model->setItem( user, 0, - new QStandardItem{ - GetIcon(*uuid).scaled(64, 64, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), - FormatUserEntryText(QString::fromStdString(username_std), *uuid)}); + new QStandardItem{GetIcon(*uuid), + FormatUserEntryText(QString::fromStdString(username_std), *uuid)}); UpdateCurrentUser(); } @@ -369,10 +365,7 @@ void ConfigureSystem::SetUserImage() { } const auto username = GetAccountUsername(*profile_manager, *uuid); - item_model->setItem( - index, 0, - new QStandardItem{ - GetIcon(*uuid).scaled(64, 64, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), - FormatUserEntryText(username, *uuid)}); + item_model->setItem(index, 0, + new QStandardItem{GetIcon(*uuid), FormatUserEntryText(username, *uuid)}); UpdateCurrentUser(); }