mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 14:02:21 -04:00
Store separate state/geometry for each Qt minor version
Quite a few users have been experiencing crashes recently that were resolved by resetting their window positions/states. I presume this is related to Qt updates, as there have been previous instances where old state caused glitchy behaviour or crashes after a Qt upgrade. The browser headers are now also reset when resetting window positions in the preferences.
This commit is contained in:
parent
4e65793966
commit
19b08eb280
3 changed files with 38 additions and 28 deletions
|
@ -321,17 +321,11 @@ class Table:
|
|||
hh.setCascadingSectionResizes(False)
|
||||
|
||||
def _save_header(self) -> None:
|
||||
saveHeader(
|
||||
self._view.horizontalHeader(), self._state.GEOMETRY_KEY_PREFIX + "31"
|
||||
)
|
||||
saveHeader(self._view.horizontalHeader(), self._state.GEOMETRY_KEY_PREFIX)
|
||||
|
||||
def _restore_header(self) -> None:
|
||||
self._view.horizontalHeader().blockSignals(True)
|
||||
# Qt 6.3.1 won't allow headers to be clicked when restoring state from a previous
|
||||
# version, so we need to bump the key.
|
||||
restoreHeader(
|
||||
self._view.horizontalHeader(), self._state.GEOMETRY_KEY_PREFIX + "31"
|
||||
)
|
||||
restoreHeader(self._view.horizontalHeader(), self._state.GEOMETRY_KEY_PREFIX)
|
||||
self._set_column_sizes()
|
||||
self._set_sort_indicator()
|
||||
self._view.horizontalHeader().blockSignals(False)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
# Copyright: Ankitects Pty Ltd and contributors
|
||||
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
import re
|
||||
from typing import Any, cast
|
||||
|
||||
import anki.lang
|
||||
|
@ -311,9 +312,9 @@ class Preferences(QDialog):
|
|||
self.mw.set_theme(Theme(index))
|
||||
|
||||
def on_reset_window_sizes(self) -> None:
|
||||
suffixes = ["Geom", "State", "Splitter"]
|
||||
regexp = re.compile(r"(Geom(etry)?|State|Splitter|Header)(\d+.\d+)?$")
|
||||
for key in list(self.prof.keys()):
|
||||
if any(key.endswith(suffix) for suffix in suffixes):
|
||||
if regexp.search(key):
|
||||
del self.prof[key]
|
||||
showInfo(tr.preferences_reset_window_sizes_complete())
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
from __future__ import annotations
|
||||
|
||||
import enum
|
||||
import inspect
|
||||
import os
|
||||
import re
|
||||
|
@ -693,11 +694,29 @@ def getSaveFile(
|
|||
return file
|
||||
|
||||
|
||||
class _QtStateKeyKind(enum.Enum):
|
||||
HEADER = enum.auto()
|
||||
SPLITTER = enum.auto()
|
||||
STATE = enum.auto()
|
||||
GEOMETRY = enum.auto()
|
||||
|
||||
|
||||
def _qt_state_key(kind: _QtStateKeyKind, key: str) -> str:
|
||||
"""Construct a key used to save/restore geometry, state, etc.
|
||||
|
||||
Adds Qt version number to key so that different data is saved per Qt version,
|
||||
preventing crashes and bugs when restoring data saved with a different Qt version.
|
||||
"""
|
||||
qt_suffix = f"{qtmajor}.{qtminor}" if qtmajor > 5 else ""
|
||||
return f"{key}{kind.name.capitalize()}{qt_suffix}"
|
||||
|
||||
|
||||
def saveGeom(widget: QWidget, key: str) -> None:
|
||||
# restoring a fullscreen window is buggy
|
||||
# (at the time of writing; Qt 6.2.2 and 5.15)
|
||||
if not widget.isFullScreen():
|
||||
aqt.mw.pm.profile[f"{key}Geom"] = widget.saveGeometry()
|
||||
key = _qt_state_key(_QtStateKeyKind.GEOMETRY, key)
|
||||
aqt.mw.pm.profile[key] = widget.saveGeometry()
|
||||
|
||||
|
||||
def restoreGeom(
|
||||
|
@ -706,7 +725,7 @@ def restoreGeom(
|
|||
adjustSize: bool = False,
|
||||
default_size: tuple[int, int] | None = None,
|
||||
) -> None:
|
||||
key += "Geom"
|
||||
key = _qt_state_key(_QtStateKeyKind.GEOMETRY, key)
|
||||
if existing_geom := aqt.mw.pm.profile.get(key):
|
||||
widget.restoreGeometry(existing_geom)
|
||||
ensureWidgetInScreenBoundaries(widget)
|
||||
|
@ -745,39 +764,35 @@ def ensureWidgetInScreenBoundaries(widget: QWidget) -> None:
|
|||
|
||||
|
||||
def saveState(widget: QFileDialog | QMainWindow, key: str) -> None:
|
||||
key += "State"
|
||||
key = _qt_state_key(_QtStateKeyKind.STATE, key)
|
||||
aqt.mw.pm.profile[key] = widget.saveState()
|
||||
|
||||
|
||||
def restoreState(widget: QFileDialog | QMainWindow, key: str) -> None:
|
||||
key += "State"
|
||||
if aqt.mw.pm.profile.get(key):
|
||||
widget.restoreState(aqt.mw.pm.profile[key])
|
||||
key = _qt_state_key(_QtStateKeyKind.STATE, key)
|
||||
if data := aqt.mw.pm.profile.get(key):
|
||||
widget.restoreState(data)
|
||||
|
||||
|
||||
def saveSplitter(widget: QSplitter, key: str) -> None:
|
||||
key += "Splitter"
|
||||
key = _qt_state_key(_QtStateKeyKind.SPLITTER, key)
|
||||
aqt.mw.pm.profile[key] = widget.saveState()
|
||||
|
||||
|
||||
def restoreSplitter(widget: QSplitter, key: str) -> None:
|
||||
key += "Splitter"
|
||||
if aqt.mw.pm.profile.get(key):
|
||||
widget.restoreState(aqt.mw.pm.profile[key])
|
||||
|
||||
|
||||
def _header_key(key: str) -> str:
|
||||
# not compatible across major versions
|
||||
qt_suffix = f"Qt{qtmajor}" if qtmajor > 5 else ""
|
||||
return f"{key}Header{qt_suffix}"
|
||||
key = _qt_state_key(_QtStateKeyKind.SPLITTER, key)
|
||||
if data := aqt.mw.pm.profile.get(key):
|
||||
widget.restoreState(data)
|
||||
|
||||
|
||||
def saveHeader(widget: QHeaderView, key: str) -> None:
|
||||
aqt.mw.pm.profile[_header_key(key)] = widget.saveState()
|
||||
key = _qt_state_key(_QtStateKeyKind.HEADER, key)
|
||||
aqt.mw.pm.profile[key] = widget.saveState()
|
||||
|
||||
|
||||
def restoreHeader(widget: QHeaderView, key: str) -> None:
|
||||
if state := aqt.mw.pm.profile.get(_header_key(key)):
|
||||
key = _qt_state_key(_QtStateKeyKind.HEADER, key)
|
||||
if state := aqt.mw.pm.profile.get(key):
|
||||
widget.restoreState(state)
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue