fix: apply the UI scale before creating the Qt app (#5686)

## Linked issue (required)

Fixes #5676

## Summary / motivation (required)

#5637 moved the `QT_SCALE_FACTOR` assignment to after `AnkiApp` is
created, but Qt only reads it when the app is constructed, so the "User
interface size" setting stopped doing anything. this sets it before the
app is created again; `setupGL()` stays where it is (smaller version
suggested in review)

## Steps to reproduce (required, use N/A if not applicable)

set "User interface size" to 200% in preferences, restart, the UI is
still the default size

## How to test (required)

### Checklist (minimum)

- [ ] I ran `./ninja check` or an equivalent relevant check locally.
- [x] I added or updated tests when the change is non-trivial or
behavior changed.

### Details

qt/tests/test_startup.py runs `_run()` with a stand-in for AnkiApp and
checks QT_SCALE_FACTOR is already set when it's constructed, fails on
main and passes with this. also checked with the 26.9.3 wheels on
Windows at 150%: device pixel ratio 1.5 before, 3.0 after

## UI evidence (required for visual changes; otherwise N/A)

N/A

## Scope

- [x] This PR is focused on one change (no unrelated edits).
This commit is contained in:
Artem Lytkin
2026-09-28 14:15:54 +03:00
committed by GitHub
parent 1f7c8d7c4c
commit 41d7464c9b
3 changed files with 42 additions and 2 deletions
+1
View File
@@ -309,6 +309,7 @@ Caleb Meadows
Michael McDonald <https://github.com/praxish>
wofiporia <1029687661@qq.com>
Zain <https://github.com/ZainnQureshii>
Artem Lytkin <146867384+4RH1T3CT0R7@users.noreply.github.com>
********************
The text of the 3 clause BSD license follows:
+4 -2
View File
@@ -688,6 +688,10 @@ def _run(argv: list[str] | None = None, exec: bool = True) -> AnkiApp | None:
traceback.print_exc()
pm = None
if pm:
# apply user-provided scale factor
os.environ["QT_SCALE_FACTOR"] = str(pm.uiScale())
# Opt-in to full HiDPI support?
if not os.environ.get("ANKI_NOHIGHDPI") and qtmajor == 5:
QCoreApplication.setAttribute(Qt.ApplicationAttribute.AA_EnableHighDpiScaling) # type: ignore
@@ -718,8 +722,6 @@ def _run(argv: list[str] | None = None, exec: bool = True) -> AnkiApp | None:
driver = pm.video_driver() if not app.safeMode else VideoDriver.Software
# gl workarounds
setupGL(pm, driver)
# apply user-provided scale factor
os.environ["QT_SCALE_FACTOR"] = str(pm.uiScale())
else:
if i18n_setup:
QMessageBox.critical(
+37
View File
@@ -0,0 +1,37 @@
# Copyright: Ankitects Pty Ltd and contributors
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
from __future__ import annotations
import os
from pathlib import Path
from unittest.mock import patch
import pytest
import aqt
from aqt.profiles import ProfileManager
@patch.dict(os.environ)
def test_ui_scale_is_applied_before_app_is_created(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
# Qt reads QT_SCALE_FACTOR when the app is constructed, so setting it
# afterwards has no effect (#5676)
monkeypatch.setattr(ProfileManager, "uiScale", lambda self: 2.0)
seen: list[str | None] = []
class FakeApp:
def __init__(self, argv: list[str]) -> None:
seen.append(os.environ.get("QT_SCALE_FACTOR"))
def secondInstance(self) -> bool:
# makes _run() return right after creating the app
return True
monkeypatch.setattr(aqt, "AnkiApp", FakeApp)
aqt._run(["anki", "-b", str(tmp_path)], exec=False)
assert seen == ["2.0"]