File indexing completed on 2024-04-28 07:51:06

0001 # -*- coding: utf-8 -*-
0002 
0003 """
0004 Copyright (C) 2008-2016 Wolfgang Rohdewald <wolfgang@rohdewald.de>
0005 
0006 partially based on C++ code from:
0007  - Copyright (C) 2006 Mauricio Piacentini <mauricio@tabuleiro.com>
0008 
0009 SPDX-License-Identifier: GPL-2.0
0010 
0011 """
0012 
0013 from collections import defaultdict
0014 
0015 from kde import KConfigSkeleton
0016 from log import logException, logDebug
0017 from common import Internal, Debug
0018 
0019 
0020 class Parameter:
0021 
0022     """helper class for defining configuration parameters"""
0023 
0024     def __init__(self, group, name, default=None):
0025         """configuration group, parameter name, default value"""
0026         self.group = group
0027         self.name = name
0028         self.default = default
0029         self.item = None
0030 
0031     def itemValue(self):
0032         """return the value of this item"""
0033         return self.item.value()
0034 
0035 
0036 class StringParameter(Parameter):
0037 
0038     """helper class for defining string parameters"""
0039 
0040     def __init__(self, group, name, default=None):
0041         if default is None:
0042             default = ''
0043         Parameter.__init__(self, group, name, default)
0044         self.value = ''
0045 
0046     def add(self, skeleton):
0047         """add tis parameter to the skeleton"""
0048         self.item = skeleton.addItem(self.name, self.value, self.default or '')
0049 
0050     def itemValue(self):
0051         """return the value of this item"""
0052         return str(self.item.value())
0053 
0054 
0055 class BoolParameter(Parameter):
0056 
0057     """helper class for defining boolean parameters"""
0058 
0059     def __init__(self, group, name, default=None):
0060         if default is None:
0061             default = False
0062         Parameter.__init__(self, group, name, default)
0063         self.value = default
0064 
0065     def add(self, skeleton):
0066         """add tis parameter to the skeleton"""
0067         self.item = skeleton.addItem(self.name, self.value, self.default)
0068 
0069 
0070 class IntParameter(Parameter):
0071 
0072     """helper class for defining integer parameters"""
0073 
0074     def __init__(self, group, name, default=None,
0075                  minValue=None, maxValue=None):
0076         """minValue and maxValue are also used by the edit widget"""
0077         if default is None:
0078             default = 0
0079         Parameter.__init__(self, group, name, default)
0080         self.value = default
0081         self.minValue = minValue
0082         self.maxValue = maxValue
0083 
0084     def add(self, skeleton):
0085         """add this parameter to the skeleton"""
0086         self.item = skeleton.addItem(self.name, self.value, self.default)
0087         if self.minValue is not None:
0088             self.item.setMinValue(self.minValue)
0089         if self.maxValue is not None:
0090             self.item.setMaxValue(self.maxValue)
0091 
0092 
0093 class SetupPreferences(KConfigSkeleton):
0094 
0095     """Holds all Kajongg options. Only instantiate this once"""
0096     _Parameters = {}
0097 
0098     def __init__(self):  # pylint: disable=super-init-not-called
0099         if Internal.Preferences:
0100             logException('Preferences is not None')
0101         self.__watching = defaultdict(list)
0102         Internal.Preferences = self
0103         KConfigSkeleton.__init__(self)
0104         self.configChanged.connect(self.callTriggers)
0105         self.__oldValues = defaultdict(str)
0106         self.addString('General', 'tilesetName', 'default')
0107         self.addString('General', 'windTilesetName', 'traditional')
0108         self.addString('General', 'backgroundName', 'wood_light')
0109         self.addBool('Display', 'showShadows', True)
0110         self.addBool('Display', 'rearrangeMelds', False)
0111         self.addBool('Display', 'showOnlyPossibleActions', True)
0112         self.addBool('Display', 'propose', True)
0113         self.addInteger('Display', 'animationSpeed', 70, 0, 99)
0114         self.addBool('Display', 'useSounds', True)
0115         self.addBool('Display', 'uploadVoice', False)
0116 
0117     def callTrigger(self, name):
0118         """call registered callback for this attribute change"""
0119         newValue = getattr(self, name)
0120         if self.__oldValues[name] != newValue:
0121             if Debug.preferences:
0122                 logDebug('{}: {} -> {} calling {}'.format(
0123                     name,
0124                     self.__oldValues[name],
0125                     newValue,
0126                     ','.join(x.__name__ for x in self.__watching[name])))
0127             for method in self.__watching[name]:
0128                 method(self.__oldValues[name], newValue)
0129         self.__oldValues[name] = newValue
0130 
0131     def callTriggers(self):
0132         """call registered callbacks for specific attribute changes"""
0133         for name in self.__watching:
0134             self.callTrigger(name)
0135 
0136     def addWatch(self, name, method):
0137         """If name changes, call method.
0138         method must accept 2 arguments: old value and new value."""
0139         if method not in self.__watching[name]:
0140             self.__watching[name].append(method)
0141             if Debug.preferences:
0142                 logDebug('addWatch on {}, hook {}'.format(
0143                     name, method.__name__))
0144             self.callTrigger(name)  # initial change
0145 
0146     def __getattr__(self, name):
0147         """undefined attributes might be parameters"""
0148         if name not in SetupPreferences._Parameters:
0149             return self.__getattribute__(name)
0150         par = SetupPreferences._Parameters[name]
0151         return par.itemValue()
0152 
0153     def __setattr__(self, name, value):
0154         """undefined attributes might be parameters"""
0155         if name not in SetupPreferences._Parameters:
0156             KConfigSkeleton.__setattr__(self, name, value)
0157             return
0158         par = SetupPreferences._Parameters[name]
0159         par.item.setValue(value)
0160 
0161     def __getitem__(self, key):
0162         return self.__getattr__(key)
0163 
0164     def __setitem__(self, key, value):
0165         self.__setattr__(key, value)
0166 
0167     def __delitem__(self, key):
0168         """pylint wants this for a complete container, but we do not need it"""
0169         del SetupPreferences._Parameters[key]
0170 
0171     def __len__(self):
0172         """pylint wants this for a complete container, but we do not need it"""
0173         return len(SetupPreferences._Parameters)
0174 
0175     def addParameter(self, par):
0176         """add a parameter to the skeleton"""
0177         if par.name not in SetupPreferences._Parameters:
0178             SetupPreferences._Parameters[par.name] = par
0179             self.setCurrentGroup(par.group)
0180             par.add(self)
0181 
0182     def addString(self, group, name, default=None):
0183         """add a string parameter to the skeleton"""
0184         self.addParameter(StringParameter(group, name, default))
0185 
0186     def addBool(self, group, name, default=None):
0187         """add a string parameter to the skeleton"""
0188         self.addParameter(BoolParameter(group, name, default))
0189 
0190     def addInteger(self, group, name, default=None,
0191                    minValue=None, maxValue=None):
0192         """add a string parameter to the skeleton"""
0193         self.addParameter(IntParameter(
0194             group, name, default, minValue, maxValue))
0195 
0196     def animationDuration(self):
0197         """in milliseconds"""
0198         return (99 - self.animationSpeed) * 100 // 4