mirror of
https://github.com/mupen64plus/mupen64plus-ui-python.git
synced 2025-04-02 10:51:53 -04:00
PEP 8
This commit is contained in:
parent
1bed133331
commit
4b6143f9a4
27 changed files with 788 additions and 731 deletions
4
m64py
4
m64py
|
@ -48,8 +48,8 @@ def main():
|
|||
QApplication.setAttribute(Qt.AA_X11InitThreads)
|
||||
except AttributeError:
|
||||
try:
|
||||
Xlib = load_library('X11')
|
||||
Xlib.XInitThreads()
|
||||
xlib = load_library('X11')
|
||||
xlib.XInitThreads()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
|
33
setup.py
33
setup.py
|
@ -19,6 +19,7 @@ sys.path.insert(0, realpath("src"))
|
|||
from m64py.core.defs import FRONTEND_VERSION
|
||||
BASE_DIR = dirname(realpath(__file__))
|
||||
|
||||
|
||||
class build_qt(Command):
|
||||
user_options = []
|
||||
|
||||
|
@ -47,7 +48,7 @@ class build_qt(Command):
|
|||
path.append(dirname(PyQt4.__file__))
|
||||
os.putenv("PATH", os.pathsep.join(path))
|
||||
if subprocess.call(["pyrcc4", qrc_file, "-o", py_file]) > 0:
|
||||
self.warn("Unable to compile resource file %s" % (qrc_file))
|
||||
self.warn("Unable to compile resource file %s" % qrc_file)
|
||||
if not os.path.exists(py_file):
|
||||
sys.exit(1)
|
||||
os.putenv('PATH', origpath)
|
||||
|
@ -62,9 +63,9 @@ class build_qt(Command):
|
|||
elif filename.endswith('.qrc'):
|
||||
self.compile_rc(join(dirpath, filename))
|
||||
|
||||
|
||||
class build_exe(Command):
|
||||
"""Needs PyQt4, pyUnRAR2, PyLZMA, PyWin32, PyInstaller, Inno Setup 5"""
|
||||
|
||||
user_options = []
|
||||
arch = "i686-w64-mingw32"
|
||||
url = "https://bitbucket.org/ecsv/mupen64plus-mxe-daily/get/master.zip"
|
||||
|
@ -107,13 +108,13 @@ class build_exe(Command):
|
|||
dest_path = join(self.dist_dir, "m64py")
|
||||
shutil.copy(unrar_dll, dest_path)
|
||||
shutil.copyfile(unrar_lic, join(dest_path, "doc", "unrar-license"))
|
||||
for file in ["AUTHORS", "ChangeLog", "COPYING", "LICENSES", "README.md"]:
|
||||
shutil.copy(join(BASE_DIR, file), dest_path)
|
||||
for file_name in ["AUTHORS", "ChangeLog", "COPYING", "LICENSES", "README.md"]:
|
||||
shutil.copy(join(BASE_DIR, file_name), dest_path)
|
||||
|
||||
def remove_files(self):
|
||||
dest_path = join(self.dist_dir, "m64py")
|
||||
for dirname in ["api", "include", "man6"]:
|
||||
shutil.rmtree(join(dest_path, dirname))
|
||||
for dir_name in ["api", "include", "man6"]:
|
||||
shutil.rmtree(join(dest_path, dir_name))
|
||||
|
||||
def run_build_installer(self):
|
||||
iss_file = ""
|
||||
|
@ -148,6 +149,7 @@ class build_exe(Command):
|
|||
self.remove_files()
|
||||
self.run_build_installer()
|
||||
|
||||
|
||||
class build_dmg(Command):
|
||||
user_options = []
|
||||
dist_dir = join(BASE_DIR, "dist", "macosx")
|
||||
|
@ -187,14 +189,14 @@ class build_dmg(Command):
|
|||
if not os.path.exists(dest_path):
|
||||
os.mkdir(dest_path)
|
||||
shutil.move(join(self.dist_dir, "M64Py.app"), dest_path)
|
||||
for file in ["AUTHORS", "ChangeLog", "COPYING", "LICENSES", "README.md"]:
|
||||
shutil.copy(join(BASE_DIR, file), dest_path)
|
||||
for file_name in ["AUTHORS", "ChangeLog", "COPYING", "LICENSES", "README.md"]:
|
||||
shutil.copy(join(BASE_DIR, file_name), dest_path)
|
||||
shutil.copy(join(BASE_DIR, "test", "mupen64plus.v64"), dest_path)
|
||||
|
||||
def remove_files(self):
|
||||
dest_path = join(self.dist_dir, "dmg", "M64Py.app", "Contents", "MacOS")
|
||||
for dirname in ["include", "lib"]:
|
||||
shutil.rmtree(join(dest_path, dirname))
|
||||
for dir_name in ["include", "lib"]:
|
||||
shutil.rmtree(join(dest_path, dir_name))
|
||||
os.remove(join(self.dist_dir, "dmg", "M64Py.app", "Contents", "Resources", "icon-windowed.icns"))
|
||||
|
||||
def run_build_dmg(self):
|
||||
|
@ -222,6 +224,7 @@ class build_dmg(Command):
|
|||
self.set_plist()
|
||||
self.run_build_dmg()
|
||||
|
||||
|
||||
def set_sdl2():
|
||||
opts_file = ""
|
||||
opts_path = join(BASE_DIR, "src", "m64py", "opts.py")
|
||||
|
@ -233,12 +236,12 @@ def set_sdl2():
|
|||
opts_file += line + "\n"
|
||||
with open(opts_path, "w") as opts: opts.write(opts_file)
|
||||
|
||||
|
||||
def set_rthook():
|
||||
import PyInstaller
|
||||
hook_file = ""
|
||||
module_dir = dirname(PyInstaller.__file__)
|
||||
rthook = join(module_dir,
|
||||
"loader", "rthooks", "pyi_rth_qt4plugins.py")
|
||||
rthook = join(module_dir, "loader", "rthooks", "pyi_rth_qt4plugins.py")
|
||||
with open(rthook, "r") as hook: data = hook.read()
|
||||
if "sip.setapi" not in data:
|
||||
lines = data.split("\n")
|
||||
|
@ -250,6 +253,7 @@ def set_rthook():
|
|||
hook_file += "sip.setapi('QVariant', 2)\n"
|
||||
with open(rthook, "w") as hook: hook.write(hook_file)
|
||||
|
||||
|
||||
class clean_local(Command):
|
||||
pats = ['*.py[co]', '*_ui.py', '*_rc.py']
|
||||
excludedirs = ['.git', 'build', 'dist']
|
||||
|
@ -275,11 +279,13 @@ class clean_local(Command):
|
|||
if any(fnmatch(fpath, p) for p in self.pats):
|
||||
yield fpath
|
||||
|
||||
|
||||
class mybuild(build):
|
||||
def run(self):
|
||||
self.run_command("build_qt")
|
||||
build.run(self)
|
||||
|
||||
|
||||
class myclean(clean):
|
||||
def run(self):
|
||||
self.run_command("clean_local")
|
||||
|
@ -294,7 +300,8 @@ cmdclass = {
|
|||
'clean_local': clean_local
|
||||
}
|
||||
|
||||
setup(name = "m64py",
|
||||
setup(
|
||||
name = "m64py",
|
||||
version = FRONTEND_VERSION,
|
||||
description = "M64Py - A frontend for Mupen64Plus",
|
||||
long_description = "M64Py is a Qt4 front-end (GUI) for Mupen64Plus 2.0, a cross-platform plugin-based Nintendo 64 emulator.",
|
||||
|
|
|
@ -28,7 +28,7 @@ try:
|
|||
import UnRAR2
|
||||
HAS_RAR = True
|
||||
RAR_CMD = None
|
||||
except:
|
||||
except ImportError:
|
||||
HAS_RAR = False
|
||||
RAR_CMD = which("rar") or which("unrar")
|
||||
|
||||
|
@ -36,7 +36,7 @@ try:
|
|||
from py7zlib import Archive7z
|
||||
HAS_7Z = True
|
||||
LZMA_CMD = None
|
||||
except:
|
||||
except ImportError:
|
||||
HAS_7Z = False
|
||||
LZMA_CMD = which("7z")
|
||||
|
||||
|
@ -52,6 +52,7 @@ ROM_TYPE = {
|
|||
'40123780': 'n64 (wordswapped)'
|
||||
}
|
||||
|
||||
|
||||
class Archive():
|
||||
"""Extracts ROM file from archive."""
|
||||
|
||||
|
@ -59,7 +60,7 @@ class Archive():
|
|||
"""Opens archive."""
|
||||
self.file = os.path.realpath(filename)
|
||||
if not os.path.isfile(self.file) or not os.access(self.file, os.R_OK):
|
||||
raise IOError("Cannot open %s. No such file." % (self.file))
|
||||
raise IOError("Cannot open %s. No such file." % self.file)
|
||||
|
||||
self.filetype = self.get_filetype()
|
||||
|
||||
|
@ -77,16 +78,16 @@ class Archive():
|
|||
elif RAR_CMD:
|
||||
self.fd = RarCmd(self.file)
|
||||
else:
|
||||
raise IOError("UnRAR2 module or rar/unrar is needed for %s." % (self.file))
|
||||
raise IOError("UnRAR2 module or rar/unrar is needed for %s." % self.file)
|
||||
elif self.filetype == LZMA:
|
||||
if HAS_7Z:
|
||||
self.fd = Archive7z(open(self.file, 'rb'))
|
||||
elif LZMA_CMD:
|
||||
self.fd = LzmaCmd(self.file)
|
||||
else:
|
||||
raise IOError("lzma module or 7z is needed for %s." % (self.file))
|
||||
raise IOError("lzma module or 7z is needed for %s." % self.file)
|
||||
else:
|
||||
raise IOError("File %s is not a N64 ROM file." % (self.file))
|
||||
raise IOError("File %s is not a N64 ROM file." % self.file)
|
||||
|
||||
self.namelist = self.get_namelist()
|
||||
|
||||
|
@ -163,6 +164,7 @@ class Archive():
|
|||
return ROM
|
||||
return None
|
||||
|
||||
|
||||
class RarCmd:
|
||||
"""Extracts ROM file from RAR archive."""
|
||||
|
||||
|
@ -170,6 +172,7 @@ class RarCmd:
|
|||
"""Opens archive."""
|
||||
self.fd = None
|
||||
self.file = archive
|
||||
self.filename = None
|
||||
self.namelist = self.namelist()
|
||||
self.tempdir = tempfile.mkdtemp()
|
||||
|
||||
|
@ -200,6 +203,7 @@ class RarCmd:
|
|||
self.fd.close()
|
||||
shutil.rmtree(self.tempdir)
|
||||
|
||||
|
||||
class LzmaCmd:
|
||||
"""Extracts ROM file from 7z archive."""
|
||||
|
||||
|
@ -207,6 +211,7 @@ class LzmaCmd:
|
|||
"""Opens archive."""
|
||||
self.fd = None
|
||||
self.file = archive
|
||||
self.filename = None
|
||||
self.namelist = self.namelist()
|
||||
self.tempdir = tempfile.mkdtemp()
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ from m64py.frontend.log import log
|
|||
SECTIONS_FUNC = C.CFUNCTYPE(None, C.c_void_p, C.c_char_p)
|
||||
PARAMETERS_FUNC = C.CFUNCTYPE(None, C.c_void_p, C.c_char_p, C.c_int)
|
||||
|
||||
|
||||
class Config:
|
||||
"""Mupen64Plus configuration"""
|
||||
|
||||
|
@ -48,8 +49,7 @@ class Config:
|
|||
"""Enumerates the list of sections in config file."""
|
||||
self.m64p.ConfigListSections.argtypes = [C.c_void_p, C.c_void_p]
|
||||
rval = self.m64p.ConfigListSections(
|
||||
C.c_void_p(),
|
||||
SECTIONS_FUNC(self.list_sections_callback))
|
||||
C.c_void_p(), SECTIONS_FUNC(self.list_sections_callback))
|
||||
if rval != M64ERR_SUCCESS:
|
||||
log.debug("list_sections()")
|
||||
log.warn(self.core.error_message(rval))
|
||||
|
@ -171,8 +171,7 @@ class Config:
|
|||
C.c_void_p, C.c_char_p, C.c_int, C.c_void_p, C.c_int]
|
||||
rval = self.m64p.ConfigGetParameter(
|
||||
self.config_handle, C.c_char_p(param_name),
|
||||
C.c_int(param_type), param_value,
|
||||
C.c_int(maxsize))
|
||||
C.c_int(param_type), param_value, C.c_int(maxsize))
|
||||
if rval != M64ERR_SUCCESS:
|
||||
log.debug("get_parameter()")
|
||||
log.warn(self.core.error_message(rval))
|
||||
|
@ -189,8 +188,7 @@ class Config:
|
|||
self.m64p.ConfigGetParameterHelp.argtypes = [
|
||||
C.c_void_p, C.c_char_p, C.POINTER(C.c_int)]
|
||||
rval = self.m64p.ConfigGetParameterType(
|
||||
self.config_handle, C.c_char_p(param_name),
|
||||
param_type)
|
||||
self.config_handle, C.c_char_p(param_name), param_type)
|
||||
if rval != M64ERR_SUCCESS:
|
||||
log.debug("get_parameter_type()")
|
||||
log.warn(self.core.error_message(rval))
|
||||
|
|
|
@ -40,6 +40,7 @@ def debug_callback(context, level, message):
|
|||
elif level == M64MSG_VERBOSE and VERBOSE:
|
||||
sys.stderr.write("%s: %s\n" % (context, message))
|
||||
|
||||
|
||||
def state_callback(context, param, value):
|
||||
if param == M64CORE_VIDEO_SIZE:
|
||||
pass
|
||||
|
@ -52,6 +53,7 @@ STATEFUNC = C.CFUNCTYPE(None, C.c_char_p, C.c_int, C.c_int)
|
|||
DEBUG_CALLBACK = DEBUGFUNC(debug_callback)
|
||||
STATE_CALLBACK = STATEFUNC(state_callback)
|
||||
|
||||
|
||||
class Core:
|
||||
"""Mupen64Plus Core library"""
|
||||
|
||||
|
@ -71,6 +73,7 @@ class Core:
|
|||
self.rom_length = None
|
||||
self.rom_header = m64p_rom_header()
|
||||
self.rom_settings = m64p_rom_settings()
|
||||
self.core_path = ""
|
||||
self.core_name = "Mupen64Plus Core"
|
||||
self.core_version = "Unknown"
|
||||
self.core_sdl2 = False
|
||||
|
@ -98,25 +101,40 @@ class Core:
|
|||
if version:
|
||||
plugin_type, plugin_version, plugin_api, plugin_name, plugin_cap = version
|
||||
if plugin_type != M64PLUGIN_CORE:
|
||||
raise Exception("library '%s' is invalid, this is not the emulator core." % (
|
||||
raise Exception(
|
||||
"library '%s' is invalid, "
|
||||
"this is not the emulator core." % (
|
||||
os.path.basename(self.core_path)))
|
||||
elif plugin_version < MINIMUM_CORE_VERSION:
|
||||
raise Exception("library '%s' is incompatible, core version %s is below minimum supported %s." % (
|
||||
os.path.basename(self.core_path), version_split(plugin_version), version_split(MINIMUM_CORE_VERSION)))
|
||||
raise Exception(
|
||||
"library '%s' is incompatible, "
|
||||
"core version %s is below minimum supported %s." % (
|
||||
os.path.basename(self.core_path),
|
||||
version_split(plugin_version),
|
||||
version_split(MINIMUM_CORE_VERSION)))
|
||||
elif plugin_api & 0xffff0000 != CORE_API_VERSION & 0xffff0000:
|
||||
raise Exception("library '%s' is incompatible, core API major version %s doesn't match application (%s)." % (
|
||||
os.path.basename(self.core_path), version_split(plugin_version), version_split(CORE_API_VERSION)))
|
||||
raise Exception(
|
||||
"library '%s' is incompatible, "
|
||||
"core API major version %s doesn't match application (%s)." % (
|
||||
os.path.basename(self.core_path),
|
||||
version_split(plugin_version),
|
||||
version_split(CORE_API_VERSION)))
|
||||
else:
|
||||
config_ver, debug_ver, vidext_ver = self.get_api_versions()
|
||||
if config_ver & 0xffff0000 != CONFIG_API_VERSION & 0xffff0000:
|
||||
raise Exception("emulator core '%s' is incompatible, config API major version %s doesn't match application: (%s)" % (
|
||||
os.path.basename(self.core_path), version_split(self.config_version), version_split(CONFIG_API_VERSION)))
|
||||
raise Exception(
|
||||
"emulator core '%s' is incompatible, "
|
||||
"config API major version %s doesn't match application: (%s)" % (
|
||||
os.path.basename(self.core_path),
|
||||
version_split(config_ver),
|
||||
version_split(CONFIG_API_VERSION)))
|
||||
|
||||
self.core_name = plugin_name
|
||||
self.core_version = plugin_version
|
||||
|
||||
if LDD_CMD:
|
||||
proc = subprocess.Popen(LDD_CMD % self.core_path, shell=True,
|
||||
proc = subprocess.Popen(
|
||||
LDD_CMD % self.core_path, shell=True,
|
||||
preexec_fn=lambda: signal.signal(signal.SIGPIPE, signal.SIG_DFL))
|
||||
proc.communicate()
|
||||
if proc.returncode == 0:
|
||||
|
@ -140,8 +158,8 @@ class Core:
|
|||
def core_startup(self, path, use_vidext):
|
||||
"""Initializes libmupen64plus for use by allocating memory,
|
||||
creating data structures, and loading the configuration file."""
|
||||
rval = self.m64p.CoreStartup(C.c_int(CORE_API_VERSION), None,
|
||||
C.c_char_p(os.path.dirname(path)),
|
||||
rval = self.m64p.CoreStartup(
|
||||
C.c_int(CORE_API_VERSION), None, C.c_char_p(os.path.dirname(path)),
|
||||
"Core", DEBUG_CALLBACK, "State", STATE_CALLBACK)
|
||||
if rval == M64ERR_SUCCESS:
|
||||
if use_vidext:
|
||||
|
@ -206,8 +224,8 @@ class Core:
|
|||
if version:
|
||||
plugin_type, plugin_version, plugin_api, plugin_desc, plugin_cap = version
|
||||
plugin_name = os.path.basename(plugin_path)
|
||||
self.plugin_map[plugin_type][plugin_name] = (plugin_handle, plugin_path,
|
||||
PLUGIN_NAME[plugin_type], plugin_desc, plugin_version)
|
||||
self.plugin_map[plugin_type][plugin_name] = (
|
||||
plugin_handle, plugin_path, PLUGIN_NAME[plugin_type], plugin_desc, plugin_version)
|
||||
|
||||
def plugin_startup(self, handle, name, desc):
|
||||
"""This function initializes plugin for use by allocating memory,
|
||||
|
@ -217,7 +235,7 @@ class Core:
|
|||
if rval != M64ERR_SUCCESS:
|
||||
log.debug("plugin_startup()")
|
||||
log.warn(self.error_message(rval))
|
||||
log.warn("%s failed to start." % (desc))
|
||||
log.warn("%s failed to start." % desc)
|
||||
|
||||
def plugin_shutdown(self, handle, desc):
|
||||
"""This function destroys data structures and releases
|
||||
|
@ -226,9 +244,9 @@ class Core:
|
|||
if rval != M64ERR_SUCCESS:
|
||||
log.debug("plugin_shutdown()")
|
||||
log.warn(self.error_message(rval))
|
||||
log.warn("%s failed to stop." % (desc))
|
||||
log.warn("%s failed to stop." % desc)
|
||||
|
||||
def attach_plugins(self, plugins={}):
|
||||
def attach_plugins(self, plugins):
|
||||
"""Attaches plugins to the emulator core."""
|
||||
self.plugins = plugins
|
||||
for plugin_type in PLUGIN_ORDER:
|
||||
|
@ -241,8 +259,7 @@ class Core:
|
|||
plugin_desc, plugin_version) = plugin_map
|
||||
|
||||
rval = self.m64p.CoreAttachPlugin(
|
||||
C.c_int(plugin_type),
|
||||
C.c_void_p(plugin_handle._handle))
|
||||
C.c_int(plugin_type), C.c_void_p(plugin_handle._handle))
|
||||
if rval != M64ERR_SUCCESS:
|
||||
log.debug("attach_plugins()")
|
||||
log.warn(self.error_message(rval))
|
||||
|
@ -282,8 +299,7 @@ class Core:
|
|||
if rval != M64ERR_SUCCESS:
|
||||
log.debug("rom_open()")
|
||||
log.warn(self.error_message(rval))
|
||||
log.error("core failed to open ROM file '%s'." % (
|
||||
filename))
|
||||
log.error("core failed to open ROM file.")
|
||||
del rombuffer
|
||||
return rval
|
||||
|
||||
|
@ -359,8 +375,7 @@ class Core:
|
|||
value of a state parameter."""
|
||||
state_ptr = C.pointer(C.c_int())
|
||||
rval = self.m64p.CoreDoCommand(
|
||||
M64CMD_CORE_STATE_QUERY,
|
||||
C.c_int(state), state_ptr)
|
||||
M64CMD_CORE_STATE_QUERY, C.c_int(state), state_ptr)
|
||||
if rval != M64ERR_SUCCESS:
|
||||
log.debug("core_state_query()")
|
||||
log.warn(self.error_message(rval))
|
||||
|
@ -371,8 +386,7 @@ class Core:
|
|||
parameter in the emulator core."""
|
||||
value_ptr = C.pointer(C.c_int(value))
|
||||
rval = self.m64p.CoreDoCommand(
|
||||
M64CMD_CORE_STATE_SET,
|
||||
C.c_int(state), value_ptr)
|
||||
M64CMD_CORE_STATE_SET, C.c_int(state), value_ptr)
|
||||
if rval != M64ERR_SUCCESS:
|
||||
log.debug("core_state_set()")
|
||||
log.warn(self.error_message(rval))
|
||||
|
@ -458,8 +472,9 @@ class Core:
|
|||
def add_cheat(self, cheat_name, cheat_code):
|
||||
"""Adds a Cheat Function to a list of currently active cheats
|
||||
which are applied to the open ROM, and set its state to Enabled"""
|
||||
rval = self.m64p.CoreAddCheat(C.c_char_p(cheat_name),
|
||||
C.pointer(cheat_code), C.c_int(C.sizeof(cheat_code)))
|
||||
rval = self.m64p.CoreAddCheat(
|
||||
C.c_char_p(cheat_name), C.pointer(cheat_code),
|
||||
C.c_int(C.sizeof(cheat_code)))
|
||||
if rval != M64ERR_SUCCESS:
|
||||
log.debug("add_cheat()")
|
||||
log.info("CoreAddCheat() failed for cheat code '%s'" % cheat_name)
|
||||
|
|
|
@ -162,6 +162,7 @@ M64P_SAVES = {
|
|||
m64p_error = C.c_int
|
||||
m64p_GLattr = C.c_int
|
||||
|
||||
|
||||
class m64p_rom_header(C.Structure):
|
||||
_fields_ = [
|
||||
('init_PI_BSB_DOM1_LAT_REG', C.c_ubyte),
|
||||
|
@ -181,6 +182,7 @@ class m64p_rom_header(C.Structure):
|
|||
('Country_code', C.c_ushort)
|
||||
]
|
||||
|
||||
|
||||
class m64p_rom_settings(C.Structure):
|
||||
_fields_ = [
|
||||
('goodname', C.c_char * 256),
|
||||
|
@ -191,12 +193,14 @@ class m64p_rom_settings(C.Structure):
|
|||
('rumble', C.c_ubyte)
|
||||
]
|
||||
|
||||
|
||||
class m64p_cheat_code(C.Structure):
|
||||
_fields_ = [
|
||||
('address', C.c_uint),
|
||||
('value', C.c_int),
|
||||
]
|
||||
|
||||
|
||||
class m64p_2d_size(C.Structure):
|
||||
_fields_ = [
|
||||
('uiWidth', C.c_uint),
|
||||
|
@ -215,6 +219,7 @@ FuncSetCaption = C.CFUNCTYPE(m64p_error, C.c_char_p)
|
|||
FuncToggleFS = C.CFUNCTYPE(m64p_error)
|
||||
FuncResizeWindow = C.CFUNCTYPE(m64p_error, C.c_int, C.c_int)
|
||||
|
||||
|
||||
class m64p_video_extension_functions(C.Structure):
|
||||
_fields_ = [
|
||||
('Functions', C.c_uint),
|
||||
|
|
|
@ -57,6 +57,7 @@ except Exception, err:
|
|||
(1280, 960), (1152, 864), (1024, 768),
|
||||
(800, 600), (640, 480), (320, 240)]
|
||||
|
||||
|
||||
class Video():
|
||||
"""Mupen64Plus video extension"""
|
||||
|
||||
|
@ -64,6 +65,7 @@ class Video():
|
|||
"""Constructor."""
|
||||
self.parent = None
|
||||
self.widget = None
|
||||
self.glformat = None
|
||||
self.glcontext = None
|
||||
|
||||
def set_widget(self, parent):
|
||||
|
@ -114,8 +116,7 @@ class Video():
|
|||
"""Sets the caption text of the
|
||||
emulator rendering window. """
|
||||
title = "M64Py :: %s" % title
|
||||
self.parent.emit(
|
||||
SIGNAL("set_caption(PyQt_PyObject)"), title)
|
||||
self.parent.emit(SIGNAL("set_caption(PyQt_PyObject)"), title)
|
||||
return M64ERR_SUCCESS
|
||||
|
||||
def toggle_fs(self):
|
||||
|
|
|
@ -27,6 +27,7 @@ from m64py.frontend.log import log
|
|||
from m64py.ui.cheat_ui import Ui_CheatDialog
|
||||
from m64py.ui.choices_ui import Ui_ChoicesDialog
|
||||
|
||||
|
||||
class Cheat(QDialog, Ui_CheatDialog):
|
||||
"""Cheats dialog"""
|
||||
|
||||
|
@ -106,13 +107,13 @@ class Cheat(QDialog, Ui_CheatDialog):
|
|||
|
||||
def on_unmark_all(self):
|
||||
"""Deactivates all cheats"""
|
||||
iter = QTreeWidgetItemIterator(self.treeWidget)
|
||||
while(iter.value()):
|
||||
item = iter.value()
|
||||
it = QTreeWidgetItemIterator(self.treeWidget)
|
||||
while it.value():
|
||||
item = it.value()
|
||||
state = item.checkState(0)
|
||||
if state == Qt.Checked:
|
||||
item.setCheckState(0, Qt.Unchecked)
|
||||
iter += 1
|
||||
it += 1
|
||||
|
||||
def activate_cheat(self, item, column):
|
||||
"""Activates selected cheat"""
|
||||
|
@ -184,8 +185,7 @@ class Cheat(QDialog, Ui_CheatDialog):
|
|||
cheat_codes = []
|
||||
|
||||
cheat_file = os.path.join(
|
||||
self.parent.worker.core.config.get_path(
|
||||
"SharedData"), 'mupencheat.txt')
|
||||
self.parent.worker.core.config.get_path( "SharedData"), 'mupencheat.txt')
|
||||
if not os.path.isfile(cheat_file) or not os.access(cheat_file, os.R_OK):
|
||||
log.warn("cheat code database file '%s' not found." % cheat_file)
|
||||
return None
|
||||
|
@ -196,14 +196,12 @@ class Cheat(QDialog, Ui_CheatDialog):
|
|||
self.parent.worker.core.rom_header.Country_code & 0xff)
|
||||
rom_section = rom_section.upper()
|
||||
|
||||
code_re = re.compile(
|
||||
'^([0-9A-F]{8})\s+([?|0-9A-F]{4})\s?(.*)$', re.M)
|
||||
code_re = re.compile('^([0-9A-F]{8})\s+([?|0-9A-F]{4})\s?(.*)$', re.M)
|
||||
|
||||
try:
|
||||
fd = open(cheat_file, 'r')
|
||||
except IOError:
|
||||
log.warn("couldn't open cheat code database file '%s'." % (
|
||||
cheat_file))
|
||||
log.warn("couldn't open cheat code database file '%s'." % cheat_file)
|
||||
return None
|
||||
else:
|
||||
lines = [line.strip() for line in fd.readlines()]
|
||||
|
@ -267,9 +265,10 @@ class Cheat(QDialog, Ui_CheatDialog):
|
|||
|
||||
if line:
|
||||
# otherwise we don't know what this line is
|
||||
log.warn("unrecognized line in cheat file: '%s'" % (line))
|
||||
log.warn("unrecognized line in cheat file: '%s'" % line)
|
||||
return None
|
||||
|
||||
|
||||
class Choices(QDialog, Ui_ChoicesDialog):
|
||||
"""Choices dialog"""
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ from m64py.ui.about_ui import Ui_AboutDialog
|
|||
from m64py.ui.license_ui import Ui_LicenseDialog
|
||||
from m64py.ui.archive_ui import Ui_ArchiveDialog
|
||||
|
||||
|
||||
class AboutDialog(QDialog, Ui_AboutDialog):
|
||||
def __init__(self, parent):
|
||||
QDialog.__init__(self, parent)
|
||||
|
@ -37,12 +38,14 @@ class AboutDialog(QDialog, Ui_AboutDialog):
|
|||
self.labelAbout.setText(text)
|
||||
self.show()
|
||||
|
||||
|
||||
class LicenseDialog(QDialog, Ui_LicenseDialog):
|
||||
def __init__(self, parent):
|
||||
QDialog.__init__(self, parent)
|
||||
self.setupUi(self)
|
||||
self.show()
|
||||
|
||||
|
||||
class InfoDialog(QMessageBox):
|
||||
def __init__(self, parent=None, text=None):
|
||||
QMessageBox.__init__(self, parent)
|
||||
|
@ -50,6 +53,7 @@ class InfoDialog(QMessageBox):
|
|||
self.setWindowTitle("Info")
|
||||
self.show()
|
||||
|
||||
|
||||
class ArchiveDialog(QDialog, Ui_ArchiveDialog):
|
||||
def __init__(self, parent, files):
|
||||
QDialog.__init__(self, parent)
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from PyQt4.QtGui import *
|
||||
from PyQt4.QtCore import *
|
||||
from PyQt4.QtOpenGL import *
|
||||
|
||||
|
@ -22,6 +21,7 @@ from m64py.core.defs import *
|
|||
from m64py.opts import SDL2
|
||||
from m64py.frontend.keymap import QT2SDL, QT2SDL2
|
||||
|
||||
|
||||
class GLWidget(QGLWidget):
|
||||
|
||||
toggle_fs = pyqtSignal()
|
||||
|
@ -34,7 +34,7 @@ class GLWidget(QGLWidget):
|
|||
self.setContentsMargins(QMargins())
|
||||
self.setFocusPolicy(Qt.StrongFocus)
|
||||
self.setFocus(True)
|
||||
self.connect(self, SIGNAL("toggle_fs()"), self.toggle_fs)
|
||||
self.connect(self, SIGNAL("toggle_fs()"), self.toggle_fullscreen)
|
||||
|
||||
def showEvent(self, event):
|
||||
self.setFocus(True)
|
||||
|
@ -47,7 +47,7 @@ class GLWidget(QGLWidget):
|
|||
pass
|
||||
|
||||
def mouseDoubleClickEvent(self, event):
|
||||
self.toggle_fs()
|
||||
self.emit(SIGNAL("toggle_fs()"))
|
||||
|
||||
def keyPressEvent(self, event):
|
||||
if self.worker.state == M64EMU_RUNNING:
|
||||
|
@ -55,7 +55,7 @@ class GLWidget(QGLWidget):
|
|||
modifiers = event.modifiers()
|
||||
if modifiers & Qt.AltModifier and \
|
||||
(key == Qt.Key_Enter or key == Qt.Key_Return):
|
||||
self.toggle_fs()
|
||||
self.emit(SIGNAL("toggle_fs()"))
|
||||
elif key == Qt.Key_F3:
|
||||
self.worker.save_title()
|
||||
elif key == Qt.Key_F4:
|
||||
|
@ -82,7 +82,7 @@ class GLWidget(QGLWidget):
|
|||
except KeyError:
|
||||
pass
|
||||
|
||||
def toggle_fs(self):
|
||||
def toggle_fullscreen(self):
|
||||
window = self.window()
|
||||
if window.isFullScreen():
|
||||
self.parent.menubar.show()
|
||||
|
|
|
@ -34,6 +34,7 @@ else:
|
|||
KEY_RE = re.compile("([a-z]+)\((.*)\)")
|
||||
AXIS_RE = re.compile("([a-z]+)\((.*?),(.*?)\)")
|
||||
|
||||
|
||||
class Input(QDialog, Ui_InputDialog):
|
||||
|
||||
def __init__(self, parent):
|
||||
|
@ -44,6 +45,9 @@ class Input(QDialog, Ui_InputDialog):
|
|||
self.controller = 1
|
||||
self.mode = 0
|
||||
self.device = -1
|
||||
self.opts = {}
|
||||
self.keys = {}
|
||||
self.section = None
|
||||
self.is_joystick = False
|
||||
self.set_section("Input-SDL-Control%d" % self.controller)
|
||||
self.joystick = Joystick()
|
||||
|
@ -104,11 +108,18 @@ class Input(QDialog, Ui_InputDialog):
|
|||
self.comboController.addItem(
|
||||
self.tr("Controller %s" % controller), controller)
|
||||
|
||||
for plugin, ptype in [(self.tr("None"), 1), (self.tr("Mem pak"), 2), (self.tr("Rumble pak"), 5)]:
|
||||
for plugin, ptype in [
|
||||
(self.tr("None"), 1),
|
||||
(self.tr("Mem pak"), 2),
|
||||
(self.tr("Rumble pak"), 5)
|
||||
]:
|
||||
self.comboPlugin.addItem(plugin, ptype)
|
||||
|
||||
for mode, mtype in [(self.tr("Fully Manual"), 0),
|
||||
(self.tr("Auto with named SDL device"), 1), (self.tr("Fully Automatic"), 2)]:
|
||||
for mode, mtype in [
|
||||
(self.tr("Fully Manual"), 0),
|
||||
(self.tr("Auto with named SDL device"), 1),
|
||||
(self.tr("Fully Automatic"), 2)
|
||||
]:
|
||||
self.comboMode.addItem(mode, mtype)
|
||||
|
||||
devices = [(self.tr("Keyboard/Mouse"), -1)]
|
||||
|
@ -226,19 +237,19 @@ class Input(QDialog, Ui_InputDialog):
|
|||
for key, val in self.opts.items():
|
||||
param, tooltip, widget, ptype = val
|
||||
if ptype == M64TYPE_BOOL:
|
||||
self.config.set_parameter(key,
|
||||
widget.isChecked())
|
||||
self.config.set_parameter(
|
||||
key, widget.isChecked())
|
||||
elif ptype == M64TYPE_INT:
|
||||
self.config.set_parameter(key,
|
||||
widget.itemData(widget.currentIndex()))
|
||||
self.config.set_parameter(
|
||||
key, widget.itemData(widget.currentIndex()))
|
||||
elif ptype == M64TYPE_STRING:
|
||||
if key in ["AnalogDeadzone", "AnalogPeak"]:
|
||||
spin1, spin2 = widget
|
||||
self.config.set_parameter(key,"%s,%s" % (
|
||||
spin1.value(), spin2.value()))
|
||||
else:
|
||||
self.config.set_parameter(key,
|
||||
str(widget.text()))
|
||||
self.config.set_parameter(
|
||||
key, str(widget.text()))
|
||||
|
||||
def get_keys(self):
|
||||
self.keys = {
|
||||
|
@ -284,7 +295,6 @@ class Input(QDialog, Ui_InputDialog):
|
|||
self.get_key("Y Axis")[1], self.pushY_Axis_D)
|
||||
}
|
||||
|
||||
|
||||
def set_keys(self):
|
||||
for key, val in self.keys.items():
|
||||
ckey, widget = val
|
||||
|
@ -405,7 +415,7 @@ class Input(QDialog, Ui_InputDialog):
|
|||
from m64py.SDL2.keyboard import SDL_GetScancodeName
|
||||
try:
|
||||
text = SDL_GetScancodeName(KEYCODE2SCANCODE[int(sdl_key)])
|
||||
except:
|
||||
except Exception:
|
||||
return self.tr("Select...")
|
||||
else:
|
||||
from m64py.SDL.keyboard import SDL_GetKeyName
|
||||
|
|
|
@ -39,6 +39,7 @@ JOYSTICK_SENSITIVITY = 0
|
|||
SDL_JOYSTICK_DEFAULT_EVENT_TIMEOUT = 25
|
||||
SDL_JOYSTICK_DEFAULT_AUTOREPEAT_DELAY = 250
|
||||
|
||||
|
||||
class Joystick(QObject):
|
||||
|
||||
axis_value_changed = pyqtSignal(int, int)
|
||||
|
@ -52,7 +53,6 @@ class Joystick(QObject):
|
|||
joystick_deadzone=JOYSTICK_DEADZONE,
|
||||
joystick_sensitivity=JOYSTICK_SENSITIVITY):
|
||||
QObject.__init__(self)
|
||||
|
||||
self.joystick_timer = QTimer()
|
||||
|
||||
self.deadzones = {}
|
||||
|
@ -81,8 +81,7 @@ class Joystick(QObject):
|
|||
self.joystick_names.append(SDL_JoystickNameForIndex(i))
|
||||
else:
|
||||
self.joystick_names.append(SDL_JoystickName(i))
|
||||
self.connect(self.joystick_timer, SIGNAL("timeout()"),
|
||||
self.process_events)
|
||||
self.connect(self.joystick_timer, SIGNAL("timeout()"), self.process_events)
|
||||
else:
|
||||
log.info("couldn't initialize SDL joystick support")
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ from PyQt4.QtGui import QDialog, QTextCursor
|
|||
|
||||
from m64py.ui.logview_ui import Ui_LogView
|
||||
|
||||
|
||||
class Log:
|
||||
def __init__(self, out=None, logview=None):
|
||||
self.out = out
|
||||
|
@ -31,8 +32,9 @@ class Log:
|
|||
if self.out:
|
||||
self.out.write(msg)
|
||||
if self.logview:
|
||||
self.logview.emit(
|
||||
SIGNAL("msg_written(PyQt_PyObject)"), msg)
|
||||
self.logview.emit(SIGNAL(
|
||||
"msg_written(PyQt_PyObject)"), msg)
|
||||
|
||||
|
||||
class LogView(QDialog, Ui_LogView):
|
||||
msg_written = pyqtSignal(str)
|
||||
|
@ -41,13 +43,14 @@ class LogView(QDialog, Ui_LogView):
|
|||
QDialog.__init__(self, parent)
|
||||
self.setupUi(self)
|
||||
self.textEdit.setReadOnly(True)
|
||||
self.connect(self, SIGNAL("msg_written(PyQt_PyObject)"),
|
||||
self.on_msg_written)
|
||||
self.connect(self, SIGNAL(
|
||||
"msg_written(PyQt_PyObject)"), self.on_msg_written)
|
||||
|
||||
def on_msg_written(self, msg):
|
||||
self.textEdit.moveCursor(QTextCursor.End)
|
||||
self.textEdit.insertPlainText(msg)
|
||||
|
||||
|
||||
class Logger():
|
||||
def __init__(self):
|
||||
log_format = 'Frontend: %(levelname)s: %(message)s'
|
||||
|
|
|
@ -33,6 +33,7 @@ from m64py.frontend.glwidget import GLWidget
|
|||
from m64py.ui.mainwindow_ui import Ui_MainWindow
|
||||
from m64py.frontend.recentfiles import RecentFiles
|
||||
|
||||
|
||||
class MainWindow(QMainWindow, Ui_MainWindow):
|
||||
"""Frontend main window"""
|
||||
|
||||
|
@ -55,9 +56,9 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
logview.setParent(self)
|
||||
logview.setWindowFlags(Qt.Dialog)
|
||||
|
||||
self.statusbarLabel = QLabel()
|
||||
self.statusbarLabel.setIndent(2)
|
||||
self.statusbar.addPermanentWidget(self.statusbarLabel, 1)
|
||||
self.statusbar_label = QLabel()
|
||||
self.statusbar_label.setIndent(2)
|
||||
self.statusbar.addPermanentWidget(self.statusbar_label, 1)
|
||||
self.update_status(self.tr(
|
||||
"Welcome to M64Py version %s." % FRONTEND_VERSION))
|
||||
|
||||
|
@ -66,6 +67,10 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
SIZE_2X: self.action2X,
|
||||
SIZE_3X: self.action3X}
|
||||
|
||||
self.slots = {}
|
||||
self.view = None
|
||||
self.stack = None
|
||||
self.glwidget = None
|
||||
self.cheats = None
|
||||
self.maximized = False
|
||||
self.widgets_height = None
|
||||
|
@ -73,8 +78,8 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
self.settings = Settings(self)
|
||||
self.worker = Worker(self)
|
||||
|
||||
self.vidext = bool(int(
|
||||
self.settings.qset.value("enable_vidext", 1)))
|
||||
self.vidext = bool(
|
||||
int(self.settings.qset.value("enable_vidext", 1)))
|
||||
|
||||
self.create_state_slots()
|
||||
self.create_widgets()
|
||||
|
@ -174,24 +179,15 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
|
||||
def connect_signals(self):
|
||||
"""Connects signals."""
|
||||
self.connect(self, SIGNAL("rom_opened()"),
|
||||
self.on_rom_opened)
|
||||
self.connect(self, SIGNAL("rom_closed()"),
|
||||
self.on_rom_closed)
|
||||
self.connect(self, SIGNAL("file_open(PyQt_PyObject, PyQt_PyObject)"),
|
||||
self.file_open)
|
||||
self.connect(self, SIGNAL("file_opening(PyQt_PyObject)"),
|
||||
self.on_file_opening)
|
||||
self.connect(self, SIGNAL("set_caption(PyQt_PyObject)"),
|
||||
self.on_set_caption)
|
||||
self.connect(self, SIGNAL("state_changed(PyQt_PyObject)"),
|
||||
self.on_state_changed)
|
||||
self.connect(self, SIGNAL("save_image(PyQt_PyObject)"),
|
||||
self.on_save_image)
|
||||
self.connect(self, SIGNAL("info_dialog(PyQt_PyObject)"),
|
||||
self.on_info_dialog)
|
||||
self.connect(self, SIGNAL("archive_dialog(PyQt_PyObject)"),
|
||||
self.on_archive_dialog)
|
||||
self.connect(self, SIGNAL("rom_opened()"), self.on_rom_opened)
|
||||
self.connect(self, SIGNAL("rom_closed()"), self.on_rom_closed)
|
||||
self.connect(self, SIGNAL("file_open(PyQt_PyObject, PyQt_PyObject)"), self.file_open)
|
||||
self.connect(self, SIGNAL("file_opening(PyQt_PyObject)"), self.on_file_opening)
|
||||
self.connect(self, SIGNAL("set_caption(PyQt_PyObject)"), self.on_set_caption)
|
||||
self.connect(self, SIGNAL("state_changed(PyQt_PyObject)"), self.on_state_changed)
|
||||
self.connect(self, SIGNAL("save_image(PyQt_PyObject)"), self.on_save_image)
|
||||
self.connect(self, SIGNAL("info_dialog(PyQt_PyObject)"), self.on_info_dialog)
|
||||
self.connect(self, SIGNAL("archive_dialog(PyQt_PyObject)"), self.on_archive_dialog)
|
||||
|
||||
def create_widgets(self):
|
||||
"""Creates central widgets."""
|
||||
|
@ -207,7 +203,6 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
|
||||
def create_state_slots(self):
|
||||
"""Creates state slot actions."""
|
||||
self.slots = {}
|
||||
group = QActionGroup(self)
|
||||
group.setExclusive(True)
|
||||
for slot in range(10):
|
||||
|
@ -226,7 +221,6 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
"""Creates window size actions."""
|
||||
group = QActionGroup(self)
|
||||
group.setExclusive(True)
|
||||
size = self.settings.qset.value("size", SIZE_1X)
|
||||
for num, size in enumerate(
|
||||
sorted(self.sizes.keys()), 1):
|
||||
width, height = size
|
||||
|
@ -236,7 +230,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
action.setText("%dX" % num)
|
||||
action.setToolTip("%sx%s" % (width, height))
|
||||
self.connect(action, SIGNAL("triggered()"),
|
||||
lambda w=w,h=h:self.resize(w, h))
|
||||
lambda wi=w, he=h: self.resize(wi, he))
|
||||
|
||||
def file_open(self, filepath=None, filename=None):
|
||||
"""Opens ROM file."""
|
||||
|
@ -252,7 +246,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
|
||||
def update_status(self, status):
|
||||
"""Updates label in status bar."""
|
||||
self.statusbarLabel.setText(status)
|
||||
self.statusbar_label.setText(status)
|
||||
|
||||
def on_set_caption(self, title):
|
||||
"""Sets window title."""
|
||||
|
@ -485,6 +479,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
"""Shows log dialog."""
|
||||
logview.show()
|
||||
|
||||
|
||||
class View(QGraphicsView):
|
||||
def __init__(self, parent=None):
|
||||
QGraphicsView.__init__(self, parent)
|
||||
|
@ -493,5 +488,4 @@ class View(QGraphicsView):
|
|||
self.setStyleSheet("QGraphicsView {border:0px solid;margin:0px;}")
|
||||
self.setResizeAnchor(QGraphicsView.AnchorViewCenter)
|
||||
self.setScene(QGraphicsScene(self))
|
||||
self.scene().addItem(
|
||||
QGraphicsPixmapItem(QPixmap(":/images/front.png")))
|
||||
self.scene().addItem(QGraphicsPixmapItem(QPixmap(":/images/front.png")))
|
||||
|
|
|
@ -21,12 +21,17 @@ from m64py.core.defs import *
|
|||
from m64py.utils import format_label, format_options
|
||||
from m64py.ui.plugin_ui import Ui_PluginDialog
|
||||
|
||||
|
||||
class Plugin(QDialog, Ui_PluginDialog):
|
||||
"""Plugin settings dialog"""
|
||||
|
||||
def __init__(self, parent):
|
||||
QDialog.__init__(self, parent)
|
||||
self.parent = parent
|
||||
self.widgets = {}
|
||||
self.items = None
|
||||
self.config = None
|
||||
self.section = None
|
||||
self.setupUi(self)
|
||||
|
||||
def showEvent(self, event):
|
||||
|
@ -61,7 +66,6 @@ class Plugin(QDialog, Ui_PluginDialog):
|
|||
del item
|
||||
|
||||
def add_items(self):
|
||||
self.widgets = {}
|
||||
row1, row2 = 0, 0
|
||||
for count, item in enumerate(self.items):
|
||||
param_name, param_type = item
|
||||
|
@ -101,7 +105,8 @@ class Plugin(QDialog, Ui_PluginDialog):
|
|||
row2 += 1
|
||||
widget = QCheckBox()
|
||||
widget.setText(format_label(param_name))
|
||||
if param_help: widget.setToolTip(param_help)
|
||||
if param_help:
|
||||
widget.setToolTip(param_help)
|
||||
self.gridLayout.addWidget(widget, row2, 3)
|
||||
self.widgets[param_name] = (widget, widget.__class__, opts)
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
from PyQt4.QtGui import QAction, QIcon, QPixmap
|
||||
from PyQt4.QtCore import QFileInfo, SIGNAL
|
||||
|
||||
|
||||
class RecentFiles():
|
||||
"""Keeps track of last opened files."""
|
||||
|
||||
|
@ -24,8 +25,9 @@ class RecentFiles():
|
|||
"""Constructor"""
|
||||
self.parent = parent
|
||||
self.max_recent = 5
|
||||
self.recent_actions = []
|
||||
self.recent_files = []
|
||||
self.recent_actions = []
|
||||
self.action_clear_history = QAction(self.parent)
|
||||
self.create()
|
||||
self.update()
|
||||
|
||||
|
@ -36,19 +38,18 @@ class RecentFiles():
|
|||
action.setIcon(QIcon(QPixmap(":/icons/action_rom.png")))
|
||||
self.recent_actions.append(action)
|
||||
self.recent_actions[i].setVisible(False)
|
||||
self.parent.connect(self.recent_actions[i],
|
||||
SIGNAL("triggered()"), self.parent.file_open)
|
||||
self.parent.connect(
|
||||
self.recent_actions[i], SIGNAL("triggered()"), self.parent.file_open)
|
||||
self.parent.menuRecent.addAction(self.recent_actions[i])
|
||||
self.parent.menuRecent.addSeparator()
|
||||
self.actionClearHistory = QAction(self.parent)
|
||||
self.actionClearHistory.setText("&Clear history")
|
||||
self.actionClearHistory.setEnabled(False)
|
||||
self.actionClearHistory.setVisible(True)
|
||||
self.actionClearHistory.setIcon(
|
||||
self.action_clear_history.setText("&Clear history")
|
||||
self.action_clear_history.setEnabled(False)
|
||||
self.action_clear_history.setVisible(True)
|
||||
self.action_clear_history.setIcon(
|
||||
QIcon(QPixmap(":/icons/action_clear.png")))
|
||||
self.parent.connect(self.actionClearHistory,
|
||||
SIGNAL("triggered()"), self.clear)
|
||||
self.parent.menuRecent.addAction(self.actionClearHistory)
|
||||
self.parent.connect(
|
||||
self.action_clear_history, SIGNAL("triggered()"), self.clear)
|
||||
self.parent.menuRecent.addAction(self.action_clear_history)
|
||||
|
||||
def update(self):
|
||||
"""Updates list of recent files."""
|
||||
|
@ -63,7 +64,7 @@ class RecentFiles():
|
|||
self.recent_files[i]).filePath())
|
||||
for j in range(num_files, self.max_recent):
|
||||
self.recent_actions[j].setVisible(False)
|
||||
self.actionClearHistory.setEnabled((num_files > 0))
|
||||
self.action_clear_history.setEnabled((num_files > 0))
|
||||
|
||||
def add(self, filepath):
|
||||
"""Adds file to recent files list."""
|
||||
|
|
|
@ -20,6 +20,7 @@ from PyQt4.QtGui import QMessageBox
|
|||
|
||||
from m64py.utils import sl
|
||||
|
||||
|
||||
class RomInfo():
|
||||
"""ROM information dialog"""
|
||||
|
||||
|
|
|
@ -29,11 +29,10 @@ from m64py.ui.romlist_ui import Ui_ROMList
|
|||
try:
|
||||
from m64py.ui import title_rc
|
||||
from m64py.ui import snapshot_rc
|
||||
bool(title_rc)
|
||||
bool(snapshot_rc)
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
|
||||
class ROMList(QMainWindow, Ui_ROMList):
|
||||
"""ROM list window"""
|
||||
|
||||
|
@ -46,6 +45,11 @@ class ROMList(QMainWindow, Ui_ROMList):
|
|||
self.setAttribute(Qt.WA_DeleteOnClose, True)
|
||||
self.qset = self.parent.settings.qset
|
||||
|
||||
self.romlist = {}
|
||||
self.title_item = None
|
||||
self.snapshot_item = None
|
||||
self.roms = self.qset.value("rom_list", [])
|
||||
|
||||
rect = self.frameGeometry()
|
||||
rect.moveCenter(QDesktopWidget().availableGeometry().center())
|
||||
self.move(rect.topLeft())
|
||||
|
@ -70,7 +74,6 @@ class ROMList(QMainWindow, Ui_ROMList):
|
|||
|
||||
def init(self):
|
||||
self.read_rom_list()
|
||||
self.roms = self.qset.value("rom_list", [])
|
||||
if bool(int(self.qset.value("show_available", 0))):
|
||||
self.add_available_items(self.roms)
|
||||
else:
|
||||
|
@ -78,29 +81,20 @@ class ROMList(QMainWindow, Ui_ROMList):
|
|||
|
||||
def connect_signals(self):
|
||||
"""Connects signals."""
|
||||
self.listWidget.currentItemChanged.connect(
|
||||
self.on_item_changed)
|
||||
self.listWidget.itemDoubleClicked.connect(
|
||||
self.on_item_activated)
|
||||
self.listWidget.itemActivated.connect(
|
||||
self.on_item_activated)
|
||||
self.checkAvailable.clicked.connect(
|
||||
self.on_available_clicked)
|
||||
self.progressBar.valueChanged.connect(
|
||||
self.on_progress_bar_changed)
|
||||
self.pushRefresh.clicked.connect(
|
||||
self.refresh_items)
|
||||
self.pushOpen.clicked.connect(
|
||||
self.on_item_open)
|
||||
self.connect(self.reader, SIGNAL("finished()"),
|
||||
self.add_available_items)
|
||||
self.listWidget.currentItemChanged.connect(self.on_item_changed)
|
||||
self.listWidget.itemDoubleClicked.connect(self.on_item_activated)
|
||||
self.listWidget.itemActivated.connect(self.on_item_activated)
|
||||
self.checkAvailable.clicked.connect(self.on_available_clicked)
|
||||
self.progressBar.valueChanged.connect(self.on_progress_bar_changed)
|
||||
self.pushRefresh.clicked.connect(self.refresh_items)
|
||||
self.pushOpen.clicked.connect(self.on_item_open)
|
||||
self.connect(self.reader, SIGNAL("finished()"), self.add_available_items)
|
||||
|
||||
def read_rom_list(self):
|
||||
"""Reads ROM list from ini file."""
|
||||
inifile = os.path.join(self.shared_data_path, "mupen64plus.ini")
|
||||
self.parser.read(inifile)
|
||||
sections = self.parser.sections()
|
||||
self.romlist = {}
|
||||
for section in sections:
|
||||
items = self.parser.items(section)
|
||||
self.romlist[section] = dict(items)
|
||||
|
@ -180,7 +174,8 @@ class ROMList(QMainWindow, Ui_ROMList):
|
|||
self.file_open(path, fname)
|
||||
|
||||
def on_item_changed(self, current, previous):
|
||||
if not current: return
|
||||
if not current:
|
||||
return
|
||||
md5, path, fname = current.data(Qt.UserRole)
|
||||
|
||||
title = QPixmap(os.path.join(
|
||||
|
@ -197,20 +192,20 @@ class ROMList(QMainWindow, Ui_ROMList):
|
|||
snapshot = QPixmap(":/images/default.png")
|
||||
|
||||
if previous is not None:
|
||||
self.titleView.scene().removeItem(self.titleItem)
|
||||
self.snapshotView.scene().removeItem(self.snapshotItem)
|
||||
self.titleView.scene().removeItem(self.title_item)
|
||||
self.snapshotView.scene().removeItem(self.snapshot_item)
|
||||
|
||||
title_pixmap = title.scaled(self.titleView.size(),
|
||||
Qt.KeepAspectRatio, Qt.SmoothTransformation)
|
||||
snapshot_pixmap = snapshot.scaled(self.snapshotView.size(),
|
||||
Qt.KeepAspectRatio, Qt.SmoothTransformation)
|
||||
title_pixmap = title.scaled(
|
||||
self.titleView.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation)
|
||||
snapshot_pixmap = snapshot.scaled(
|
||||
self.snapshotView.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation)
|
||||
|
||||
titleItem = QGraphicsPixmapItem(title_pixmap)
|
||||
snapshotItem = QGraphicsPixmapItem(snapshot_pixmap)
|
||||
self.titleView.scene().addItem(titleItem)
|
||||
self.snapshotView.scene().addItem(snapshotItem)
|
||||
self.titleItem = titleItem
|
||||
self.snapshotItem = snapshotItem
|
||||
title_item = QGraphicsPixmapItem(title_pixmap)
|
||||
snapshot_item = QGraphicsPixmapItem(snapshot_pixmap)
|
||||
self.titleView.scene().addItem(title_item)
|
||||
self.snapshotView.scene().addItem(snapshot_item)
|
||||
self.title_item = title_item
|
||||
self.snapshot_item = snapshot_item
|
||||
|
||||
def on_available_clicked(self):
|
||||
is_checked = self.checkAvailable.isChecked()
|
||||
|
@ -224,6 +219,7 @@ class ROMList(QMainWindow, Ui_ROMList):
|
|||
self.reader.stop()
|
||||
self.add_items()
|
||||
|
||||
|
||||
class ROMReader(QThread):
|
||||
"""ROM reader thread"""
|
||||
|
||||
|
@ -269,8 +265,7 @@ class ROMReader(QThread):
|
|||
log.warn(str(err))
|
||||
continue
|
||||
percent = float(filenum) / float(num_files) * 100
|
||||
self.parent.progressBar.emit(
|
||||
SIGNAL("valueChanged(int)"), percent)
|
||||
self.parent.progressBar.emit(SIGNAL("valueChanged(int)"), percent)
|
||||
self.exit()
|
||||
|
||||
def stop(self):
|
||||
|
|
|
@ -28,6 +28,7 @@ from m64py.frontend.plugin import Plugin
|
|||
from m64py.frontend.input import Input
|
||||
from m64py.ui.settings_ui import Ui_Settings
|
||||
|
||||
|
||||
class Settings(QDialog, Ui_Settings):
|
||||
"""Settings dialog"""
|
||||
|
||||
|
@ -37,6 +38,8 @@ class Settings(QDialog, Ui_Settings):
|
|||
self.setupUi(self)
|
||||
self.core = None
|
||||
self.plugins = []
|
||||
self.emumode = []
|
||||
self.combomap = {}
|
||||
self.qset = QSettings("m64py", "m64py")
|
||||
self.input = Input(self.parent)
|
||||
self.add_items()
|
||||
|
@ -61,12 +64,14 @@ class Settings(QDialog, Ui_Settings):
|
|||
Plugin(self.parent)),
|
||||
M64PLUGIN_INPUT: (
|
||||
self.comboInput, self.pushButtonInput,
|
||||
self.input)}
|
||||
self.input)
|
||||
}
|
||||
|
||||
self.emumode = [
|
||||
QRadioButton(self.tr("Pure Interpreter")),
|
||||
QRadioButton(self.tr("Cached Interpreter")),
|
||||
QRadioButton(self.tr("Dynamic Recompiler"))]
|
||||
QRadioButton(self.tr("Dynamic Recompiler"))
|
||||
]
|
||||
|
||||
vbox = QVBoxLayout(self.groupEmuMode)
|
||||
for widget in self.emumode:
|
||||
|
@ -151,7 +156,7 @@ class Settings(QDialog, Ui_Settings):
|
|||
desc = combo.itemData(index)
|
||||
name = os.path.splitext(plugin)[0][12:]
|
||||
section = "-".join([n.capitalize() for n in name.split("-")[0:2]])
|
||||
return (section, desc)
|
||||
return section, desc
|
||||
|
||||
def set_section(self, combo, button, settings):
|
||||
if settings:
|
||||
|
@ -171,10 +176,10 @@ class Settings(QDialog, Ui_Settings):
|
|||
button.setEnabled(False)
|
||||
|
||||
def set_paths(self):
|
||||
path_library = self.qset.value("Paths/Library",
|
||||
find_library(CORE_NAME))
|
||||
path_data = self.qset.value("Paths/Data",
|
||||
self.core.config.get_path("SharedData"))
|
||||
path_library = self.qset.value(
|
||||
"Paths/Library", find_library(CORE_NAME))
|
||||
path_data = self.qset.value(
|
||||
"Paths/Data", self.core.config.get_path("SharedData"))
|
||||
path_roms = self.qset.value("Paths/ROM")
|
||||
|
||||
try:
|
||||
|
@ -266,19 +271,16 @@ class Settings(QDialog, Ui_Settings):
|
|||
current = self.qset.value("Plugins/%s" % (
|
||||
PLUGIN_NAME[plugin_type]), PLUGIN_DEFAULT[plugin_type])
|
||||
index = combo.findText(current)
|
||||
if index == -1: index = 0
|
||||
if index == -1:
|
||||
index = 0
|
||||
combo.setCurrentIndex(index)
|
||||
self.set_section(combo, button, settings)
|
||||
|
||||
def save_paths(self):
|
||||
self.qset.setValue("Paths/Library",
|
||||
self.pathLibrary.text())
|
||||
self.qset.setValue("Paths/Plugins",
|
||||
self.pathPlugins.text())
|
||||
self.qset.setValue("Paths/Data",
|
||||
self.pathData.text())
|
||||
self.qset.setValue("Paths/ROM",
|
||||
self.pathROM.text())
|
||||
self.qset.setValue("Paths/Library", self.pathLibrary.text())
|
||||
self.qset.setValue("Paths/Plugins", self.pathPlugins.text())
|
||||
self.qset.setValue("Paths/Data", self.pathData.text())
|
||||
self.qset.setValue("Paths/ROM", self.pathROM.text())
|
||||
|
||||
def save_video(self):
|
||||
if not self.parent.vidext:
|
||||
|
@ -294,24 +296,15 @@ class Settings(QDialog, Ui_Settings):
|
|||
def save_core(self):
|
||||
self.core.config.open_section("Core")
|
||||
emumode = [n for n,m in enumerate(self.emumode) if m.isChecked()][0]
|
||||
self.core.config.set_parameter("R4300Emulator",
|
||||
emumode)
|
||||
self.core.config.set_parameter("OnScreenDisplay",
|
||||
self.checkOSD.isChecked())
|
||||
self.core.config.set_parameter("NoCompiledJump",
|
||||
self.checkNoCompiledJump.isChecked())
|
||||
self.core.config.set_parameter("DisableExtraMem",
|
||||
self.checkDisableExtraMem.isChecked())
|
||||
self.core.config.set_parameter("DelaySI",
|
||||
self.checkDelaySI.isChecked())
|
||||
self.core.config.set_parameter("CountPerOp",
|
||||
self.comboCountPerOp.currentIndex())
|
||||
self.core.config.set_parameter("SharedDataPath",
|
||||
self.pathData.text())
|
||||
self.core.config.set_parameter("R4300Emulator", emumode)
|
||||
self.core.config.set_parameter("OnScreenDisplay", self.checkOSD.isChecked())
|
||||
self.core.config.set_parameter("NoCompiledJump", self.checkNoCompiledJump.isChecked())
|
||||
self.core.config.set_parameter("DisableExtraMem", self.checkDisableExtraMem.isChecked())
|
||||
self.core.config.set_parameter("DelaySI", self.checkDelaySI.isChecked())
|
||||
self.core.config.set_parameter("CountPerOp", self.comboCountPerOp.currentIndex())
|
||||
self.core.config.set_parameter("SharedDataPath", self.pathData.text())
|
||||
|
||||
def save_plugins(self):
|
||||
for plugin_type in self.combomap:
|
||||
combo, button, settings = self.combomap[plugin_type]
|
||||
self.qset.setValue("Plugins/%s" %
|
||||
PLUGIN_NAME[plugin_type],
|
||||
combo.currentText())
|
||||
self.qset.setValue("Plugins/%s" % PLUGIN_NAME[plugin_type], combo.currentText())
|
||||
|
|
|
@ -29,6 +29,7 @@ from m64py.core.vidext import video
|
|||
from m64py.archive import Archive
|
||||
from m64py.platform import DLL_EXT, DEFAULT_DYNLIB, SEARCH_DIRS
|
||||
|
||||
|
||||
class Worker(QThread):
|
||||
"""Mupen64Plus thread worker"""
|
||||
|
||||
|
@ -38,6 +39,9 @@ class Worker(QThread):
|
|||
self.parent = parent
|
||||
self.video = video
|
||||
self.plugin_files = []
|
||||
self.archive = None
|
||||
self.filepath = None
|
||||
self.filename = None
|
||||
self.library_path = None
|
||||
self.state = M64EMU_STOPPED
|
||||
self.settings = self.parent.settings
|
||||
|
@ -53,13 +57,13 @@ class Worker(QThread):
|
|||
|
||||
self.parent.settings.core = self.core
|
||||
if self.parent.args:
|
||||
self.parent.emit(SIGNAL("file_open(PyQt_PyObject, PyQt_PyObject)"),
|
||||
self.parent.args[0], None)
|
||||
self.parent.emit(SIGNAL(
|
||||
"file_open(PyQt_PyObject, PyQt_PyObject)"), self.parent.args[0], None)
|
||||
else:
|
||||
self.parent.emit(SIGNAL("state_changed(PyQt_PyObject)"),
|
||||
(False, False, False, False))
|
||||
self.parent.emit(SIGNAL("info_dialog(PyQt_PyObject)"),
|
||||
self.tr("Mupen64Plus library not found."))
|
||||
self.parent.emit(SIGNAL(
|
||||
"state_changed(PyQt_PyObject)"), (False, False, False, False))
|
||||
self.parent.emit(SIGNAL(
|
||||
"info_dialog(PyQt_PyObject)"), self.tr("Mupen64Plus library not found."))
|
||||
|
||||
def quit(self):
|
||||
if self.state in [M64EMU_RUNNING, M64EMU_PAUSED]:
|
||||
|
@ -230,11 +234,10 @@ class Worker(QThread):
|
|||
if screenshot:
|
||||
image_name = "%s.png" % self.core.rom_settings.MD5
|
||||
try:
|
||||
shutil.copyfile(screenshot,
|
||||
os.path.join(dst_path, image_name))
|
||||
shutil.copyfile(screenshot, os.path.join(dst_path, image_name))
|
||||
log.info("Captured %s" % capture)
|
||||
except IOError:
|
||||
log.exception("couldn't save image %s" % image)
|
||||
log.exception("couldn't save image %s" % image_name)
|
||||
|
||||
def save_title(self):
|
||||
"""Saves title."""
|
||||
|
|
|
@ -51,6 +51,7 @@ def _environ_path(name):
|
|||
else:
|
||||
return []
|
||||
|
||||
|
||||
class LibraryLoader(object):
|
||||
def __init__(self):
|
||||
self.other_dirs = []
|
||||
|
@ -126,7 +127,7 @@ class DarwinLibraryLoader(LibraryLoader):
|
|||
if os.path.pathsep in libname:
|
||||
names = [libname]
|
||||
else:
|
||||
names = [format % libname for format in self.name_formats]
|
||||
names = [f % libname for f in self.name_formats]
|
||||
|
||||
for dirname in self.getdirs(libname):
|
||||
for name in names:
|
||||
|
@ -194,23 +195,23 @@ class PosixLibraryLoader(LibraryLoader):
|
|||
except IOError:
|
||||
pass
|
||||
|
||||
directories.extend(['/lib', '/usr/lib', '/lib64',
|
||||
'/usr/lib64', '/usr/games/lib', '/usr/games/lib64',
|
||||
directories.extend(['/lib', '/usr/lib', '/lib64', '/usr/lib64',
|
||||
'/usr/games/lib', '/usr/games/lib64',
|
||||
'/usr/lib/x86_64-linux-gnu', '/usr/lib/i386-linux-gnu'])
|
||||
|
||||
cache = {}
|
||||
lib_re = re.compile(r'lib(.*)\.s[ol]')
|
||||
for dir in directories:
|
||||
for d in directories:
|
||||
try:
|
||||
for path in glob.glob("%s/*.s[ol]*" % dir):
|
||||
file = os.path.basename(path)
|
||||
for path in glob.glob("%s/*.s[ol]*" % d):
|
||||
f = os.path.basename(path)
|
||||
|
||||
# Index by filename
|
||||
if file not in cache:
|
||||
cache[file] = path
|
||||
if f not in cache:
|
||||
cache[f] = path
|
||||
|
||||
# Index by library name
|
||||
match = lib_re.match(file)
|
||||
match = lib_re.match(f)
|
||||
if match:
|
||||
library = match.group(1)
|
||||
if library not in cache:
|
||||
|
@ -225,10 +226,13 @@ class PosixLibraryLoader(LibraryLoader):
|
|||
self._create_ld_so_cache()
|
||||
|
||||
result = self._ld_so_cache.get(libname)
|
||||
if result: yield result
|
||||
if result:
|
||||
yield result
|
||||
|
||||
path = ctypes.util.find_library(libname)
|
||||
if path: yield os.path.join("/lib",path)
|
||||
if path:
|
||||
yield os.path.join("/lib", path)
|
||||
|
||||
|
||||
class _WindowsLibrary(object):
|
||||
def __init__(self, path):
|
||||
|
@ -244,9 +248,11 @@ class _WindowsLibrary(object):
|
|||
self.windll = ctypes.windll.LoadLibrary(path)
|
||||
|
||||
def __getattr__(self, name):
|
||||
try: return getattr(self.cdll,name)
|
||||
try:
|
||||
return getattr(self.cdll, name)
|
||||
except AttributeError:
|
||||
try: return getattr(self.windll,name)
|
||||
try:
|
||||
return getattr(self.windll, name)
|
||||
except AttributeError:
|
||||
raise
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ import subprocess
|
|||
|
||||
from m64py.frontend.log import log
|
||||
|
||||
|
||||
class LinuxScreenSaver:
|
||||
cookie = None
|
||||
screensaver = None
|
||||
|
@ -35,7 +36,8 @@ class LinuxScreenSaver:
|
|||
def disable(self):
|
||||
if self.screensaver:
|
||||
try:
|
||||
self.cookie = self.screensaver.Inhibit("M64Py", "Emulation started")
|
||||
self.cookie = self.screensaver.Inhibit(
|
||||
"M64Py", "Emulation started")
|
||||
log.info("ScreenSaver disabled")
|
||||
except Exception, err:
|
||||
log.exception(str(err))
|
||||
|
@ -49,6 +51,7 @@ class LinuxScreenSaver:
|
|||
except Exception, err:
|
||||
log.exception(str(err))
|
||||
|
||||
|
||||
class DarwinScreenSaver:
|
||||
def __init__(self):
|
||||
try:
|
||||
|
@ -70,6 +73,7 @@ class DarwinScreenSaver:
|
|||
shell=True)
|
||||
log.info("ScreenSaver enabled")
|
||||
|
||||
|
||||
class WindowsScreenSaver:
|
||||
sys_param_info = None
|
||||
SPI_SETSCREENSAVEACTIVE = 17
|
||||
|
|
|
@ -27,8 +27,8 @@ class ImageView(QGraphicsView):
|
|||
size = event.size()
|
||||
for item in self.scene().items():
|
||||
pixmap = item.pixmap()
|
||||
pixmap = pixmap.scaled(size,
|
||||
Qt.KeepAspectRatio, Qt.SmoothTransformation)
|
||||
pixmap = pixmap.scaled(
|
||||
size, Qt.KeepAspectRatio, Qt.SmoothTransformation)
|
||||
item.setPixmap(pixmap)
|
||||
self.ensureVisible(item)
|
||||
self.centerOn(item)
|
||||
|
|
|
@ -31,6 +31,8 @@ class InputButton(QPushButton):
|
|||
QPushButton.__init__(self, parent)
|
||||
self.key = None
|
||||
self.parent = parent
|
||||
self.input = None
|
||||
self.joystick = None
|
||||
self.setFocusPolicy(Qt.ClickFocus)
|
||||
|
||||
def showEvent(self, event):
|
||||
|
|
|
@ -17,6 +17,7 @@ import os
|
|||
import re
|
||||
from hashlib import md5
|
||||
|
||||
|
||||
def md5sum(filename=None, filedata=None, buf_size=8192):
|
||||
m = md5()
|
||||
if filename:
|
||||
|
@ -31,6 +32,7 @@ def md5sum(filename=None, filedata=None, buf_size=8192):
|
|||
m.update(data)
|
||||
return m.hexdigest()
|
||||
|
||||
|
||||
def which(prog):
|
||||
def is_exe(fpath):
|
||||
return os.path.exists(fpath) and os.access(fpath, os.X_OK)
|
||||
|
@ -45,11 +47,13 @@ def which(prog):
|
|||
return filename
|
||||
return None
|
||||
|
||||
|
||||
def version_split(ver):
|
||||
return "%d.%d.%d" % (
|
||||
(((ver) >> 16) & 0xffff),
|
||||
(((ver) >> 8) & 0xff),
|
||||
(((ver) & 0xff)))
|
||||
((ver >> 16) & 0xffff),
|
||||
((ver >> 8) & 0xff),
|
||||
((ver & 0xff)))
|
||||
|
||||
|
||||
def sl(mot):
|
||||
return ((mot & 0x000000FF) << 24) |\
|
||||
|
@ -57,6 +61,7 @@ def sl(mot):
|
|||
((mot & 0x00FF0000) >> 8) |\
|
||||
((mot & 0xFF000000) >> 24)
|
||||
|
||||
|
||||
def format_tooltip(tooltip):
|
||||
if len(tooltip) > 80:
|
||||
lines = tooltip.split(". ")
|
||||
|
@ -67,6 +72,7 @@ def format_tooltip(tooltip):
|
|||
tooltip += "\n"
|
||||
return tooltip
|
||||
|
||||
|
||||
def format_label(label):
|
||||
words = label.split("_")
|
||||
if len(words) > 1:
|
||||
|
@ -75,6 +81,7 @@ def format_label(label):
|
|||
label = label.capitalize()
|
||||
return label
|
||||
|
||||
|
||||
def format_options(param_help):
|
||||
opts = {}
|
||||
if not param_help:
|
||||
|
|
Loading…
Add table
Reference in a new issue