More work on custom widget geometry restore

This commit is contained in:
Kovid Goyal 2022-10-12 20:58:21 +05:30
parent 623b1d69f2
commit 0561f520a8
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C

View File

@ -8,6 +8,13 @@
from qt.core import QRect, QScreen, QSize, QWidget, QApplication, Qt
from calibre.constants import DEBUG
def debug(*a, **kw):
if DEBUG:
from pprint import pprint
pprint(*a, **kw)
def size_as_dict(self: QSize):
@ -32,6 +39,7 @@ def screen_as_dict(self: QScreen):
'device_pixel_ratio': self.devicePixelRatio(),
'size_in_logical_pixels': size_as_dict(self.size()),
'geometry_in_logical_pixels': rect_as_dict(self.geometry()),
'virtual_geometry': rect_as_dict(self.virtualGeometry()),
'index_in_screens_list': num,
}
@ -40,7 +48,7 @@ def geometry_for_restore_as_dict(self: QWidget):
s = self.screen()
if s is None:
return {}
return {
ans = {
'screen': screen_as_dict(s),
'geometry': rect_as_dict(self.geometry()),
'frame_geometry': rect_as_dict(self.frameGeometry()),
@ -48,20 +56,25 @@ def geometry_for_restore_as_dict(self: QWidget):
'maximized': self.isMaximized(),
'full_screened': self.isFullScreen(),
}
return ans
def save_geometry(self: QWidget, prefs: dict, name: str):
x = geometry_for_restore_as_dict(self)
if x:
if DEBUG:
debug('Saving geometry for:', name)
debug(x)
prefs.set(f'geometry-of-{name}', x)
def find_matching_screen(screen_as_dict):
screens = QApplication.instance().screens()
size = QSize(**screen_as_dict['size'])
vg = QRect(**screen_as_dict['virtual_geometry'])
screens_of_matching_size = tuple(
s for s in screens if
s.size() == size and s.devicePixelRatio() == screen_as_dict['device_pixel_ratio'])
s.size() == size and vg == s.virtualGeometry() and s.devicePixelRatio() == screen_as_dict['device_pixel_ratio'])
if screen_as_dict['serial']:
for q in screens_of_matching_size:
if q.serialNumber() == screen_as_dict['serial']:
@ -76,21 +89,33 @@ def find_matching_screen(screen_as_dict):
return q
def _restore_geometry(self: QWidget, prefs: dict, name: str) -> bool:
x = prefs.get(f'geometry-of-{name}')
if not x:
return False
s = find_matching_screen(x['screen'])
if s is None:
p = self.nativeParentWidget()
if p is not None:
s = p.screen()
if s is None:
s = self.screen()
if s is None:
s = QApplication.instance().primaryScreen()
if s is None:
return False
def _do_restore(self: QWidget, s: QScreen, geometry: QRect, x: dict):
ws = self.windowState()
if ws & (Qt.WindowState.WindowFullScreen | Qt.WindowState.WindowMaximized):
debug('Not restoring geometry as widget is already maximized or fullscreen')
return True
if self.screen() is not s:
debug('Moving widget to saved screen')
self.setScreen(s)
debug('Setting widget geometry to:', geometry)
self.setGeometry(geometry)
if x['full_screened']:
debug('Restoring widget to full screen')
self.showFullScreen()
elif x['maximized']:
debug('Restoring widget to maximized')
self.showMaximized()
return True
def _restore_to_matching_screen(self: QWidget, s: QScreen, saved_data: dict) -> bool:
x = saved_data
saved_geometry = QRect(**x['geometry'])
return _do_restore(self, s, saved_geometry, x)
def _restore_to_new_screen(self: QWidget, s: QScreen, saved_data: dict) -> bool:
x = saved_data
saved_geometry = QRect(**x['geometry'])
saved_frame_geometry = QRect(**x['frame_geometry'])
if not saved_geometry.isValid() or not saved_frame_geometry.isValid():
@ -105,14 +130,33 @@ def _restore_geometry(self: QWidget, prefs: dict, name: str) -> bool:
max_left = available_geometry.left() + (available_size.width() - sz.width())
max_top = available_geometry.top() + (available_size.height() - sz.height())
geometry = QRect(min(saved_geometry.left(), max_left), min(saved_geometry.top(), max_top), sz.width(), sz.height())
ws = self.windowState()
if ws & (Qt.WindowState.WindowFullScreen | Qt.WindowState.WindowMaximized):
return True
self.setGeometry(geometry)
if x['full_screened']:
self.showFullScreen()
elif x['maximized']:
self.showMaximized()
return _do_restore(self, s, geometry, x)
def _restore_geometry(self: QWidget, prefs: dict, name: str) -> bool:
x = prefs.get(f'geometry-of-{name}')
if not x:
return False
if DEBUG:
debug('Restoring geometry for:', name)
debug(x)
s = find_matching_screen(x['screen'])
debug('Matching screen:', screen_as_dict(s) if s else None)
if s is None:
if DEBUG:
debug('No screens matched saved screen. Available screens:', tuple(map(screen_as_dict, QApplication.instance().screens())))
p = self.nativeParentWidget()
if p is not None:
s = p.screen()
if s is None:
s = self.screen()
if s is None:
s = QApplication.instance().primaryScreen()
else:
return _restore_to_matching_screen(self, s, x)
if s is None:
return False
return _restore_to_new_screen(self, s, x)
def restore_geometry(self: QWidget, prefs: dict, name: str) -> bool: