Save dock panel position on quit

* Restore the details dialog dock position if it was previously docked (i.e. not floating).
* Since the details_dialog instance was not deleted after closing by default, the previous instances were still saving their own geometry. We now delete them explicitely if we have to recreate a new instance to avoid the signal triggering the callback to save the geometry.
* Since restoreGeometry() and saveGeometry() are only called in our QDockWidget, it should be safe to modify the methods for the Preferences class (in qtlib).
This commit is contained in:
glubsy 2020-07-30 20:25:20 +02:00
parent 23642815f6
commit 11254381a8
3 changed files with 22 additions and 9 deletions

View File

@ -285,16 +285,18 @@ class DupeGuru(QObject):
"""Creates resultWindow and details_dialog depending on the selected ``app_mode``. """Creates resultWindow and details_dialog depending on the selected ``app_mode``.
""" """
if self.details_dialog is not None: if self.details_dialog is not None:
# The object is not deleted entirely, avoid saving its geometry in the future
# self.willSavePrefs.disconnect(self.details_dialog.appWillSavePrefs)
# or simply delete it on close which is probably cleaner:
self.details_dialog.setAttribute(Qt.WA_DeleteOnClose)
self.details_dialog.close() self.details_dialog.close()
self.details_dialog.setParent(None) # self.details_dialog.setParent(None) # seems unnecessary
if self.resultWindow is not None: if self.resultWindow is not None:
self.resultWindow.close() self.resultWindow.close()
self.resultWindow.setParent(None) self.resultWindow.setParent(None)
self.resultWindow = ResultWindow(self.directories_dialog, self) self.resultWindow = ResultWindow(self.directories_dialog, self)
self.directories_dialog._updateActionsState() self.directories_dialog._updateActionsState()
self.details_dialog = self._get_details_dialog_class()(self.resultWindow, self) self.details_dialog = self._get_details_dialog_class()(self.resultWindow, self)
self.resultWindow.addDockWidget(
Qt.BottomDockWidgetArea, self.details_dialog)
def show_results_window(self): def show_results_window(self):
self.showResultsWindow() self.showResultsWindow()

View File

@ -24,18 +24,22 @@ class DetailsDialog(QDockWidget):
# To avoid saving uninitialized geometry on appWillSavePrefs, we track whether our dialog # To avoid saving uninitialized geometry on appWillSavePrefs, we track whether our dialog
# has been shown. If it has, we know that our geometry should be saved. # has been shown. If it has, we know that our geometry should be saved.
self._shown_once = False self._shown_once = False
self.app.prefs.restoreGeometry("DetailsWindowRect", self) self._wasDocked, area = self.app.prefs.restoreGeometry("DetailsWindowRect", self)
self.tableModel = DetailsModel(self.model, app) self.tableModel = DetailsModel(self.model, app)
# tableView is defined in subclasses # tableView is defined in subclasses
self.tableView.setModel(self.tableModel) self.tableView.setModel(self.tableModel)
self.model.view = self self.model.view = self
self.app.willSavePrefs.connect(self.appWillSavePrefs) self.app.willSavePrefs.connect(self.appWillSavePrefs)
# self.setAttribute(Qt.WA_DeleteOnClose)
parent.addDockWidget(
area if self._wasDocked else Qt.BottomDockWidgetArea, self)
def _setupUi(self): # Virtual def _setupUi(self): # Virtual
pass pass
def show(self): def show(self):
if not self._shown_once and self._wasDocked:
self.setFloating(False)
self._shown_once = True self._shown_once = True
super().show() super().show()
self.update_options() self.update_options()
@ -63,7 +67,7 @@ class DetailsDialog(QDockWidget):
# --- Events # --- Events
def appWillSavePrefs(self): def appWillSavePrefs(self):
if self._shown_once and self.isFloating(): if self._shown_once:
self.app.prefs.saveGeometry("DetailsWindowRect", self) self.app.prefs.saveGeometry("DetailsWindowRect", self)
# --- model --> view # --- model --> view

View File

@ -7,6 +7,7 @@
# http://www.gnu.org/licenses/gpl-3.0.html # http://www.gnu.org/licenses/gpl-3.0.html
from PyQt5.QtCore import Qt, QSettings, QRect, QObject, pyqtSignal from PyQt5.QtCore import Qt, QSettings, QRect, QObject, pyqtSignal
from PyQt5.QtWidgets import QDockWidget
from hscommon.trans import trget from hscommon.trans import trget
from hscommon.util import tryint from hscommon.util import tryint
@ -123,16 +124,22 @@ class Preferences(QObject):
# We save geometry under a 5-sized int array: first item is a flag for whether the widget # We save geometry under a 5-sized int array: first item is a flag for whether the widget
# is maximized and the other 4 are (x, y, w, h). # is maximized and the other 4 are (x, y, w, h).
m = 1 if widget.isMaximized() else 0 m = 1 if widget.isMaximized() else 0
d = 1 if isinstance(widget, QDockWidget) and not widget.isFloating() else 0
area = widget.parent.dockWidgetArea(widget) if d else 0
r = widget.geometry() r = widget.geometry()
rectAsList = [r.x(), r.y(), r.width(), r.height()] rectAsList = [r.x(), r.y(), r.width(), r.height()]
self.set_value(name, [m] + rectAsList) self.set_value(name, [m, d, area] + rectAsList)
def restoreGeometry(self, name, widget): def restoreGeometry(self, name, widget):
geometry = self.get_value(name) geometry = self.get_value(name)
if geometry and len(geometry) == 5: if geometry and len(geometry) == 7:
m, x, y, w, h = geometry m, d, area, x, y, w, h = geometry
if m: if m:
widget.setWindowState(Qt.WindowMaximized) widget.setWindowState(Qt.WindowMaximized)
else: else:
r = QRect(x, y, w, h) r = QRect(x, y, w, h)
widget.setGeometry(r) widget.setGeometry(r)
if isinstance(widget, QDockWidget):
# Inform of the previous dock state and the area used
return bool(d), area
return False, 0