File indexing completed on 2024-04-21 04:01:50
0001 #!/usr/bin/env python3 0002 # -*- coding: utf-8 -*- 0003 0004 """ 0005 Copyright (C) 2008-2016 Wolfgang Rohdewald <wolfgang@rohdewald.de> 0006 0007 SPDX-License-Identifier: GPL-2.0 0008 0009 """ 0010 0011 # pylint: disable=wrong-import-position 0012 0013 # keyboardinterrupt should simply terminate 0014 # import signal 0015 # signal.signal(signal.SIGINT, signal.SIG_DFL) 0016 import sys 0017 import os 0018 import logging 0019 0020 from qt import QObject, QCommandLineParser, QCommandLineOption, Qt, QGuiApplication 0021 from qtpy import QT5 0022 from kde import KApplication 0023 from mi18n import i18n, MLocale 0024 0025 from common import Options, SingleshotOptions, Internal, Debug 0026 # do not import modules using twisted before our reactor is running 0027 0028 def initRulesets(): 0029 """exits if user only wanted to see available rulesets""" 0030 import predefined 0031 predefined.load() 0032 if Options.showRulesets or Options.rulesetName: 0033 from rule import Ruleset 0034 rulesets = {x.name: x for x in Ruleset.selectableRulesets()} 0035 if Options.showRulesets: 0036 for name in rulesets: 0037 print(name) 0038 Internal.db.close() 0039 sys.exit(0) 0040 elif Options.rulesetName in rulesets: 0041 # we have an exact match 0042 Options.ruleset = rulesets[Options.rulesetName] 0043 else: 0044 matches = [x for x in rulesets if Options.rulesetName in x] 0045 if len(matches) != 1: 0046 if not matches: 0047 msg = 'Ruleset %s is unknown' % Options.rulesetName 0048 else: 0049 msg = 'Ruleset %s is ambiguous: %s' % ( 0050 Options.rulesetName, 0051 ', '.join(matches)) 0052 Internal.db.close() 0053 raise SystemExit(msg) 0054 Options.ruleset = rulesets[matches[0]] 0055 0056 0057 class CommandLineOption(QCommandLineOption): 0058 """add some helping attributes""" 0059 def __init__(self, name, description, valueName=None, 0060 defaultValue=None, optName=None, argType=None, singleshot=False): 0061 QCommandLineOption.__init__(self, [name], description, valueName, defaultValue) 0062 if argType is None: 0063 if valueName is None: 0064 argType = bool 0065 else: 0066 argType = str 0067 self.argType = argType 0068 self.optName = optName or name 0069 self.singleshot = singleshot 0070 0071 def defineOptions(): 0072 """define command line options""" 0073 parser = QCommandLineParser() 0074 options = [] 0075 def option(*args, optName=None, argType=None, singleshot=False): 0076 """helper""" 0077 opt = CommandLineOption(*args, optName=optName, argType=argType, singleshot=singleshot) 0078 options.append(opt) 0079 parser.addOption(opt) 0080 0081 parser.setApplicationDescription(i18n('Mah Jongg - the ancient Chinese board game for 4 players')) 0082 0083 parser.addHelpOption() 0084 parser.addVersionOption() 0085 option('playopen', i18n('all robots play with visible concealed tiles'), optName='playOpen') 0086 option('demo', i18n('start with demo mode')) 0087 option('host', i18n("login to HOST"), 'HOST', '') 0088 option('table', i18n('start new TABLE'), 'TABLE', '1', argType=int, singleshot=True) 0089 option('join', i18n('join TABLE'), 'TABLE', '1', argType=int, singleshot=True) 0090 option('ruleset', i18n('use RULESET without asking'), 'RULESET', '', optName='rulesetName') 0091 option('rounds', i18n('play only ROUNDS rounds per game. Only for debugging!'), 'ROUNDS', '4', argType=int) 0092 option('player', i18n('prefer PLAYER for next login'), 'PLAYER', '') 0093 option('ai', i18n('use AI variant for human player in demo mode'), 'AI', '', optName='AI') 0094 option('csv', i18n('write statistics to CSV'), 'CSV', '') 0095 option('rulesets', i18n('show all available rulesets'), optName='showRulesets') 0096 option('game', i18n('for testing purposes: Initializes the random generator'), 0097 'seed(/firsthand)(..(lasthand))', '0') 0098 option('nogui', i18n('show no graphical user interface. Intended only for testing'), optName='gui') 0099 option('socket', i18n('use a dedicated server listening on SOCKET. Intended only for testing'), 'SOCKET', '') 0100 option('port', i18n('use a dedicated server listening on PORT. Intended only for testing'), 'PORT', '') 0101 option('debug', Debug.help(), 'DEBUG', '') 0102 return parser, options 0103 0104 def parseOptions(): 0105 """parse command line options and save the values""" 0106 Options.gui = True 0107 parser, options = defineOptions() 0108 parser.process(Internal.app) 0109 for option in options: 0110 if parser.isSet(option): 0111 value = parser.value(option) 0112 if option.optName == 'debug': 0113 msg = Debug.setOptions(value) 0114 if msg: 0115 Internal.logger.debug(msg) 0116 logging.shutdown() 0117 sys.exit(2) 0118 continue 0119 if option.optName in SingleshotOptions.__dict__: 0120 target = SingleshotOptions 0121 else: 0122 target = Options 0123 if option.argType is bool: 0124 setattr(target, option.optName, not option.names()[0].startswith('no')) 0125 elif option.argType is int: 0126 setattr(target, option.optName, int(value)) 0127 else: 0128 setattr(target, option.optName, value) 0129 0130 Options.demo |= not Options.gui 0131 Internal.autoPlay = Options.demo 0132 0133 from query import initDb 0134 if not initDb(): 0135 raise SystemExit('Cannot initialize database') 0136 initRulesets() 0137 Options.fixed = True # may not be changed anymore 0138 0139 0140 class EvHandler(QObject): 0141 0142 """an application wide event handler""" 0143 0144 def eventFilter(self, receiver, event): 0145 """will be called for all events""" 0146 from log import EventData 0147 EventData(receiver, event) 0148 return QObject.eventFilter(self, receiver, event) 0149 0150 from util import gitHead 0151 0152 if os.name == 'nt': 0153 _ = os.path.dirname(os.path.realpath(__file__)) 0154 if _.endswith('.zip'): 0155 # cx_freeze 0156 os.chdir(os.path.dirname(_)) 0157 0158 QGuiApplication.setAttribute(Qt.AA_ShareOpenGLContexts, True) 0159 Internal.app = KApplication() 0160 parseOptions() 0161 0162 if hasattr(QGuiApplication, 'setDesktopFileName'): 0163 QGuiApplication.setDesktopFileName('org.kde.kajongg') 0164 0165 if Debug.neutral: 0166 MLocale.translation = None 0167 0168 if Debug.locate: 0169 # this has been read before Debug.locate is set 0170 Internal.logger.debug('Configuration in %s', Internal.kajonggrc.path) 0171 0172 if Debug.events: 0173 EVHANDLER = EvHandler() 0174 Internal.app.installEventFilter(EVHANDLER) 0175 0176 from config import SetupPreferences 0177 SetupPreferences() 0178 0179 if Options.csv: 0180 if gitHead() == 'current': 0181 Internal.logger.debug( 0182 'You cannot write to %s with changes uncommitted to git', 0183 Options.csv) 0184 sys.exit(2) 0185 from mainwindow import MainWindow 0186 if QT5: 0187 QGuiApplication.setAttribute(Qt.AA_UseHighDpiPixmaps, True) 0188 MainWindow() 0189 Internal.app.exec_()