diff --git a/CHANGELOG.md b/CHANGELOG.md index 45bc166..87f6b99 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ All notable changes to SearchMob Desktop are documented here. The version scheme ## 26.07.01 — 2026-07-02 +### Fixed +- **The About popup now opens wide enough to show all of its content.** Its opening width was + fixed, so a larger text size (or a language with longer button labels) could make the widest + row overflow and force a horizontal scrollbar. The width is now derived from the content and + clamped to the screen. + ### Added - **Google-style search operators.** `"exact phrase"`, `-term`, `site:` / `-site:`, `intitle:`, `inurl:`, `filetype:` (or `ext:`), `before:` / `after:` dates, and `OR`. Operators the upstream diff --git a/src/searchmob_desktop/gui/about_dialog.py b/src/searchmob_desktop/gui/about_dialog.py index 85b0a4c..a3386c1 100644 --- a/src/searchmob_desktop/gui/about_dialog.py +++ b/src/searchmob_desktop/gui/about_dialog.py @@ -8,7 +8,7 @@ from __future__ import annotations from PySide6.QtCore import QUrl -from PySide6.QtGui import QDesktopServices +from PySide6.QtGui import QDesktopServices, QGuiApplication from PySide6.QtWidgets import ( QDialog, QFrame, @@ -36,7 +36,6 @@ def __init__(self, parent: QWidget | None = None) -> None: super().__init__(parent) self.setWindowTitle(tr("About SearchMob Desktop")) self.setModal(True) - self.resize(640, 720) outer = QVBoxLayout(self) scroll = QScrollArea(self) @@ -177,6 +176,27 @@ def __init__(self, parent: QWidget | None = None) -> None: scroll.setWidget(host) outer.addWidget(scroll) + # Open wide enough that the content never needs a horizontal scrollbar. The widest rows + # (the buttons row, the unwrapped footer lines) track the app font size and the current + # language, so any fixed width falls short for some combination and forces one. Derive + # the width from the content's minimum plus the scroll-area chrome, and clamp both sides + # to the available screen so an extreme font size still yields a usable dialog. + margins = outer.contentsMargins() + content_width = ( + host.minimumSizeHint().width() + + scroll.verticalScrollBar().sizeHint().width() + + 2 * scroll.frameWidth() + + margins.left() + + margins.right() + ) + width, height = max(640, content_width), 720 + screen = self.screen() or QGuiApplication.primaryScreen() + if screen is not None: + available = screen.availableGeometry() + width = min(width, available.width() - 80) + height = min(height, available.height() - 80) + self.resize(width, height) + @staticmethod def _add_section( layout: QVBoxLayout, diff --git a/tests/gui/test_about_dialog.py b/tests/gui/test_about_dialog.py index be2fbf8..b85df1b 100644 --- a/tests/gui/test_about_dialog.py +++ b/tests/gui/test_about_dialog.py @@ -33,3 +33,37 @@ def test_about_has_a_link_to_the_android_app(qapp: object) -> None: labels = [b.text() for b in dialog.findChildren(QPushButton)] assert any("Android" in t for t in labels) assert ANDROID_URL.endswith("/SearchMob") # the sibling repo, not the desktop one + + +def test_about_opens_wide_enough_for_its_content(qapp: object) -> None: + """The dialog derives its opening width from the content, so no horizontal scrollbar. + + A fixed opening width regressed whenever the app font size or the active language made the + widest row (the buttons row, the unwrapped footer lines) wider than it: the scroll area then + showed a horizontal scrollbar over what is a short static page. Guard the derivation at a + larger-than-default font, mocking a roomy screen so the small offscreen test display's clamp + does not mask the width calculation. + """ + from unittest.mock import patch + + from PySide6.QtCore import QRect + from PySide6.QtWidgets import QApplication, QScrollArea + + font = QApplication.font() + original_size = font.pointSize() + font.setPointSize(20) + QApplication.setFont(font) + try: + screen_type = type(QApplication.primaryScreen()) + with patch.object(screen_type, "availableGeometry", lambda self: QRect(0, 0, 1920, 1052)): + dialog = AboutDialog() + dialog.show() + QApplication.processEvents() + scroll = dialog.findChild(QScrollArea) + assert scroll is not None + assert scroll.viewport().width() >= scroll.widget().minimumSizeHint().width() + assert not scroll.horizontalScrollBar().isVisible() + dialog.close() + finally: + font.setPointSize(original_size) + QApplication.setFont(font)