diff --git a/src/duckstation-qt/graphicssettingswidget.cpp b/src/duckstation-qt/graphicssettingswidget.cpp index 6e7ba33bb..4db101456 100644 --- a/src/duckstation-qt/graphicssettingswidget.cpp +++ b/src/duckstation-qt/graphicssettingswidget.cpp @@ -939,25 +939,9 @@ void GraphicsSettingsWidget::populateGPUAdaptersAndResolutions(RenderAPI render_ m_ui.resolutionScale->disconnect(); m_ui.resolutionScale->clear(); - static constexpr const std::pair templates[] = { - {0, QT_TRANSLATE_NOOP("GraphicsSettingsWidget", "Automatic (Based on Window Size)")}, - {1, QT_TRANSLATE_NOOP("GraphicsSettingsWidget", "1x Native (Default)")}, - {3, QT_TRANSLATE_NOOP("GraphicsSettingsWidget", "3x Native (for 720p)")}, - {5, QT_TRANSLATE_NOOP("GraphicsSettingsWidget", "5x Native (for 1080p)")}, - {6, QT_TRANSLATE_NOOP("GraphicsSettingsWidget", "6x Native (for 1440p)")}, - {9, QT_TRANSLATE_NOOP("GraphicsSettingsWidget", "9x Native (for 4K)")}, - }; - const int max_scale = static_cast(current_adapter ? std::max(current_adapter->max_texture_size / 1024, 1) : 16); - for (int scale = 0; scale <= max_scale; scale++) - { - const auto it = std::find_if(std::begin(templates), std::end(templates), - [&scale](const std::pair& it) { return scale == it.first; }); - m_ui.resolutionScale->addItem((it != std::end(templates)) ? - qApp->translate("GraphicsSettingsWidget", it->second) : - qApp->translate("GraphicsSettingsWidget", "%1x Native").arg(scale)); - } + populateUpscalingModes(m_ui.resolutionScale, max_scale); SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.resolutionScale, "GPU", "ResolutionScale", 1); connect(m_ui.resolutionScale, QOverload::of(&QComboBox::currentIndexChanged), this, @@ -1011,6 +995,25 @@ void GraphicsSettingsWidget::populateGPUAdaptersAndResolutions(RenderAPI render_ } } +void GraphicsSettingsWidget::populateUpscalingModes(QComboBox* cb, int max_scale) +{ + static constexpr const std::pair templates[] = { + {0, QT_TRANSLATE_NOOP("GraphicsSettingsWidget", "Automatic (Based on Window Size)")}, + {1, QT_TRANSLATE_NOOP("GraphicsSettingsWidget", "1x Native (Default)")}, + {3, QT_TRANSLATE_NOOP("GraphicsSettingsWidget", "3x Native (for 720p)")}, + {5, QT_TRANSLATE_NOOP("GraphicsSettingsWidget", "5x Native (for 1080p)")}, + {6, QT_TRANSLATE_NOOP("GraphicsSettingsWidget", "6x Native (for 1440p)")}, + {9, QT_TRANSLATE_NOOP("GraphicsSettingsWidget", "9x Native (for 4K)")}, + }; + for (int scale = 0; scale <= max_scale; scale++) + { + const auto it = std::find_if(std::begin(templates), std::end(templates), + [&scale](const std::pair& it) { return scale == it.first; }); + cb->addItem((it != std::end(templates)) ? qApp->translate("GraphicsSettingsWidget", it->second) : + qApp->translate("GraphicsSettingsWidget", "%1x Native").arg(scale)); + } +} + void GraphicsSettingsWidget::updatePGXPSettingsEnabled() { const bool enabled = (effectiveRendererIsHardware() && m_dialog->getEffectiveBoolValue("GPU", "PGXPEnable", false) && diff --git a/src/duckstation-qt/graphicssettingswidget.h b/src/duckstation-qt/graphicssettingswidget.h index f86913901..d85cbcc2e 100644 --- a/src/duckstation-qt/graphicssettingswidget.h +++ b/src/duckstation-qt/graphicssettingswidget.h @@ -21,6 +21,8 @@ public: GraphicsSettingsWidget(SettingsWindow* dialog, QWidget* parent); ~GraphicsSettingsWidget(); + static void populateUpscalingModes(QComboBox* cb, int max_scale); + public Q_SLOTS: void onShowDebugSettingsChanged(bool enabled); diff --git a/src/duckstation-qt/setupwizarddialog.cpp b/src/duckstation-qt/setupwizarddialog.cpp index d9071a133..cfe3702b9 100644 --- a/src/duckstation-qt/setupwizarddialog.cpp +++ b/src/duckstation-qt/setupwizarddialog.cpp @@ -2,19 +2,23 @@ // SPDX-License-Identifier: CC-BY-NC-ND-4.0 #include "setupwizarddialog.h" +#include "achievementlogindialog.h" #include "controllerbindingwidgets.h" #include "controllersettingwidgetbinder.h" +#include "graphicssettingswidget.h" #include "interfacesettingswidget.h" #include "mainwindow.h" #include "qthost.h" #include "qtutils.h" #include "settingwidgetbinder.h" +#include "core/achievements.h" #include "core/controller.h" #include "util/input_manager.h" #include "common/file_system.h" +#include "common/string_util.h" #include "fmt/format.h" @@ -169,6 +173,8 @@ void SetupWizardDialog::setupUi() m_page_labels[Page_BIOS] = m_ui.labelBIOS; m_page_labels[Page_GameList] = m_ui.labelGameList; m_page_labels[Page_Controller] = m_ui.labelController; + m_page_labels[Page_Graphics] = m_ui.labelGraphics; + m_page_labels[Page_Achievements] = m_ui.labelAchievements; m_page_labels[Page_Complete] = m_ui.labelComplete; connect(m_ui.back, &QPushButton::clicked, this, &SetupWizardDialog::previousPage); @@ -179,6 +185,8 @@ void SetupWizardDialog::setupUi() setupBIOSPage(); setupGameListPage(); setupControllerPage(true); + setupGraphicsPage(true); + setupAchievementsPage(true); } void SetupWizardDialog::setupLanguagePage() @@ -209,6 +217,8 @@ void SetupWizardDialog::languageChanged() QtHost::UpdateApplicationLanguage(this); m_ui.retranslateUi(this); setupControllerPage(false); + setupGraphicsPage(false); + setupAchievementsPage(false); } void SetupWizardDialog::setupBIOSPage() @@ -505,3 +515,198 @@ void SetupWizardDialog::doMultipleDeviceAutomaticBinding(u32 port, QLabel* updat update_label->setText(findCurrentDeviceForPort(port)); } + +void SetupWizardDialog::setupGraphicsPage(bool initial) +{ + m_ui.renderer->disconnect(); + m_ui.renderer->clear(); + + for (u32 i = 0; i < static_cast(GPURenderer::Count); i++) + { + m_ui.renderer->addItem(QString::fromUtf8(Settings::GetRendererDisplayName(static_cast(i)))); + } + + SettingWidgetBinder::BindWidgetToEnumSetting(nullptr, m_ui.renderer, "GPU", "Renderer", &Settings::ParseRendererName, + &Settings::GetRendererName, Settings::DEFAULT_GPU_RENDERER); + + m_ui.resolutionScale->disconnect(); + m_ui.resolutionScale->clear(); + GraphicsSettingsWidget::populateUpscalingModes(m_ui.resolutionScale, 16); + SettingWidgetBinder::BindWidgetToIntSetting(nullptr, m_ui.resolutionScale, "GPU", "ResolutionScale", 1); + + m_ui.textureFiltering->disconnect(); + m_ui.textureFiltering->clear(); + m_ui.spriteTextureFiltering->disconnect(); + m_ui.spriteTextureFiltering->clear(); + + for (u32 i = 0; i < static_cast(GPUTextureFilter::Count); i++) + { + m_ui.textureFiltering->addItem( + QString::fromUtf8(Settings::GetTextureFilterDisplayName(static_cast(i)))); + m_ui.spriteTextureFiltering->addItem( + QString::fromUtf8(Settings::GetTextureFilterDisplayName(static_cast(i)))); + } + + SettingWidgetBinder::BindWidgetToEnumSetting(nullptr, m_ui.textureFiltering, "GPU", "TextureFilter", + &Settings::ParseTextureFilterName, &Settings::GetTextureFilterName, + Settings::DEFAULT_GPU_TEXTURE_FILTER); + SettingWidgetBinder::BindWidgetToEnumSetting(nullptr, m_ui.spriteTextureFiltering, "GPU", "SpriteTextureFilter", + &Settings::ParseTextureFilterName, &Settings::GetTextureFilterName, + Settings::DEFAULT_GPU_TEXTURE_FILTER); + + m_ui.displayAspectRatio->disconnect(); + m_ui.displayAspectRatio->clear(); + + for (u32 i = 0; i < static_cast(DisplayAspectRatio::Count); i++) + { + m_ui.displayAspectRatio->addItem( + QString::fromUtf8(Settings::GetDisplayAspectRatioDisplayName(static_cast(i)))); + } + + SettingWidgetBinder::BindWidgetToEnumSetting(nullptr, m_ui.displayAspectRatio, "Display", "AspectRatio", + &Settings::ParseDisplayAspectRatio, &Settings::GetDisplayAspectRatioName, + Settings::DEFAULT_DISPLAY_ASPECT_RATIO); + SettingWidgetBinder::BindWidgetToIntSetting(nullptr, m_ui.customAspectRatioNumerator, "Display", + "CustomAspectRatioNumerator", 1); + SettingWidgetBinder::BindWidgetToIntSetting(nullptr, m_ui.customAspectRatioDenominator, "Display", + "CustomAspectRatioDenominator", 1); + connect(m_ui.displayAspectRatio, QOverload::of(&QComboBox::currentIndexChanged), this, + &SetupWizardDialog::onGraphicsAspectRatioChanged); + onGraphicsAspectRatioChanged(); + + m_ui.displayCropMode->disconnect(); + m_ui.displayCropMode->clear(); + + for (u32 i = 0; i < static_cast(DisplayCropMode::MaxCount); i++) + { + m_ui.displayCropMode->addItem( + QString::fromUtf8(Settings::GetDisplayCropModeDisplayName(static_cast(i)))); + } + + SettingWidgetBinder::BindWidgetToEnumSetting(nullptr, m_ui.displayCropMode, "Display", "CropMode", + &Settings::ParseDisplayCropMode, &Settings::GetDisplayCropModeName, + Settings::DEFAULT_DISPLAY_CROP_MODE); + + m_ui.displayScaling->disconnect(); + m_ui.displayScaling->clear(); + + for (u32 i = 0; i < static_cast(DisplayScalingMode::Count); i++) + { + m_ui.displayScaling->addItem( + QString::fromUtf8(Settings::GetDisplayScalingDisplayName(static_cast(i)))); + } + + SettingWidgetBinder::BindWidgetToEnumSetting(nullptr, m_ui.displayScaling, "Display", "Scaling", + &Settings::ParseDisplayScaling, &Settings::GetDisplayScalingName, + Settings::DEFAULT_DISPLAY_SCALING); + + if (initial) + { + SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.pgxpEnable, "GPU", "PGXPEnable", false); + SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.widescreenHack, "GPU", "WidescreenHack", false); + } +} + +void SetupWizardDialog::onGraphicsAspectRatioChanged() +{ + const DisplayAspectRatio ratio = + Settings::ParseDisplayAspectRatio( + Host::GetBaseStringSettingValue("Display", "AspectRatio", + Settings::GetDisplayAspectRatioName(Settings::DEFAULT_DISPLAY_ASPECT_RATIO)) + .c_str()) + .value_or(Settings::DEFAULT_DISPLAY_ASPECT_RATIO); + + const bool is_custom = (ratio == DisplayAspectRatio::Custom); + + m_ui.customAspectRatioNumerator->setVisible(is_custom); + m_ui.customAspectRatioDenominator->setVisible(is_custom); + m_ui.customAspectRatioSeparator->setVisible(is_custom); +} + +void SetupWizardDialog::setupAchievementsPage(bool initial) +{ + if (initial) + { + SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.enable, "Cheevos", "Enabled", false); + SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.hardcoreMode, "Cheevos", "ChallengeMode", false); + connect(m_ui.enable, &QCheckBox::checkStateChanged, this, &SetupWizardDialog::updateAchievementsEnableState); + connect(m_ui.loginButton, &QPushButton::clicked, this, &SetupWizardDialog::onAchievementsLoginLogoutClicked); + connect(m_ui.viewProfile, &QPushButton::clicked, this, &SetupWizardDialog::onAchievementsViewProfileClicked); + } + + updateAchievementsEnableState(); + updateAchievementsLoginState(); +} + +void SetupWizardDialog::updateAchievementsEnableState() +{ + const bool enabled = Host::GetBaseBoolSettingValue("Cheevos", "Enabled", false); + m_ui.hardcoreMode->setEnabled(enabled); +} + +void SetupWizardDialog::updateAchievementsLoginState() +{ + const std::string username(Host::GetBaseStringSettingValue("Cheevos", "Username")); + const bool logged_in = !username.empty(); + + if (logged_in) + { + const u64 login_unix_timestamp = + StringUtil::FromChars(Host::GetBaseStringSettingValue("Cheevos", "LoginTimestamp", "0")).value_or(0); + const QDateTime login_timestamp(QDateTime::fromSecsSinceEpoch(static_cast(login_unix_timestamp))); + m_ui.loginStatus->setText(tr("Username: %1\nLogin token generated on %2.") + .arg(QString::fromStdString(username)) + .arg(login_timestamp.toString(Qt::TextDate))); + m_ui.loginButton->setText(tr("Logout")); + } + else + { + m_ui.loginStatus->setText(tr("Not Logged In.")); + m_ui.loginButton->setText(tr("Login...")); + } + + m_ui.viewProfile->setEnabled(logged_in); +} + +void SetupWizardDialog::onAchievementsLoginLogoutClicked() +{ + if (!Host::GetBaseStringSettingValue("Cheevos", "Username").empty()) + { + Host::RunOnCPUThread([]() { Achievements::Logout(); }, true); + updateAchievementsLoginState(); + return; + } + + AchievementLoginDialog login(this, Achievements::LoginRequestReason::UserInitiated); + int res = login.exec(); + if (res != 0) + return; + + updateAchievementsEnableState(); + updateAchievementsLoginState(); + + // Login can enable achievements/hardcore. + if (!m_ui.enable->isChecked() && Host::GetBaseBoolSettingValue("Cheevos", "Enabled", false)) + { + QSignalBlocker sb(m_ui.enable); + m_ui.enable->setChecked(true); + updateAchievementsLoginState(); + } + if (!m_ui.hardcoreMode->isChecked() && Host::GetBaseBoolSettingValue("Cheevos", "ChallengeMode", false)) + { + QSignalBlocker sb(m_ui.hardcoreMode); + m_ui.hardcoreMode->setChecked(true); + } +} + +void SetupWizardDialog::onAchievementsViewProfileClicked() +{ + const std::string username(Host::GetBaseStringSettingValue("Cheevos", "Username")); + if (username.empty()) + return; + + const QByteArray encoded_username(QUrl::toPercentEncoding(QString::fromStdString(username))); + QtUtils::OpenURL( + QtUtils::GetRootWidget(this), + QUrl(QStringLiteral("https://retroachievements.org/user/%1").arg(QString::fromUtf8(encoded_username)))); +} diff --git a/src/duckstation-qt/setupwizarddialog.h b/src/duckstation-qt/setupwizarddialog.h index 471f326a0..fe3768454 100644 --- a/src/duckstation-qt/setupwizarddialog.h +++ b/src/duckstation-qt/setupwizarddialog.h @@ -57,6 +57,8 @@ private: Page_BIOS, Page_GameList, Page_Controller, + Page_Graphics, + Page_Achievements, Page_Complete, Page_Count, }; @@ -66,6 +68,8 @@ private: void setupBIOSPage(); void setupGameListPage(); void setupControllerPage(bool initial); + void setupGraphicsPage(bool initial); + void setupAchievementsPage(bool initial); void updateStylesheets(); void pageChangedTo(int page); @@ -78,6 +82,14 @@ private: void openAutomaticMappingMenu(u32 port, QLabel* update_label); void doDeviceAutomaticBinding(u32 port, QLabel* update_label, const QString& device); +private Q_SLOTS: + void onGraphicsAspectRatioChanged(); + void onAchievementsLoginLogoutClicked(); + void onAchievementsViewProfileClicked(); + void updateAchievementsEnableState(); + void updateAchievementsLoginState(); + +private: Ui::SetupWizardDialog m_ui; std::array m_page_labels; diff --git a/src/duckstation-qt/setupwizarddialog.ui b/src/duckstation-qt/setupwizarddialog.ui index e353d48b7..906ee63e0 100644 --- a/src/duckstation-qt/setupwizarddialog.ui +++ b/src/duckstation-qt/setupwizarddialog.ui @@ -7,7 +7,7 @@ 0 0 760 - 389 + 452 @@ -22,6 +22,172 @@ 10 + + + + + + + 0 + 0 + + + + + 128 + 128 + + + + + 128 + 128 + + + + + + + true + + + + + + + Qt::Orientation::Vertical + + + QSizePolicy::Policy::Fixed + + + + 20 + 20 + + + + + + + + 20 + + + + + + true + + + + Language + + + + + + + BIOS Image + + + + + + + Game Directories + + + + + + + Controller Setup + + + + + + + Graphics Setup + + + + + + + RetroAchievements + + + + + + + Complete + + + + + + + + + Qt::Orientation::Vertical + + + + 1 + 1 + + + + + + + + + + 6 + + + + + Qt::Orientation::Horizontal + + + + 40 + 20 + + + + + + + + &Back + + + + + + + &Next + + + true + + + + + + + &Cancel + + + + + @@ -50,7 +216,7 @@ <html><head/><body><h1 style=" margin-top:18px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:xx-large; font-weight:700;">Welcome to DuckStation!</span></h1><p>This wizard will help guide you through the configuration steps required to use the application. It is recommended if this is your first time installing DuckStation that you view the setup guide at <a href="https://github.com/stenzek/duckstation#downloading-and-running">https://github.com/stenzek/duckstation#downloading-and-running</a>.</p><p>By default, DuckStation will connect to the server at <a href="https://github.com/">github.com</a> to check for updates, and if available and confirmed, download update packages from <a href="https://github.com/">github.com</a>. If you do not wish for DuckStation to make any network connections on startup, you should uncheck the Automatic Updates option now. The Automatic Update setting can be changed later at any time in Interface Settings.</p><p>Please choose a language and theme to begin.</p></body></html> - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop true @@ -59,7 +225,7 @@ true - Qt::TextBrowserInteraction + Qt::TextInteractionFlag::TextBrowserInteraction @@ -95,7 +261,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -136,7 +302,7 @@ <html><head/><body><p>DuckStation requires a PS1 or PS2 BIOS in order to run.</p><p>For legal reasons, you must obtain a BIOS <span style=" font-weight:700;">from an actual PS1 unit that you own</span> (borrowing doesn't count). You should use Caetla or another utility to create an image from your console's BIOS ROM on your PC.</p><p>Once dumped, this BIOS image should be placed in the bios folder within the data directory shown below, or you can instruct DuckStation to scan an alternative directory.</p></body></html> - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop true @@ -231,7 +397,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -260,7 +426,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -292,7 +458,7 @@ <html><head/><body><p>DuckStation will automatically scan and identify games from the selected directories below, and populate the game list. These games should be dumped from discs you own. Utilities such as ImgBurn can be used to create images of game discs in .bin/.cue format.</p><p>Supported formats for dumps include: <span style=" font-weight:700;">.cue</span> (Cue Sheets), <span style=" font-weight:700;">.iso/.img</span> (Single Track Image), <span style=" font-weight:700;">.ecm</span> (Error Code Modeling Image), <span style=" font-weight:700;">.mds</span> (Media Descriptor Sidecar), <span style=" font-weight:700;">.chd</span> (Compressed Hunks of Data), <span style=" font-weight:700;">.pbp</span> (PlayStation Portable, Only Decrypted).</p></body></html> - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop true @@ -311,7 +477,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -333,11 +499,10 @@ Add... - - .. + - Qt::ToolButtonTextBesideIcon + Qt::ToolButtonStyle::ToolButtonTextBesideIcon @@ -353,11 +518,10 @@ Remove - - .. + - Qt::ToolButtonTextBesideIcon + Qt::ToolButtonStyle::ToolButtonTextBesideIcon @@ -441,7 +605,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -457,10 +621,10 @@ Automatic Mapping - + - Qt::ToolButtonTextBesideIcon + Qt::ToolButtonStyle::ToolButtonTextBesideIcon @@ -504,7 +668,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -520,10 +684,10 @@ Automatic Mapping - + - Qt::ToolButtonTextBesideIcon + Qt::ToolButtonStyle::ToolButtonTextBesideIcon @@ -535,12 +699,292 @@ - Qt::Vertical + Qt::Orientation::Vertical 20 - 40 + 1 + + + + + + + + + + 10 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + <html><head/><body><p>This page includes some of the commonly set graphics options in DuckStation.</p><p>These options are generally safe to enable, and compatible with most games. Changing the internal resolution and enabling PGXP geometry correction will significantly improve the graphical fidelty of most games.</p><p>It is recommended to use the <span style=" font-weight:700;">Automatic </span>renderer. You can change these options and others in <span style=" font-weight:700;">Graphics Settings </span>after completing setup.</p></body></html> + + + true + + + + + + + 10 + + + 10 + + + 10 + + + 10 + + + + + Renderer: + + + + + + + + + + Internal Resolution: + + + + + + + + + + Texture Filtering: + + + + + + + + + + Sprite Texture Filtering: + + + + + + + + + + Aspect Ratio: + + + + + + + + + + + + 1 + + + 9999 + + + + + + + : + + + + + + + 1 + + + 9999 + + + + + + + + + Crop: + + + + + + + + + + Scaling: + + + + + + + + + + + + Widescreen Rendering + + + + + + + PGXP Geometry Correction + + + + + + + + + + + Qt::Orientation::Vertical + + + + 20 + 1 + + + + + + + + + + 10 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + <html><head/><body><p>DuckStation supports earning achievements and leaderboard tracking with RetroAchievements.</p><p>If you have a RetroAchievements account, you can use the form below to log in. If not, you can register at <a href="https://retroachievements.org/createaccount.php"><span style=" text-decoration: underline; color:#99ebff;">https://retroachievements.org/createaccount.php</span></a>.</p><p>A RetroAchievements account is <span style=" font-weight:700;">not</span> required to use DuckStation.</p></body></html> + + + true + + + + + + + Settings + + + + + + Enable Achievements + + + + + + + Enable Hardcore Mode + + + + + + + + + + Account + + + + + + Username: +Login token generated at: + + + Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop + + + + + + + + + View Profile... + + + + + + + Login... + + + + + + + + + + + + Qt::Orientation::Vertical + + + + 20 + 1 @@ -567,7 +1011,7 @@ <html><head/><body><h1 style=" margin-top:18px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:xx-large; font-weight:700;">Setup Complete!</span></h1><p>You are now ready to run games.</p><p>Further options are available under the settings menu. You can also use the Big Picture UI for navigation entirely with a gamepad.</p><p>We hope you enjoy using DuckStation.</p></body></html> - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop true @@ -578,163 +1022,10 @@ - - - - - - - 0 - 0 - - - - - 128 - 128 - - - - - 128 - 128 - - - - - - - true - - - - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 20 - 20 - - - - - - - - 20 - - - - - - true - - - - Language - - - - - - - BIOS Image - - - - - - - Game Directories - - - - - - - Controller Setup - - - - - - - Complete - - - - - - - - - Qt::Vertical - - - - 1 - 1 - - - - - - - - - - 6 - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - &Back - - - - - - - &Next - - - true - - - - - - - &Cancel - - - - - - - +