From 11254381a8ba38242dde9478624221a1132a3db2 Mon Sep 17 00:00:00 2001 From: glubsy Date: Thu, 30 Jul 2020 20:25:20 +0200 Subject: [PATCH] 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). --- qt/app.py | 8 +++++--- qt/details_dialog.py | 10 +++++++--- qtlib/preferences.py | 13 ++++++++++--- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/qt/app.py b/qt/app.py index 8d3d7404..bd85d8a0 100644 --- a/qt/app.py +++ b/qt/app.py @@ -285,16 +285,18 @@ class DupeGuru(QObject): """Creates resultWindow and details_dialog depending on the selected ``app_mode``. """ 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.setParent(None) + # self.details_dialog.setParent(None) # seems unnecessary if self.resultWindow is not None: self.resultWindow.close() self.resultWindow.setParent(None) self.resultWindow = ResultWindow(self.directories_dialog, self) self.directories_dialog._updateActionsState() self.details_dialog = self._get_details_dialog_class()(self.resultWindow, self) - self.resultWindow.addDockWidget( - Qt.BottomDockWidgetArea, self.details_dialog) def show_results_window(self): self.showResultsWindow() diff --git a/qt/details_dialog.py b/qt/details_dialog.py index 517f8511..c39f81e2 100644 --- a/qt/details_dialog.py +++ b/qt/details_dialog.py @@ -24,18 +24,22 @@ class DetailsDialog(QDockWidget): # 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. 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) # tableView is defined in subclasses self.tableView.setModel(self.tableModel) self.model.view = self - 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 pass def show(self): + if not self._shown_once and self._wasDocked: + self.setFloating(False) self._shown_once = True super().show() self.update_options() @@ -63,7 +67,7 @@ class DetailsDialog(QDockWidget): # --- Events def appWillSavePrefs(self): - if self._shown_once and self.isFloating(): + if self._shown_once: self.app.prefs.saveGeometry("DetailsWindowRect", self) # --- model --> view diff --git a/qtlib/preferences.py b/qtlib/preferences.py index 76a5a73c..7e3ba864 100644 --- a/qtlib/preferences.py +++ b/qtlib/preferences.py @@ -7,6 +7,7 @@ # http://www.gnu.org/licenses/gpl-3.0.html from PyQt5.QtCore import Qt, QSettings, QRect, QObject, pyqtSignal +from PyQt5.QtWidgets import QDockWidget from hscommon.trans import trget 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 # is maximized and the other 4 are (x, y, w, h). 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() 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): geometry = self.get_value(name) - if geometry and len(geometry) == 5: - m, x, y, w, h = geometry + if geometry and len(geometry) == 7: + m, d, area, x, y, w, h = geometry if m: widget.setWindowState(Qt.WindowMaximized) else: r = QRect(x, y, w, h) widget.setGeometry(r) + if isinstance(widget, QDockWidget): + # Inform of the previous dock state and the area used + return bool(d), area + return False, 0