summaryrefslogtreecommitdiff
path: root/Source/Core/DolphinQt/Achievements/AchievementBox.cpp
blob: 463e4e6e0b91e5430b2a3f5fcd2d444c2fe26ce4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
// Copyright 2024 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#ifdef USE_RETRO_ACHIEVEMENTS
#include "DolphinQt/Achievements/AchievementBox.h"

#include <QByteArray>
#include <QDateTime>
#include <QHBoxLayout>
#include <QLabel>
#include <QProgressBar>
#include <QSizePolicy>
#include <QVBoxLayout>
#include <QWidget>

#include "Core/AchievementManager.h"

#include "DolphinQt/QtUtils/FromStdString.h"

static constexpr size_t PROGRESS_LENGTH = 24;

AchievementBox::AchievementBox(QWidget* parent, const rc_client_achievement_t* achievement)
    : QGroupBox(parent), m_achievement(achievement)
{
  const auto& instance = AchievementManager::GetInstance();
  if (!instance.IsGameLoaded())
    return;

  m_badge = new QLabel();
  QLabel* title = new QLabel(QString::fromUtf8(achievement->title, strlen(achievement->title)));
  title->setWordWrap(true);
  title->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
  QLabel* description =
      new QLabel(QString::fromUtf8(achievement->description, strlen(achievement->description)));
  description->setWordWrap(true);
  description->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
  QLabel* points = new QLabel(tr("%1 points").arg(achievement->points));
  m_status = new QLabel();
  m_progress_bar = new QProgressBar();
  QSizePolicy sp_retain = m_progress_bar->sizePolicy();
  sp_retain.setRetainSizeWhenHidden(true);
  m_progress_bar->setSizePolicy(sp_retain);
  m_progress_label = new QLabel();
  m_progress_label->setStyleSheet(QStringLiteral("background-color:transparent;"));
  m_progress_label->setAlignment(Qt::AlignCenter);

  QVBoxLayout* a_col_left = new QVBoxLayout();
  a_col_left->addSpacerItem(new QSpacerItem(0, 0));
  a_col_left->addWidget(m_badge);
  a_col_left->addSpacerItem(new QSpacerItem(0, 0));
  a_col_left->setSizeConstraint(QLayout::SetFixedSize);
  a_col_left->setAlignment(Qt::AlignCenter);
  QVBoxLayout* a_col_right = new QVBoxLayout();
  a_col_right->addWidget(title);
  a_col_right->addWidget(description);
  a_col_right->addWidget(points);
  a_col_right->addWidget(m_status);
  a_col_right->addWidget(m_progress_bar);
  QVBoxLayout* a_prog_layout = new QVBoxLayout(m_progress_bar);
  a_prog_layout->setContentsMargins(0, 0, 0, 0);
  a_prog_layout->addWidget(m_progress_label);
  QHBoxLayout* a_total = new QHBoxLayout();
  a_total->addLayout(a_col_left);
  a_total->addLayout(a_col_right);
  setLayout(a_total);

  UpdateData();
}

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->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.data(), 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->unlocked)
    {
      if (m_achievement->unlock_time != 0)
      {
        m_status->setText(
            // i18n: %1 is a date/time.
            tr("Unlocked at %1")
                .arg(QDateTime::fromSecsSinceEpoch(m_achievement->unlock_time).toString()));
      }
      else
      {
        m_status->setText(tr("Unlocked"));
      }
    }
    else
    {
      m_status->setText(tr("Locked"));
    }
  }

  UpdateProgress();
}

void AchievementBox::UpdateProgress()
{
  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;

  if (m_achievement->measured_percent > 0.000)
  {
    m_progress_bar->setRange(0, 100);
    m_progress_bar->setValue(m_achievement->unlocked ? 100 : m_achievement->measured_percent);
    m_progress_bar->setTextVisible(false);
    m_progress_label->setText(
        QString::fromUtf8(m_achievement->measured_progress,
                          qstrnlen(m_achievement->measured_progress, PROGRESS_LENGTH)));
    m_progress_label->setVisible(!m_achievement->unlocked);
    m_progress_bar->setVisible(true);
  }
  else
  {
    m_progress_bar->setVisible(false);
  }
}

#endif  // USE_RETRO_ACHIEVEMENTS