From 8b55a15808a99ac7e278eff5cc0c3c0fdc46a8c0 Mon Sep 17 00:00:00 2001 From: crueter Date: Fri, 30 Jan 2026 14:35:05 +0100 Subject: [PATCH] [desktop] Fix double profile deletion (#3422) Classic case of double-emission of signals. Epic Also fixed a bug that caused profile manager to not immediately update when a profile was deleted from Qlaunch. Signed-off-by: crueter Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3422 Reviewed-by: Lizzie --- src/core/hle/service/acc/profile_manager.cpp | 22 ++++++++----------- src/core/hle/service/acc/profile_manager.h | 5 +++-- .../configure_profile_manager.cpp | 20 ++++++++++------- .../configuration/configure_profile_manager.h | 10 +++++++-- 4 files changed, 32 insertions(+), 25 deletions(-) diff --git a/src/core/hle/service/acc/profile_manager.cpp b/src/core/hle/service/acc/profile_manager.cpp index b32ea5c597..aeceec1cac 100644 --- a/src/core/hle/service/acc/profile_manager.cpp +++ b/src/core/hle/service/acc/profile_manager.cpp @@ -88,11 +88,14 @@ bool ProfileManager::RemoveProfileAtIndex(std::size_t index) { if (index >= MAX_USERS || index >= user_count) { return false; } - if (index < user_count - 1) { - std::rotate(profiles.begin() + index, profiles.begin() + index + 1, profiles.end()); - } - profiles.back() = {}; - user_count--; + + profiles[index] = ProfileInfo{}; + std::stable_partition(profiles.begin(), profiles.end(), + [](const ProfileInfo& profile) { return profile.user_uuid.IsValid(); }); + + is_save_needed = true; + WriteUserSaveFile(); + return true; } @@ -355,14 +358,7 @@ bool ProfileManager::RemoveUser(UUID uuid) { return false; } - profiles[*index] = ProfileInfo{}; - std::stable_partition(profiles.begin(), profiles.end(), - [](const ProfileInfo& profile) { return profile.user_uuid.IsValid(); }); - - is_save_needed = true; - WriteUserSaveFile(); - - return true; + return RemoveProfileAtIndex(*index); } bool ProfileManager::SetProfileBase(UUID uuid, const ProfileBase& profile_new) { diff --git a/src/core/hle/service/acc/profile_manager.h b/src/core/hle/service/acc/profile_manager.h index 4948118b92..1fd0cc700f 100644 --- a/src/core/hle/service/acc/profile_manager.h +++ b/src/core/hle/service/acc/profile_manager.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project @@ -97,6 +97,8 @@ public: bool CanSystemRegisterUser() const; bool RemoveUser(Common::UUID uuid); + bool RemoveProfileAtIndex(std::size_t index); + bool SetProfileBase(Common::UUID uuid, const ProfileBase& profile_new); bool SetProfileBaseAndData(Common::UUID uuid, const ProfileBase& profile_new, const UserData& data_new); @@ -113,7 +115,6 @@ public: private: void ParseUserSaveFile(); std::optional AddToProfiles(const ProfileInfo& profile); - bool RemoveProfileAtIndex(std::size_t index); void RemoveAllProfiles(); bool is_save_needed{}; diff --git a/src/yuzu/configuration/configure_profile_manager.cpp b/src/yuzu/configuration/configure_profile_manager.cpp index 1a9152c41d..aa19203498 100644 --- a/src/yuzu/configuration/configure_profile_manager.cpp +++ b/src/yuzu/configuration/configure_profile_manager.cpp @@ -113,6 +113,8 @@ ConfigureProfileManager::ConfigureProfileManager(Core::System& system_, QWidget* connect(ui->pm_add, &QPushButton::clicked, this, &ConfigureProfileManager::AddUser); confirm_dialog = new ConfigureProfileManagerDeleteDialog(this); + connect(confirm_dialog, &ConfigureProfileManagerDeleteDialog::deleteUser, this, + &ConfigureProfileManager::DeleteUser); scene = new QGraphicsScene; ui->current_user_icon->setScene(scene); @@ -146,6 +148,7 @@ void ConfigureProfileManager::SetConfiguration() { } void ConfigureProfileManager::PopulateUserList() { + profile_manager.ResetUserSaveFile(); const auto& profiles = profile_manager.GetAllUsers(); for (const auto& user : profiles) { Service::Account::ProfileBase profile{}; @@ -323,16 +326,16 @@ void ConfigureProfileManager::ConfirmDeleteUser() { ASSERT(uuid); const auto username = GetAccountUsername(profile_manager, *uuid); - confirm_dialog->SetInfo(username, *uuid, [this, uuid]() { DeleteUser(*uuid); }); + confirm_dialog->SetInfo(username, *uuid, index); confirm_dialog->show(); } -void ConfigureProfileManager::DeleteUser(const Common::UUID& uuid) { +void ConfigureProfileManager::DeleteUser(const int index) { if (Settings::values.current_user.GetValue() == tree_view->currentIndex().row()) { Settings::values.current_user = 0; } - if (!profile_manager.RemoveUser(uuid)) { + if (!profile_manager.RemoveProfileAtIndex(index)) { return; } @@ -378,19 +381,20 @@ ConfigureProfileManagerDeleteDialog::ConfigureProfileManagerDeleteDialog(QWidget setMinimumSize(380, 160); connect(dialog_button_box, &QDialogButtonBox::rejected, this, [this]() { close(); }); + connect(dialog_button_box, &QDialogButtonBox::accepted, this, [this]() { + close(); + emit deleteUser(m_index); + }); } ConfigureProfileManagerDeleteDialog::~ConfigureProfileManagerDeleteDialog() = default; void ConfigureProfileManagerDeleteDialog::SetInfo(const QString& username, const Common::UUID& uuid, - std::function accept_callback) { + int index) { label_info->setText( tr("Name: %1\nUUID: %2").arg(username, QString::fromStdString(uuid.FormattedString()))); icon_scene->clear(); icon_scene->addPixmap(GetIcon(uuid)); - connect(dialog_button_box, &QDialogButtonBox::accepted, this, [this, accept_callback]() { - close(); - accept_callback(); - }); + m_index = index; } diff --git a/src/yuzu/configuration/configure_profile_manager.h b/src/yuzu/configuration/configure_profile_manager.h index cdc0bd7fff..6e8c762452 100644 --- a/src/yuzu/configuration/configure_profile_manager.h +++ b/src/yuzu/configuration/configure_profile_manager.h @@ -40,18 +40,24 @@ namespace Ui { class ConfigureProfileManager; } +// TODO(crueter): Move this to a .ui def class ConfigureProfileManagerDeleteDialog : public QDialog { + Q_OBJECT public: explicit ConfigureProfileManagerDeleteDialog(QWidget* parent); ~ConfigureProfileManagerDeleteDialog(); void SetInfo(const QString& username, const Common::UUID& uuid, - std::function accept_callback); + int index); + +signals: + void deleteUser(int index); private: QDialogButtonBox* dialog_button_box; QGraphicsScene* icon_scene; QLabel* label_info; + int m_index = 0; }; class ConfigureProfileManager : public QWidget { @@ -66,6 +72,7 @@ public: private slots: void saveImage(QPixmap pixmap, Common::UUID uuid); void showContextMenu(const QPoint &pos); + void DeleteUser(const int index); private: void changeEvent(QEvent* event) override; @@ -80,7 +87,6 @@ private: void AddUser(); void EditUser(); void ConfirmDeleteUser(); - void DeleteUser(const Common::UUID& uuid); bool LoadAvatarData(); std::vector DecompressYaz0(const FileSys::VirtualFile& file);