This commit is contained in:
恍兮惚兮 2024-08-04 00:35:44 +08:00
parent b1159f5ede
commit bc908638c7
30 changed files with 621 additions and 202 deletions

View File

@ -16,7 +16,7 @@ from myutils.config import (
globalconfig,
static_data,
)
from myutils.localetools import getgamecamptoolsname, localeswitchedrun
from myutils.localetools import getgamecamptools, localeswitchedrun, maycreatesettings
from myutils.hwnd import getExeIcon
from myutils.wrapper import (
Singleton_close,
@ -66,6 +66,7 @@ from gui.usefulwidget import (
MySwitch,
auto_select_webview,
Prompt_dialog,
clearlayout,
getsimplecombobox,
D_getsimpleswitch,
getspinbox,
@ -751,6 +752,9 @@ class dialog_setting_game_internal(QWidget):
self.methodtab = methodtab
vbox.addWidget(methodtab)
do()
self.__launch_method.currentIndexChanged.emit(
self.__launch_method.currentIndex()
)
def openrefmainpage(self, key, idname, gameuid):
try:
@ -767,7 +771,7 @@ class dialog_setting_game_internal(QWidget):
list(targetmod.keys()),
globalconfig,
"primitivtemetaorigin",
internallist=list(targetmod.keys()),
internal=list(targetmod.keys()),
static=True,
),
)
@ -823,31 +827,29 @@ class dialog_setting_game_internal(QWidget):
layout.addWidget(w)
def starttab(self, formLayout: LFormLayout, gameuid):
box = QGroupBox()
settinglayout = LFormLayout()
box.setLayout(settinglayout)
formLayout.addRow(
"转区启动",
getboxlayout(
[
getsimpleswitch(savehook_new_data[gameuid], "leuse"),
getsimplecombobox(
getgamecamptoolsname(uid2gamepath[gameuid]),
savehook_new_data[gameuid],
"localeswitcher",
static=True,
),
]
),
)
formLayout.addRow(
"命令行启动",
getboxlayout(
[
getsimpleswitch(savehook_new_data[gameuid], "startcmduse"),
getlineedit(savehook_new_data[gameuid], "startcmd"),
]
def __(box, layout, config, uid):
clearlayout(layout)
maycreatesettings(layout, config, uid)
if layout.count() == 0:
box.hide()
else:
box.show()
self.__launch_method = getsimplecombobox(
[_.name for _ in getgamecamptools(uid2gamepath[gameuid])],
savehook_new_data[gameuid],
"launch_method",
internal=[_.id for _ in getgamecamptools(uid2gamepath[gameuid])],
callback=functools.partial(
__, box, settinglayout, savehook_new_data[gameuid]
),
)
formLayout.addRow("启动方式", self.__launch_method)
formLayout.addRow(box)
formLayout.addRow(
"自动切换到模式",
@ -1367,7 +1369,7 @@ class dialog_setting_game_internal(QWidget):
static_data["language_list_translator"],
savehook_new_data[gameuid],
"private_srclang_2",
internallist=static_data["language_list_translator_inner"],
internal=static_data["language_list_translator_inner"],
),
)
formLayout2.addRow(
@ -1376,7 +1378,7 @@ class dialog_setting_game_internal(QWidget):
static_data["language_list_translator"],
savehook_new_data[gameuid],
"private_tgtlang_2",
internallist=static_data["language_list_translator_inner"],
internal=static_data["language_list_translator_inner"],
),
)
@ -1620,47 +1622,7 @@ def startgame(gameuid):
)
gobject.baseobject.starttextsource(use=_[mode], checked=True)
dirpath = os.path.dirname(game)
if savehook_new_data[gameuid]["startcmduse"]:
usearg = savehook_new_data[gameuid]["startcmd"].format(exepath=game)
windows.CreateProcess(
None,
usearg,
None,
None,
False,
0,
None,
dirpath,
windows.STARTUPINFO(),
)
return
if savehook_new_data[gameuid]["leuse"] == False or (
game.lower()[-4:] not in [".lnk", ".exe"]
):
# 对于其他文件需要AssocQueryStringW获取命令行才能正确le太麻烦放弃。
windows.ShellExecute(None, "open", game, "", dirpath, windows.SW_SHOW)
return
execheck3264 = game
usearg = '"{}"'.format(game)
if game.lower()[-4:] == ".lnk":
exepath, args, iconpath, dirp = winsharedutils.GetLnkTargetPath(game)
if args != "":
usearg = '"{}" {}'.format(exepath, args)
elif exepath != "":
usearg = '"{}"'.format(exepath)
if exepath != "":
execheck3264 = exepath
if dirp != "":
dirpath = dirp
localeswitcher = savehook_new_data[gameuid]["localeswitcher"]
localeswitchedrun(execheck3264, localeswitcher, usearg, dirpath)
localeswitchedrun(gameuid)
except:
print_exc()
@ -2085,7 +2047,7 @@ class dialog_savedgame_new(QWidget):
globalconfig,
"currvislistuid",
self.resetcurrvislist,
internallist=uid,
internal=uid,
static=True,
),
)
@ -2398,22 +2360,18 @@ class dialog_savedgame_lagacy(QWidget):
self.model.insertRow(
row,
[
QStandardItem(),
QStandardItem(),
keyitem,
QStandardItem((savehook_new_data[k]["title"])),
],
)
self.table.setIndexWidget(
self.model.index(row, 0), D_getsimpleswitch(savehook_new_data[k], "leuse")
)
self.table.setIndexWidget(
self.model.index(row, 1),
self.model.index(row, 0),
functools.partial(self.delayloadicon, k),
)
self.table.setIndexWidget(
self.model.index(row, 2),
self.model.index(row, 1),
D_getIconButton(
functools.partial(self.showsettingdialog, k), icon="fa.gear"
),
@ -2427,7 +2385,7 @@ class dialog_savedgame_lagacy(QWidget):
formLayout = QVBoxLayout(self) #
model = LStandardItemModel()
model.setHorizontalHeaderLabels(["转区", "", "设置", "游戏"]) # ,'HOOK'])
model.setHorizontalHeaderLabels(["", "设置", "游戏"]) # ,'HOOK'])
self.model = model

View File

@ -163,7 +163,7 @@ class edittrans(LMainWindow):
[globalconfig["fanyi"][x]["name"] for x in globalconfig["fanyi"]],
globalconfig,
"realtime_edit_target",
internallist=list(globalconfig["fanyi"]),
internal=list(globalconfig["fanyi"]),
)
)
qv.addWidget(submit)

