1#!/usr/bin/env python
2# -*- mode: python; coding: utf-8; -*-
3# ---------------------------------------------------------------------------##
4#
5# Copyright (C) 1998-2003 Markus Franz Xaver Johannes Oberhumer
6# Copyright (C) 2003 Mt. Hood Playing Card Co.
7# Copyright (C) 2005-2009 Skomoroh
8#
9# This program is free software: you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation, either version 3 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program.  If not, see <http://www.gnu.org/licenses/>.
21#
22# ---------------------------------------------------------------------------##
23
24# imports
25import os
26try:
27    import site
28except Exception:
29    class Dummy:
30        def __init__(self):
31            self.PREFIXES = []
32    site = Dummy()
33import sys
34
35# PySol imports
36from pysollib.mfxutil import Image
37from pysollib.mygettext import _
38from pysollib.settings import DATA_DIRS, TOOLKIT
39
40# ************************************************************************
41# * constants
42# ************************************************************************
43
44# Suits values are 0-3. This maps to colors 0-1.
45SUITS = (_("Club"), _("Spade"), _("Heart"), _("Diamond"))
46SUITS_PL = (_("Clubs"), _("Spades"), _("Hearts"), _("Diamonds"))
47COLORS = (_("black"), _("red"))
48
49# Specific suits
50CLUB = 0
51SPADE = 1
52HEART = 2
53DIAMOND = 3
54
55# Card ranks are 0-12.  We also define symbolic names for the picture cards.
56RANKS = (_("Ace"), "2", "3", "4", "5", "6", "7", "8", "9", "10",
57         _("Jack"), _("Queen"), _("King"))
58ACE = 0
59JACK = 10
60QUEEN = 11
61KING = 12
62
63# Special values for Stack.cap:
64ANY_SUIT = -1
65ANY_COLOR = -1
66ANY_RANK = -1
67NO_SUIT = 999999            # no card can ever match this suit
68NO_COLOR = 999999           # no card can ever match this color
69NO_RANK = 999999            # no card can ever match this rank
70UNLIMITED_MOVES = 999999    # for max_move
71UNLIMITED_ACCEPTS = 999999  # for max_accept
72UNLIMITED_CARDS = 999999    # for max_cards
73#
74NO_REDEAL = 0
75UNLIMITED_REDEALS = -1
76VARIABLE_REDEALS = -2
77
78CARDSET = _("cardset")
79
80IMAGE_EXTENSIONS = (".gif", ".ppm", ".png")
81if 1 and os.name == "nt":
82    IMAGE_EXTENSIONS = (".png", ".gif", ".ppm", ".jpg",)
83    pass
84
85if Image:
86    IMAGE_EXTENSIONS = (".png", ".gif", ".jpg", ".ppm", ".bmp")
87
88if TOOLKIT == 'kivy':
89    IMAGE_EXTENSIONS = (".png", ".bmp", ".ppm", ".jpg", ".tiff")
90
91# ************************************************************************
92# * DataLoader
93# ************************************************************************
94
95
96class DataLoader:
97    def __init__(self, argv0, filenames, path=[]):
98        self.dir = None
99        if isinstance(filenames, str):
100            filenames = (filenames,)
101        assert isinstance(filenames, (tuple, list))
102        # init path
103        path = path[:]
104        head, tail = os.path.split(argv0)
105        if not head:
106            head = os.curdir
107        # dir where placed startup script
108        path.append(head)
109        path.append(os.path.join(head, "data"))
110        path.append(os.path.join(head, os.pardir, "data"))
111        # dir where placed pysol package
112        path.append(os.path.join(sys.path[0], "data"))
113        path.append(os.path.join(sys.path[0], "pysollib", "data"))
114        # from settings.py
115        path.extend(DATA_DIRS)
116        # py2app compatibility, see
117        # https://github.com/shlomif/PySolFC/issues/100
118        _prefixes = []
119        try:
120            _prefixes = site.PREFIXES
121        except Exception:
122            _prefixes = []
123        # itz 2018-10-21 in case of venv installation
124        # (or even homedir installation), path[0] will be quite wrong.
125        # Just directly use the location where setup.py puts the data.
126        for pref in _prefixes:
127            path.append(os.path.join(pref, 'share', 'PySolFC'))
128        # check path for valid directories
129        self.path = []
130        for p in path:
131            if not p:
132                continue
133            np = os.path.abspath(p)
134            if np and (np not in self.path) and os.path.isdir(np):
135                self.path.append(np)
136        # now try to find all filenames along path
137        for p in self.path:
138            if all(os.path.isfile(os.path.join(p, fn)) for fn in filenames):
139                self.dir = p
140                break
141        else:
142            raise OSError(str(argv0)+": DataLoader could not find " +
143                          str(filenames))
144
145    def __findFile(self, func, filename, subdirs=None, do_raise=1):
146        if subdirs is None:
147            subdirs = ("",)
148        elif isinstance(subdirs, str):
149            subdirs = (subdirs,)
150        for dir in subdirs:
151            f = os.path.join(self.dir, dir, filename)
152            f = os.path.normpath(f)
153            if func(f):
154                return f
155        if do_raise:
156            raise OSError("DataLoader could not find "+filename+" in " +
157                          self.dir+" "+str(subdirs))
158        return None
159
160    def findFile(self, filename, subdirs=None):
161        return self.__findFile(os.path.isfile, filename, subdirs)
162
163    def findImage(self, filename, subdirs=None):
164        for ext in IMAGE_EXTENSIONS:
165            f = self.__findFile(os.path.isfile, filename+ext, subdirs, 0)
166            if f:
167                return f
168        raise OSError("DataLoader could not find image "+filename +
169                      " in "+self.dir+" "+str(subdirs))
170
171    def findAllIconSizes(self, filename='pysol.png'):
172        try:
173            icondir = self.findDir(os.path.join('images', 'icons'))
174            icons = [os.path.join(icondir, subdir, filename) for subdir in
175                     os.listdir(icondir)]
176        except OSError:
177            try:
178                # pysol06.png is known to have transparent borders around it
179                # which is unsuitable for a window icon
180                icon_blacklist = ('pysol06.png',)
181                miscdir = self.findDir(os.path.join('images', 'misc'))
182                icons = [os.path.join(miscdir, f) for f in os.listdir(miscdir)
183                         if f not in icon_blacklist]
184            except OSError:
185                icons = []
186        return filter(os.path.isfile, icons)
187
188    def findDir(self, filename, subdirs=None):
189        return self.__findFile(os.path.isdir, filename, subdirs)
190