dupeguru/qtlib/preferences.py

148 lines
4.6 KiB
Python

# Created By: Virgil Dupras
# Created On: 2009-05-03
# Copyright 2015 Hardcoded Software (http://www.hardcoded.net)
#
# This software is licensed under the "GPLv3" License as described in the "LICENSE" file,
# which should be included with this package. The terms are also available at
# 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
tr = trget("qtlib")
def get_langnames():
return {
"en": tr("English"),
"fr": tr("French"),
"de": tr("German"),
"el": tr("Greek"),
"zh_CN": tr("Chinese (Simplified)"),
"cs": tr("Czech"),
"it": tr("Italian"),
"hy": tr("Armenian"),
"ko": tr("Korean"),
"ru": tr("Russian"),
"uk": tr("Ukrainian"),
"nl": tr("Dutch"),
"pl_PL": tr("Polish"),
"pt_BR": tr("Brazilian"),
"es": tr("Spanish"),
"vi": tr("Vietnamese"),
}
def normalize_for_serialization(v):
# QSettings doesn't consider set/tuple as "native" typs for serialization, so if we don't
# change them into a list, we get a weird serialized QVariant value which isn't a very
# "portable" value.
if isinstance(v, (set, tuple)):
v = list(v)
if isinstance(v, list):
v = [normalize_for_serialization(item) for item in v]
return v
def adjust_after_deserialization(v):
# In some cases, when reading from prefs, we end up with strings that are supposed to be
# bool or int. Convert these.
if isinstance(v, list):
return [adjust_after_deserialization(sub) for sub in v]
if isinstance(v, str):
# might be bool or int, try them
if v == "true":
return True
elif v == "false":
return False
else:
return tryint(v, v)
return v
# About QRect conversion:
# I think Qt supports putting basic structures like QRect directly in QSettings, but I prefer not
# to rely on it and stay with generic structures.
class Preferences(QObject):
prefsChanged = pyqtSignal()
def __init__(self):
QObject.__init__(self)
self.reset()
self._settings = QSettings()
def _load_values(self, settings, get):
pass
def get_rect(self, name, default=None):
r = self.get_value(name, default)
if r is not None:
return QRect(*r)
else:
return None
def get_value(self, name, default=None):
if self._settings.contains(name):
result = adjust_after_deserialization(self._settings.value(name))
if result is not None:
return result
else:
# If result is None, but still present in self._settings, it usually means a value
# like "@Invalid".
return default
else:
return default
def load(self):
self.reset()
self._load_values(self._settings)
def reset(self):
pass
def _save_values(self, settings, set_):
pass
def save(self):
self._save_values(self._settings)
self._settings.sync()
def set_rect(self, name, r):
if isinstance(r, QRect):
rectAsList = [r.x(), r.y(), r.width(), r.height()]
self.set_value(name, rectAsList)
def set_value(self, name, value):
self._settings.setValue(name, normalize_for_serialization(value))
def saveGeometry(self, name, widget):
# We save geometry under a 7-sized int array: first item is a flag
# for whether the widget is maximized, second item is a flag for whether
# the widget is docked, third item is a Qt::DockWidgetArea enum value,
# 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, d, area] + rectAsList)
def restoreGeometry(self, name, widget):
geometry = self.get_value(name)
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