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