View File

@ -13,6 +13,7 @@ from gui.usefulwidget import (
getQMessageBox,
D_getspinbox,
D_getIconButton,
clearlayout,
getboxlayout,
D_getcolorbutton,
getcolorbutton,
@ -89,23 +90,6 @@ class extrahtml(saveposwindow):
self.show()
def clearlayout(ll: QLayout):
while ll.count():
item = ll.takeAt(0)
if not item:
continue
ll.removeItem(item)
w = item.widget()
if w:
w.deleteLater()
continue
l = item.layout()
if l:
clearlayout(l)
l.deleteLater()
continue
def createinternalfontsettings(self, forml: LFormLayout, group, _type):
globalconfig["rendertext_using_internal"][group] = _type
@ -312,7 +296,7 @@ def _createseletengeinecombo(self):
visengine,
globalconfig,
"rendertext_using",
internallist=visengine_internal,
internal=visengine_internal,
callback=functools.partial(resetgroudswitchcallback, self),
static=True,
)

View File

@ -28,7 +28,7 @@ def setTablanglz(self):
static_data["language_list_translator"],
globalconfig,
"srclang4",
internallist=static_data[
internal=static_data[
"language_list_translator_inner"
],
),
@ -39,7 +39,7 @@ def setTablanglz(self):
static_data["language_list_translator"],
globalconfig,
"tgtlang4",
internallist=static_data[
internal=static_data[
"language_list_translator_inner"
],
),
@ -64,7 +64,7 @@ def setTablanglz(self):
"languageuse2",
callback=changelang,
static=True,
internallist=inner,
internal=inner,
),
D_getIconButton(
callback=lambda: os.startfile(

View File

@ -330,7 +330,7 @@ def gethookembedgrid(self):
alltransvis,
globalconfig["embedded"],
"translator_2",
internallist=alltrans,
internal=alltrans,
),
],
[

View File

@ -154,7 +154,7 @@ def setTab5lz(self):
static_data["audioengine_vis"],
globalconfig,
"audioengine",
internallist=static_data["audioengine"],
internal=static_data["audioengine"],
static=True,
),
],

View File

