mirror of
https://github.com/shlomif/PySolFC.git
synced 2025-04-05 00:02:29 -04:00
873 lines
29 KiB
Python
873 lines
29 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/>.
|
|
#
|
|
# ---------------------------------------------------------------------------##
|
|
|
|
import os
|
|
import sys
|
|
import traceback
|
|
|
|
import configobj
|
|
|
|
import pysollib.settings
|
|
from pysollib.mfxutil import USE_PIL,\
|
|
get_default_resampling, print_err
|
|
from pysollib.mygettext import _
|
|
from pysollib.mygettext import myGettext
|
|
from pysollib.pysoltk import STATUSBAR_ITEMS, TOOLBAR_BUTTONS, TOOLKIT
|
|
from pysollib.resource import CSI
|
|
|
|
|
|
import six
|
|
|
|
import validate
|
|
|
|
# ************************************************************************
|
|
# * Options
|
|
# ************************************************************************
|
|
|
|
_global_settings = {
|
|
'mouse_button1': 1,
|
|
'mouse_button2': 2,
|
|
'mouse_button3': 3,
|
|
}
|
|
|
|
|
|
def calcCustomMouseButtonsBinding(binding_format):
|
|
assert _global_settings['mouse_button1']
|
|
return binding_format.format(
|
|
mouse_button1=_global_settings['mouse_button1'],
|
|
mouse_button2=_global_settings['mouse_button2'],
|
|
mouse_button3=_global_settings['mouse_button3'],
|
|
)
|
|
|
|
|
|
configspec = '''
|
|
[general]
|
|
last_version = list
|
|
player = string
|
|
confirm = boolean
|
|
update_player_stats = boolean
|
|
autofaceup = boolean
|
|
autodrop = boolean
|
|
autodeal = boolean
|
|
quickplay = boolean
|
|
shuffle = boolean
|
|
undo = boolean
|
|
bookmarks = boolean
|
|
hint = boolean
|
|
free_hint = boolean
|
|
highlight_piles = boolean
|
|
highlight_cards = boolean
|
|
highlight_samerank = boolean
|
|
highlight_not_matching = boolean
|
|
peek_facedown = boolean
|
|
stuck_notification = 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, 2)
|
|
statusbar = boolean
|
|
num_recent_games = integer(10, 100)
|
|
last_gameid = integer
|
|
game_holded = integer
|
|
wm_maximized = boolean
|
|
splashscreen = boolean
|
|
date_format = string
|
|
mouse_type = string
|
|
mouse_undo = boolean
|
|
negative_bottom = boolean
|
|
randomize_place = boolean
|
|
use_cardset_bottoms = 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)
|
|
music = boolean
|
|
tabletile_name = string
|
|
tabletile_scale_method = integer
|
|
center_layout = boolean
|
|
recent_gameid = int_list
|
|
favorite_gameid = int_list
|
|
visible_buttons = string_list
|
|
visible_status = string_list
|
|
translate_game_names = boolean
|
|
solver_presets = string_list
|
|
solver_show_progress = boolean
|
|
solver_max_iterations = integer
|
|
solver_iterations_output_step = integer
|
|
solver_preset = string
|
|
display_win_message = boolean
|
|
language = string
|
|
|
|
[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
|
|
extra = 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)
|
|
1_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)
|
|
10 = string_list(min=2, max=2)
|
|
scale_cards = boolean
|
|
scale_x = float
|
|
scale_y = float
|
|
auto_scale = boolean
|
|
spread_stacks = boolean
|
|
preserve_aspect_ratio = boolean
|
|
resampling = integer(0, 10)
|
|
'''.splitlines()
|
|
|
|
|
|
class Options:
|
|
GENERAL_OPTIONS = [
|
|
('last_version', 'list'),
|
|
('player', 'str'),
|
|
('confirm', 'bool'),
|
|
('update_player_stats', 'bool'),
|
|
('autofaceup', 'bool'),
|
|
('autodrop', 'bool'),
|
|
('autodeal', 'bool'),
|
|
('quickplay', 'bool'),
|
|
('shuffle', 'bool'),
|
|
('undo', 'bool'),
|
|
('bookmarks', 'bool'),
|
|
('hint', 'bool'),
|
|
('free_hint', 'bool'),
|
|
('highlight_piles', 'bool'),
|
|
('highlight_cards', 'bool'),
|
|
('highlight_samerank', 'bool'),
|
|
('highlight_not_matching', 'bool'),
|
|
('peek_facedown', 'bool'),
|
|
('stuck_notification', 'bool'),
|
|
('mahjongg_show_removed', 'bool'),
|
|
('mahjongg_create_solvable', 'int'),
|
|
('shisen_show_hint', 'bool'),
|
|
('shisen_show_matching', 'bool'),
|
|
('accordion_deal_all', 'bool'),
|
|
('pegged_auto_remove', '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'),
|
|
('date_format', 'str'),
|
|
('mouse_type', 'str'),
|
|
('mouse_undo', 'bool'),
|
|
('negative_bottom', 'bool'),
|
|
('randomize_place', 'bool'),
|
|
('use_cardset_bottoms', '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'),
|
|
('music', 'bool'),
|
|
('tabletile_name', 'str'),
|
|
('tabletile_scale_method', 'int'),
|
|
('center_layout', 'bool'),
|
|
('translate_game_names', 'bool'),
|
|
('solver_presets', 'list'),
|
|
('solver_show_progress', 'bool'),
|
|
('solver_max_iterations', 'int'),
|
|
('solver_iterations_output_step', 'int'),
|
|
('solver_preset', 'string'),
|
|
('mouse_button1', 'int'),
|
|
('mouse_button2', 'int'),
|
|
('mouse_button3', 'int'),
|
|
# ('toolbar_vars', 'list'),
|
|
# ('recent_gameid', 'list'),
|
|
# ('favorite_gameid', 'list'),
|
|
('display_win_message', 'bool'),
|
|
('language', 'str'),
|
|
]
|
|
|
|
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
|
|
|
|
self.last_version = (2, 20, 1)
|
|
# 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.free_hint = False
|
|
self.highlight_piles = True
|
|
self.highlight_cards = True
|
|
self.highlight_samerank = True
|
|
self.highlight_not_matching = True
|
|
self.peek_facedown = False
|
|
self.stuck_notification = False
|
|
self.mahjongg_show_removed = False
|
|
self.mahjongg_create_solvable = 2 # 0 - none, 1 - easy, 2 - hard
|
|
self.accordion_deal_all = True
|
|
self.pegged_auto_remove = True
|
|
if TOOLKIT == 'kivy':
|
|
self.mahjongg_create_solvable = 1 # 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
|
|
if TOOLKIT == 'kivy':
|
|
self.redeal_animation = False
|
|
self.win_animation = False
|
|
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'
|
|
if TOOLKIT == 'kivy':
|
|
self.toolbar = 4 # 0 == hide, 1,2,3,4 == top, bottom, lef, right
|
|
self.toolbar_style = 'remix'
|
|
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_vars = {}
|
|
for w, x in STATUSBAR_ITEMS:
|
|
self.statusbar_vars[w] = True
|
|
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.date_format = '%m-%d'
|
|
self.mouse_button1 = 1
|
|
self.mouse_button2 = 2
|
|
self.mouse_button3 = 3
|
|
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
|
|
self.display_win_message = True
|
|
self.language = ''
|
|
# sound
|
|
self.sound = True
|
|
self.sound_mode = 1
|
|
self.sound_sample_volume = 75
|
|
self.sound_music_volume = 100
|
|
self.sound_sample_buffer_size = 1 # 1 - 4 (1024 - 4096 bytes)
|
|
self.music = True
|
|
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 = []
|
|
if TOOLKIT == 'kivy':
|
|
self.favorite_gameid = [2, 7, 8, 19, 140, 116, 152, 176, 181,
|
|
194, 207, 706, 721, 756, 903, 5034,
|
|
11004, 14405, 14410, 15411, 22225]
|
|
self.last_gameid = 0 # last game played
|
|
self.game_holded = 0 # gameid or 0
|
|
self.wm_maximized = 1
|
|
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.use_cardset_bottoms = 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 = True
|
|
self.spread_stacks = False
|
|
self.center_layout = True
|
|
self.preserve_aspect_ratio = True
|
|
self.tabletile_scale_method = 0
|
|
self.resampling = 0
|
|
if USE_PIL:
|
|
self.resampling = int(get_default_resampling())
|
|
|
|
# solver
|
|
self.solver_presets = [
|
|
'none',
|
|
'abra-kadabra',
|
|
'blue-yonder',
|
|
'conspiracy-theory',
|
|
'cookie-monster',
|
|
'cool-jives',
|
|
'crooked-nose',
|
|
'fools-gold',
|
|
'good-intentions',
|
|
'hello-world',
|
|
'john-galt-line',
|
|
'looking-glass',
|
|
'one-big-family',
|
|
'rin-tin-tin',
|
|
'slick-rock',
|
|
'the-last-mohican',
|
|
'video-editing',
|
|
'yellow-brick-road',
|
|
]
|
|
self.solver_show_progress = True
|
|
self.solver_max_iterations = 100000
|
|
self.solver_iterations_output_step = 100
|
|
self.solver_preset = 'video-editing'
|
|
|
|
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 = "Felt_Green.gif" # basename
|
|
else:
|
|
self.tabletile_name = None
|
|
# cardsets
|
|
c = "Standard"
|
|
if sw < 800 or sh < 600:
|
|
c = "2000"
|
|
if TOOLKIT == 'kivy':
|
|
c = "Standard"
|
|
|
|
# if sw > 1024 and sh > 768:
|
|
# c = 'Dondorf'
|
|
if USE_PIL:
|
|
self.cardset = {
|
|
0: {0: ("Neo", "")},
|
|
CSI.TYPE_FRENCH: {0: ("Neo", ""), 1: ("Neo", "")},
|
|
CSI.TYPE_HANAFUDA: {0: ("Louie Mantia Hanafuda", "")},
|
|
CSI.TYPE_MAHJONGG: {0: ("Uni Mahjongg", "")},
|
|
CSI.TYPE_TAROCK: {0: ("Neo Tarock", "")},
|
|
CSI.TYPE_HEXADECK: {0: ("Neo Hex", "")},
|
|
CSI.TYPE_MUGHAL_GANJIFA: {0: ("Mughal Ganjifa XL", "")},
|
|
# CSI.TYPE_NAVAGRAHA_GANJIFA: {0: ("Navagraha Ganjifa", "")},
|
|
CSI.TYPE_NAVAGRAHA_GANJIFA:
|
|
{0: ("Dashavatara Ganjifa XL", "")},
|
|
CSI.TYPE_DASHAVATARA_GANJIFA:
|
|
{0: ("Dashavatara Ganjifa XL", "")},
|
|
CSI.TYPE_TRUMP_ONLY: {0: ("Next Matrix", "")},
|
|
CSI.TYPE_MATCHING: {0: ("Neo", "")}
|
|
}
|
|
else:
|
|
self.cardset = {
|
|
# game_type: (cardset_name, back_file)
|
|
0: {0: (c, "")},
|
|
CSI.TYPE_FRENCH: {0: (c, ""), 1: (c, "")},
|
|
CSI.TYPE_HANAFUDA: {0: ("Kintengu", "")},
|
|
CSI.TYPE_MAHJONGG: {0: ("Crystal Mahjongg", "")},
|
|
CSI.TYPE_TAROCK: {0: ("Vienna 2K", "")},
|
|
CSI.TYPE_HEXADECK: {0: ("Hex A Deck", "")},
|
|
CSI.TYPE_MUGHAL_GANJIFA: {0: ("Mughal Ganjifa", "")},
|
|
# CSI.TYPE_NAVAGRAHA_GANJIFA: {0: ("Navagraha Ganjifa", "")},
|
|
CSI.TYPE_NAVAGRAHA_GANJIFA: {0: ("Dashavatara Ganjifa", "")},
|
|
CSI.TYPE_DASHAVATARA_GANJIFA: {0: ("Dashavatara Ganjifa", "")},
|
|
CSI.TYPE_TRUMP_ONLY: {0: ("Matrix", "")},
|
|
CSI.TYPE_MATCHING: {0: (c, "")}
|
|
}
|
|
|
|
# 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
|
|
|
|
self.last_version = self.version_tuple
|
|
|
|
# general
|
|
for key, t in self.GENERAL_OPTIONS:
|
|
val = getattr(self, key)
|
|
if isinstance(val, str):
|
|
if sys.version_info < (3,):
|
|
val = six.text_type(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
|
|
visible_status = [b for b in self.statusbar_vars
|
|
if self.statusbar_vars[b]]
|
|
config['general']['visible_status'] = visible_status
|
|
if 'none' in config['general']['solver_presets']:
|
|
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():
|
|
for key2, val2 in val.items():
|
|
if key2 > 0:
|
|
config['cardsets'][str(key) + "_" + str(key2)] = val2
|
|
else:
|
|
config['cardsets'][str(key)] = val2
|
|
for key in ('scale_cards', 'scale_x', 'scale_y',
|
|
'auto_scale', 'spread_stacks',
|
|
'preserve_aspect_ratio', 'resampling'):
|
|
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 Exception:
|
|
print_err('load option error: %s: %s' % (section, key))
|
|
traceback.print_exc()
|
|
val = None
|
|
return val
|
|
|
|
def load(self, filename):
|
|
|
|
# create ConfigObj instance
|
|
try:
|
|
config = configobj.ConfigObj(filename,
|
|
configspec=configspec,
|
|
encoding=self._config_encoding)
|
|
except configobj.ParseError:
|
|
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 isinstance(res, dict):
|
|
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 Exception:
|
|
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 Exception:
|
|
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)
|
|
visible_status = self._getOption('general', 'visible_status', 'list')
|
|
if visible_status is not None:
|
|
for key, label in STATUSBAR_ITEMS:
|
|
self.statusbar_vars[key] = (key in visible_status)
|
|
|
|
myGettext.language = self.language
|
|
|
|
# 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 Exception:
|
|
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:
|
|
for key2 in self.cardset[key]:
|
|
if key2 > 0:
|
|
val = self._getOption('cardsets',
|
|
str(key) + "_" + str(key2), 'list')
|
|
else:
|
|
val = self._getOption('cardsets', str(key), 'list')
|
|
if val is not None:
|
|
try:
|
|
self.cardset[int(key)][int(key2)] = val
|
|
except Exception:
|
|
traceback.print_exc()
|
|
for key, t in (('scale_cards', 'bool'),
|
|
('scale_x', 'float'),
|
|
('scale_y', 'float'),
|
|
('auto_scale', 'bool'),
|
|
('spread_stacks', 'bool'),
|
|
('preserve_aspect_ratio', 'bool'),
|
|
('resampling', 'int')):
|
|
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 Exception:
|
|
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 Exception:
|
|
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 Exception:
|
|
traceback.print_exc()
|
|
|
|
# mouse buttons swap
|
|
def _positive(button):
|
|
return max([button, 1])
|
|
_global_settings['mouse_button1'] = _positive(self.mouse_button1)
|
|
_global_settings['mouse_button2'] = _positive(self.mouse_button2)
|
|
_global_settings['mouse_button3'] = _positive(self.mouse_button3)
|
|
|
|
def calcCustomMouseButtonsBinding(self, binding_format):
|
|
"""docstring for calcCustomMouseButtonsBinding"""
|
|
def _positive(button):
|
|
return max([button, 1])
|
|
return binding_format.format(
|
|
mouse_button1=_positive(self.mouse_button1),
|
|
mouse_button2=_positive(self.mouse_button2),
|
|
mouse_button3=_positive(self.mouse_button3),
|
|
)
|