1
0
Fork 0
mirror of https://github.com/shlomif/PySolFC.git synced 2025-04-05 00:02:29 -04:00
PySolFC/pysollib/options.py
Shlomi Fish aa4f9ee5da Crude code to get some func running in py3.
Right now klondike and freecell sort of work, but this is very hacky and
there are many leftover debug traces.
2017-08-25 18:25:58 +03:00

719 lines
23 KiB
Python

#!/usr/bin/env python
# -*- mode: python; coding: utf-8; -*-
# ---------------------------------------------------------------------------##
#
# Copyright (C) 1998-2003 Markus Franz Xaver Johannes Oberhumer
# Copyright (C) 2003 Mt. Hood Playing Card Co.
# Copyright (C) 2005-2009 Skomoroh
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# ---------------------------------------------------------------------------##
# imports
import sys
import os
import traceback
# PySol imports
from pysollib.mfxutil import print_err
from pysollib.resource import CSI
from pysollib.configobj import configobj, validate
import pysollib.settings
# Toolkit imports
from pysollib.pysoltk import TOOLBAR_BUTTONS
from pysollib.mygettext import _
if sys.version_info > (3,):
unicode = str
# ************************************************************************
# * Options
# ************************************************************************
configspec = '''
[general]
player = string
confirm = boolean
update_player_stats = boolean
autofaceup = boolean
autodrop = boolean
autodeal = boolean
quickplay = boolean
shuffle = boolean
undo = boolean
bookmarks = boolean
hint = boolean
highlight_piles = boolean
highlight_cards = boolean
highlight_samerank = boolean
highlight_not_matching = boolean
mahjongg_show_removed = boolean
mahjongg_create_solvable = integer(0, 2)
shisen_show_hint = boolean
shisen_show_matching = boolean
animations = integer(0, 5)
redeal_animation = boolean
win_animation = boolean
flip_animation = boolean
compact_stacks = boolean
shadow = boolean
shade = boolean
shrink_face_down = boolean
shade_filled_stacks = boolean
demo_logo = boolean
tile_theme = string
default_tile_theme = string
toolbar = integer(0, 4)
toolbar_style = string
toolbar_relief = string
toolbar_compound = string
toolbar_size = integer(0, 1)
statusbar = boolean
statusbar_game_number = boolean
statusbar_stuck = boolean
num_cards = boolean
helpbar = boolean
num_recent_games = integer(10, 100)
last_gameid = integer
game_holded = integer
wm_maximized = boolean
splashscreen = boolean
mouse_type = string
mouse_undo = boolean
negative_bottom = boolean
randomize_place = boolean
save_cardsets = boolean
dragcursor = boolean
save_games_geometry = boolean
game_geometry = int_list(min=2, max=2)
sound = boolean
sound_mode = integer(0, 1)
sound_sample_volume = integer(0, 128)
sound_sample_buffer_size = integer(1, 4)
tabletile_name = string
recent_gameid = int_list
favorite_gameid = int_list
visible_buttons = string_list
translate_game_names = boolean
solver_presets = string_list
[sound_samples]
move = boolean
autodrop = boolean
drop = boolean
nomove = boolean
gameperfect = boolean
deal = boolean
gamelost = boolean
autopilotwon = boolean
flip = boolean
undo = boolean
gamefinished = boolean
areyousure = boolean
startdrag = boolean
autoflip = boolean
autopilotlost = boolean
turnwaste = boolean
gamewon = boolean
droppair = boolean
redo = boolean
dealwaste = boolean
[fonts]
sans = list
small = list
fixed = list
canvas_default = list
canvas_small = list
canvas_fixed = list
canvas_large = list
[colors]
piles = string
text = string
table = string
hintarrow = string
cards_1 = string
cards_2 = string
samerank_1 = string
samerank_2 = string
not_matching = string
[timeouts]
highlight_samerank = float(0.2, 9.9)
raise_card = float(0.2, 9.9)
demo = float(0.2, 9.9)
highlight_cards = float(0.2, 9.9)
hint = float(0.2, 9.9)
highlight_piles = float(0.2, 9.9)
[cardsets]
0 = string_list(min=2, max=2)
1 = string_list(min=2, max=2)
2 = string_list(min=2, max=2)
3 = string_list(min=2, max=2)
4 = string_list(min=2, max=2)
5 = string_list(min=2, max=2)
6 = string_list(min=2, max=2)
7 = string_list(min=2, max=2)
8 = string_list(min=2, max=2)
9 = string_list(min=2, max=2)
scale_cards = boolean
scale_x = float
scale_y = float
auto_scale = boolean
preserve_aspect_ratio = boolean
'''.splitlines()
class Options:
GENERAL_OPTIONS = [
('player', 'str'),
('confirm', 'bool'),
('update_player_stats', 'bool'),
('autofaceup', 'bool'),
('autodrop', 'bool'),
('autodeal', 'bool'),
('quickplay', 'bool'),
('shuffle', 'bool'),
('undo', 'bool'),
('bookmarks', 'bool'),
('hint', 'bool'),
('highlight_piles', 'bool'),
('highlight_cards', 'bool'),
('highlight_samerank', 'bool'),
('highlight_not_matching', 'bool'),
('mahjongg_show_removed', 'bool'),
('mahjongg_create_solvable', 'int'),
('shisen_show_hint', 'bool'),
('shisen_show_matching', 'bool'),
('animations', 'int'),
('redeal_animation', 'bool'),
('win_animation', 'bool'),
('flip_animation', 'bool'),
('compact_stacks', 'bool'),
('shadow', 'bool'),
('shade', 'bool'),
('shrink_face_down', 'bool'),
('shade_filled_stacks', 'bool'),
('demo_logo', 'bool'),
('tile_theme', 'str'),
('default_tile_theme', 'str'),
('toolbar', 'int'),
('toolbar_style', 'str'),
('toolbar_relief', 'str'),
('toolbar_compound', 'str'),
('toolbar_size', 'int'),
('statusbar', 'bool'),
('statusbar_game_number', 'bool'),
('statusbar_stuck', 'bool'),
('num_cards', 'bool'),
('helpbar', 'bool'),
('num_recent_games', 'int'),
('last_gameid', 'int'),
('game_holded', 'int'),
('wm_maximized', 'bool'),
('splashscreen', 'bool'),
('mouse_type', 'str'),
('mouse_undo', 'bool'),
('negative_bottom', 'bool'),
('randomize_place', 'bool'),
('save_cardsets', 'bool'),
('dragcursor', 'bool'),
('save_games_geometry', 'bool'),
('sound', 'bool'),
('sound_mode', 'int'),
('sound_sample_volume', 'int'),
('sound_music_volume', 'int'),
('sound_sample_buffer_size', 'int'),
('tabletile_name', 'str'),
('translate_game_names', 'bool'),
('solver_presets', 'list'),
# ('toolbar_vars', 'list'),
# ('recent_gameid', 'list'),
# ('favorite_gameid', 'list'),
]
def __init__(self):
self._config = None # configobj.ConfigObj instance
self._config_encoding = 'utf-8'
self.version_tuple = pysollib.settings.VERSION_TUPLE # XXX
self.saved = 0 # XXX
# options menu:
self.player = _("Unknown")
self.confirm = True
self.update_player_stats = True
self.autofaceup = True
self.autodrop = False
self.autodeal = True
self.quickplay = True
self.shuffle = True
self.undo = True
self.bookmarks = True
self.hint = True
self.highlight_piles = True
self.highlight_cards = True
self.highlight_samerank = True
self.highlight_not_matching = True
self.mahjongg_show_removed = False
self.mahjongg_create_solvable = 2 # 0 - none, 1 - easy, 2 - hard
self.shisen_show_hint = True
self.shisen_show_matching = False
self.animations = 3 # default to Medium
self.redeal_animation = True
self.win_animation = True
self.flip_animation = True
self.compact_stacks = True
self.shadow = True
self.shade = True
self.shrink_face_down = True
self.shade_filled_stacks = True
self.demo_logo = True
self.tile_theme = 'default'
self.default_tile_theme = 'default'
self.toolbar = 1 # 0 == hide, 1,2,3,4 == top, bottom, lef, right
# self.toolbar_style = 'default'
self.toolbar_style = 'bluecurve'
self.toolbar_relief = 'flat'
self.toolbar_compound = 'none' # icons only
self.toolbar_size = 0
self.toolbar_vars = {}
for w in TOOLBAR_BUTTONS:
self.toolbar_vars[w] = True # show all buttons
self.statusbar = True
self.statusbar_game_number = False # show game number in statusbar
self.statusbar_stuck = False # show stuck indicator
self.num_cards = False
self.helpbar = False
self.splashscreen = True
self.mouse_type = 'drag-n-drop' # or 'sticky-mouse' or 'point-n-click'
self.mouse_undo = False # use mouse for undo/redo
self.negative_bottom = True
self.translate_game_names = True
# sound
self.sound = True
self.sound_mode = 1
self.sound_sample_volume = 80
self.sound_music_volume = 100
self.sound_sample_buffer_size = 1 # 1 - 4 (1024 - 4096 bytes)
self.sound_samples = {
'areyousure': True,
'autodrop': True,
'autoflip': True,
'autopilotlost': True,
'autopilotwon': True,
'deal': True,
'dealwaste': True,
'droppair': True,
'drop': True,
# 'extra': True,
'flip': True,
'move': True,
'nomove': True,
'redo': True,
'startdrag': True,
'turnwaste': True,
'undo': True,
'gamefinished': False,
'gamelost': False,
'gameperfect': False,
'gamewon': False,
}
# fonts
self.fonts = {
"default": None,
# "default": ("helvetica", 12),
"sans": ("times", 12), # for html
"fixed": ("courier", 12), # for html & log
"small": ("helvetica", 12),
"canvas_default": ("helvetica", 12),
# "canvas_card": ("helvetica", 12),
"canvas_fixed": ("courier", 12),
"canvas_large": ("helvetica", 16),
"canvas_small": ("helvetica", 10),
}
# colors
self.colors = {
'table': '#008200',
'text': '#ffffff',
'piles': '#ffc000',
'cards_1': '#ffc000',
'cards_2': '#0000ff',
'samerank_1': '#ffc000',
'samerank_2': '#0000ff',
'hintarrow': '#303030',
'not_matching': '#ff0000',
}
# delays
self.timeouts = {
'hint': 1.0,
'demo': 1.0,
'raise_card': 1.0,
'highlight_piles': 1.0,
'highlight_cards': 1.0,
'highlight_samerank': 1.0,
}
# additional startup information
self.num_recent_games = 15
self.recent_gameid = []
self.favorite_gameid = []
self.last_gameid = 0 # last game played
self.game_holded = 0 # gameid or 0
self.wm_maximized = 0
self.save_games_geometry = False
# saved games geometry (gameid: (width, height))
self.games_geometry = {}
self.game_geometry = (0, 0) # game geometry before exit
self.offsets = {} # cards offsets
#
self.randomize_place = False
self.save_cardsets = True
self.dragcursor = True
#
self.scale_cards = False
self.scale_x = 1.0
self.scale_y = 1.0
self.auto_scale = False
self.preserve_aspect_ratio = True
# solver
self.solver_presets = [
'none',
'abra-kadabra',
'blue-yonder',
'conspiracy-theory',
'cool-jives',
'crooked-nose',
'fools-gold',
'good-intentions',
'hello-world',
'john-galt-line',
'one-big-family',
'rin-tin-tin',
'slick-rock',
'the-last-mohican',
'video-editing',
'yellow-brick-road',
]
def setDefaults(self, top=None):
WIN_SYSTEM = pysollib.settings.WIN_SYSTEM
# toolbar
# if WIN_SYSTEM == 'win32':
# self.toolbar_style = 'crystal'
# fonts
if WIN_SYSTEM == 'win32':
self.fonts["sans"] = ("times new roman", 12)
self.fonts["fixed"] = ("courier new", 10)
elif WIN_SYSTEM == 'x11':
self.fonts["sans"] = ("helvetica", -12)
# tile theme
if WIN_SYSTEM == 'win32':
self.tile_theme = self.default_tile_theme = 'winnative'
if sys.getwindowsversion() >= (5, 1): # xp
self.tile_theme = 'xpnative'
elif WIN_SYSTEM == 'x11':
self.tile_theme = 'clam'
self.default_tile_theme = 'default'
elif WIN_SYSTEM == 'aqua':
self.tile_theme = self.default_tile_theme = 'aqua'
#
sw, sh, sd = 0, 0, 8
if top:
sw, sh, sd = (top.winfo_screenwidth(),
top.winfo_screenheight(),
top.winfo_screendepth())
# bg
if sd > 8:
self.tabletile_name = "Nostalgy.gif" # basename
else:
self.tabletile_name = None
# cardsets
c = "Standard"
if sw < 800 or sh < 600:
c = "2000"
# if sw > 1024 and sh > 768:
# c = 'Dondorf'
self.cardset = {
# game_type: (cardset_name, back_file)
0: (c, ""),
CSI.TYPE_FRENCH: (c, ""),
CSI.TYPE_HANAFUDA: ("Kintengu", ""),
CSI.TYPE_MAHJONGG: ("Crystal Mahjongg", ""),
CSI.TYPE_TAROCK: ("Vienna 2K", ""),
CSI.TYPE_HEXADECK: ("Hex A Deck", ""),
CSI.TYPE_MUGHAL_GANJIFA: ("Mughal Ganjifa", ""),
# CSI.TYPE_NAVAGRAHA_GANJIFA: ("Navagraha Ganjifa", ""),
CSI.TYPE_NAVAGRAHA_GANJIFA: ("Dashavatara Ganjifa", ""),
CSI.TYPE_DASHAVATARA_GANJIFA: ("Dashavatara Ganjifa", ""),
CSI.TYPE_TRUMP_ONLY: ("Matrix", ""),
}
# not changeable options
def setConstants(self):
if 'shuffle' not in self.toolbar_vars:
# new in v.1.1
self.toolbar_vars['shuffle'] = True
if isinstance(self.mahjongg_create_solvable, bool):
# changed in v.1.1
self.mahjongg_create_solvable = 2
pass
def copy(self):
opt = Options()
opt.__dict__.update(self.__dict__)
opt.setConstants()
return opt
def save(self, filename):
config = self._config
# general
for key, t in self.GENERAL_OPTIONS:
val = getattr(self, key)
if isinstance(val, str):
if sys.version_info < (3,):
val = unicode(val, 'utf-8')
config['general'][key] = val
config['general']['recent_gameid'] = self.recent_gameid
config['general']['favorite_gameid'] = self.favorite_gameid
visible_buttons = [b for b in self.toolbar_vars
if self.toolbar_vars[b]]
config['general']['visible_buttons'] = visible_buttons
config['general']['solver_presets'].remove('none')
# sound_samples
config['sound_samples'] = self.sound_samples
# fonts
for key, val in self.fonts.items():
if key == 'default':
continue
if val is None:
continue
config['fonts'][key] = val
# colors
config['colors'] = self.colors
# timeouts
config['timeouts'] = self.timeouts
# cardsets
for key, val in self.cardset.items():
config['cardsets'][str(key)] = val
for key in ('scale_cards', 'scale_x', 'scale_y',
'auto_scale', 'preserve_aspect_ratio'):
config['cardsets'][key] = getattr(self, key)
# games_geometry
config['games_geometry'].clear()
for key, val in self.games_geometry.items():
config['games_geometry'][str(key)] = val
config['general']['game_geometry'] = self.game_geometry
# offsets
for key, val in self.offsets.items():
config['offsets'][key] = val
config.write()
# config.write(sys.stdout); print
def _getOption(self, section, key, t):
config = self._config
try:
if config[section][key] is None:
# invalid value
return None
if t == 'bool':
val = config[section].as_bool(key)
elif t == 'int':
val = config[section].as_int(key)
elif t == 'float':
val = config[section].as_float(key)
elif t == 'list':
val = config[section][key]
assert isinstance(val, (list, tuple))
else: # str
val = config[section][key]
except KeyError:
val = None
except:
print_err('load option error: %s: %s' % (section, key))
traceback.print_exc()
val = None
return val
def load(self, filename):
# create ConfigObj instance
try:
print(filename)
config = configobj.ConfigObj(filename,
configspec=configspec,
encoding=self._config_encoding)
except configobj.ParseError:
raise BaseException('foo')
traceback.print_exc()
config = configobj.ConfigObj(configspec=configspec,
encoding=self._config_encoding)
self._config = config
# create sections
for section in (
'general',
'sound_samples',
'fonts',
'colors',
'timeouts',
'cardsets',
'games_geometry',
'offsets',
):
if section not in config:
config[section] = {}
# add initial comment
if not os.path.exists(filename):
config.initial_comment = ['-*- coding: %s -*-' %
self._config_encoding]
return
# validation
vdt = validate.Validator()
res = config.validate(vdt)
# from pprint import pprint; pprint(res)
if res is not True:
for section, data in res.items():
if data is True:
continue
for key, value in data.items():
if value is False:
print_err('config file: validation error: '
'section: "%s", key: "%s"' % (section, key))
config[section][key] = None
# general
for key, t in self.GENERAL_OPTIONS:
val = self._getOption('general', key, t)
if val == 'None':
setattr(self, key, None)
elif val is not None:
setattr(self, key, val)
pysollib.settings.TRANSLATE_GAME_NAMES = self.translate_game_names
recent_gameid = self._getOption('general', 'recent_gameid', 'list')
if recent_gameid is not None:
try:
self.recent_gameid = [int(i) for i in recent_gameid]
except:
traceback.print_exc()
favorite_gameid = self._getOption('general', 'favorite_gameid', 'list')
if favorite_gameid is not None:
try:
self.favorite_gameid = [int(i) for i in favorite_gameid]
except:
traceback.print_exc()
visible_buttons = self._getOption('general', 'visible_buttons', 'list')
if visible_buttons is not None:
for key in TOOLBAR_BUTTONS:
self.toolbar_vars[key] = (key in visible_buttons)
# solver
solver_presets = self._getOption('general', 'solver_presets', 'list')
if solver_presets is not None:
if 'none' not in solver_presets:
solver_presets.insert(0, 'none')
self.solver_presets = solver_presets
# sound_samples
for key in self.sound_samples:
val = self._getOption('sound_samples', key, 'bool')
if val is not None:
self.sound_samples[key] = val
# fonts
for key in self.fonts:
if key == 'default':
continue
val = self._getOption('fonts', key, 'str')
if val is not None:
try:
val[1] = int(val[1])
except:
traceback.print_exc()
else:
val = tuple(val)
self.fonts[key] = val
# colors
for key in self.colors:
val = self._getOption('colors', key, 'str')
if val is not None:
self.colors[key] = val
# timeouts
for key in self.timeouts:
val = self._getOption('timeouts', key, 'float')
if val is not None:
self.timeouts[key] = val
# cardsets
for key in self.cardset:
val = self._getOption('cardsets', str(key), 'list')
if val is not None:
try:
self.cardset[int(key)] = val
except:
traceback.print_exc()
for key, t in (('scale_cards', 'bool'),
('scale_x', 'float'),
('scale_y', 'float'),
('auto_scale', 'bool'),
('preserve_aspect_ratio', 'bool')):
val = self._getOption('cardsets', key, t)
if val is not None:
setattr(self, key, val)
# games_geometry
for key, val in config['games_geometry'].items():
try:
val = [int(i) for i in val]
assert len(val) == 2
self.games_geometry[int(key)] = val
except:
traceback.print_exc()
game_geometry = self._getOption('general', 'game_geometry', 'list')
if game_geometry is not None:
try:
self.game_geometry = tuple(int(i) for i in game_geometry)
except:
traceback.print_exc()
# cards offsets
for key, val in config['offsets'].items():
try:
val = [int(i) for i in val]
assert len(val) == 2
self.offsets[key] = val
except:
traceback.print_exc()