@ -713,8 +713,8 @@ def callbackwrap(d, k, call, _):
print_exc()
def comboboxcallbackwrap(internallist, d, k, call, _):
_ = internallist[_]
def comboboxcallbackwrap(internal, d, k, call, _):
_ = internal[_]
d[k] = _
if call:
@ -724,8 +724,9 @@ def comboboxcallbackwrap(internallist, d, k, call, _):
print_exc()
@tryprint
def getsimplecombobox(
lst, d, k, callback=None, fixedsize=False, internallist=None, static=False
lst, d, k, callback=None, fixedsize=False, internal=None, static=False, emit=False
):
if static:
s = FocusCombo()
@ -734,30 +735,29 @@ def getsimplecombobox(
s = LFocusCombo()
s.addItems(lst)
if internallist:
if (k not in d) or (d[k] not in internallist):
d[k] = internallist[0]
s.setCurrentIndex(internallist.index(d[k]))
if internal:
if (k not in d) or (d[k] not in internal):
d[k] = internal[0]
s.setCurrentIndex(internal.index(d[k]))
s.currentIndexChanged.connect(
functools.partial(comboboxcallbackwrap, internallist, d, k, callback)
functools.partial(comboboxcallbackwrap, internal, d, k, callback)
)
else:
if (k not in d) or (d[k] >= len(lst)):
d[k] = 0
s.setCurrentIndex(d[k])
s.currentIndexChanged.connect(functools.partial(callbackwrap, d, k, callback))
if fixedsize:
s.setSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed)
return s
def D_getsimplecombobox(
lst, d, k, callback=None, fixedsize=False, internallist=None, static=False
lst, d, k, callback=None, fixedsize=False, internal=None, static=False
):
return lambda: getsimplecombobox(
lst, d, k, callback, fixedsize, internallist, static
)
return lambda: getsimplecombobox(lst, d, k, callback, fixedsize, internal, static)
def getlineedit(d, key, callback=None, readonly=False):
@ -2022,3 +2022,20 @@ class SplitLine(QFrame):
super().__init__(*argc)
self.setStyleSheet("background-color: gray;")
self.setFixedHeight(2)
def clearlayout(ll: QLayout):
while ll.count():
item = ll.takeAt(0)
if not item:
continue
ll.removeItem(item)
w = item.widget()
if w:
w.deleteLater()
continue
l = item.layout()
if l:
clearlayout(l)
l.deleteLater()
continue

View File

