From 665f7267e4df61f80b13d5b38153a56278d77411 Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Sun, 18 Oct 2026 22:48:50 +0200 Subject: [PATCH] [Client] Settings: enlarge the settings dialog (#7483) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [Client] Settings: enlarge the settings dialog Keep settings modal per review: size to ~90% of the main window (5% margins each side) with screen fallback, size grip and 750x700 minimum bounded to the screen. Drops the tab approach while giving dense pages room without the tab-switch friction. * [Client] Settings: clamp dialog width to 1280 per review * [Client] Settings: extract dialog size calculation per review Move the host/screen target math out of the DlgSettings constructor into a calculateDialogSize helper. Drop the leftover 'per review' wording from the clamp comment. No behavior change. --------- Co-authored-by: Lukas BrĂ¼bach --- .../widgets/dialogs/dlg_settings.cpp | 46 +++++++++++++++++-- .../interface/widgets/dialogs/dlg_settings.h | 3 +- .../interface/widgets/dialogs/settings_view.h | 4 +- 3 files changed, 46 insertions(+), 7 deletions(-) diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_settings.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_settings.cpp index 9b20372db..ab870a2c8 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_settings.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_settings.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -28,10 +29,49 @@ #include #include +static constexpr int MIN_DIALOG_WIDTH = 750; +static constexpr int MIN_DIALOG_HEIGHT = 700; +static constexpr int MAX_DIALOG_WIDTH = 1280; +static constexpr double DIALOG_SIZE_RATIO = 0.9; + +/** + * @brief Calculates the initial dialog size from the host window or screen + * @param hostSize Size of the hosting main window, or empty when parentless + * @param availableSize Available screen area the dialog must fit into + * @param minimumSize Minimum dialog size already applied via setMinimumSize + * @return Target size at ~90% of the host with small margins, clamped to fit + */ +static QSize calculateDialogSize(const QSize &hostSize, const QSize &availableSize, const QSize &minimumSize) +{ + QSize target = !hostSize.isEmpty() ? QSize(qRound(hostSize.width() * DIALOG_SIZE_RATIO), + qRound(hostSize.height() * DIALOG_SIZE_RATIO)) + : QSize(qRound(availableSize.width() * DIALOG_SIZE_RATIO), + qRound(availableSize.height() * DIALOG_SIZE_RATIO)); + // Evenly-spaced columns leave unnatural dead space on very wide windows, so clamp the width. + target.setWidth(qMin(target.width(), MAX_DIALOG_WIDTH)); + return target.expandedTo(minimumSize).boundedTo(availableSize); +} + DlgSettings::DlgSettings(QWidget *parent) : QDialog(parent) { - auto rec = QGuiApplication::primaryScreen()->availableGeometry(); - setMinimumSize(qMin(750, rec.width()), qMin(700, rec.height())); + // Fill the main window with small margins so multi-group pages (e.g. Deck Editor) are not buried in a scroll. + // 90% of the host window leaves ~5% margins on each side; falls back to 90% of the screen when parentless. + QWidget *hostWindow = parent ? parent->window() : nullptr; + QScreen *screen = nullptr; + QSize hostSize; + if (hostWindow) { + hostSize = hostWindow->size(); + screen = QGuiApplication::screenAt(hostWindow->geometry().center()); + } + if (!screen) { + screen = QGuiApplication::primaryScreen(); + } + const QRect available = screen ? screen->availableGeometry() : QRect(0, 0, 1280, 800); + const QSize minimum(qMin(MIN_DIALOG_WIDTH, available.width()), qMin(MIN_DIALOG_HEIGHT, available.height())); + setMinimumSize(minimum); + + resize(calculateDialogSize(hostSize, available.size(), minimum)); + setSizeGripEnabled(true); connect(&SettingsCache::instance().personal(), &PersonalSettings::langChanged, this, &DlgSettings::updateLanguage); @@ -54,8 +94,6 @@ DlgSettings::DlgSettings(QWidget *parent) : QDialog(parent) connect(&SettingsCache::instance().personal(), &PersonalSettings::langChanged, this, &DlgSettings::retranslateUi); retranslateUi(); - - adjustSize(); } void DlgSettings::setTab(int index) diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_settings.h b/cockatrice/src/interface/widgets/dialogs/dlg_settings.h index 9942b410c..03ccd6b7e 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_settings.h +++ b/cockatrice/src/interface/widgets/dialogs/dlg_settings.h @@ -22,7 +22,8 @@ inline Q_LOGGING_CATEGORY(DlgSettingsLog, "dlg_settings"); * * Thin QDialog frame around SettingsView: only the window title, the OK button * and the close validation live here. All pages, navigation and search are - * owned by SettingsView so other hosts (e.g. a settings tab) can reuse them. + * owned by SettingsView. The dialog fills ~90% of the main window so dense + * pages stay visible without losing the modal adjust-and-return flow. */ class DlgSettings : public QDialog { diff --git a/cockatrice/src/interface/widgets/dialogs/settings_view.h b/cockatrice/src/interface/widgets/dialogs/settings_view.h index fe1b925d8..f1d248679 100644 --- a/cockatrice/src/interface/widgets/dialogs/settings_view.h +++ b/cockatrice/src/interface/widgets/dialogs/settings_view.h @@ -1,6 +1,6 @@ /** * @file settings_view.h - * @brief Settings content widget hosted by the settings dialog (and, later, the settings tab) + * @brief Settings content widget hosted by the settings dialog * @ingroup Dialogs */ #ifndef SETTINGS_VIEW_H @@ -28,7 +28,7 @@ class SettingsSearchDelegate; * @brief Settings pages with tabbed navigation and search, without any dialog chrome * * Owns the search bar, the tab bar, the stacked settings pages and the search - * results view. Dialog/tab hosts only add their own frame (buttons, titles). + * results view. The settings dialog only adds its own frame (buttons, titles). */ class SettingsView : public QWidget {