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

0001 # -*- coding: utf-8 -*-
0002 
0003 """
0004 Authors of original libkmahjongg in C++:
0005     Copyright (C) 1997 Mathias Mueller <in5y158@public.uni-hamburg.de>
0006     Copyright (C) 2006 Mauricio Piacentini <mauricio@tabuleiro.com>
0007 
0008 this adapted python code:
0009     Copyright (C) 2008-2016 Wolfgang Rohdewald <wolfgang@rohdewald.de>
0010 
0011 SPDX-License-Identifier: GPL-2.0
0012 
0013 """
0014 
0015 import os
0016 from qt import QStandardPaths
0017 from log import logWarning, logException
0018 from kde import KConfig
0019 from mi18n import i18n
0020 
0021 RESOURCEFORMAT = 1 # as long as backgrounds and tilesets are synchronous in their versions
0022 
0023 
0024 class Resource:
0025 
0026     """Common code for backgrounds and tilesets"""
0027 
0028     resourceName = None # to be overridden in Tileset and Background
0029     configGroupName = None
0030 
0031     """represents a complete tileset"""
0032     # pylint: disable=too-many-instance-attributes
0033 
0034     cache = {}
0035 
0036     def __new__(cls, name):
0037         return cls.cache.get(name) or cls.cache.get(cls.__name(name)) or cls.__build(name)
0038 
0039     @classmethod
0040     def __directories(cls):
0041         """where to look for resources"""
0042         result = QStandardPaths.locateAll(
0043             QStandardPaths.GenericDataLocation,
0044             'kmahjongglib/{}s'.format(cls.resourceName), QStandardPaths.LocateDirectory)
0045         result.insert(0, os.path.join('share', 'kmahjongglib', '{}s'.format(cls.resourceName)))
0046         return (x for x in result if os.path.exists(x))
0047 
0048     @classmethod
0049     def locate(cls, which):
0050         """locate the file with a resource"""
0051         for directory in cls.__directories():
0052             path = os.path.join(directory, which)
0053             if os.path.exists(path):
0054                 return path
0055         logException('cannot find kmahjongg%s %s in %s' % (cls.resourceName, which, cls.__directories()))
0056         return None
0057 
0058     @classmethod
0059     def loadAll(cls):
0060         """loads all available resources into cache"""
0061         resourceDirectories = cls.__directories()
0062         for directory in resourceDirectories:
0063             for name in os.listdir(directory):
0064                 if name.endswith('.desktop'):
0065                     if not name.endswith('alphabet.desktop') and not name.endswith('egypt.desktop'):
0066                         cls(os.path.join(directory, name))
0067 
0068     @classmethod
0069     def available(cls):
0070         """ready for the selector dialog, default first"""
0071         cls.loadAll()
0072         return sorted(set(cls.cache.values()), key=lambda x: x.desktopFileName != 'default')
0073 
0074     @classmethod
0075     def __noTilesetFound(cls):
0076         """No resources found"""
0077         directories = '\n\n' + '\n'.join(cls.__directories())
0078         logException(
0079             i18n(
0080                 'cannot find any %1 in the following directories, '
0081                 'is libkmahjongg installed?', cls.resourceName) + directories) # TODO: nicht schoen
0082 
0083     @staticmethod
0084     def __name(path):
0085         """extract the name from path: this is the filename minus the .desktop ending"""
0086         return os.path.split(path)[1].replace('.desktop', '')
0087 
0088     @classmethod
0089     def __build(cls, name):
0090         """build a new Resource. name is either a full file path or a desktop name. None stands for 'default'."""
0091         result = object.__new__(cls)
0092         if os.path.exists(name):
0093             result.path = name
0094             result.desktopFileName = cls.__name(name)
0095         else:
0096             result.desktopFileName = name or 'default'
0097             result.path = cls.locate(result.desktopFileName + '.desktop')
0098             if not result.path:
0099                 result.path = cls.locate('default.desktop')
0100                 result.desktopFileName = 'default'
0101                 if not result.path:
0102                     cls.__noTilesetFound()
0103                 else:
0104                     logWarning(i18n('cannot find %1, using default', name))
0105 
0106         cls.cache[result.desktopFileName] = result
0107         cls.cache[result.path] = result
0108         return result
0109 
0110     def __init__(self, unusedName):
0111         """continue __build"""
0112         self.group = KConfig(self.path).group(self.configGroupName)
0113 
0114         self.name = self.group.readEntry("Name") or i18n("unknown name")
0115         self.author = self.group.readEntry("Author") or i18n("unknown author")
0116         self.description = self.group.readEntry(
0117             "Description") or i18n(
0118                 "no description available")
0119         self.authorEmail = self.group.readEntry(
0120             "AuthorEmail") or i18n(
0121                 "no E-Mail address available")
0122 
0123         # Version control
0124         resourceVersion = self.group.readInteger("VersionFormat", default=0)
0125         # Format is increased when we have incompatible changes, meaning that
0126         # older clients are not able to use the remaining information safely
0127         if resourceVersion > RESOURCEFORMAT:
0128             logException('version file / program: %d/%d' % (resourceVersion, RESOURCEFORMAT))
0129 
0130     def __str__(self):
0131         return "%s id=%d name=%s, name id=%d" % \
0132             (self.resourceName, id(self), self.desktopFileName, id(self.desktopFileName))
0133 
0134     @staticmethod
0135     def current():
0136         """the currently wanted tileset. If not yet defined, do so"""