@ -119,16 +119,14 @@ def getdefaultsavehook(title=None):
# "private_tgtlang_2": 0,
"follow_default_ankisettings": True,
# "anki_DeckName":str
"localeswitcher": 0,
# "localeswitcher": 0,废弃
"onloadautochangemode2": 0,
"needinserthookcode": [],
"embedablehook": [],
"statistic_playtime": 0,
"statistic_wordcount": 0,
"statistic_wordcount_nodump": 0,
"leuse": True,
"startcmd": '"{exepath}"',
"startcmduse": False,
# "leuse": True, 废弃
"hook": [],
"inserthooktimeout": 1000,
"needinserthookcode": [],
@ -193,38 +191,36 @@ def getdefaultsavehook(title=None):
oldlanguage = ["zh","ja","en","ru","es","ko","fr","cht","vi","tr","pl","uk","it","ar","th","bo","de","sv","nl"]
# fmt: on
_dfsavehook = getdefaultsavehook("")
for uid in savehook_new_data:
for gameconfig in savehook_new_data.values():
if (
("allow_tts_auto_names_v4" not in savehook_new_data[uid])
and ("allow_tts_auto_names" in savehook_new_data[uid])
and len(savehook_new_data[uid]["allow_tts_auto_names"])
("allow_tts_auto_names_v4" not in gameconfig)
and ("allow_tts_auto_names" in gameconfig)
and len(gameconfig["allow_tts_auto_names"])
):
savehook_new_data[uid]["allow_tts_auto_names_v4"] = savehook_new_data[uid][
gameconfig["allow_tts_auto_names_v4"] = gameconfig[
"allow_tts_auto_names"
].split("|")
if ("allow_tts_auto_names_v4" in savehook_new_data[uid]) and (
"tts_skip_regex" not in savehook_new_data[uid]
if ("allow_tts_auto_names_v4" in gameconfig) and (
"tts_skip_regex" not in gameconfig
):
savehook_new_data[uid]["tts_skip_regex"] = []
for name in savehook_new_data[uid]["allow_tts_auto_names_v4"]:
savehook_new_data[uid]["tts_skip_regex"].append(
gameconfig["tts_skip_regex"] = []
for name in gameconfig["allow_tts_auto_names_v4"]:
gameconfig["tts_skip_regex"].append(
{"regex": False, "key": name, "condition": 0}
)
if ("private_srclang" in savehook_new_data[uid]) and (
"private_srclang_2" not in savehook_new_data[uid]
):
savehook_new_data[uid]["private_srclang_2"] = oldlanguage[
savehook_new_data[uid]["private_srclang"]
]
savehook_new_data[uid]["private_tgtlang_2"] = oldlanguage[
savehook_new_data[uid]["private_tgtlang"]
]
if ("private_srclang" in gameconfig) and ("private_srclang_2" not in gameconfig):
gameconfig["private_srclang_2"] = oldlanguage[gameconfig["private_srclang"]]
gameconfig["private_tgtlang_2"] = oldlanguage[gameconfig["private_tgtlang"]]
for __k, __v in _dfsavehook.items():
if __k not in savehook_new_data[uid]:
if __k not in gameconfig:
if isinstance(__v, (list, dict)):
__v = __v.copy()
savehook_new_data[uid][__k] = __v
gameconfig[__k] = __v
if not gameconfig.get("leuse", True):
gameconfig.pop("leuse")
gameconfig["launch_method"] = "direct"
class __uid2gamepath:

View File

@ -1,26 +1,84 @@
import windows, os
import windows, os, winreg, winsharedutils, re
from qtsymbols import *
from myutils.config import savehook_new_data, uid2gamepath
from gui.usefulwidget import (
getlineedit,
getsimplecombobox,
getspinbox,
getsimpleswitch,
getspinbox,
)
from traceback import print_exc
class leXX:
class Launcher:
name = ...
id = ...
@staticmethod
def run(bit, config, usearg, dirpath): ...
def valid(self):
return True
def run(self, gameexe, config): ...
def setting(self, layout, config): ...
class LocaleEmulator(leXX):
name = "Locale Emulator"
class LEbase(Launcher):
@staticmethod
def run(bit, config, usearg, dirpath):
def runX(self, exe, usearg, dirpath, config): ...
def run(self, game, config):
dirpath = os.path.dirname(game)
if game.lower()[-4:] not in [".lnk", ".exe"]:
# 对于其他文件需要AssocQueryStringW获取命令行才能正确le太麻烦放弃。
windows.ShellExecute(None, "open", game, "", dirpath, windows.SW_SHOW)
return
execheck3264 = game
usearg = '"{}"'.format(game)
if game.lower()[-4:] == ".lnk":
exepath, args, iconpath, dirp = winsharedutils.GetLnkTargetPath(game)
if args != "":
usearg = '"{}" {}'.format(exepath, args)
elif exepath != "":
usearg = '"{}"'.format(exepath)
if exepath != "":
execheck3264 = exepath
if dirp != "":
dirpath = dirp
self.runX(execheck3264, usearg, dirpath, config)
class le_internal(LEbase):
name = "内置_Locale Emulator"
id = "le_internal"
default = dict(
LCID=0x11, CodePage=932, RedirectRegistry=False, HookUILanguageAPI=False
)
def loaddf(self, config):
for k, v in self.default.items():
k = "LE_" + k
if k in config:
continue
config[k] = v
def runX(self, exe, usearg, dirpath, config):
shareddllproxy = os.path.abspath("./files/plugins/shareddllproxy32")
def _get(k):
return config.get("LE_" + k, self.default[k])
param = '{ANSICodePage} {OEMCodePage} {LCID} "{dirname}" {RedirectRegistry} {HookUILanguageAPI}'.format(
LCID=0x11,
OEMCodePage=932,
ANSICodePage=932,
LCID=_get("LCID"),
OEMCodePage=_get("CodePage"),
ANSICodePage=_get("CodePage"),
dirname=dirpath,
RedirectRegistry=int(False),
HookUILanguageAPI=int(False),
RedirectRegistry=int(_get("RedirectRegistry")),
HookUILanguageAPI=int(_get("HookUILanguageAPI")),
)
windows.CreateProcess(
None,
@ -34,26 +92,52 @@ class LocaleEmulator(leXX):
windows.STARTUPINFO(),
)
def setting(self, layout, config):
self.loaddf(config)
class NTLEAS(leXX):
name = "Ntleas"
layout.addRow("LCID", getspinbox(0, 0xFFFFF, config, "LE_LCID"))
layout.addRow("CodePage", getspinbox(0, 0xFFFFF, config, "LE_CodePage"))
layout.addRow(
"RedirectRegistry", getsimpleswitch(config, "LE_RedirectRegistry")
)
layout.addRow(
"HookUILanguageAPI", getsimpleswitch(config, "LE_HookUILanguageAPI")
)
@staticmethod
def run(bit, config, usearg, dirpath):
class NTLEAS64(LEbase):
name = "内置_Ntleas"
id = "ntlea_internal"
bit = 6
default = dict(LCID=0x411, CodePage=932, TimeZone=540)
def loaddf(self, config):
for k, v in self.default.items():
k = "NT_" + k
if k in config:
continue
config[k] = v
def runX(self, exe, usearg, dirpath, config):
shareddllproxy = os.path.abspath(
("./files/plugins/shareddllproxy32", "./files/plugins/shareddllproxy64")[
bit == 6
self.bit == 6
]
)
param = '{dwCompOption} {dwCodePage} {dwLCID} {dwTimeZone}'.format(
def _get(k):
return config.get("NT_" + k, self.default[k])
param = "{dwCompOption} {dwCodePage} {dwLCID} {dwTimeZone}".format(
dwCompOption=0,
dwCodePage=932,
dwLCID=0x411,
dwTimeZone=-540,
dwCodePage=_get("CodePage"),
dwLCID=_get("LCID"),
dwTimeZone=-_get("TimeZone"),
)
windows.CreateProcess(
None,
'"{}" {} {} {}'.format(shareddllproxy, "ntleas", param,usearg),
'"{}" {} {} {}'.format(shareddllproxy, "ntleas", param, usearg),
None,
None,
False,
@ -63,19 +147,43 @@ class NTLEAS(leXX):
windows.STARTUPINFO(),
)
def setting(self, layout, config):
self.loaddf(config)
class LocaleRemulator(leXX):
name = "Locale Remulator"
layout.addRow("LCID", getspinbox(0, 0xFFFFF, config, "NT_LCID"))
layout.addRow("CodePage", getspinbox(0, 0xFFFFF, config, "NT_CodePage"))
layout.addRow("TimeZone", getspinbox(0, 0xFFFFF, config, "NT_TimeZone"))
@staticmethod
def run(bit, config, usearg, dirpath):
class NTLEAS32(NTLEAS64):
bit = 3
class lr_internal(LEbase):
name = "内置_Locale Remulator"
id = "lr_internal"
default = dict(LCID=0x411, CodePage=932, TimeZone=540, HookIME=False, HookLCID=True)
def loaddf(self, config):
for k, v in self.default.items():
k = "LR_" + k
if k in config:
continue
config[k] = v
def runX(self, exe, usearg, dirpath, config):
shareddllproxy = os.path.abspath("./files/plugins/shareddllproxy32")
def _get(k):
return config.get("LR_" + k, self.default[k])
param = "{CodePage} {LCID} {Bias} {HookIME} {HookLCID}".format(
LCID=0x0411,
CodePage=932,
Bias=540,
HookIME=0,
HookLCID=1,
LCID=_get("LCID"),
CodePage=_get("CodePage"),
Bias=_get("TimeZone"),
HookIME=int(_get("HookIME")),
HookLCID=int(_get("HookLCID")),
)
windows.CreateProcess(
None,
@ -89,9 +197,307 @@ class LocaleRemulator(leXX):
windows.STARTUPINFO(),
)
def setting(self, layout, config):
self.loaddf(config)
x86tools = [LocaleEmulator, LocaleRemulator, NTLEAS]
x64tools = [LocaleRemulator, NTLEAS]
layout.addRow("LCID", getspinbox(0, 0xFFFFF, config, "LR_LCID"))
layout.addRow("CodePage", getspinbox(0, 0xFFFFF, config, "LR_CodePage"))
layout.addRow("TimeZone", getspinbox(0, 0xFFFFF, config, "LR_TimeZone"))
layout.addRow("HookIME", getsimpleswitch(config, "LR_HookIME"))
layout.addRow("HookLCID", getsimpleswitch(config, "LR_HookLCID"))
class le_installed(LEbase):
name = "Locale Emulator"
id = "le_installed"
def fundleproc(self):
for key in [winreg.HKEY_LOCAL_MACHINE, winreg.HKEY_CURRENT_USER]:
try:
k = winreg.OpenKeyEx(
key,
r"Software\Classes\CLSID\{C52B9871-E5E9-41FD-B84D-C5ACADBEC7AE}\InprocServer32",
0,
winreg.KEY_QUERY_VALUE,
)
LEContextMenuHandler: str = winreg.QueryValueEx(k, "CodeBase")[0]
winreg.CloseKey(k)
if not LEContextMenuHandler.startswith("file:///"):
continue
LEContextMenuHandler = LEContextMenuHandler[8:]
LEProc = os.path.join(
os.path.dirname(LEContextMenuHandler), "LEProc.exe"
)
if not os.path.exists(LEProc):
continue
return LEProc
except:
continue
return None
def valid(self):
return (self.fundleproc() is not None) and (len(self.profiles()[1]) > 0)
def profiles(self, exe=None):
_Names = []
_Guids = []
def parseone(xmlpath):
Names, Guids = [], []
with open(xmlpath, "r", encoding="utf8") as ff:
for Name, Guid in re.findall('Name="(.*?)" Guid="(.*?)"', ff.read()):
Names.append(Name)
Guids.append(Guid)
return Names, Guids
finds = [os.path.join(os.path.dirname(self.fundleproc()), "LEConfig.xml")]
if exe:
finds.append(exe + ".le.config")
for f in finds:
try:
Names, Guids = parseone(f)
_Guids += Guids
_Names += Names
except:
pass
return _Names, _Guids
def runX(self, exe, usearg, dirpath, config):
LEProc = self.fundleproc()
if not LEProc:
return
guids = self.profiles(config["gamepath"])[1]
guid = config.get("leguid", None)
if guid not in guids:
guids = guids[0]
arg = '"{}" -runas {} {}'.format(LEProc, guid, usearg)
windows.CreateProcess(
None,
arg,
None,
None,
False,
0,
None,
dirpath,
windows.STARTUPINFO(),
)
def setting(self, layout, config):
Names, Guids = self.profiles(config["gamepath"])
layout.addRow(
"Profile",
getsimplecombobox(Names, config, "leguid", internal=Guids),
)
class lr_installed(LEbase):
name = "Locale Remulator"
id = "lr_installed"
def fundleproc(self):
try:
k = winreg.OpenKeyEx(
winreg.HKEY_LOCAL_MACHINE,
r"SOFTWARE\Classes\LRSubMenus.LRSubMenuExtension\CLSID",
0,
winreg.KEY_QUERY_VALUE,
)
CLSID: str = winreg.QueryValueEx(k, "")[0]
winreg.CloseKey(k)
k = winreg.OpenKeyEx(
winreg.HKEY_LOCAL_MACHINE,
rf"Software\Classes\CLSID\{CLSID}\InprocServer32",
0,
winreg.KEY_QUERY_VALUE,
)
LRSubMenuExtension: str = winreg.QueryValueEx(k, "CodeBase")[0]
winreg.CloseKey(k)
if not LRSubMenuExtension.startswith("file:///"):
return None
LRSubMenuExtension = LRSubMenuExtension[8:]
LRProc = os.path.join(os.path.dirname(LRSubMenuExtension), "LRProc.exe")
if not os.path.exists(LRProc):
return None
return LRProc
except:
return None
def valid(self):
return (self.fundleproc() is not None) and (len(self.profiles()[1]) > 0)
def profiles(self):
Names, Guids = [], []
try:
with open(
os.path.join(os.path.dirname(self.fundleproc()), "LRConfig.xml"),
"r",
encoding="utf8",
) as ff:
for Name, Guid in re.findall('Name="(.*?)" Guid="(.*?)"', ff.read()):
Names.append(Name)
Guids.append(Guid)
except:
pass
return Names, Guids
def runX(self, exe, usearg, dirpath, config):
LEProc = self.fundleproc()
if not LEProc:
return
guids = self.profiles()[1]
guid = config.get("lrguid", None)
if guid not in guids:
guids = guids[0]
arg = '"{}" {} {}'.format(LEProc, guid, usearg)
windows.CreateProcess(
None,
arg,
None,
None,
False,
0,
None,
dirpath,
windows.STARTUPINFO(),
)
def setting(self, layout, config):
Names, Guids = self.profiles()
layout.addRow(
"Profile",
getsimplecombobox(Names, config, "lrguid", internal=Guids),
)
class ntleas_installed(LEbase):
name = "Ntleas"
id = "ntleas_installed"
bit64 = True
def fundleproc(self):
try:
CLSID = "{9C31DD66-412C-4B28-BD17-1F0BEBE29E8B}"
k = winreg.OpenKeyEx(
winreg.HKEY_LOCAL_MACHINE,
rf"Software\Classes\CLSID\{CLSID}\InprocServer32",
0,
winreg.KEY_QUERY_VALUE,
)
LRSubMenuExtension: str = winreg.QueryValueEx(k, "")[0]
winreg.CloseKey(k)
LRProc = os.path.join(
os.path.dirname(LRSubMenuExtension),
["x86", "x64"][self.bit64],
"ntleas.exe",
)
if not os.path.exists(LRProc):
return None
return LRProc
except:
return None
def valid(self):
return self.fundleproc() is not None
def runX(self, exe, usearg, dirpath, config):
LEProc = self.fundleproc()
if not LEProc:
return
arg = '"{}" {} {}'.format(
LEProc,
usearg,
config.get("ntleasparam", '"C932" "L1041" "FMS PGothic" "P4"'),
)
windows.CreateProcess(
None,
arg,
None,
None,
False,
0,
None,
dirpath,
windows.STARTUPINFO(),
)
def setting(self, layout, config):
if "ntleasparam" not in config:
config["ntleasparam"] = '"C932" "L1041" "FMS PGothic" "P4"'
layout.addRow(
"params",
getlineedit(config, "ntleasparam"),
)
class ntleas_installed32(ntleas_installed):
bit64 = False
class CommandLine(Launcher):
name = "命令行启动"
id = "cmd"
def run(self, gameexe, config):
dirpath = os.path.dirname(gameexe)
usearg = config.get("startcmd", "{exepath}").format(exepath=gameexe)
windows.CreateProcess(
None,
usearg,
None,
None,
False,
0,
None,
dirpath,
windows.STARTUPINFO(),
)
def setting(self, layout, config):
if "startcmd" not in config:
config["startcmd"] = "{exepath}"
layout.addRow(
"命令行启动",
getlineedit(config, "startcmd"),
)
class Direct(Launcher):
name = "直接启动"
id = "direct"
def run(self, gameexe, argsdict):
dirpath = os.path.dirname(gameexe)
windows.ShellExecute(None, "open", gameexe, "", dirpath, windows.SW_SHOW)
x86tools = [
le_internal,
lr_internal,
NTLEAS32,
le_installed,
lr_installed,
ntleas_installed32,
CommandLine,
Direct,
]
x64tools = [lr_internal, NTLEAS64, lr_installed, ntleas_installed, CommandLine, Direct]
def getgamecamptools(gameexe):
@ -100,18 +506,36 @@ def getgamecamptools(gameexe):
_methods = x64tools
else:
_methods = x86tools
return _methods
ms = []
for _ in _methods:
if not _().valid():
continue
ms.append(_)
return ms
def getgamecamptoolsname(gameexe):
return [_.name for _ in getgamecamptools(gameexe)]
def fundlauncher(_id):
for _ in x86tools + x64tools:
if _.id != _id:
continue
return _
return None
def localeswitchedrun(gameexe, idx, usearg, dirpath):
b = windows.GetBinaryType(gameexe)
def localeswitchedrun(gameuid):
config = savehook_new_data[gameuid]
launch_method = config.get("launch_method", None)
gameexe = uid2gamepath[gameuid]
tools = getgamecamptools(gameexe)
if idx < 0 or idx >= len(tools):
idx = 0
ids = [_.id for _ in getgamecamptools(uid2gamepath[gameuid])]
if launch_method not in ids:
index = 0
else:
index = ids.index(launch_method)
tool: Launcher = tools[index]()
tool.run(gameexe, config)
tool = tools[idx]
tool.run(b, 0, usearg, dirpath)
def maycreatesettings(layout, config, launcherid):
launcher = fundlauncher(launcherid)()
launcher.setting(layout, config)

View File

@ -838,5 +838,7 @@
"粘贴": "لصق",
"首尾": "الرأس والذيل",
"包含": "احتواء",
"删除图片文件": "حذف ملف الصورة"
"删除图片文件": "حذف ملف الصورة",
"启动方式": "طريقة البدء",
"直接启动": "بدء التشغيل مباشرة"
}

View File

@ -838,5 +838,7 @@
"粘贴": "粘貼",
"首尾": "首尾",
"包含": "包含",
"删除图片文件": "删除圖片檔案"
"删除图片文件": "删除圖片檔案",
"启动方式": "啟動管道",
"直接启动": "直接啟動"
}

View File

@ -838,5 +838,7 @@
"粘贴": "pasta",
"首尾": "Konec k konci",
"包含": "obsahovat",
"删除图片文件": "Smazat obrázkové soubory"
"删除图片文件": "Smazat obrázkové soubory",
"启动方式": "Metoda spuštění",
"直接启动": "Přímo spustit"
}

View File

@ -838,5 +838,7 @@
"粘贴": "Paste",
"首尾": "Ende zu Ende",
"包含": "enthalten",
"删除图片文件": "Bilddateien löschen"
"删除图片文件": "Bilddateien löschen",
"启动方式": "Startmethode",
"直接启动": "Direkt starten"
}

