From 2b9935e6f4445cda15479e631752a9029479a0db Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Sat, 10 May 2025 15:03:07 -0500 Subject: [PATCH 1/8] DolphinQt: Change main settings window QTabWidget into a QListWidget and QStackedWidget. --- .../Core/DolphinQt/Config/SettingsWindow.cpp | 148 ++++++++++++++---- Source/Core/DolphinQt/Config/SettingsWindow.h | 32 +++- Source/Core/DolphinQt/Settings/AudioPane.cpp | 2 +- 3 files changed, 148 insertions(+), 34 deletions(-) diff --git a/Source/Core/DolphinQt/Config/SettingsWindow.cpp b/Source/Core/DolphinQt/Config/SettingsWindow.cpp index 1883e8562e..f3618cc810 100644 --- a/Source/Core/DolphinQt/Config/SettingsWindow.cpp +++ b/Source/Core/DolphinQt/Config/SettingsWindow.cpp @@ -4,13 +4,13 @@ #include "DolphinQt/Config/SettingsWindow.h" #include -#include -#include +#include +#include +#include #include +#include "DolphinQt/QtUtils/QtUtils.h" #include "DolphinQt/QtUtils/WrapInScrollArea.h" -#include "DolphinQt/Resources.h" -#include "DolphinQt/Settings.h" #include "DolphinQt/Settings/AdvancedPane.h" #include "DolphinQt/Settings/AudioPane.h" #include "DolphinQt/Settings/GameCubePane.h" @@ -19,45 +19,137 @@ #include "DolphinQt/Settings/PathPane.h" #include "DolphinQt/Settings/WiiPane.h" -#include "Core/Core.h" - -SettingsWindow::SettingsWindow(QWidget* parent) : QDialog(parent) +StackedSettingsWindow::StackedSettingsWindow(QWidget* parent) : QDialog{parent} { - // Set Window Properties - setWindowTitle(tr("Settings")); setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); - // Main Layout - QVBoxLayout* layout = new QVBoxLayout; + // This eliminates the ugly line between the title bar and window contents with KDE Plasma. + setStyleSheet(QStringLiteral("QDialog { border: none; }")); - // Add content to layout before dialog buttons. - m_tab_widget = new QTabWidget(); - layout->addWidget(m_tab_widget); + auto* const layout = new QHBoxLayout{this}; - m_tab_widget->addTab(GetWrappedWidget(new GeneralPane, this, 125, 100), tr("General")); - m_tab_widget->addTab(GetWrappedWidget(new InterfacePane, this, 125, 100), tr("Interface")); - m_tab_widget->addTab(GetWrappedWidget(new AudioPane, this, 125, 100), tr("Audio")); - m_tab_widget->addTab(GetWrappedWidget(new PathPane, this, 125, 100), tr("Paths")); - m_tab_widget->addTab(GetWrappedWidget(new GameCubePane, this, 125, 100), tr("GameCube")); - m_tab_widget->addTab(GetWrappedWidget(new WiiPane, this, 125, 100), tr("Wii")); - m_tab_widget->addTab(GetWrappedWidget(new AdvancedPane, this, 125, 200), tr("Advanced")); + // Calculated value for the padding in our list items. + const int list_item_padding = layout->contentsMargins().left() / 2; - // Dialog box buttons - QDialogButtonBox* close_box = new QDialogButtonBox(QDialogButtonBox::Close); + // Eliminate padding around layouts. + layout->setContentsMargins(QMargins{}); + layout->setSpacing(0); - connect(close_box, &QDialogButtonBox::rejected, this, &QDialog::reject); + m_navigation_list = new QListWidget; - layout->addWidget(close_box); + // Ensure list doesn't grow horizontally and is not resized smaller than its contents. + m_navigation_list->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum); + m_navigation_list->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents); - setLayout(layout); + // FYI: "base" is the window color on Windows and "alternate-base" is very high contrast on macOS. + const auto [list_background, list_hover_background] = +#if defined(_WIN32) + std::pair("palette(alternate-base)", "palette(base)"); +#else + std::pair("palette(base)", "palette(alternate-base)"); +#endif + + m_navigation_list->setStyleSheet( + QString::fromUtf8( + // Remove border around entire widget and adjust background color. + "QListWidget { border: 0; background: %1; } " + "QListWidget::item { padding: %2; " +#if defined(__linux__) + "} " +#else + // For some reason this is needed to fix inconsistent item padding on Windows and macOS, + // but it unfortunately also breaks item background color changes. + "border: 0; } " + // Restore selected item color. + "QListWidget::item:selected { background: palette(highlight); " +#if defined(_WIN32) + // Prevent text color change on focus loss on Windows. + // This seems to breaks the nice white text on macOS. + "color: palette(highlighted-text); " +#endif + "} " + // Restore hovered item color, though not really the correct color. + "QListWidget::item:hover:!selected { background: %3; } " +#endif +#if defined(_WIN32) + // Remove ugly dotted outline on selected row. + "* { outline: none; } " +#endif + ) + .arg(QString::fromUtf8(list_background)) + .arg(list_item_padding) +#if !defined(__linux__) + .arg(QString::fromUtf8(list_hover_background)) +#endif + ); + + layout->addWidget(m_navigation_list); + + auto* const right_side = new QVBoxLayout; + layout->addLayout(right_side); + + m_stacked_panes = new QStackedWidget; + + right_side->addWidget(m_stacked_panes); + + // The QFrame gives us some padding around the button. + auto* const button_frame = new QFrame; + auto* const button_layout = new QGridLayout{button_frame}; + auto* const button_box = new QDialogButtonBox(QDialogButtonBox::Close); + right_side->addWidget(button_frame); + button_layout->addWidget(button_box); + + connect(button_box, &QDialogButtonBox::rejected, this, &QDialog::reject); + + connect(m_navigation_list, &QListWidget::currentRowChanged, m_stacked_panes, + &QStackedWidget::setCurrentIndex); +} + +void StackedSettingsWindow::OnDoneCreatingPanes() +{ + // Make sure the first item is actually selected by default. + ActivatePane(0); + // Take on the preferred size. + adjustSize(); +} + +void StackedSettingsWindow::AddPane(QWidget* widget, const QString& name) +{ + m_stacked_panes->addWidget(widget); + m_navigation_list->addItem(name); +} + +void StackedSettingsWindow::AddWrappedPane(QWidget* widget, const QString& name) +{ + AddPane(GetWrappedWidget(widget), name); +} + +void StackedSettingsWindow::ActivatePane(int index) +{ + m_navigation_list->setCurrentRow(index); +} + +SettingsWindow::SettingsWindow(QWidget* parent) : StackedSettingsWindow{parent} +{ + setWindowTitle(tr("Settings")); + + AddWrappedPane(new GeneralPane, tr("General")); + AddWrappedPane(new InterfacePane, tr("Interface")); + AddWrappedPane(new AudioPane, tr("Audio")); + AddWrappedPane(new PathPane, tr("Paths")); + AddWrappedPane(new GameCubePane, tr("GameCube")); + AddWrappedPane(new WiiPane, tr("Wii")); + AddWrappedPane(new AdvancedPane, tr("Advanced")); + + OnDoneCreatingPanes(); } void SettingsWindow::SelectAudioPane() { - m_tab_widget->setCurrentIndex(static_cast(TabIndex::Audio)); + ActivatePane(static_cast(TabIndex::Audio)); } void SettingsWindow::SelectGeneralPane() { - m_tab_widget->setCurrentIndex(static_cast(TabIndex::General)); + ActivatePane(static_cast(TabIndex::General)); } diff --git a/Source/Core/DolphinQt/Config/SettingsWindow.h b/Source/Core/DolphinQt/Config/SettingsWindow.h index 02285ed244..b1217bb41b 100644 --- a/Source/Core/DolphinQt/Config/SettingsWindow.h +++ b/Source/Core/DolphinQt/Config/SettingsWindow.h @@ -5,7 +5,31 @@ #include -class QTabWidget; +class QStackedWidget; +class QListWidget; + +// A settings window with a QListWidget to switch between panes of a QStackedWidget. +class StackedSettingsWindow : public QDialog +{ + Q_OBJECT +public: + explicit StackedSettingsWindow(QWidget* parent = nullptr); + + void ActivatePane(int index); + +protected: + void AddPane(QWidget*, const QString& name); + + // Adds a scrollable Pane. + void AddWrappedPane(QWidget*, const QString& name); + + // For derived classes to call after they create their settings panes. + void OnDoneCreatingPanes(); + +private: + QStackedWidget* m_stacked_panes; + QListWidget* m_navigation_list; +}; enum class TabIndex { @@ -13,14 +37,12 @@ enum class TabIndex Audio = 2 }; -class SettingsWindow final : public QDialog +class SettingsWindow final : public StackedSettingsWindow { Q_OBJECT public: explicit SettingsWindow(QWidget* parent = nullptr); + void SelectGeneralPane(); void SelectAudioPane(); - -private: - QTabWidget* m_tab_widget; }; diff --git a/Source/Core/DolphinQt/Settings/AudioPane.cpp b/Source/Core/DolphinQt/Settings/AudioPane.cpp index 70baf158ac..fe8866ddd9 100644 --- a/Source/Core/DolphinQt/Settings/AudioPane.cpp +++ b/Source/Core/DolphinQt/Settings/AudioPane.cpp @@ -76,7 +76,7 @@ void AudioPane::CreateWidgets() m_volume_slider->setOrientation(Qt::Vertical); m_volume_indicator->setAlignment(Qt::AlignVCenter | Qt::AlignHCenter); - m_volume_indicator->setFixedWidth(QFontMetrics(font()).boundingRect(tr("%1 %").arg(100)).width()); + m_volume_indicator->setFixedWidth(QFontMetrics(font()).boundingRect(volume_box->title()).width()); volume_layout->addWidget(m_volume_slider, 0, Qt::AlignHCenter); volume_layout->addWidget(m_volume_indicator, 0, Qt::AlignHCenter); From e796e82e8c7d3067216ae9694359319dbd4eccdb Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Mon, 12 May 2025 16:59:59 -0500 Subject: [PATCH 2/8] DolphinQt: Change game properties QTabWidget to QListWidget. --- .../DolphinQt/Config/PropertiesDialog.cpp | 61 ++++++------------- .../Core/DolphinQt/Config/PropertiesDialog.h | 4 +- 2 files changed, 23 insertions(+), 42 deletions(-) diff --git a/Source/Core/DolphinQt/Config/PropertiesDialog.cpp b/Source/Core/DolphinQt/Config/PropertiesDialog.cpp index d82a843285..f95edf40c6 100644 --- a/Source/Core/DolphinQt/Config/PropertiesDialog.cpp +++ b/Source/Core/DolphinQt/Config/PropertiesDialog.cpp @@ -7,7 +7,6 @@ #include #include -#include #include #include "DiscIO/Enums.h" @@ -24,28 +23,22 @@ #include "DolphinQt/QtUtils/WrapInScrollArea.h" #include "UICommon/GameFile.h" -#include "VideoCommon/VideoConfig.h" PropertiesDialog::PropertiesDialog(QWidget* parent, const UICommon::GameFile& game) - : QDialog(parent) + : StackedSettingsWindow{parent} { setWindowTitle(QStringLiteral("%1: %2 - %3") .arg(QString::fromStdString(game.GetFileName()), QString::fromStdString(game.GetGameID()), QString::fromStdString(game.GetLongName()))); - setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); - QVBoxLayout* layout = new QVBoxLayout(); - - QTabWidget* tab_widget = new QTabWidget(this); - InfoWidget* info = new InfoWidget(game); - - ARCodeWidget* ar = new ARCodeWidget(game.GetGameID(), game.GetRevision()); - GeckoCodeWidget* gecko = + auto* const info = new InfoWidget(game); + auto* const ar = new ARCodeWidget(game.GetGameID(), game.GetRevision()); + auto* const gecko = new GeckoCodeWidget(game.GetGameID(), game.GetGameTDBID(), game.GetRevision()); - PatchesWidget* patches = new PatchesWidget(game); - GameConfigWidget* game_config = new GameConfigWidget(game); - GraphicsModListWidget* graphics_mod_list = new GraphicsModListWidget(game); + auto* const patches = new PatchesWidget(game); + auto* const game_config = new GameConfigWidget(game); + auto* const graphics_mod_list = new GraphicsModListWidget(game); connect(gecko, &GeckoCodeWidget::OpenGeneralSettings, this, &PropertiesDialog::OpenGeneralSettings); @@ -63,45 +56,31 @@ PropertiesDialog::PropertiesDialog(QWidget* parent, const UICommon::GameFile& ga connect(graphics_mod_list, &GraphicsModListWidget::OpenGraphicsSettings, this, &PropertiesDialog::OpenGraphicsSettings); - const int padding_width = 120; - const int padding_height = 100; - tab_widget->addTab(GetWrappedWidget(info, this, padding_width, padding_height), tr("Info")); - tab_widget->addTab(GetWrappedWidget(game_config, this, padding_width, padding_height), - tr("Game Config")); - tab_widget->addTab(GetWrappedWidget(patches, this, padding_width, padding_height), tr("Patches")); - tab_widget->addTab(GetWrappedWidget(ar, this, padding_width, padding_height), tr("AR Codes")); - tab_widget->addTab(GetWrappedWidget(gecko, this, padding_width, padding_height), - tr("Gecko Codes")); - tab_widget->addTab(GetWrappedWidget(graphics_mod_list, this, padding_width, padding_height), - tr("Graphics Mods")); + // Note: Intentional selective use of AddWrappedPane for a sensible dialog "minimumSize". + AddWrappedPane(info, tr("Info")); + AddPane(game_config, tr("Game Config")); + AddPane(patches, tr("Patches")); + AddPane(ar, tr("AR Codes")); + AddPane(gecko, tr("Gecko Codes")); + AddWrappedPane(graphics_mod_list, tr("Graphics Mods")); if (game.GetPlatform() != DiscIO::Platform::ELFOrDOL) { std::shared_ptr volume = DiscIO::CreateVolume(game.GetFilePath()); if (volume) { - VerifyWidget* verify = new VerifyWidget(volume); - tab_widget->addTab(GetWrappedWidget(verify, this, padding_width, padding_height), - tr("Verify")); + auto* const verify = new VerifyWidget(volume); + AddPane(verify, tr("Verify")); if (DiscIO::IsDisc(game.GetPlatform())) { - FilesystemWidget* filesystem = new FilesystemWidget(volume); - tab_widget->addTab(GetWrappedWidget(filesystem, this, padding_width, padding_height), - tr("Filesystem")); + auto* const filesystem = new FilesystemWidget(volume); + AddPane(filesystem, tr("Filesystem")); } } } - layout->addWidget(tab_widget); + connect(this, &QDialog::rejected, graphics_mod_list, &GraphicsModListWidget::SaveToDisk); - QDialogButtonBox* close_box = new QDialogButtonBox(QDialogButtonBox::Close); - - connect(close_box, &QDialogButtonBox::rejected, this, &QDialog::reject); - connect(close_box, &QDialogButtonBox::rejected, graphics_mod_list, - &GraphicsModListWidget::SaveToDisk); - - layout->addWidget(close_box); - - setLayout(layout); + OnDoneCreatingPanes(); } diff --git a/Source/Core/DolphinQt/Config/PropertiesDialog.h b/Source/Core/DolphinQt/Config/PropertiesDialog.h index 29d282a6e8..9079ed925a 100644 --- a/Source/Core/DolphinQt/Config/PropertiesDialog.h +++ b/Source/Core/DolphinQt/Config/PropertiesDialog.h @@ -5,12 +5,14 @@ #include +#include "DolphinQt/Config/SettingsWindow.h" + namespace UICommon { class GameFile; } -class PropertiesDialog final : public QDialog +class PropertiesDialog final : public StackedSettingsWindow { Q_OBJECT public: From 543b85a4513d2d1da8b0220529c28de1a989a51e Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Mon, 12 May 2025 22:17:49 -0500 Subject: [PATCH 3/8] DolphinQt: Make WrapInScrollArea and GetWrappedWidget less hacky. --- .../Achievements/AchievementsWindow.cpp | 15 +++--- .../DolphinQt/CheatSearchFactoryWidget.cpp | 6 +-- .../Core/DolphinQt/CheatSearchFactoryWidget.h | 2 - Source/Core/DolphinQt/CheatSearchWidget.cpp | 4 +- Source/Core/DolphinQt/CheatSearchWidget.h | 10 +--- Source/Core/DolphinQt/CheatsManager.cpp | 17 +++--- Source/Core/DolphinQt/Config/ARCodeWidget.cpp | 7 +-- .../DolphinQt/Config/ControllersWindow.cpp | 2 + .../DolphinQt/Config/GameConfigWidget.cpp | 11 ++-- .../Core/DolphinQt/Config/GeckoCodeWidget.cpp | 6 +-- .../Graphics/ColorCorrectionConfigWindow.cpp | 2 +- .../Config/Graphics/GraphicsWindow.cpp | 13 ++--- .../Config/Mapping/MappingWindow.cpp | 5 +- .../Core/DolphinQt/Config/SettingsWindow.cpp | 2 +- Source/Core/DolphinQt/QtUtils/QtUtils.cpp | 10 ++++ Source/Core/DolphinQt/QtUtils/QtUtils.h | 3 ++ .../DolphinQt/QtUtils/WrapInScrollArea.cpp | 52 ++++++++++++------- .../Core/DolphinQt/QtUtils/WrapInScrollArea.h | 8 +-- 18 files changed, 93 insertions(+), 82 deletions(-) diff --git a/Source/Core/DolphinQt/Achievements/AchievementsWindow.cpp b/Source/Core/DolphinQt/Achievements/AchievementsWindow.cpp index c9a00a01ed..9289ee9ad5 100644 --- a/Source/Core/DolphinQt/Achievements/AchievementsWindow.cpp +++ b/Source/Core/DolphinQt/Achievements/AchievementsWindow.cpp @@ -56,20 +56,21 @@ void AchievementsWindow::CreateMainLayout() m_settings_widget = new AchievementSettingsWidget(m_tab_widget); m_progress_widget = new AchievementProgressWidget(m_tab_widget); m_leaderboard_widget = new AchievementLeaderboardWidget(m_tab_widget); - m_tab_widget->addTab(GetWrappedWidget(m_settings_widget, this, 125, 100), tr("Settings")); - m_tab_widget->addTab(GetWrappedWidget(m_progress_widget, this, 125, 100), tr("Progress")); - m_tab_widget->setTabVisible(1, is_game_loaded); - m_tab_widget->addTab(GetWrappedWidget(m_leaderboard_widget, this, 125, 100), tr("Leaderboards")); - m_tab_widget->setTabVisible(2, is_game_loaded); + m_tab_widget->addTab(GetWrappedWidget(m_settings_widget), tr("Settings")); + m_tab_widget->addTab(GetWrappedWidget(m_progress_widget), tr("Progress")); + m_tab_widget->addTab(GetWrappedWidget(m_leaderboard_widget), tr("Leaderboards")); m_button_box = new QDialogButtonBox(QDialogButtonBox::Close); - auto* layout = new QVBoxLayout(); + auto* const layout = new QVBoxLayout{this}; layout->addWidget(m_header_widget); layout->addWidget(m_tab_widget); layout->addWidget(m_button_box); - WrapInScrollArea(this, layout); + adjustSize(); + + m_tab_widget->setTabVisible(1, is_game_loaded); + m_tab_widget->setTabVisible(2, is_game_loaded); } void AchievementsWindow::ConnectWidgets() diff --git a/Source/Core/DolphinQt/CheatSearchFactoryWidget.cpp b/Source/Core/DolphinQt/CheatSearchFactoryWidget.cpp index aa5a0943e0..3ec1f31568 100644 --- a/Source/Core/DolphinQt/CheatSearchFactoryWidget.cpp +++ b/Source/Core/DolphinQt/CheatSearchFactoryWidget.cpp @@ -18,14 +18,12 @@ #include "Common/StringUtil.h" #include "Core/CheatSearch.h" -#include "Core/Config/MainSettings.h" #include "Core/Core.h" #include "Core/HW/Memmap.h" #include "Core/PowerPC/MMU.h" #include "Core/System.h" #include "DolphinQt/QtUtils/ModalMessageBox.h" #include "DolphinQt/QtUtils/NonDefaultQPushButton.h" -#include "DolphinQt/QtUtils/WrapInScrollArea.h" CheatSearchFactoryWidget::CheatSearchFactoryWidget() { @@ -40,7 +38,7 @@ Q_DECLARE_METATYPE(Cheats::DataType); void CheatSearchFactoryWidget::CreateWidgets() { - auto* layout = new QVBoxLayout(); + auto* const layout = new QVBoxLayout{this}; auto* address_space_group = new QGroupBox(tr("Address Space")); auto* address_space_layout = new QVBoxLayout(); @@ -124,8 +122,6 @@ void CheatSearchFactoryWidget::CreateWidgets() layout->addWidget(m_new_search); layout->addStretch(); - - WrapInScrollArea(this, layout); } void CheatSearchFactoryWidget::ConnectWidgets() diff --git a/Source/Core/DolphinQt/CheatSearchFactoryWidget.h b/Source/Core/DolphinQt/CheatSearchFactoryWidget.h index 576f7f97ad..12e590da15 100644 --- a/Source/Core/DolphinQt/CheatSearchFactoryWidget.h +++ b/Source/Core/DolphinQt/CheatSearchFactoryWidget.h @@ -3,8 +3,6 @@ #pragma once -#include - #include #include "Core/CheatSearch.h" diff --git a/Source/Core/DolphinQt/CheatSearchWidget.cpp b/Source/Core/DolphinQt/CheatSearchWidget.cpp index df4cb8dd11..bbd8675f3e 100644 --- a/Source/Core/DolphinQt/CheatSearchWidget.cpp +++ b/Source/Core/DolphinQt/CheatSearchWidget.cpp @@ -249,7 +249,7 @@ void CheatSearchWidget::CreateWidgets() checkboxes_layout->addWidget(m_autoupdate_current_values); checkboxes_layout->setStretchFactor(m_autoupdate_current_values, 2); - QVBoxLayout* layout = new QVBoxLayout(); + auto* const layout = new QVBoxLayout{this}; layout->addWidget(session_info_label); layout->addWidget(instructions_label); layout->addLayout(value_layout); @@ -258,8 +258,6 @@ void CheatSearchWidget::CreateWidgets() layout->addWidget(m_info_label_1); layout->addWidget(m_info_label_2); layout->addWidget(m_address_table); - - WrapInScrollArea(this, layout); } void CheatSearchWidget::ConnectWidgets() diff --git a/Source/Core/DolphinQt/CheatSearchWidget.h b/Source/Core/DolphinQt/CheatSearchWidget.h index f6c4576d87..f7427ca6a6 100644 --- a/Source/Core/DolphinQt/CheatSearchWidget.h +++ b/Source/Core/DolphinQt/CheatSearchWidget.h @@ -5,19 +5,13 @@ #include -#include -#include #include #include -#include #include "Common/CommonTypes.h" +#include "Core/ActionReplay.h" #include "Core/CheatSearch.h" -namespace ActionReplay -{ -struct ARCode; -} namespace Core { class System; @@ -57,7 +51,7 @@ public: signals: void ActionReplayCodeGenerated(const ActionReplay::ARCode& ar_code); void RequestWatch(QString name, u32 address); - void ShowMemory(const u32 address); + void ShowMemory(u32 address); private: void CreateWidgets(); diff --git a/Source/Core/DolphinQt/CheatsManager.cpp b/Source/Core/DolphinQt/CheatsManager.cpp index 67e177cef6..4ad038013f 100644 --- a/Source/Core/DolphinQt/CheatsManager.cpp +++ b/Source/Core/DolphinQt/CheatsManager.cpp @@ -3,17 +3,15 @@ #include "DolphinQt/CheatsManager.h" -#include - #include #include -#include "Core/ActionReplay.h" #include "Core/CheatSearch.h" #include "Core/ConfigManager.h" #include "Core/Core.h" -#include "UICommon/GameFile.h" +#include "DolphinQt/QtUtils/QtUtils.h" +#include "DolphinQt/QtUtils/WrapInScrollArea.h" #include "DolphinQt/CheatSearchFactoryWidget.h" #include "DolphinQt/CheatSearchWidget.h" @@ -36,6 +34,8 @@ CheatsManager::CheatsManager(Core::System& system, QWidget* parent) CreateWidgets(); ConnectWidgets(); + QtUtils::AdjustSizeWithinScreen(this); + auto& settings = Settings::GetQSettings(); restoreGeometry(settings.value(QStringLiteral("cheatsmanager/geometry")).toByteArray()); } @@ -124,18 +124,19 @@ void CheatsManager::CreateWidgets() m_tab_widget = new PartiallyClosableTabWidget; m_button_box = new QDialogButtonBox(QDialogButtonBox::Close); - int tab_index; + int tab_index = 0; m_ar_code = new ARCodeWidget(m_game_id, m_revision, false); - tab_index = m_tab_widget->addTab(m_ar_code, tr("AR Code")); + tab_index = m_tab_widget->addTab(GetWrappedWidget(m_ar_code), tr("AR Code")); m_tab_widget->setTabUnclosable(tab_index); m_gecko_code = new GeckoCodeWidget(m_game_id, m_game_tdb_id, m_revision, false); - tab_index = m_tab_widget->addTab(m_gecko_code, tr("Gecko Codes")); + tab_index = m_tab_widget->addTab(GetWrappedWidget(m_gecko_code), tr("Gecko Codes")); m_tab_widget->setTabUnclosable(tab_index); m_cheat_search_new = new CheatSearchFactoryWidget(); - tab_index = m_tab_widget->addTab(m_cheat_search_new, tr("Start New Cheat Search")); + tab_index = + m_tab_widget->addTab(GetWrappedWidget(m_cheat_search_new), tr("Start New Cheat Search")); m_tab_widget->setTabUnclosable(tab_index); auto* layout = new QVBoxLayout; diff --git a/Source/Core/DolphinQt/Config/ARCodeWidget.cpp b/Source/Core/DolphinQt/Config/ARCodeWidget.cpp index f73017d723..17b0f61b4b 100644 --- a/Source/Core/DolphinQt/Config/ARCodeWidget.cpp +++ b/Source/Core/DolphinQt/Config/ARCodeWidget.cpp @@ -24,9 +24,6 @@ #include "DolphinQt/Config/HardcoreWarningWidget.h" #include "DolphinQt/QtUtils/NonDefaultQPushButton.h" #include "DolphinQt/QtUtils/SetWindowDecorations.h" -#include "DolphinQt/QtUtils/WrapInScrollArea.h" - -#include "UICommon/GameFile.h" ARCodeWidget::ARCodeWidget(std::string game_id, u16 game_revision, bool restart_required) : m_game_id(std::move(game_id)), m_game_revision(game_revision), @@ -77,7 +74,7 @@ void ARCodeWidget::CreateWidgets() button_layout->addWidget(m_code_edit); button_layout->addWidget(m_code_remove); - QVBoxLayout* layout = new QVBoxLayout; + auto* const layout = new QVBoxLayout{this}; layout->addWidget(m_warning); #ifdef USE_RETRO_ACHIEVEMENTS @@ -85,8 +82,6 @@ void ARCodeWidget::CreateWidgets() #endif // USE_RETRO_ACHIEVEMENTS layout->addWidget(m_code_list); layout->addLayout(button_layout); - - WrapInScrollArea(this, layout); } void ARCodeWidget::ConnectWidgets() diff --git a/Source/Core/DolphinQt/Config/ControllersWindow.cpp b/Source/Core/DolphinQt/Config/ControllersWindow.cpp index 2470910e8e..5f6029a977 100644 --- a/Source/Core/DolphinQt/Config/ControllersWindow.cpp +++ b/Source/Core/DolphinQt/Config/ControllersWindow.cpp @@ -9,6 +9,7 @@ #include "DolphinQt/Config/CommonControllersWidget.h" #include "DolphinQt/Config/GamecubeControllersWidget.h" #include "DolphinQt/Config/WiimoteControllersWidget.h" +#include "DolphinQt/QtUtils/QtUtils.h" #include "DolphinQt/QtUtils/WrapInScrollArea.h" ControllersWindow::ControllersWindow(QWidget* parent) : QDialog(parent) @@ -41,6 +42,7 @@ void ControllersWindow::CreateMainLayout() layout->addWidget(m_button_box); WrapInScrollArea(this, layout); + QtUtils::AdjustSizeWithinScreen(this); } void ControllersWindow::ConnectWidgets() diff --git a/Source/Core/DolphinQt/Config/GameConfigWidget.cpp b/Source/Core/DolphinQt/Config/GameConfigWidget.cpp index a96046f916..4505605de0 100644 --- a/Source/Core/DolphinQt/Config/GameConfigWidget.cpp +++ b/Source/Core/DolphinQt/Config/GameConfigWidget.cpp @@ -205,14 +205,11 @@ void GameConfigWidget::CreateWidgets() auto* gfx_tabs = new QTabWidget; - gfx_tabs->addTab(GetWrappedWidget(new GeneralWidget(this, m_layer.get()), this, 125, 100), - tr("General")); - gfx_tabs->addTab(GetWrappedWidget(new EnhancementsWidget(this, m_layer.get()), this, 125, 100), + gfx_tabs->addTab(GetWrappedWidget(new GeneralWidget(this, m_layer.get())), tr("General")); + gfx_tabs->addTab(GetWrappedWidget(new EnhancementsWidget(this, m_layer.get())), tr("Enhancements")); - gfx_tabs->addTab(GetWrappedWidget(new HacksWidget(this, m_layer.get()), this, 125, 100), - tr("Hacks")); - gfx_tabs->addTab(GetWrappedWidget(new AdvancedWidget(this, m_layer.get()), this, 125, 100), - tr("Advanced")); + gfx_tabs->addTab(GetWrappedWidget(new HacksWidget(this, m_layer.get())), tr("Hacks")); + gfx_tabs->addTab(GetWrappedWidget(new AdvancedWidget(this, m_layer.get())), tr("Advanced")); const int editor_index = tab_widget->addTab(advanced_widget, tr("Editor")); gfx_layout->addWidget(gfx_tabs); diff --git a/Source/Core/DolphinQt/Config/GeckoCodeWidget.cpp b/Source/Core/DolphinQt/Config/GeckoCodeWidget.cpp index bce1e89b68..6b7e487bde 100644 --- a/Source/Core/DolphinQt/Config/GeckoCodeWidget.cpp +++ b/Source/Core/DolphinQt/Config/GeckoCodeWidget.cpp @@ -32,8 +32,6 @@ #include "DolphinQt/QtUtils/SetWindowDecorations.h" #include "DolphinQt/QtUtils/WrapInScrollArea.h" -#include "UICommon/GameFile.h" - GeckoCodeWidget::GeckoCodeWidget(std::string game_id, std::string gametdb_id, u16 game_revision, bool restart_required) : m_game_id(std::move(game_id)), m_gametdb_id(std::move(gametdb_id)), @@ -105,7 +103,7 @@ void GeckoCodeWidget::CreateWidgets() m_download_codes->setToolTip(tr("Download Codes from the WiiRD Database")); - auto* layout = new QVBoxLayout; + auto* const layout = new QVBoxLayout{this}; layout->addWidget(m_warning); #ifdef USE_RETRO_ACHIEVEMENTS @@ -139,8 +137,6 @@ void GeckoCodeWidget::CreateWidgets() btn_layout->addWidget(m_download_codes); layout->addLayout(btn_layout); - - WrapInScrollArea(this, layout); } void GeckoCodeWidget::ConnectWidgets() diff --git a/Source/Core/DolphinQt/Config/Graphics/ColorCorrectionConfigWindow.cpp b/Source/Core/DolphinQt/Config/Graphics/ColorCorrectionConfigWindow.cpp index 082e5dcc90..62f2437b57 100644 --- a/Source/Core/DolphinQt/Config/Graphics/ColorCorrectionConfigWindow.cpp +++ b/Source/Core/DolphinQt/Config/Graphics/ColorCorrectionConfigWindow.cpp @@ -156,8 +156,8 @@ void ColorCorrectionConfigWindow::Create() layout->addStretch(); layout->addWidget(m_button_box); - setLayout(layout); WrapInScrollArea(this, layout); + adjustSize(); } void ColorCorrectionConfigWindow::ConnectWidgets() diff --git a/Source/Core/DolphinQt/Config/Graphics/GraphicsWindow.cpp b/Source/Core/DolphinQt/Config/Graphics/GraphicsWindow.cpp index 627dd11b75..41d2081e38 100644 --- a/Source/Core/DolphinQt/Config/Graphics/GraphicsWindow.cpp +++ b/Source/Core/DolphinQt/Config/Graphics/GraphicsWindow.cpp @@ -12,17 +12,16 @@ #include "Common/Config/Config.h" #include "Core/Config/MainSettings.h" -#include "Core/ConfigManager.h" #include "DolphinQt/Config/Graphics/AdvancedWidget.h" #include "DolphinQt/Config/Graphics/EnhancementsWidget.h" #include "DolphinQt/Config/Graphics/GeneralWidget.h" #include "DolphinQt/Config/Graphics/HacksWidget.h" #include "DolphinQt/MainWindow.h" +#include "DolphinQt/QtUtils/QtUtils.h" #include "DolphinQt/QtUtils/WrapInScrollArea.h" #include "VideoCommon/VideoBackendBase.h" -#include "VideoCommon/VideoConfig.h" GraphicsWindow::GraphicsWindow(MainWindow* parent) : QDialog(parent), m_main_window(parent) { @@ -32,6 +31,8 @@ GraphicsWindow::GraphicsWindow(MainWindow* parent) : QDialog(parent), m_main_win setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); OnBackendChanged(QString::fromStdString(Config::Get(Config::MAIN_GFX_BACKEND))); + + QtUtils::AdjustSizeWithinScreen(this); } void GraphicsWindow::CreateMainLayout() @@ -52,10 +53,10 @@ void GraphicsWindow::CreateMainLayout() connect(general_widget, &GeneralWidget::BackendChanged, this, &GraphicsWindow::OnBackendChanged); - QWidget* const wrapped_general = GetWrappedWidget(general_widget, this, 50, 100); - QWidget* const wrapped_enhancements = GetWrappedWidget(enhancements_widget, this, 50, 100); - QWidget* const wrapped_hacks = GetWrappedWidget(hacks_widget, this, 50, 100); - QWidget* const wrapped_advanced = GetWrappedWidget(advanced_widget, this, 50, 100); + QWidget* const wrapped_general = GetWrappedWidget(general_widget); + QWidget* const wrapped_enhancements = GetWrappedWidget(enhancements_widget); + QWidget* const wrapped_hacks = GetWrappedWidget(hacks_widget); + QWidget* const wrapped_advanced = GetWrappedWidget(advanced_widget); tab_widget->addTab(wrapped_general, tr("General")); tab_widget->addTab(wrapped_enhancements, tr("Enhancements")); diff --git a/Source/Core/DolphinQt/Config/Mapping/MappingWindow.cpp b/Source/Core/DolphinQt/Config/Mapping/MappingWindow.cpp index aab247dfa0..7c5cb41939 100644 --- a/Source/Core/DolphinQt/Config/Mapping/MappingWindow.cpp +++ b/Source/Core/DolphinQt/Config/Mapping/MappingWindow.cpp @@ -50,6 +50,7 @@ #include "DolphinQt/Config/Mapping/WiimoteEmuMotionControlIMU.h" #include "DolphinQt/QtUtils/ModalMessageBox.h" #include "DolphinQt/QtUtils/NonDefaultQPushButton.h" +#include "DolphinQt/QtUtils/QtUtils.h" #include "DolphinQt/QtUtils/SetWindowDecorations.h" #include "DolphinQt/QtUtils/WindowActivationEventFilter.h" #include "DolphinQt/QtUtils/WrapInScrollArea.h" @@ -96,6 +97,8 @@ MappingWindow::MappingWindow(QWidget* parent, Type type, int port_num) [] { HotkeyManagerEmu::Enable(false); }); MappingCommon::CreateMappingProcessor(this); + + QtUtils::AdjustSizeWithinScreen(this); } void MappingWindow::CreateDevicesLayout() @@ -543,7 +546,7 @@ void MappingWindow::PopulateProfileSelection() QWidget* MappingWindow::AddWidget(const QString& name, QWidget* widget) { - QWidget* wrapper = GetWrappedWidget(widget, this, 150, 210); + auto* const wrapper = GetWrappedWidget(widget); m_tab_widget->addTab(wrapper, name); return wrapper; } diff --git a/Source/Core/DolphinQt/Config/SettingsWindow.cpp b/Source/Core/DolphinQt/Config/SettingsWindow.cpp index f3618cc810..3bf63f955a 100644 --- a/Source/Core/DolphinQt/Config/SettingsWindow.cpp +++ b/Source/Core/DolphinQt/Config/SettingsWindow.cpp @@ -110,7 +110,7 @@ void StackedSettingsWindow::OnDoneCreatingPanes() // Make sure the first item is actually selected by default. ActivatePane(0); // Take on the preferred size. - adjustSize(); + QtUtils::AdjustSizeWithinScreen(this); } void StackedSettingsWindow::AddPane(QWidget* widget, const QString& name) diff --git a/Source/Core/DolphinQt/QtUtils/QtUtils.cpp b/Source/Core/DolphinQt/QtUtils/QtUtils.cpp index fa90dde215..5914448a91 100644 --- a/Source/Core/DolphinQt/QtUtils/QtUtils.cpp +++ b/Source/Core/DolphinQt/QtUtils/QtUtils.cpp @@ -6,6 +6,7 @@ #include #include #include +#include namespace QtUtils { @@ -35,4 +36,13 @@ QWidget* CreateIconWarning(QWidget* parent, QStyle::StandardPixmap standard_pixm return widget; } +void AdjustSizeWithinScreen(QWidget* widget) +{ + const auto screen_size = widget->screen()->availableSize(); + + const auto adj_screen_size = screen_size * 9 / 10; + + widget->resize(widget->sizeHint().boundedTo(adj_screen_size)); +} + } // namespace QtUtils diff --git a/Source/Core/DolphinQt/QtUtils/QtUtils.h b/Source/Core/DolphinQt/QtUtils/QtUtils.h index 53251b3b4d..7d490347b6 100644 --- a/Source/Core/DolphinQt/QtUtils/QtUtils.h +++ b/Source/Core/DolphinQt/QtUtils/QtUtils.h @@ -16,4 +16,7 @@ void ShowFourDigitYear(QDateTimeEdit* widget); QWidget* CreateIconWarning(QWidget* parent, QStyle::StandardPixmap standard_pixmap, QLabel* label); +// Similar to QWidget::adjustSize except maximum size is 9/10 of screen rather than 2/3. +void AdjustSizeWithinScreen(QWidget* widget); + } // namespace QtUtils diff --git a/Source/Core/DolphinQt/QtUtils/WrapInScrollArea.cpp b/Source/Core/DolphinQt/QtUtils/WrapInScrollArea.cpp index 4a8910502c..0f75706b58 100644 --- a/Source/Core/DolphinQt/QtUtils/WrapInScrollArea.cpp +++ b/Source/Core/DolphinQt/QtUtils/WrapInScrollArea.cpp @@ -7,43 +7,59 @@ #include #include #include +#include #include #include -QWidget* GetWrappedWidget(QWidget* wrapped_widget, QWidget* to_resize, int margin_width, - int margin_height) +namespace { - auto* scroll = new QScrollArea; - scroll->setWidget(wrapped_widget); - scroll->setWidgetResizable(true); - scroll->setFrameStyle(QFrame::NoFrame); - if (to_resize != nullptr) +// This scroll area prefers the size of its underlying widget. +class HintingScrollArea final : public QScrollArea +{ +public: + HintingScrollArea() { - // For some reason width() is bigger than it needs to be. - auto min_size = wrapped_widget->minimumSizeHint(); - int recommended_width = min_size.width() + margin_width; - int recommended_height = min_size.height() + margin_height; + setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); + setWidgetResizable(true); - to_resize->resize(std::max(recommended_width, to_resize->width()), - std::max(recommended_height, to_resize->height())); + // Make things not look horrendous on Windows. + setFrameStyle(QFrame::NoFrame); } + QSize sizeHint() const override + { + // Including the scrollbars in our hint can prevent + // a window undersized in one direction gaining unnecessary scrolling in both directions. + const auto scrollbar_padding = + QSize{verticalScrollBar()->sizeHint().width(), horizontalScrollBar()->sizeHint().height()}; + + const auto size_hint = widget()->sizeHint(); + + return size_hint + scrollbar_padding; + } +}; + +} // namespace + +QWidget* GetWrappedWidget(QWidget* wrapped_widget) +{ + auto* const scroll = new HintingScrollArea; + scroll->setWidget(wrapped_widget); + + // Workaround for transparency issues on macOS. Not sure if this is still needed. scroll->viewport()->setAutoFillBackground(false); wrapped_widget->setAutoFillBackground(false); return scroll; } -void WrapInScrollArea(QWidget* parent, QLayout* wrapped_layout, QWidget* to_resize) +void WrapInScrollArea(QWidget* parent, QLayout* wrapped_layout) { - if (to_resize == nullptr) - to_resize = parent; - auto* widget = new QWidget; widget->setLayout(wrapped_layout); - auto* scroll_area = GetWrappedWidget(widget, to_resize, 0, 0); + auto* scroll_area = GetWrappedWidget(widget); auto* scroll_layout = new QVBoxLayout; scroll_layout->addWidget(scroll_area); diff --git a/Source/Core/DolphinQt/QtUtils/WrapInScrollArea.h b/Source/Core/DolphinQt/QtUtils/WrapInScrollArea.h index 389e9aa5ce..61607cea3a 100644 --- a/Source/Core/DolphinQt/QtUtils/WrapInScrollArea.h +++ b/Source/Core/DolphinQt/QtUtils/WrapInScrollArea.h @@ -6,8 +6,8 @@ class QLayout; class QWidget; -QWidget* GetWrappedWidget(QWidget* wrapped_widget, QWidget* to_resize = nullptr, - int margin_width = 50, int margin_height = 50); +// Puts the given widget in a QScrollArea and returns that. +QWidget* GetWrappedWidget(QWidget* wrapped_widget); -// Wrap wrapped_layout in a QScrollArea and fill the parent widget with it -void WrapInScrollArea(QWidget* parent, QLayout* wrapped_layout, QWidget* to_resize = nullptr); +// Wrap wrapped_layout in a QScrollArea and fill the parent widget with it. +void WrapInScrollArea(QWidget* parent, QLayout* wrapped_layout); From fcff7a3a491944054cd9c73e7ef6d80b8bf0b542 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Wed, 14 May 2025 20:45:28 -0500 Subject: [PATCH 4/8] DolphinQt: Fix FilesystemWidget QTreeView visual style. --- Source/Core/DolphinQt/Config/FilesystemWidget.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Source/Core/DolphinQt/Config/FilesystemWidget.cpp b/Source/Core/DolphinQt/Config/FilesystemWidget.cpp index 53b447fc47..1a40e938bf 100644 --- a/Source/Core/DolphinQt/Config/FilesystemWidget.cpp +++ b/Source/Core/DolphinQt/Config/FilesystemWidget.cpp @@ -6,12 +6,12 @@ #include #include #include +#include #include #include #include #include #include -#include #include @@ -55,7 +55,10 @@ FilesystemWidget::~FilesystemWidget() = default; void FilesystemWidget::CreateWidgets() { - auto* layout = new QVBoxLayout; + // Note: At least with KDE Plasma, + // QTreeView takes on an ugly square-corner style when alone in a QVBoxLayout. + // QGridLayout does not produce this problem. + auto* const layout = new QGridLayout{this}; m_tree_model = new QStandardItemModel(0, 2); m_tree_model->setHorizontalHeaderLabels({tr("Name"), tr("Size")}); @@ -78,8 +81,6 @@ void FilesystemWidget::CreateWidgets() #endif layout->addWidget(m_tree_view); - - setLayout(layout); } void FilesystemWidget::ConnectWidgets() From 5bc661aecabba8b570d2261c9bbf52aad9decc0c Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Wed, 14 May 2025 22:23:21 -0500 Subject: [PATCH 5/8] DolphinQt/AudioPane: Fix Volume QGroupBox title uglyness on Windows and inconsistent percent-sign spacing. --- Source/Core/DolphinQt/Settings/AudioPane.cpp | 36 +++++++++++++------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/Source/Core/DolphinQt/Settings/AudioPane.cpp b/Source/Core/DolphinQt/Settings/AudioPane.cpp index fe8866ddd9..4d3ee8ba85 100644 --- a/Source/Core/DolphinQt/Settings/AudioPane.cpp +++ b/Source/Core/DolphinQt/Settings/AudioPane.cpp @@ -33,6 +33,11 @@ #include "DolphinQt/Config/SettingsWindow.h" #include "DolphinQt/Settings.h" +static QString GetVolumeLabelText(int volume_level) +{ + return QWidget::tr("%1%").arg(volume_level); +} + AudioPane::AudioPane() { CheckNeedForLatencyControl(); @@ -67,16 +72,26 @@ void AudioPane::CreateWidgets() dsp_layout->addWidget(m_dsp_combo, Qt::AlignLeft); auto* volume_box = new QGroupBox(tr("Volume")); - auto* volume_layout = new QVBoxLayout; + auto* volume_layout = new QVBoxLayout{volume_box}; + m_volume_slider = new ConfigSlider(0, 100, Config::MAIN_AUDIO_VOLUME); - m_volume_indicator = new QLabel(tr("%1 %").arg(m_volume_slider->value())); - - volume_box->setLayout(volume_layout); - m_volume_slider->setOrientation(Qt::Vertical); + // Volume indicator text label. + m_volume_indicator = new QLabel; m_volume_indicator->setAlignment(Qt::AlignVCenter | Qt::AlignHCenter); - m_volume_indicator->setFixedWidth(QFontMetrics(font()).boundingRect(volume_box->title()).width()); + auto update_volume_label = [this]() { + m_volume_indicator->setText(GetVolumeLabelText(m_volume_slider->value())); + }; + update_volume_label(); + connect(m_volume_slider, &QSlider::valueChanged, this, std::move(update_volume_label)); + + const QFontMetrics font_metrics{font()}; + const int label_width = font_metrics.boundingRect(GetVolumeLabelText(100)).width(); + // Ensure the label is at least as wide as the QGroupBox title. + // This prevents [-Volume] title uglyness on Windows. + const int title_width = font_metrics.boundingRect(volume_box->title()).width(); + m_volume_indicator->setFixedWidth(std::max(label_width, title_width)); volume_layout->addWidget(m_volume_slider, 0, Qt::AlignHCenter); volume_layout->addWidget(m_volume_indicator, 0, Qt::AlignHCenter); @@ -92,8 +107,7 @@ void AudioPane::CreateWidgets() translated_backends.reserve(backends.size()); for (const std::string& backend : backends) { - translated_backends.push_back( - std::make_pair(tr(backend.c_str()), QString::fromStdString(backend))); + translated_backends.emplace_back(tr(backend.c_str()), QString::fromStdString(backend)); } m_backend_combo = new ConfigStringChoice(translated_backends, Config::MAIN_AUDIO_BACKEND); } @@ -203,10 +217,8 @@ void AudioPane::ConnectWidgets() connect(m_backend_combo, &QComboBox::currentIndexChanged, this, &AudioPane::OnBackendChanged); connect(m_dolby_pro_logic, &ConfigBool::toggled, this, &AudioPane::OnDspChanged); connect(m_dsp_combo, &ConfigComplexChoice::currentIndexChanged, this, &AudioPane::OnDspChanged); - connect(m_volume_slider, &QSlider::valueChanged, this, [this](int value) { - m_volume_indicator->setText(tr("%1%").arg(value)); - AudioCommon::UpdateSoundStream(Core::System::GetInstance()); - }); + connect(m_volume_slider, &QSlider::valueChanged, this, + [] { AudioCommon::UpdateSoundStream(Core::System::GetInstance()); }); if (m_latency_control_supported) { From 1e4dfc0956f8bad702c9a57b09c2fd4922c6342b Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Fri, 16 May 2025 19:31:00 -0500 Subject: [PATCH 6/8] DolphinQt: Fix the WiiPane hinting a larger than required size. --- Source/Core/DolphinQt/QtUtils/QtUtils.h | 14 ++++++++++++++ Source/Core/DolphinQt/Settings/WiiPane.cpp | 9 ++++----- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/Source/Core/DolphinQt/QtUtils/QtUtils.h b/Source/Core/DolphinQt/QtUtils/QtUtils.h index 7d490347b6..715a6c67db 100644 --- a/Source/Core/DolphinQt/QtUtils/QtUtils.h +++ b/Source/Core/DolphinQt/QtUtils/QtUtils.h @@ -19,4 +19,18 @@ QWidget* CreateIconWarning(QWidget* parent, QStyle::StandardPixmap standard_pixm // Similar to QWidget::adjustSize except maximum size is 9/10 of screen rather than 2/3. void AdjustSizeWithinScreen(QWidget* widget); +// A QWidget that returns the minimumSizeHint as the primary sizeHint. +// Useful for QListWidget which hints a fairly large height even when entirely empty. +// Usage: QtUtils::MinimumSizeHintWidget +template +class MinimumSizeHintWidget : public Widget +{ +public: + using Widget::Widget; + + // Note: Some widget (e.g. QPushButton) minimumSizeHint implementations themselves use sizeHint, + // which would cause this to stack overflow. + QSize sizeHint() const override { return Widget::minimumSizeHint(); } +}; + } // namespace QtUtils diff --git a/Source/Core/DolphinQt/Settings/WiiPane.cpp b/Source/Core/DolphinQt/Settings/WiiPane.cpp index 5d6bc23f7e..2c9c965b71 100644 --- a/Source/Core/DolphinQt/Settings/WiiPane.cpp +++ b/Source/Core/DolphinQt/Settings/WiiPane.cpp @@ -24,7 +24,6 @@ #include "Common/Config/Config.h" #include "Common/FatFsUtil.h" #include "Common/FileUtil.h" -#include "Common/StringUtil.h" #include "Core/Config/MainSettings.h" #include "Core/Config/SYSCONFSettings.h" @@ -36,6 +35,7 @@ #include "DolphinQt/QtUtils/ModalMessageBox.h" #include "DolphinQt/QtUtils/NonDefaultQPushButton.h" #include "DolphinQt/QtUtils/ParallelProgressDialog.h" +#include "DolphinQt/QtUtils/QtUtils.h" #include "DolphinQt/QtUtils/SetWindowDecorations.h" #include "DolphinQt/QtUtils/SignalBlocking.h" #include "DolphinQt/Settings.h" @@ -98,13 +98,11 @@ WiiPane::WiiPane(QWidget* parent) : QWidget(parent) void WiiPane::CreateLayout() { - m_main_layout = new QVBoxLayout; + m_main_layout = new QVBoxLayout{this}; CreateMisc(); CreateSDCard(); CreateWhitelistedUSBPassthroughDevices(); CreateWiiRemoteSettings(); - m_main_layout->addStretch(1); - setLayout(m_main_layout); } void WiiPane::ConnectLayout() @@ -324,7 +322,8 @@ void WiiPane::CreateSDCard() void WiiPane::CreateWhitelistedUSBPassthroughDevices() { - m_whitelist_usb_list = new QListWidget(); + m_whitelist_usb_list = new QtUtils::MinimumSizeHintWidget; + m_whitelist_usb_add_button = new NonDefaultQPushButton(tr("Add...")); m_whitelist_usb_remove_button = new NonDefaultQPushButton(tr("Remove")); From eed7843d4a91c9862a3a3c52c8a4319f479e7a25 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Mon, 26 May 2025 14:57:45 -0500 Subject: [PATCH 7/8] DolphinQt: Add stretch to the end of the game config Info tab. --- Source/Core/DolphinQt/Config/InfoWidget.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Source/Core/DolphinQt/Config/InfoWidget.cpp b/Source/Core/DolphinQt/Config/InfoWidget.cpp index 81371f0caf..53785d3cd0 100644 --- a/Source/Core/DolphinQt/Config/InfoWidget.cpp +++ b/Source/Core/DolphinQt/Config/InfoWidget.cpp @@ -37,6 +37,8 @@ InfoWidget::InfoWidget(const UICommon::GameFile& game) : m_game(game) if (!game.GetLanguages().empty()) layout->addWidget(CreateBannerDetails()); + layout->addStretch(1); + setLayout(layout); } From aafe961177f252aacbb1b439b89c3590b79cf08b Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Mon, 26 May 2025 15:09:37 -0500 Subject: [PATCH 8/8] DolphinQt: Make GeckoCodeWidget default size not taller than it needs to be. --- Source/Core/DolphinQt/Config/GeckoCodeWidget.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/Core/DolphinQt/Config/GeckoCodeWidget.cpp b/Source/Core/DolphinQt/Config/GeckoCodeWidget.cpp index 6b7e487bde..de0f79a904 100644 --- a/Source/Core/DolphinQt/Config/GeckoCodeWidget.cpp +++ b/Source/Core/DolphinQt/Config/GeckoCodeWidget.cpp @@ -29,6 +29,7 @@ #include "DolphinQt/Config/HardcoreWarningWidget.h" #include "DolphinQt/QtUtils/ModalMessageBox.h" #include "DolphinQt/QtUtils/NonDefaultQPushButton.h" +#include "DolphinQt/QtUtils/QtUtils.h" #include "DolphinQt/QtUtils/SetWindowDecorations.h" #include "DolphinQt/QtUtils/WrapInScrollArea.h" @@ -74,7 +75,7 @@ void GeckoCodeWidget::CreateWidgets() #ifdef USE_RETRO_ACHIEVEMENTS m_hc_warning = new HardcoreWarningWidget(this); #endif // USE_RETRO_ACHIEVEMENTS - m_code_list = new QListWidget; + m_code_list = new QtUtils::MinimumSizeHintWidget; m_name_label = new QLabel; m_creator_label = new QLabel;