diff --git a/Source/Core/DolphinQt/Achievements/AchievementBox.cpp b/Source/Core/DolphinQt/Achievements/AchievementBox.cpp index 1e524db38f..1a8818aa04 100644 --- a/Source/Core/DolphinQt/Achievements/AchievementBox.cpp +++ b/Source/Core/DolphinQt/Achievements/AchievementBox.cpp @@ -65,32 +65,48 @@ AchievementBox::AchievementBox(QWidget* parent, rc_client_achievement_t* achieve } void AchievementBox::UpdateData() +{ + { + std::lock_guard lg{AchievementManager::GetInstance().GetLock()}; + // rc_client guarantees m_achievement will be valid as long as the game is loaded + if (!AchievementManager::GetInstance().IsGameLoaded()) + return; + + const auto& badge = AchievementManager::GetInstance().GetAchievementBadge( + m_achievement->id, m_achievement->state != RC_CLIENT_ACHIEVEMENT_STATE_UNLOCKED); + std::string_view color = AchievementManager::GRAY; + if (m_achievement->unlocked & RC_CLIENT_ACHIEVEMENT_UNLOCKED_HARDCORE) + color = AchievementManager::GOLD; + else if (m_achievement->unlocked & RC_CLIENT_ACHIEVEMENT_UNLOCKED_SOFTCORE) + color = AchievementManager::BLUE; + QImage i_badge(&badge.data.front(), badge.width, badge.height, QImage::Format_RGBA8888); + m_badge->setPixmap( + QPixmap::fromImage(i_badge).scaled(64, 64, Qt::KeepAspectRatio, Qt::SmoothTransformation)); + m_badge->adjustSize(); + m_badge->setStyleSheet( + QStringLiteral("border: 4px solid %1").arg(QtUtils::FromStdString(color))); + + if (m_achievement->state == RC_CLIENT_ACHIEVEMENT_STATE_UNLOCKED) + { + m_status->setText( + tr("Unlocked at %1") + .arg(QDateTime::fromSecsSinceEpoch(m_achievement->unlock_time).toString())); + } + else + { + m_status->setText(tr("Locked")); + } + } + + UpdateProgress(); +} + +void AchievementBox::UpdateProgress() { std::lock_guard lg{AchievementManager::GetInstance().GetLock()}; - - const auto& badge = AchievementManager::GetInstance().GetAchievementBadge( - m_achievement->id, m_achievement->state != RC_CLIENT_ACHIEVEMENT_STATE_UNLOCKED); - std::string_view color = AchievementManager::GRAY; - if (m_achievement->unlocked & RC_CLIENT_ACHIEVEMENT_UNLOCKED_HARDCORE) - color = AchievementManager::GOLD; - else if (m_achievement->unlocked & RC_CLIENT_ACHIEVEMENT_UNLOCKED_SOFTCORE) - color = AchievementManager::BLUE; - QImage i_badge(&badge.data.front(), badge.width, badge.height, QImage::Format_RGBA8888); - m_badge->setPixmap( - QPixmap::fromImage(i_badge).scaled(64, 64, Qt::KeepAspectRatio, Qt::SmoothTransformation)); - m_badge->adjustSize(); - m_badge->setStyleSheet(QStringLiteral("border: 4px solid %1").arg(QtUtils::FromStdString(color))); - - if (m_achievement->state == RC_CLIENT_ACHIEVEMENT_STATE_UNLOCKED) - { - m_status->setText( - tr("Unlocked at %1") - .arg(QDateTime::fromSecsSinceEpoch(m_achievement->unlock_time).toString())); - } - else - { - m_status->setText(tr("Locked")); - } + // rc_client guarantees m_achievement will be valid as long as the game is loaded + if (!AchievementManager::GetInstance().IsGameLoaded()) + return; if (m_achievement->measured_percent > 0.000) { diff --git a/Source/Core/DolphinQt/Achievements/AchievementBox.h b/Source/Core/DolphinQt/Achievements/AchievementBox.h index 596893b148..92b1e75878 100644 --- a/Source/Core/DolphinQt/Achievements/AchievementBox.h +++ b/Source/Core/DolphinQt/Achievements/AchievementBox.h @@ -20,6 +20,7 @@ class AchievementBox final : public QGroupBox public: explicit AchievementBox(QWidget* parent, rc_client_achievement_t* achievement); void UpdateData(); + void UpdateProgress(); private: QLabel* m_badge; diff --git a/Source/Core/DolphinQt/Achievements/AchievementProgressWidget.cpp b/Source/Core/DolphinQt/Achievements/AchievementProgressWidget.cpp index 741cb61227..235f37a5d8 100644 --- a/Source/Core/DolphinQt/Achievements/AchievementProgressWidget.cpp +++ b/Source/Core/DolphinQt/Achievements/AchievementProgressWidget.cpp @@ -42,33 +42,51 @@ void AchievementProgressWidget::UpdateData(bool clean_all) { m_achievement_boxes.clear(); ClearLayoutRecursively(m_common_layout); - - auto& instance = AchievementManager::GetInstance(); - if (!instance.IsGameLoaded()) - return; - auto* client = instance.GetClient(); - auto* achievement_list = rc_client_create_achievement_list( - client, RC_CLIENT_ACHIEVEMENT_CATEGORY_CORE_AND_UNOFFICIAL, - RC_CLIENT_ACHIEVEMENT_LIST_GROUPING_PROGRESS); - for (u32 ix = 0; ix < achievement_list->num_buckets; ix++) - { - m_common_layout->addWidget(new QLabel(tr(achievement_list->buckets[ix].label))); - for (u32 jx = 0; jx < achievement_list->buckets[ix].num_achievements; jx++) - { - auto* achievement = achievement_list->buckets[ix].achievements[jx]; - m_achievement_boxes[achievement->id] = std::make_shared(this, achievement); - m_common_layout->addWidget(m_achievement_boxes[achievement->id].get()); - } - } - rc_client_destroy_achievement_list(achievement_list); } else { - for (auto box : m_achievement_boxes) + while (auto* item = m_common_layout->takeAt(0)) { - box.second->UpdateData(); + auto* widget = item->widget(); + m_common_layout->removeWidget(widget); + if (std::strcmp(widget->metaObject()->className(), "QLabel") == 0) + { + widget->deleteLater(); + delete item; + } } } + + auto& instance = AchievementManager::GetInstance(); + if (!instance.IsGameLoaded()) + return; + auto* client = instance.GetClient(); + auto* achievement_list = + rc_client_create_achievement_list(client, RC_CLIENT_ACHIEVEMENT_CATEGORY_CORE_AND_UNOFFICIAL, + RC_CLIENT_ACHIEVEMENT_LIST_GROUPING_PROGRESS); + if (!achievement_list) + return; + for (u32 ix = 0; ix < achievement_list->num_buckets; ix++) + { + m_common_layout->addWidget(new QLabel(tr(achievement_list->buckets[ix].label))); + for (u32 jx = 0; jx < achievement_list->buckets[ix].num_achievements; jx++) + { + auto* achievement = achievement_list->buckets[ix].achievements[jx]; + auto box_itr = m_achievement_boxes.lower_bound(achievement->id); + if (box_itr != m_achievement_boxes.end() && box_itr->first == achievement->id) + { + box_itr->second->UpdateProgress(); + m_common_layout->addWidget(box_itr->second.get()); + } + else + { + const auto new_box_itr = m_achievement_boxes.try_emplace( + box_itr, achievement->id, std::make_shared(this, achievement)); + m_common_layout->addWidget(new_box_itr->second.get()); + } + } + } + rc_client_destroy_achievement_list(achievement_list); } void AchievementProgressWidget::UpdateData( diff --git a/Source/Core/DolphinQt/Achievements/AchievementsWindow.cpp b/Source/Core/DolphinQt/Achievements/AchievementsWindow.cpp index a0e750c4ba..4598e37231 100644 --- a/Source/Core/DolphinQt/Achievements/AchievementsWindow.cpp +++ b/Source/Core/DolphinQt/Achievements/AchievementsWindow.cpp @@ -91,7 +91,7 @@ void AchievementsWindow::UpdateData(AchievementManager::UpdatedItems updated_ite { m_header_widget->UpdateData(); } - if (updated_items.all_achievements) + if (updated_items.all_achievements || updated_items.rich_presence) m_progress_widget->UpdateData(false); else if (updated_items.achievements.size() > 0) m_progress_widget->UpdateData(updated_items.achievements);