View File

@ -838,5 +838,7 @@
"粘贴": "paste",
"首尾": "End to end",
"包含": "contain",
"删除图片文件": "Delete image files"
"删除图片文件": "Delete image files",
"启动方式": "Startup method",
"直接启动": "Directly start"
}

View File

@ -838,5 +838,7 @@
"粘贴": "Pegar",
"首尾": "De principio a fin",
"包含": "Contiene",
"删除图片文件": "Eliminar archivos de imagen"
"删除图片文件": "Eliminar archivos de imagen",
"启动方式": "Modo de arranque",
"直接启动": "Arranque directo"
}

View File

@ -838,5 +838,7 @@
"粘贴": "Coller",
"首尾": "Première queue",
"包含": "Contient",
"删除图片文件": "Supprimer un fichier image"
"删除图片文件": "Supprimer un fichier image",
"启动方式": "Mode de démarrage",
"直接启动": "Démarrage direct"
}

View File

@ -838,5 +838,7 @@
"粘贴": "pasta",
"首尾": "Fine a fine",
"包含": "contiene",
"删除图片文件": "Elimina file immagine"
"删除图片文件": "Elimina file immagine",
"启动方式": "Metodo di avvio",
"直接启动": "Avvia direttamente"
}

View File

@ -838,5 +838,7 @@
"粘贴": "貼り付け",
"首尾": "首尾",
"包含": "含める",
"删除图片文件": "画像ファイルを削除"
"删除图片文件": "画像ファイルを削除",
"启动方式": "起動モード",
"直接启动": "ダイレクトスタート"
}

