diff --git a/LunaTranslator/LunaTranslator/gui/dialog_savedgame.py b/LunaTranslator/LunaTranslator/gui/dialog_savedgame.py index 2bf828bf..507ed0b2 100644 --- a/LunaTranslator/LunaTranslator/gui/dialog_savedgame.py +++ b/LunaTranslator/LunaTranslator/gui/dialog_savedgame.py @@ -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 diff --git a/LunaTranslator/LunaTranslator/gui/edittext.py b/LunaTranslator/LunaTranslator/gui/edittext.py index 4bd38718..95f4978e 100644 --- a/LunaTranslator/LunaTranslator/gui/edittext.py +++ b/LunaTranslator/LunaTranslator/gui/edittext.py @@ -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) diff --git a/LunaTranslator/LunaTranslator/gui/setting_display_text.py b/LunaTranslator/LunaTranslator/gui/setting_display_text.py index 2002dcb1..27905c9e 100644 --- a/LunaTranslator/LunaTranslator/gui/setting_display_text.py +++ b/LunaTranslator/LunaTranslator/gui/setting_display_text.py @@ -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, ) diff --git a/LunaTranslator/LunaTranslator/gui/setting_lang.py b/LunaTranslator/LunaTranslator/gui/setting_lang.py index cb604827..2d9661dc 100644 --- a/LunaTranslator/LunaTranslator/gui/setting_lang.py +++ b/LunaTranslator/LunaTranslator/gui/setting_lang.py @@ -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( diff --git a/LunaTranslator/LunaTranslator/gui/setting_textinput.py b/LunaTranslator/LunaTranslator/gui/setting_textinput.py index 83c0bc51..8c34a003 100644 --- a/LunaTranslator/LunaTranslator/gui/setting_textinput.py +++ b/LunaTranslator/LunaTranslator/gui/setting_textinput.py @@ -330,7 +330,7 @@ def gethookembedgrid(self): alltransvis, globalconfig["embedded"], "translator_2", - internallist=alltrans, + internal=alltrans, ), ], [ diff --git a/LunaTranslator/LunaTranslator/gui/setting_tts.py b/LunaTranslator/LunaTranslator/gui/setting_tts.py index 42eb8f75..dd37f1e4 100644 --- a/LunaTranslator/LunaTranslator/gui/setting_tts.py +++ b/LunaTranslator/LunaTranslator/gui/setting_tts.py @@ -154,7 +154,7 @@ def setTab5lz(self): static_data["audioengine_vis"], globalconfig, "audioengine", - internallist=static_data["audioengine"], + internal=static_data["audioengine"], static=True, ), ], diff --git a/LunaTranslator/LunaTranslator/gui/usefulwidget.py b/LunaTranslator/LunaTranslator/gui/usefulwidget.py index 89beeebb..7c786eba 100644 --- a/LunaTranslator/LunaTranslator/gui/usefulwidget.py +++ b/LunaTranslator/LunaTranslator/gui/usefulwidget.py @@ -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 diff --git a/LunaTranslator/LunaTranslator/myutils/config.py b/LunaTranslator/LunaTranslator/myutils/config.py index e07c0694..7da6958d 100644 --- a/LunaTranslator/LunaTranslator/myutils/config.py +++ b/LunaTranslator/LunaTranslator/myutils/config.py @@ -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: diff --git a/LunaTranslator/LunaTranslator/myutils/localetools.py b/LunaTranslator/LunaTranslator/myutils/localetools.py index 066a9ca6..3d658959 100644 --- a/LunaTranslator/LunaTranslator/myutils/localetools.py +++ b/LunaTranslator/LunaTranslator/myutils/localetools.py @@ -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) diff --git a/LunaTranslator/files/lang/ar.json b/LunaTranslator/files/lang/ar.json index 0d84493a..5335e21c 100644 --- a/LunaTranslator/files/lang/ar.json +++ b/LunaTranslator/files/lang/ar.json @@ -838,5 +838,7 @@ "粘贴": "لصق", "首尾": "الرأس والذيل", "包含": "احتواء", - "删除图片文件": "حذف ملف الصورة" + "删除图片文件": "حذف ملف الصورة", + "启动方式": "طريقة البدء", + "直接启动": "بدء التشغيل مباشرة" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/cht.json b/LunaTranslator/files/lang/cht.json index 754f0455..9ccb847e 100644 --- a/LunaTranslator/files/lang/cht.json +++ b/LunaTranslator/files/lang/cht.json @@ -838,5 +838,7 @@ "粘贴": "粘貼", "首尾": "首尾", "包含": "包含", - "删除图片文件": "删除圖片檔案" + "删除图片文件": "删除圖片檔案", + "启动方式": "啟動管道", + "直接启动": "直接啟動" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/cs.json b/LunaTranslator/files/lang/cs.json index d9a5e89a..32bc86b1 100644 --- a/LunaTranslator/files/lang/cs.json +++ b/LunaTranslator/files/lang/cs.json @@ -838,5 +838,7 @@ "粘贴": "pasta", "首尾": "Konec k konci", "包含": "obsahovat", - "删除图片文件": "Smazat obrázkové soubory" + "删除图片文件": "Smazat obrázkové soubory", + "启动方式": "Metoda spuštění", + "直接启动": "Přímo spustit" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/de.json b/LunaTranslator/files/lang/de.json index edcbf57a..6ebbae94 100644 --- a/LunaTranslator/files/lang/de.json +++ b/LunaTranslator/files/lang/de.json @@ -838,5 +838,7 @@ "粘贴": "Paste", "首尾": "Ende zu Ende", "包含": "enthalten", - "删除图片文件": "Bilddateien löschen" + "删除图片文件": "Bilddateien löschen", + "启动方式": "Startmethode", + "直接启动": "Direkt starten" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/en.json b/LunaTranslator/files/lang/en.json index 096c3914..f36e21d6 100644 --- a/LunaTranslator/files/lang/en.json +++ b/LunaTranslator/files/lang/en.json @@ -838,5 +838,7 @@ "粘贴": "paste", "首尾": "End to end", "包含": "contain", - "删除图片文件": "Delete image files" + "删除图片文件": "Delete image files", + "启动方式": "Startup method", + "直接启动": "Directly start" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/es.json b/LunaTranslator/files/lang/es.json index da8953bb..84d9fb33 100644 --- a/LunaTranslator/files/lang/es.json +++ b/LunaTranslator/files/lang/es.json @@ -838,5 +838,7 @@ "粘贴": "Pegar", "首尾": "De principio a fin", "包含": "Contiene", - "删除图片文件": "Eliminar archivos de imagen" + "删除图片文件": "Eliminar archivos de imagen", + "启动方式": "Modo de arranque", + "直接启动": "Arranque directo" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/fr.json b/LunaTranslator/files/lang/fr.json index f381901b..3552810d 100644 --- a/LunaTranslator/files/lang/fr.json +++ b/LunaTranslator/files/lang/fr.json @@ -838,5 +838,7 @@ "粘贴": "Coller", "首尾": "Première queue", "包含": "Contient", - "删除图片文件": "Supprimer un fichier image" + "删除图片文件": "Supprimer un fichier image", + "启动方式": "Mode de démarrage", + "直接启动": "Démarrage direct" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/it.json b/LunaTranslator/files/lang/it.json index de662446..f9f2fef0 100644 --- a/LunaTranslator/files/lang/it.json +++ b/LunaTranslator/files/lang/it.json @@ -838,5 +838,7 @@ "粘贴": "pasta", "首尾": "Fine a fine", "包含": "contiene", - "删除图片文件": "Elimina file immagine" + "删除图片文件": "Elimina file immagine", + "启动方式": "Metodo di avvio", + "直接启动": "Avvia direttamente" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/ja.json b/LunaTranslator/files/lang/ja.json index 99fe4042..c4bc1bb2 100644 --- a/LunaTranslator/files/lang/ja.json +++ b/LunaTranslator/files/lang/ja.json @@ -838,5 +838,7 @@ "粘贴": "貼り付け", "首尾": "首尾", "包含": "含める", - "删除图片文件": "画像ファイルを削除" + "删除图片文件": "画像ファイルを削除", + "启动方式": "起動モード", + "直接启动": "ダイレクトスタート" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/ko.json b/LunaTranslator/files/lang/ko.json index a70484d0..f4d57c78 100644 --- a/LunaTranslator/files/lang/ko.json +++ b/LunaTranslator/files/lang/ko.json @@ -838,5 +838,7 @@ "粘贴": "붙여넣기", "首尾": "수미", "包含": "포함", - "删除图片文件": "그림 파일 삭제" + "删除图片文件": "그림 파일 삭제", + "启动方式": "시작 방법", + "直接启动": "직접 시작" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/nl.json b/LunaTranslator/files/lang/nl.json index e5343626..fb9ece75 100644 --- a/LunaTranslator/files/lang/nl.json +++ b/LunaTranslator/files/lang/nl.json @@ -838,5 +838,7 @@ "粘贴": "plakken", "首尾": "End to end", "包含": "bevatten", - "删除图片文件": "Afbeeldingsbestanden verwijderen" + "删除图片文件": "Afbeeldingsbestanden verwijderen", + "启动方式": "Opstartmethode", + "直接启动": "Direct starten" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/pl.json b/LunaTranslator/files/lang/pl.json index a749de31..58dd4f0e 100644 --- a/LunaTranslator/files/lang/pl.json +++ b/LunaTranslator/files/lang/pl.json @@ -838,5 +838,7 @@ "粘贴": "pasta", "首尾": "Koniec do końca", "包含": "zawierać", - "删除图片文件": "Usuń pliki obrazów" + "删除图片文件": "Usuń pliki obrazów", + "启动方式": "Metoda uruchomienia", + "直接启动": "Bezpośredni start" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/pt.json b/LunaTranslator/files/lang/pt.json index 8ee85310..a7070baa 100644 --- a/LunaTranslator/files/lang/pt.json +++ b/LunaTranslator/files/lang/pt.json @@ -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" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/ru.json b/LunaTranslator/files/lang/ru.json index 78992697..4215e22e 100644 --- a/LunaTranslator/files/lang/ru.json +++ b/LunaTranslator/files/lang/ru.json @@ -838,5 +838,7 @@ "粘贴": "Вставить", "首尾": "Голова и хвост", "包含": "Включение", - "删除图片文件": "Удалить файл изображения" + "删除图片文件": "Удалить файл изображения", + "启动方式": "Режим запуска", + "直接启动": "Прямой запуск" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/sv.json b/LunaTranslator/files/lang/sv.json index e7bfbe28..53038f2e 100644 --- a/LunaTranslator/files/lang/sv.json +++ b/LunaTranslator/files/lang/sv.json @@ -838,5 +838,7 @@ "粘贴": "klistra", "首尾": "Slut till slut", "包含": "innehåller", - "删除图片文件": "Ta bort bildfiler" + "删除图片文件": "Ta bort bildfiler", + "启动方式": "Startmetod", + "直接启动": "Starta direkt" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/th.json b/LunaTranslator/files/lang/th.json index 5dc2eda5..356ee16d 100644 --- a/LunaTranslator/files/lang/th.json +++ b/LunaTranslator/files/lang/th.json @@ -838,5 +838,7 @@ "粘贴": "วางบน", "首尾": "หัวหาง", "包含": "ประกอบด้วย", - "删除图片文件": "ลบไฟล์รูปภาพ" + "删除图片文件": "ลบไฟล์รูปภาพ", + "启动方式": "วิธีการเริ่มต้น", + "直接启动": "เริ่มต้นโดยตรง" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/tr.json b/LunaTranslator/files/lang/tr.json index 5b77c9dc..a4afaa41 100644 --- a/LunaTranslator/files/lang/tr.json +++ b/LunaTranslator/files/lang/tr.json @@ -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" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/uk.json b/LunaTranslator/files/lang/uk.json index 56e3f12a..43d4861d 100644 --- a/LunaTranslator/files/lang/uk.json +++ b/LunaTranslator/files/lang/uk.json @@ -838,5 +838,7 @@ "粘贴": "вставити", "首尾": "Кінець до кінця", "包含": "містити", - "删除图片文件": "Вилучити файли зображення" + "删除图片文件": "Вилучити файли зображення", + "启动方式": "Метод запуску", + "直接启动": "Прямо запустити" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/vi.json b/LunaTranslator/files/lang/vi.json index 84b0c7c2..024e9a15 100644 --- a/LunaTranslator/files/lang/vi.json +++ b/LunaTranslator/files/lang/vi.json @@ -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" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/zh.json b/LunaTranslator/files/lang/zh.json index 3874975d..e36c84ed 100644 --- a/LunaTranslator/files/lang/zh.json +++ b/LunaTranslator/files/lang/zh.json @@ -838,5 +838,7 @@ "粘贴": "", "首尾": "", "包含": "", - "删除图片文件": "" + "删除图片文件": "", + "启动方式": "", + "直接启动": "" } \ No newline at end of file diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 7eb037c4..a9a167ec 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -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)