File indexing completed on 2024-04-21 04:01:55

0001 # -*- coding: utf-8 -*-
0002 
0003 """
0004 Copyright (C) 2008-2016 Wolfgang Rohdewald <wolfgang@rohdewald.de>
0005 
0006 SPDX-License-Identifier: GPL-2.0
0007 
0008 """
0009 
0010 from qt import QObject, QByteArray, QEvent, QSplitter, QHeaderView
0011 
0012 from common import Internal, isAlive
0013 from mi18n import english
0014 
0015 
0016 class StateSaver(QObject):
0017 
0018     """saves and restores the state for widgets"""
0019 
0020     savers = {}
0021 
0022     def __init__(self, *widgets):
0023         QObject.__init__(self)
0024         pref = Internal.Preferences
0025         if widgets[0] not in StateSaver.savers:
0026             StateSaver.savers[widgets[0]] = self
0027             widgets[0].installEventFilter(self)
0028         self.widgets = []
0029         for widget in widgets:
0030             name = self.__generateName(widget)
0031             self.widgets.append((name, widget))
0032             pref.addString('States', name + 'State')
0033             pref.addString('States', name + 'Geometry')
0034         for name, widget in self.widgets:
0035             stateFound = self.__restore(widget, name + 'State')
0036             geometryFound = self.__restore(widget, name + 'Geometry')
0037             if not stateFound and not geometryFound:
0038                 pref.addString('States', name)
0039                 self.__restore(widget, name)
0040 
0041     @staticmethod
0042     def __restore(widget, name):
0043         """decode the saved string"""
0044         # pylint: disable=unsubscriptable-object
0045         def canRestore(name,what):
0046             return name.endswith(what) and hasattr(widget, 'restore' + what)
0047         state = QByteArray.fromHex(Internal.Preferences[name].encode())
0048         if state:
0049             if canRestore(name, 'State'):
0050                 widget.restoreState(state)
0051             elif canRestore(name, 'Geometry'):
0052                 widget.restoreGeometry(state)
0053             else:
0054                 # legacy
0055                 if isinstance(widget, (QSplitter, QHeaderView)):
0056                     widget.restoreState(state)
0057                 else:
0058                     widget.restoreGeometry(state)
0059         return bool(state)
0060 
0061     @staticmethod
0062     def __generateName(widget):
0063         """generate a name for this widget to be used in the config file"""
0064         orgWidget = widget
0065         name = english(widget.objectName())
0066         if not name:
0067             while widget.parentWidget():
0068                 name = widget.__class__.__name__ + name
0069                 widget = widget.parentWidget()
0070                 if widget.parentWidget():
0071                     widgetName = english(widget.parentWidget().objectName())
0072                     if widgetName:
0073                         name = widgetName + name
0074                         break
0075         if not name:
0076             name = orgWidget.__class__.__name__
0077         return str(name)
0078 
0079     def eventFilter(self, unusedWatched, event):
0080         """if the watched widget hides, save its state.
0081         Return False if the event should be handled further"""
0082         if QEvent is not None:
0083             # while appquit, QEvent may be None. Maybe not anymore
0084             # with later versions?
0085             if event.type() == QEvent.Hide:
0086                 self.save()
0087             elif event.type() == QEvent.Close:
0088                 self.save()
0089                 widget = self.widgets[0][1]
0090                 if widget in StateSaver.savers:
0091                     del StateSaver.savers[widget]
0092         return False
0093 
0094     @staticmethod
0095     def saveAll():
0096         """execute all registered savers and write states to config file"""
0097         for saver in StateSaver.savers.values():
0098             saver.save()
0099         Internal.Preferences.writeConfig()
0100 
0101     @staticmethod
0102     def stateStr(state):
0103         """convert hex string to str"""
0104         return str(bytes(state.toHex()).decode())
0105 
0106     def save(self):
0107         """writes the state into Preferences, but does not save"""
0108         for name, widget in self.widgets:
0109             if isAlive(widget):
0110                 # pylint: disable=unsupported-assignment-operation
0111                 if hasattr(widget, 'saveState'):
0112                     Internal.Preferences[name + 'State'] = self.stateStr(widget.saveState())
0113                 if hasattr(widget, 'saveGeometry'):
0114                     Internal.Preferences[name + 'Geometry'] = self.stateStr(widget.saveGeometry())