mirror of
https://github.com/WinampDesktop/winamp.git
synced 2025-06-15 11:15:47 -04:00
Achievements: Switch to rc_client
This commit is contained in:
@ -1,16 +1,29 @@
|
||||
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||
|
||||
#include "achievementlogindialog.h"
|
||||
#include "core/achievements.h"
|
||||
#include "qthost.h"
|
||||
|
||||
#include "core/achievements.h"
|
||||
|
||||
#include "common/error.h"
|
||||
|
||||
#include <QtWidgets/QMessageBox>
|
||||
|
||||
AchievementLoginDialog::AchievementLoginDialog(QWidget* parent) : QDialog(parent)
|
||||
AchievementLoginDialog::AchievementLoginDialog(QWidget* parent, Achievements::LoginRequestReason reason)
|
||||
: QDialog(parent)
|
||||
{
|
||||
m_ui.setupUi(this);
|
||||
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||
|
||||
// Adjust text if needed based on reason.
|
||||
if (reason == Achievements::LoginRequestReason::TokenInvalid)
|
||||
{
|
||||
m_ui.instructionText->setText(tr("<strong>Your RetroAchievements login token is no longer valid.</strong> You must "
|
||||
"re-enter your credentials for achievements to be tracked. Your password will not "
|
||||
"be saved in DuckStation, an access token will be generated and used instead."));
|
||||
}
|
||||
|
||||
m_login = m_ui.buttonBox->addButton(tr("&Login"), QDialogButtonBox::AcceptRole);
|
||||
m_login->setEnabled(false);
|
||||
connectUi();
|
||||
@ -28,8 +41,11 @@ void AchievementLoginDialog::loginClicked()
|
||||
enableUI(false);
|
||||
|
||||
Host::RunOnCPUThread([this, username, password]() {
|
||||
const bool result = Achievements::Login(username.toStdString().c_str(), password.toStdString().c_str());
|
||||
QMetaObject::invokeMethod(this, "processLoginResult", Qt::QueuedConnection, Q_ARG(bool, result));
|
||||
Error error;
|
||||
const bool result = Achievements::Login(username.toUtf8().constData(), password.toUtf8().constData(), &error);
|
||||
const QString message = QString::fromStdString(error.GetDescription());
|
||||
QMetaObject::invokeMethod(this, "processLoginResult", Qt::QueuedConnection, Q_ARG(bool, result),
|
||||
Q_ARG(const QString&, message));
|
||||
});
|
||||
}
|
||||
|
||||
@ -38,12 +54,13 @@ void AchievementLoginDialog::cancelClicked()
|
||||
done(1);
|
||||
}
|
||||
|
||||
void AchievementLoginDialog::processLoginResult(bool result)
|
||||
void AchievementLoginDialog::processLoginResult(bool result, const QString& message)
|
||||
{
|
||||
if (!result)
|
||||
{
|
||||
QMessageBox::critical(this, tr("Login Error"),
|
||||
tr("Login failed. Please check your username and password, and try again."));
|
||||
QMessageBox::critical(
|
||||
this, tr("Login Error"),
|
||||
tr("Login failed.\nError: %1\n\nPlease check your username and password, and try again.").arg(message));
|
||||
m_ui.status->setText(tr("Login failed."));
|
||||
enableUI(true);
|
||||
return;
|
||||
|
@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||
|
||||
#pragma once
|
||||
@ -6,18 +6,22 @@
|
||||
#include <QtWidgets/QDialog>
|
||||
#include <QtWidgets/QPushButton>
|
||||
|
||||
namespace Achievements {
|
||||
enum class LoginRequestReason;
|
||||
}
|
||||
|
||||
class AchievementLoginDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
AchievementLoginDialog(QWidget* parent);
|
||||
AchievementLoginDialog(QWidget* parent, Achievements::LoginRequestReason reason);
|
||||
~AchievementLoginDialog();
|
||||
|
||||
private Q_SLOTS:
|
||||
void loginClicked();
|
||||
void cancelClicked();
|
||||
void processLoginResult(bool result);
|
||||
void processLoginResult(bool result, const QString& message);
|
||||
|
||||
private:
|
||||
void connectUi();
|
||||
|
@ -64,9 +64,9 @@
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<widget class="QLabel" name="instructionText">
|
||||
<property name="text">
|
||||
<string>Please enter user name and password for retroachievements.org below. Your password will not be saved in DuckStation, an access token will be generated and used instead.</string>
|
||||
<string>Please enter your user name and password for retroachievements.org below. Your password will not be saved in DuckStation, an access token will be generated and used instead.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
|
@ -24,54 +24,64 @@ AchievementSettingsWidget::AchievementSettingsWidget(SettingsDialog* dialog, QWi
|
||||
m_ui.setupUi(this);
|
||||
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.enable, "Cheevos", "Enabled", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.richPresence, "Cheevos", "RichPresence", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.challengeMode, "Cheevos", "ChallengeMode", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.testMode, "Cheevos", "TestMode", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.unofficialTestMode, "Cheevos", "UnofficialTestMode", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.hardcoreMode, "Cheevos", "ChallengeMode", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.achievementNotifications, "Cheevos", "Notifications", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.leaderboardNotifications, "Cheevos",
|
||||
"LeaderboardNotifications", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.soundEffects, "Cheevos", "SoundEffects", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.overlays, "Cheevos", "Overlays", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.encoreMode, "Cheevos", "EncoreMode", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.spectatorMode, "Cheevos", "SpectatorMode", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.unofficialAchievements, "Cheevos", "UnofficialTestMode",
|
||||
false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.useFirstDiscFromPlaylist, "Cheevos",
|
||||
"UseFirstDiscFromPlaylist", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.leaderboards, "Cheevos", "Leaderboards", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.notifications, "Cheevos", "Notifications", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.soundEffects, "Cheevos", "SoundEffects", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.primedIndicators, "Cheevos", "PrimedIndicators", true);
|
||||
SettingWidgetBinder::BindWidgetToFloatSetting(sif, m_ui.achievementNotificationsDuration, "Cheevos",
|
||||
"NotificationsDuration",
|
||||
Settings::DEFAULT_ACHIEVEMENT_NOTIFICATION_TIME);
|
||||
SettingWidgetBinder::BindWidgetToFloatSetting(sif, m_ui.leaderboardNotificationsDuration, "Cheevos",
|
||||
"LeaderboardsDuration",
|
||||
Settings::DEFAULT_LEADERBOARD_NOTIFICATION_TIME);
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.enable, tr("Enable Achievements"), tr("Unchecked"),
|
||||
tr("When enabled and logged in, DuckStation will scan for achievements on startup."));
|
||||
dialog->registerWidgetHelp(m_ui.testMode, tr("Enable Test Mode"), tr("Unchecked"),
|
||||
tr("When enabled, DuckStation will assume all achievements are locked and not send any "
|
||||
"unlock notifications to the server."));
|
||||
dialog->registerWidgetHelp(
|
||||
m_ui.unofficialTestMode, tr("Test Unofficial Achievements"), tr("Unchecked"),
|
||||
tr("When enabled, DuckStation will list achievements from unofficial sets. Please note that these achievements are "
|
||||
"not tracked by RetroAchievements, so they unlock every time."));
|
||||
dialog->registerWidgetHelp(
|
||||
m_ui.richPresence, tr("Enable Rich Presence"), tr("Unchecked"),
|
||||
tr("When enabled, rich presence information will be collected and sent to the server where supported."));
|
||||
dialog->registerWidgetHelp(
|
||||
m_ui.useFirstDiscFromPlaylist, tr("Use First Disc From Playlist"), tr("Unchecked"),
|
||||
tr(
|
||||
"When enabled, the first disc in a playlist will be used for achievements, regardless of which disc is active."));
|
||||
dialog->registerWidgetHelp(m_ui.challengeMode, tr("Enable Hardcore Mode"), tr("Unchecked"),
|
||||
dialog->registerWidgetHelp(m_ui.hardcoreMode, tr("Enable Hardcore Mode"), tr("Unchecked"),
|
||||
tr("\"Challenge\" mode for achievements, including leaderboard tracking. Disables save "
|
||||
"state, cheats, and slowdown functions."));
|
||||
dialog->registerWidgetHelp(m_ui.achievementNotifications, tr("Show Achievement Notifications"), tr("Checked"),
|
||||
tr("Displays popup messages on events such as achievement unlocks and game completion."));
|
||||
dialog->registerWidgetHelp(
|
||||
m_ui.notifications, tr("Show Notifications"), tr("Checked"),
|
||||
tr("Displays popup messages on events such as achievement unlocks and leaderboard submissions."));
|
||||
m_ui.leaderboardNotifications, tr("Show Leaderboard Notifications"), tr("Checked"),
|
||||
tr("Displays popup messages when starting, submitting, or failing a leaderboard challenge."));
|
||||
dialog->registerWidgetHelp(
|
||||
m_ui.soundEffects, tr("Enable Sound Effects"), tr("Checked"),
|
||||
tr("Plays sound effects for events such as achievement unlocks and leaderboard submissions."));
|
||||
dialog->registerWidgetHelp(
|
||||
m_ui.leaderboards, tr("Enable Leaderboards"), tr("Checked"),
|
||||
tr("Enables tracking and submission of leaderboards in supported games. If leaderboards "
|
||||
"are disabled, you will still be able to view the leaderboard and scores, but no scores will be uploaded."));
|
||||
dialog->registerWidgetHelp(
|
||||
m_ui.primedIndicators, tr("Show Challenge Indicators"), tr("Checked"),
|
||||
m_ui.overlays, tr("Enable In-Game Overlays"), tr("Checked"),
|
||||
tr("Shows icons in the lower-right corner of the screen when a challenge/primed achievement is active."));
|
||||
dialog->registerWidgetHelp(m_ui.encoreMode, tr("Enable Encore Mode"), tr("Unchecked"),
|
||||
tr("When enabled, each session will behave as if no achievements have been unlocked."));
|
||||
dialog->registerWidgetHelp(m_ui.spectatorMode, tr("Enable Spectator Mode"), tr("Unchecked"),
|
||||
tr("When enabled, DuckStation will assume all achievements are locked and not send any "
|
||||
"unlock notifications to the server."));
|
||||
dialog->registerWidgetHelp(
|
||||
m_ui.unofficialAchievements, tr("Test Unofficial Achievements"), tr("Unchecked"),
|
||||
tr("When enabled, DuckStation will list achievements from unofficial sets. Please note that these achievements are "
|
||||
"not tracked by RetroAchievements, so they unlock every time."));
|
||||
dialog->registerWidgetHelp(
|
||||
m_ui.useFirstDiscFromPlaylist, tr("Use First Disc From Playlist"), tr("Unchecked"),
|
||||
tr(
|
||||
"When enabled, the first disc in a playlist will be used for achievements, regardless of which disc is active."));
|
||||
|
||||
connect(m_ui.enable, &QCheckBox::stateChanged, this, &AchievementSettingsWidget::updateEnableState);
|
||||
connect(m_ui.notifications, &QCheckBox::stateChanged, this, &AchievementSettingsWidget::updateEnableState);
|
||||
connect(m_ui.challengeMode, &QCheckBox::stateChanged, this, &AchievementSettingsWidget::updateEnableState);
|
||||
connect(m_ui.challengeMode, &QCheckBox::stateChanged, this, &AchievementSettingsWidget::onChallengeModeStateChanged);
|
||||
connect(m_ui.hardcoreMode, &QCheckBox::stateChanged, this, &AchievementSettingsWidget::updateEnableState);
|
||||
connect(m_ui.hardcoreMode, &QCheckBox::stateChanged, this, &AchievementSettingsWidget::onHardcoreModeStateChanged);
|
||||
connect(m_ui.achievementNotifications, &QCheckBox::stateChanged, this, &AchievementSettingsWidget::updateEnableState);
|
||||
connect(m_ui.leaderboardNotifications, &QCheckBox::stateChanged, this, &AchievementSettingsWidget::updateEnableState);
|
||||
connect(m_ui.achievementNotificationsDuration, &QSlider::valueChanged, this,
|
||||
&AchievementSettingsWidget::onAchievementsNotificationDurationSliderChanged);
|
||||
connect(m_ui.leaderboardNotificationsDuration, &QSlider::valueChanged, this,
|
||||
&AchievementSettingsWidget::onLeaderboardsNotificationDurationSliderChanged);
|
||||
|
||||
if (!m_dialog->isPerGameSettings())
|
||||
{
|
||||
@ -95,6 +105,8 @@ AchievementSettingsWidget::AchievementSettingsWidget(SettingsDialog* dialog, QWi
|
||||
}
|
||||
|
||||
updateEnableState();
|
||||
onAchievementsNotificationDurationSliderChanged();
|
||||
onLeaderboardsNotificationDurationSliderChanged();
|
||||
}
|
||||
|
||||
AchievementSettingsWidget::~AchievementSettingsWidget() = default;
|
||||
@ -102,19 +114,24 @@ AchievementSettingsWidget::~AchievementSettingsWidget() = default;
|
||||
void AchievementSettingsWidget::updateEnableState()
|
||||
{
|
||||
const bool enabled = m_dialog->getEffectiveBoolValue("Cheevos", "Enabled", false);
|
||||
const bool challenge = m_dialog->getEffectiveBoolValue("Cheevos", "ChallengeMode", false);
|
||||
m_ui.testMode->setEnabled(enabled);
|
||||
m_ui.useFirstDiscFromPlaylist->setEnabled(enabled);
|
||||
m_ui.richPresence->setEnabled(enabled);
|
||||
m_ui.challengeMode->setEnabled(enabled);
|
||||
m_ui.leaderboards->setEnabled(enabled && challenge);
|
||||
m_ui.unofficialTestMode->setEnabled(enabled);
|
||||
m_ui.notifications->setEnabled(enabled);
|
||||
const bool notifications = enabled && m_dialog->getEffectiveBoolValue("Cheevos", "Notifications", true);
|
||||
const bool lb_notifications = enabled && m_dialog->getEffectiveBoolValue("Cheevos", "LeaderboardNotifications", true);
|
||||
m_ui.hardcoreMode->setEnabled(enabled);
|
||||
m_ui.achievementNotifications->setEnabled(enabled);
|
||||
m_ui.leaderboardNotifications->setEnabled(enabled);
|
||||
m_ui.achievementNotificationsDuration->setEnabled(notifications);
|
||||
m_ui.achievementNotificationsDurationLabel->setEnabled(notifications);
|
||||
m_ui.leaderboardNotificationsDuration->setEnabled(lb_notifications);
|
||||
m_ui.leaderboardNotificationsDurationLabel->setEnabled(lb_notifications);
|
||||
m_ui.soundEffects->setEnabled(enabled);
|
||||
m_ui.primedIndicators->setEnabled(enabled);
|
||||
m_ui.overlays->setEnabled(enabled);
|
||||
m_ui.encoreMode->setEnabled(enabled);
|
||||
m_ui.spectatorMode->setEnabled(enabled);
|
||||
m_ui.unofficialAchievements->setEnabled(enabled);
|
||||
m_ui.useFirstDiscFromPlaylist->setEnabled(enabled);
|
||||
}
|
||||
|
||||
void AchievementSettingsWidget::onChallengeModeStateChanged()
|
||||
void AchievementSettingsWidget::onHardcoreModeStateChanged()
|
||||
{
|
||||
if (!QtHost::IsSystemValid())
|
||||
return;
|
||||
@ -140,6 +157,20 @@ void AchievementSettingsWidget::onChallengeModeStateChanged()
|
||||
g_emu_thread->resetSystem();
|
||||
}
|
||||
|
||||
void AchievementSettingsWidget::onAchievementsNotificationDurationSliderChanged()
|
||||
{
|
||||
const float duration = m_dialog->getEffectiveFloatValue("Cheevos", "NotificationsDuration",
|
||||
Settings::DEFAULT_ACHIEVEMENT_NOTIFICATION_TIME);
|
||||
m_ui.achievementNotificationsDurationLabel->setText(tr("%n seconds", nullptr, static_cast<int>(duration)));
|
||||
}
|
||||
|
||||
void AchievementSettingsWidget::onLeaderboardsNotificationDurationSliderChanged()
|
||||
{
|
||||
const float duration = m_dialog->getEffectiveFloatValue("Cheevos", "LeaderboardsDuration",
|
||||
Settings::DEFAULT_ACHIEVEMENT_NOTIFICATION_TIME);
|
||||
m_ui.leaderboardNotificationsDurationLabel->setText(tr("%n seconds", nullptr, static_cast<int>(duration)));
|
||||
}
|
||||
|
||||
void AchievementSettingsWidget::updateLoginState()
|
||||
{
|
||||
const std::string username(Host::GetBaseStringSettingValue("Cheevos", "Username"));
|
||||
@ -173,7 +204,7 @@ void AchievementSettingsWidget::onLoginLogoutPressed()
|
||||
return;
|
||||
}
|
||||
|
||||
AchievementLoginDialog login(this);
|
||||
AchievementLoginDialog login(this, Achievements::LoginRequestReason::UserInitiated);
|
||||
int res = login.exec();
|
||||
if (res != 0)
|
||||
return;
|
||||
@ -193,8 +224,7 @@ void AchievementSettingsWidget::onViewProfilePressed()
|
||||
QUrl(QStringLiteral("https://retroachievements.org/user/%1").arg(QString::fromUtf8(encoded_username))));
|
||||
}
|
||||
|
||||
void AchievementSettingsWidget::onAchievementsRefreshed(quint32 id, const QString& game_info_string, quint32 total,
|
||||
quint32 points)
|
||||
void AchievementSettingsWidget::onAchievementsRefreshed(quint32 id, const QString& game_info_string)
|
||||
{
|
||||
m_ui.gameInfo->setText(game_info_string);
|
||||
}
|
||||
|
@ -17,10 +17,12 @@ public:
|
||||
|
||||
private Q_SLOTS:
|
||||
void updateEnableState();
|
||||
void onChallengeModeStateChanged();
|
||||
void onHardcoreModeStateChanged();
|
||||
void onAchievementsNotificationDurationSliderChanged();
|
||||
void onLeaderboardsNotificationDurationSliderChanged();
|
||||
void onLoginLogoutPressed();
|
||||
void onViewProfilePressed();
|
||||
void onAchievementsRefreshed(quint32 id, const QString& game_info_string, quint32 total, quint32 points);
|
||||
void onAchievementsRefreshed(quint32 id, const QString& game_info_string);
|
||||
|
||||
private:
|
||||
void updateLoginState();
|
||||
|
@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>648</width>
|
||||
<height>475</height>
|
||||
<width>674</width>
|
||||
<height>481</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@ -29,20 +29,13 @@
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Global Settings</string>
|
||||
<string>Settings</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="1">
|
||||
<widget class="QCheckBox" name="richPresence">
|
||||
<property name="text">
|
||||
<string>Enable Rich Presence</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QCheckBox" name="leaderboards">
|
||||
<widget class="QCheckBox" name="spectatorMode">
|
||||
<property name="text">
|
||||
<string>Enable Leaderboards</string>
|
||||
<string>Enable Spectator Mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -53,52 +46,146 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="unofficialAchievements">
|
||||
<property name="text">
|
||||
<string>Test Unofficial Achievements</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="challengeMode">
|
||||
<widget class="QCheckBox" name="encoreMode">
|
||||
<property name="text">
|
||||
<string>Enable Encore Mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QCheckBox" name="hardcoreMode">
|
||||
<property name="text">
|
||||
<string>Enable Hardcore Mode</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="primedIndicators">
|
||||
<property name="text">
|
||||
<string>Show Challenge Indicators</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<item row="2" column="1">
|
||||
<widget class="QCheckBox" name="useFirstDiscFromPlaylist">
|
||||
<property name="text">
|
||||
<string>Use First Disc From Playlist</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QCheckBox" name="testMode">
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="notificationBox">
|
||||
<property name="title">
|
||||
<string>Notifications</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2" columnstretch="1,1">
|
||||
<item row="0" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3" stretch="1,0">
|
||||
<item>
|
||||
<widget class="QSlider" name="achievementNotificationsDuration">
|
||||
<property name="minimum">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>30</number>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="invertedAppearance">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="tickPosition">
|
||||
<enum>QSlider::TicksBelow</enum>
|
||||
</property>
|
||||
<property name="tickInterval">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="achievementNotificationsDurationLabel">
|
||||
<property name="text">
|
||||
<string>5 seconds</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="achievementNotifications">
|
||||
<property name="text">
|
||||
<string>Enable Test Mode</string>
|
||||
<string>Show Achievement Notifications</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QCheckBox" name="unofficialTestMode">
|
||||
<item row="1" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2" stretch="1,0">
|
||||
<item>
|
||||
<widget class="QSlider" name="leaderboardNotificationsDuration">
|
||||
<property name="minimum">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>30</number>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="invertedAppearance">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="tickPosition">
|
||||
<enum>QSlider::TicksBelow</enum>
|
||||
</property>
|
||||
<property name="tickInterval">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="leaderboardNotificationsDurationLabel">
|
||||
<property name="text">
|
||||
<string>5 seconds</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="leaderboardNotifications">
|
||||
<property name="text">
|
||||
<string>Test Unofficial Achievements</string>
|
||||
<string>Show Leaderboard Notifications</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="soundEffects">
|
||||
<property name="text">
|
||||
<string>Enable Sound Effects</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="notifications">
|
||||
<item row="2" column="1">
|
||||
<widget class="QCheckBox" name="overlays">
|
||||
<property name="text">
|
||||
<string>Show Notifications</string>
|
||||
<string>Enable In-Game Overlays</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -113,20 +200,17 @@
|
||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,0">
|
||||
<item>
|
||||
<widget class="QLabel" name="loginStatus">
|
||||
<property name="text">
|
||||
<string>Username:
|
||||
Login token generated at:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QPushButton" name="loginButton">
|
||||
<property name="text">
|
||||
<string>Login...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<widget class="QPushButton" name="viewProfile">
|
||||
<property name="text">
|
||||
@ -134,6 +218,13 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="loginButton">
|
||||
<property name="text">
|
||||
<string>Login...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
@ -144,7 +235,7 @@
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>120</height>
|
||||
<height>75</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title">
|
||||
|
@ -1,8 +1,9 @@
|
||||
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||
|
||||
#include "mainwindow.h"
|
||||
#include "aboutdialog.h"
|
||||
#include "achievementlogindialog.h"
|
||||
#include "autoupdaterdialog.h"
|
||||
#include "cheatmanagerdialog.h"
|
||||
#include "coverdownloaddialog.h"
|
||||
@ -507,14 +508,14 @@ void MainWindow::onSystemStarting()
|
||||
s_system_valid = false;
|
||||
s_system_paused = false;
|
||||
|
||||
updateEmulationActions(true, false, Achievements::ChallengeModeActive());
|
||||
updateEmulationActions(true, false, Achievements::IsHardcoreModeActive());
|
||||
}
|
||||
|
||||
void MainWindow::onSystemStarted()
|
||||
{
|
||||
m_was_disc_change_request = false;
|
||||
s_system_valid = true;
|
||||
updateEmulationActions(false, true, Achievements::ChallengeModeActive());
|
||||
updateEmulationActions(false, true, Achievements::IsHardcoreModeActive());
|
||||
updateWindowTitle();
|
||||
updateStatusBarWidgetVisibility();
|
||||
}
|
||||
@ -572,7 +573,7 @@ void MainWindow::onSystemDestroyed()
|
||||
return;
|
||||
}
|
||||
|
||||
updateEmulationActions(false, false, Achievements::ChallengeModeActive());
|
||||
updateEmulationActions(false, false, Achievements::IsHardcoreModeActive());
|
||||
if (m_display_widget)
|
||||
updateDisplayWidgetCursor();
|
||||
else
|
||||
@ -724,7 +725,7 @@ void MainWindow::populateGameListContextMenu(const GameList::Entry* entry, QWidg
|
||||
{
|
||||
std::vector<SaveStateInfo> available_states(System::GetAvailableSaveStates(entry->serial.c_str()));
|
||||
const QString timestamp_format = QLocale::system().dateTimeFormat(QLocale::ShortFormat);
|
||||
const bool challenge_mode = Achievements::ChallengeModeActive();
|
||||
const bool challenge_mode = Achievements::IsHardcoreModeActive();
|
||||
for (SaveStateInfo& ssi : available_states)
|
||||
{
|
||||
if (ssi.global)
|
||||
@ -1382,7 +1383,7 @@ void MainWindow::onGameListEntryContextMenuRequested(const QPoint& point)
|
||||
g_emu_thread->bootSystem(std::move(boot_params));
|
||||
});
|
||||
|
||||
if (m_ui.menuDebug->menuAction()->isVisible() && !Achievements::ChallengeModeActive())
|
||||
if (m_ui.menuDebug->menuAction()->isVisible() && !Achievements::IsHardcoreModeActive())
|
||||
{
|
||||
connect(menu.addAction(tr("Boot and Debug")), &QAction::triggered, [this, entry]() {
|
||||
m_open_debugger_on_start = true;
|
||||
@ -1874,7 +1875,7 @@ void MainWindow::switchToEmulationView()
|
||||
|
||||
void MainWindow::connectSignals()
|
||||
{
|
||||
updateEmulationActions(false, false, Achievements::ChallengeModeActive());
|
||||
updateEmulationActions(false, false, Achievements::IsHardcoreModeActive());
|
||||
|
||||
connect(qApp, &QGuiApplication::applicationStateChanged, this, &MainWindow::onApplicationStateChanged);
|
||||
|
||||
@ -1980,10 +1981,10 @@ void MainWindow::connectSignals()
|
||||
connect(g_emu_thread, &EmuThread::runningGameChanged, this, &MainWindow::onRunningGameChanged);
|
||||
connect(g_emu_thread, &EmuThread::mouseModeRequested, this, &MainWindow::onMouseModeRequested);
|
||||
connect(g_emu_thread, &EmuThread::fullscreenUIStateChange, this, &MainWindow::onFullscreenUIStateChange);
|
||||
#ifdef WITH_CHEEVOS
|
||||
connect(g_emu_thread, &EmuThread::achievementsLoginRequested, this, &MainWindow::onAchievementsLoginRequested);
|
||||
connect(g_emu_thread, &EmuThread::achievementsLoginSucceeded, this, &MainWindow::onAchievementsLoginSucceeded);
|
||||
connect(g_emu_thread, &EmuThread::achievementsChallengeModeChanged, this,
|
||||
&MainWindow::onAchievementsChallengeModeChanged);
|
||||
#endif
|
||||
|
||||
// These need to be queued connections to stop crashing due to menus opening/closing and switching focus.
|
||||
connect(m_game_list_widget, &GameListWidget::refreshProgress, this, &MainWindow::onGameListRefreshProgress);
|
||||
@ -2619,10 +2620,28 @@ void MainWindow::openMemoryCardEditor(const QString& card_a_path, const QString&
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::onAchievementsLoginRequested(Achievements::LoginRequestReason reason)
|
||||
{
|
||||
const auto lock = pauseAndLockSystem();
|
||||
|
||||
AchievementLoginDialog dlg(lock.getDialogParent(), reason);
|
||||
dlg.exec();
|
||||
}
|
||||
|
||||
void MainWindow::onAchievementsLoginSucceeded(const QString& display_name, quint32 points, quint32 sc_points,
|
||||
quint32 unread_messages)
|
||||
{
|
||||
const QString message = tr("RA: Logged in as %1 (%2, %3 softcore). %4 unread messages.")
|
||||
.arg(display_name)
|
||||
.arg(points)
|
||||
.arg(sc_points)
|
||||
.arg(unread_messages);
|
||||
m_ui.statusBar->showMessage(message);
|
||||
}
|
||||
|
||||
void MainWindow::onAchievementsChallengeModeChanged()
|
||||
{
|
||||
#ifdef WITH_CHEEVOS
|
||||
const bool active = Achievements::ChallengeModeActive();
|
||||
const bool active = Achievements::IsHardcoreModeActive();
|
||||
if (active)
|
||||
{
|
||||
if (m_cheat_manager_dialog)
|
||||
@ -2641,7 +2660,6 @@ void MainWindow::onAchievementsChallengeModeChanged()
|
||||
}
|
||||
|
||||
updateEmulationActions(false, System::IsValid(), active);
|
||||
#endif
|
||||
}
|
||||
|
||||
void MainWindow::onToolsMemoryCardEditorTriggered()
|
||||
|
@ -33,6 +33,9 @@ class DebuggerWindow;
|
||||
class MainWindow;
|
||||
|
||||
class GPUDevice;
|
||||
namespace Achievements {
|
||||
enum class LoginRequestReason;
|
||||
}
|
||||
namespace GameList {
|
||||
struct Entry;
|
||||
}
|
||||
@ -128,6 +131,9 @@ private Q_SLOTS:
|
||||
void onSystemPaused();
|
||||
void onSystemResumed();
|
||||
void onRunningGameChanged(const QString& filename, const QString& game_serial, const QString& game_title);
|
||||
void onAchievementsLoginRequested(Achievements::LoginRequestReason reason);
|
||||
void onAchievementsLoginSucceeded(const QString& display_name, quint32 points, quint32 sc_points,
|
||||
quint32 unread_messages);
|
||||
void onAchievementsChallengeModeChanged();
|
||||
void onApplicationStateChanged(Qt::ApplicationState state);
|
||||
|
||||
|
@ -1204,32 +1204,33 @@ void EmuThread::saveScreenshot()
|
||||
System::SaveScreenshot(nullptr, true, true);
|
||||
}
|
||||
|
||||
void Host::OnAchievementsLoginRequested(Achievements::LoginRequestReason reason)
|
||||
{
|
||||
emit g_emu_thread->achievementsLoginRequested(reason);
|
||||
}
|
||||
|
||||
void Host::OnAchievementsLoginSuccess(const char* username, u32 points, u32 sc_points, u32 unread_messages)
|
||||
{
|
||||
emit g_emu_thread->achievementsLoginSucceeded(QString::fromUtf8(username), points, sc_points, unread_messages);
|
||||
}
|
||||
|
||||
void Host::OnAchievementsRefreshed()
|
||||
{
|
||||
#ifdef WITH_CHEEVOS
|
||||
u32 game_id = 0;
|
||||
u32 achievement_count = 0;
|
||||
u32 max_points = 0;
|
||||
|
||||
QString game_info;
|
||||
|
||||
if (Achievements::HasActiveGame())
|
||||
{
|
||||
game_id = Achievements::GetGameID();
|
||||
achievement_count = Achievements::GetAchievementCount();
|
||||
max_points = Achievements::GetMaximumPointsForGame();
|
||||
|
||||
game_info = qApp
|
||||
->translate("EmuThread", "Game ID: %1\n"
|
||||
"Game Title: %2\n"
|
||||
"Achievements: %5 (%6)\n\n")
|
||||
.arg(game_id)
|
||||
.arg(QString::fromStdString(Achievements::GetGameTitle()))
|
||||
.arg(achievement_count)
|
||||
.arg(qApp->translate("EmuThread", "%n points", "", max_points));
|
||||
->translate("EmuThread", "Game: %1 (%2)\n")
|
||||
.arg(QString::fromStdString(Achievements::GetGameTitle()))
|
||||
.arg(game_id);
|
||||
|
||||
const std::string rich_presence_string(Achievements::GetRichPresenceString());
|
||||
if (!rich_presence_string.empty())
|
||||
const std::string& rich_presence_string = Achievements::GetRichPresenceString();
|
||||
if (Achievements::HasRichPresence() && !rich_presence_string.empty())
|
||||
game_info.append(QString::fromStdString(rich_presence_string));
|
||||
else
|
||||
game_info.append(qApp->translate("EmuThread", "Rich presence inactive or unsupported."));
|
||||
@ -1239,15 +1240,12 @@ void Host::OnAchievementsRefreshed()
|
||||
game_info = qApp->translate("EmuThread", "Game not loaded or no RetroAchievements available.");
|
||||
}
|
||||
|
||||
emit g_emu_thread->achievementsRefreshed(game_id, game_info, achievement_count, max_points);
|
||||
#endif
|
||||
emit g_emu_thread->achievementsRefreshed(game_id, game_info);
|
||||
}
|
||||
|
||||
void Host::OnAchievementsChallengeModeChanged()
|
||||
void Host::OnAchievementsHardcoreModeChanged()
|
||||
{
|
||||
#ifdef WITH_CHEEVOS
|
||||
emit g_emu_thread->achievementsChallengeModeChanged();
|
||||
#endif
|
||||
}
|
||||
|
||||
void EmuThread::doBackgroundControllerPoll()
|
||||
|
@ -45,14 +45,13 @@ class GPUDevice;
|
||||
class MainWindow;
|
||||
class DisplayWidget;
|
||||
|
||||
namespace Achievements {
|
||||
enum class LoginRequestReason;
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(std::optional<bool>);
|
||||
Q_DECLARE_METATYPE(std::shared_ptr<SystemBootParameters>);
|
||||
|
||||
// These cause errors when compiling with gcc, implicitly defined?
|
||||
// Q_DECLARE_METATYPE(std::function<void()>);
|
||||
// Q_DECLARE_METATYPE(GPURenderer);
|
||||
// Q_DECLARE_METATYPE(InputBindingKey);
|
||||
|
||||
class EmuThread : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -141,7 +140,10 @@ Q_SIGNALS:
|
||||
void inputProfileLoaded();
|
||||
void mouseModeRequested(bool relative, bool hide_cursor);
|
||||
void fullscreenUIStateChange(bool running);
|
||||
void achievementsRefreshed(quint32 id, const QString& game_info_string, quint32 total, quint32 points);
|
||||
void achievementsLoginRequested(Achievements::LoginRequestReason reason);
|
||||
void achievementsLoginSucceeded(const QString& display_name, quint32 points, quint32 sc_points,
|
||||
quint32 unread_messages);
|
||||
void achievementsRefreshed(quint32 id, const QString& game_info_string);
|
||||
void achievementsChallengeModeChanged();
|
||||
void cheatEnabled(quint32 index, bool enabled);
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||
|
||||
#include "settingsdialog.h"
|
||||
@ -7,6 +7,7 @@
|
||||
#include "biossettingswidget.h"
|
||||
#include "consolesettingswidget.h"
|
||||
|
||||
#include "achievementsettingswidget.h"
|
||||
#include "displaysettingswidget.h"
|
||||
#include "emulationsettingswidget.h"
|
||||
#include "enhancementsettingswidget.h"
|
||||
@ -19,6 +20,7 @@
|
||||
#include "postprocessingsettingswidget.h"
|
||||
#include "qthost.h"
|
||||
|
||||
#include "core/achievements.h"
|
||||
#include "core/host.h"
|
||||
|
||||
#include "util/ini_settings_interface.h"
|
||||
@ -29,11 +31,6 @@
|
||||
#include <QtWidgets/QMessageBox>
|
||||
#include <QtWidgets/QTextEdit>
|
||||
|
||||
#ifdef WITH_CHEEVOS
|
||||
#include "achievementsettingswidget.h"
|
||||
#include "core/achievements.h"
|
||||
#endif
|
||||
|
||||
static QList<SettingsDialog*> s_open_game_properties_dialogs;
|
||||
|
||||
SettingsDialog::SettingsDialog(QWidget* parent) : QDialog(parent)
|
||||
@ -129,7 +126,6 @@ void SettingsDialog::addPages()
|
||||
QString help_text(tr("<strong>Achievement Settings</strong><hr>These options control RetroAchievements. Mouse over "
|
||||
"an option for additional information."));
|
||||
|
||||
#ifdef WITH_CHEEVOS
|
||||
if (!Achievements::IsUsingRAIntegration())
|
||||
{
|
||||
addWidget(m_achievement_settings = new AchievementSettingsWidget(this, m_ui.settingsContainer), std::move(title),
|
||||
@ -144,13 +140,6 @@ void SettingsDialog::addPages()
|
||||
|
||||
addWidget(placeholder_label, std::move(title), std::move(icon_text), std::move(help_text));
|
||||
}
|
||||
#else
|
||||
QLabel* placeholder_label =
|
||||
new QLabel(tr("This DuckStation build was not compiled with RetroAchievements support."), m_ui.settingsContainer);
|
||||
placeholder_label->setAlignment(Qt::AlignLeft | Qt::AlignTop);
|
||||
|
||||
addWidget(placeholder_label, std::move(title), std::move(icon_text), std::move(help_text));
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!isPerGameSettings())
|
||||
|
Reference in New Issue
Block a user