Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
stenzek
GitHub Repository: stenzek/duckstation
Path: blob/master/src/duckstation-qt/achievementlogindialog.cpp
7493 views
1
// SPDX-FileCopyrightText: 2019-2025 Connor McLaughlin <[email protected]>
2
// SPDX-License-Identifier: CC-BY-NC-ND-4.0
3
4
#include "achievementlogindialog.h"
5
#include "qthost.h"
6
7
#include "core/achievements.h"
8
#include "core/core.h"
9
10
#include "common/error.h"
11
12
#include "moc_achievementlogindialog.cpp"
13
14
AchievementLoginDialog::AchievementLoginDialog(QWidget* parent, Achievements::LoginRequestReason reason)
15
: QDialog(parent), m_reason(reason)
16
{
17
m_ui.setupUi(this);
18
m_ui.iconLabel->setPixmap(QPixmap(QtHost::GetResourceQPath("images/ra-icon.webp", true)));
19
QFont title_font(m_ui.titleLabel->font());
20
title_font.setBold(true);
21
title_font.setPixelSize(20);
22
m_ui.titleLabel->setFont(title_font);
23
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
24
setAttribute(Qt::WA_DeleteOnClose);
25
26
// Adjust text if needed based on reason.
27
if (reason == Achievements::LoginRequestReason::TokenInvalid)
28
{
29
m_ui.instructionText->setText(tr("<strong>Your RetroAchievements login token is no longer valid.</strong> You must "
30
"re-enter your credentials for achievements to be tracked. Your password will not "
31
"be saved in DuckStation, an access token will be generated and used instead."));
32
}
33
34
m_login = m_ui.buttonBox->addButton(tr("&Login"), QDialogButtonBox::AcceptRole);
35
m_login->setEnabled(false);
36
connectUi();
37
}
38
39
AchievementLoginDialog::~AchievementLoginDialog() = default;
40
41
void AchievementLoginDialog::loginClicked()
42
{
43
const QString username(m_ui.userName->text());
44
const QString password(m_ui.password->text());
45
46
// TODO: Make cancellable.
47
m_ui.status->setText(tr("Logging in..."));
48
enableUI(false);
49
50
Host::RunOnCoreThread([this, username, password]() {
51
Error error;
52
const bool result = Achievements::Login(username.toUtf8().constData(), password.toUtf8().constData(), &error);
53
const QString message = QString::fromStdString(error.GetDescription());
54
QMetaObject::invokeMethod(this, &AchievementLoginDialog::processLoginResult, Qt::QueuedConnection, result, message);
55
});
56
}
57
58
void AchievementLoginDialog::cancelClicked()
59
{
60
// Disable hardcore mode if we cancelled reauthentication.
61
if (m_reason == Achievements::LoginRequestReason::TokenInvalid && QtHost::IsSystemValid())
62
{
63
Host::RunOnCoreThread([]() {
64
if (System::IsValid() && !Achievements::HasActiveGame())
65
Achievements::DisableHardcoreMode(false, false);
66
});
67
}
68
69
reject();
70
}
71
72
void AchievementLoginDialog::processLoginResult(bool result, const QString& message)
73
{
74
if (!result)
75
{
76
QtUtils::AsyncMessageBox(
77
this, QMessageBox::Critical, tr("Login Error"),
78
tr("Login failed.\nError: %1\n\nPlease check your username and password, and try again.").arg(message));
79
m_ui.status->setText(tr("Login failed."));
80
enableUI(true);
81
return;
82
}
83
84
// don't ask to enable etc if we are just reauthenticating
85
if (m_reason == Achievements::LoginRequestReason::TokenInvalid)
86
{
87
accept();
88
return;
89
}
90
91
askToEnableAchievementsAndAccept();
92
}
93
94
void AchievementLoginDialog::askToEnableAchievementsAndAccept()
95
{
96
if (Core::GetBaseBoolSettingValue("Cheevos", "Enabled", false))
97
{
98
askToEnableHardcoreModeAndAccept();
99
return;
100
}
101
102
QMessageBox* const msgbox =
103
QtUtils::NewMessageBox(this, QMessageBox::Question, tr("Enable Achievements"),
104
tr("Achievement tracking is not currently enabled. Your login will have no effect until "
105
"after tracking is enabled.\n\nDo you want to enable tracking now?"),
106
QMessageBox::Yes | QMessageBox::No, QMessageBox::NoButton);
107
msgbox->connect(msgbox, &QMessageBox::accepted, this, [this]() {
108
Core::SetBaseBoolSettingValue("Cheevos", "Enabled", true);
109
Host::CommitBaseSettingChanges();
110
g_core_thread->applySettings();
111
askToEnableHardcoreModeAndAccept();
112
});
113
msgbox->connect(msgbox, &QMessageBox::rejected, this, &AchievementLoginDialog::accept);
114
msgbox->open();
115
}
116
117
void AchievementLoginDialog::askToEnableHardcoreModeAndAccept()
118
{
119
if (Core::GetBaseBoolSettingValue("Cheevos", "ChallengeMode", false))
120
{
121
askToResetGameAndAccept();
122
return;
123
}
124
125
QMessageBox* const msgbox = QtUtils::NewMessageBox(
126
this, QMessageBox::Question, tr("Enable Hardcore Mode"),
127
tr("Hardcore mode is not currently enabled. Enabling hardcore mode allows you to set times, scores, and "
128
"participate in game-specific leaderboards.\n\nHowever, hardcore mode also prevents the usage of save "
129
"states, cheats and slowdown functionality.\n\nDo you want to enable hardcore mode?"),
130
QMessageBox::Yes | QMessageBox::No, QMessageBox::NoButton);
131
msgbox->connect(msgbox, &QMessageBox::accepted, this, [this]() {
132
Core::SetBaseBoolSettingValue("Cheevos", "ChallengeMode", true);
133
Host::CommitBaseSettingChanges();
134
g_core_thread->applySettings();
135
askToResetGameAndAccept();
136
});
137
msgbox->connect(msgbox, &QMessageBox::rejected, this, &AchievementLoginDialog::accept);
138
msgbox->open();
139
}
140
141
void AchievementLoginDialog::askToResetGameAndAccept()
142
{
143
if (!QtHost::IsSystemValid())
144
{
145
accept();
146
return;
147
}
148
149
QMessageBox* const msgbox = QtUtils::NewMessageBox(
150
this, QMessageBox::Question, tr("Restart Game"),
151
tr("Hardcore mode will not be enabled until the game is restarted. Do you want to restart the game now?"),
152
QMessageBox::Yes | QMessageBox::No, QMessageBox::NoButton);
153
msgbox->connect(msgbox, &QMessageBox::accepted, this, [this]() {
154
g_core_thread->resetSystem(true);
155
accept();
156
});
157
msgbox->connect(msgbox, &QMessageBox::rejected, this, &AchievementLoginDialog::accept);
158
msgbox->open();
159
}
160
161
void AchievementLoginDialog::connectUi()
162
{
163
connect(m_ui.buttonBox, &QDialogButtonBox::accepted, this, &AchievementLoginDialog::loginClicked);
164
connect(m_ui.buttonBox, &QDialogButtonBox::rejected, this, &AchievementLoginDialog::cancelClicked);
165
166
auto enableLoginButton = [this](const QString&) { m_login->setEnabled(canEnableLoginButton()); };
167
connect(m_ui.userName, &QLineEdit::textChanged, enableLoginButton);
168
connect(m_ui.password, &QLineEdit::textChanged, enableLoginButton);
169
}
170
171
void AchievementLoginDialog::enableUI(bool enabled)
172
{
173
m_ui.userName->setEnabled(enabled);
174
m_ui.password->setEnabled(enabled);
175
m_ui.buttonBox->button(QDialogButtonBox::Cancel)->setEnabled(enabled);
176
m_login->setEnabled(enabled && canEnableLoginButton());
177
}
178
179
bool AchievementLoginDialog::canEnableLoginButton() const
180
{
181
return !m_ui.userName->text().isEmpty() && !m_ui.password->text().isEmpty();
182
}
183
184