View File

@ -838,5 +838,7 @@
"粘贴": "붙여넣기",
"首尾": "수미",
"包含": "포함",
"删除图片文件": "그림 파일 삭제"
"删除图片文件": "그림 파일 삭제",
"启动方式": "시작 방법",
"直接启动": "직접 시작"
}

View File

@ -838,5 +838,7 @@
"粘贴": "plakken",
"首尾": "End to end",
"包含": "bevatten",
"删除图片文件": "Afbeeldingsbestanden verwijderen"
"删除图片文件": "Afbeeldingsbestanden verwijderen",
"启动方式": "Opstartmethode",
"直接启动": "Direct starten"
}

View File

@ -838,5 +838,7 @@
"粘贴": "pasta",
"首尾": "Koniec do końca",
"包含": "zawierać",
"删除图片文件": "Usuń pliki obrazów"
"删除图片文件": "Usuń pliki obrazów",
"启动方式": "Metoda uruchomienia",
"直接启动": "Bezpośredni start"
}

View File

@ -838,5 +838,7 @@
"粘贴": "colar",
"首尾": "De ponta a ponta",
"包含": "contém",
"删除图片文件": "Apagar os ficheiros de imagem"
"删除图片文件": "Apagar os ficheiros de imagem",
"启动方式": "Método de arranque",
"直接启动": "Iniciar directamente"
}

View File

@ -838,5 +838,7 @@
"粘贴": "Вставить",
"首尾": "Голова и хвост",
"包含": "Включение",
"删除图片文件": "Удалить файл изображения"
"删除图片文件": "Удалить файл изображения",
"启动方式": "Режим запуска",
"直接启动": "Прямой запуск"
}

View File

@ -838,5 +838,7 @@
"粘贴": "klistra",
"首尾": "Slut till slut",
"包含": "innehåller",
"删除图片文件": "Ta bort bildfiler"
"删除图片文件": "Ta bort bildfiler",
"启动方式": "Startmetod",
"直接启动": "Starta direkt"
}

View File

@ -838,5 +838,7 @@
"粘贴": "วางบน",
"首尾": "หัวหาง",
"包含": "ประกอบด้วย",
"删除图片文件": "ลบไฟล์รูปภาพ"
"删除图片文件": "ลบไฟล์รูปภาพ",
"启动方式": "วิธีการเริ่มต้น",
"直接启动": "เริ่มต้นโดยตรง"
}

View File

@ -838,5 +838,7 @@
"粘贴": "Yapıştır",
"首尾": "Sonuna kadar",
"包含": "içerir",
"删除图片文件": "Resim dosyalarını sil"
"删除图片文件": "Resim dosyalarını sil",
"启动方式": "Başlangıç yöntemi",
"直接启动": "Direkten başla"
}

View File

@ -838,5 +838,7 @@
"粘贴": "вставити",
"首尾": "Кінець до кінця",
"包含": "містити",
"删除图片文件": "Вилучити файли зображення"
"删除图片文件": "Вилучити файли зображення",
"启动方式": "Метод запуску",
"直接启动": "Прямо запустити"
}

View File

@ -838,5 +838,7 @@
"粘贴": "Dán",
"首尾": "Trang chủ",
"包含": "Bao gồm",
"删除图片文件": "Xoá tập tin ảnh"
"删除图片文件": "Xoá tập tin ảnh",
"启动方式": "Cách bắt đầu",
"直接启动": "Khởi động trực tiếp"
}

View File

@ -838,5 +838,7 @@
"粘贴": "",
"首尾": "",
"包含": "",
"删除图片文件": ""
"删除图片文件": "",
"启动方式": "",
"直接启动": ""
}

View File

@ -28,8 +28,8 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/version)
include(generate_product_version)
set(VERSION_MAJOR 5)
set(VERSION_MINOR 20)
set(VERSION_PATCH 1)
set(VERSION_MINOR 21)
set(VERSION_PATCH 0)
add_library(pch pch.cpp)
target_precompile_headers(pch PUBLIC pch.h)