diff --git a/LunaTranslator/LunaTranslator/LunaTranslator.py b/LunaTranslator/LunaTranslator/LunaTranslator.py index bc7c7bc9..8afb4e6e 100644 --- a/LunaTranslator/LunaTranslator/LunaTranslator.py +++ b/LunaTranslator/LunaTranslator/LunaTranslator.py @@ -6,6 +6,8 @@ from myutils.config import ( globalconfig, _TR, savehook_new_list, + uid2gamepath, + gamepath2uid, savehook_new_data, setlanguage, static_data, @@ -407,7 +409,9 @@ class MAINUI: try: time.sleep(globalconfig["textthreaddelay"] / 1000) name = self.textsource.currentname - names = savehook_new_data[self.textsource.pname]["allow_tts_auto_names_v4"] + names = savehook_new_data[self.textsource.gameuid][ + "allow_tts_auto_names_v4" + ] needpass = False if name in names: needpass = True @@ -438,7 +442,7 @@ class MAINUI: text = self.ttsrepair(self.currentread, globalconfig["ttscommon"]) try: text = self.ttsrepair( - text, savehook_new_data[self.textsource.pname] + text, savehook_new_data[self.textsource.gameuid] ) except: pass @@ -476,7 +480,8 @@ class MAINUI: pids, pexe, hwnd = selectedp checkifnewgame(savehook_new_list, pexe, windows.GetWindowText(hwnd)) if globalconfig["sourcestatus2"]["texthook"]["use"]: - self.textsource = texthook(pids, hwnd, pexe) + self.textsource = texthook(pids, hwnd, pexe, gamepath2uid[pexe]) + self.textsource.start() def starttextsource(self, use=None, checked=True): self.translation_ui.showhidestate = False @@ -683,7 +688,11 @@ class MAINUI: hwnd = windows.GetForegroundWindow() pid = windows.GetWindowThreadProcessId(hwnd) name_ = getpidexe(pid) - if name_ and name_ in savehook_new_list: + if ( + name_ + and name_ in gamepath2uid + and gamepath2uid[name_] in savehook_new_list + ): lps = ListProcess(False) for pids, _exe in lps: if _exe == name_: @@ -692,23 +701,26 @@ class MAINUI: self.textsource = None if globalconfig["sourcestatus2"]["texthook"]["use"]: if globalconfig["startgamenototop"] == False: - idx = savehook_new_list.index(name_) + idx = savehook_new_list.index( + gamepath2uid[name_] + ) savehook_new_list.insert( 0, savehook_new_list.pop(idx) ) - needinserthookcode = savehook_new_data[name_][ - "needinserthookcode" - ] + needinserthookcode = savehook_new_data[ + gamepath2uid[name_] + ]["needinserthookcode"] self.textsource = texthook( pids, hwnd, name_, - autostarthookcode=savehook_new_data[name_][ - "hook" - ], + gamepath2uid[name_], + autostarthookcode=savehook_new_data[ + gamepath2uid[name_] + ]["hook"], needinserthookcode=needinserthookcode, ) - + self.textsource.start() else: pids = self.textsource.pids if sum([int(pid_running(pid)) for pid in pids]) == 0: @@ -778,9 +790,10 @@ class MAINUI: ) def createsavegamedb(self): - os.makedirs("userconfig", exist_ok=True) self.sqlsavegameinfo = sqlite3.connect( - "userconfig/savegame.db", check_same_thread=False, isolation_level=None + gobject.getuserconfigdir("savegame.db"), + check_same_thread=False, + isolation_level=None, ) try: self.sqlsavegameinfo.execute( @@ -843,21 +856,22 @@ class MAINUI: savehook_new_data[k].pop("imagepath") savehook_new_data[k].pop("imagepath_much2") - def querytraceplaytime_v4(self, k): - gameinternalid = self.get_gameinternalid(k) + def querytraceplaytime_v4(self, gameuid): + gameinternalid = self.get_gameinternalid(uid2gamepath[gameuid]) return self.sqlsavegameinfo.execute( "SELECT timestart,timestop FROM traceplaytime_v4 WHERE gameinternalid = ?", (gameinternalid,), ).fetchall() - def get_gameinternalid(self, k): + def get_gameinternalid(self, gamepath): while True: ret = self.sqlsavegameinfo.execute( - "SELECT gameinternalid FROM gameinternalid WHERE gamepath = ?", (k,) + "SELECT gameinternalid FROM gameinternalid WHERE gamepath = ?", + (gamepath,), ).fetchone() if ret is None: self.sqlsavegameinfo.execute( - "INSERT INTO gameinternalid VALUES(NULL,?)", (k,) + "INSERT INTO gameinternalid VALUES(NULL,?)", (gamepath,) ) else: return ret[0] @@ -869,9 +883,9 @@ class MAINUI: (to, _id), ) - def traceplaytime(self, k, start, end, new): + def traceplaytime(self, gamepath, start, end, new): - gameinternalid = self.get_gameinternalid(k) + gameinternalid = self.get_gameinternalid(gamepath) if new: self.sqlsavegameinfo.execute( "INSERT INTO traceplaytime_v4 VALUES(NULL,?,?,?)", @@ -891,16 +905,21 @@ class MAINUI: time.sleep(1) _t = time.time() - def isok(name_): - savehook_new_data[name_]["statistic_playtime"] += _t - __t + def isok(gameuid): + savehook_new_data[gameuid]["statistic_playtime"] += _t - __t if self.__currentexe == name_: - self.traceplaytime(name_, self.__statistictime - 1, _t, False) + self.traceplaytime( + uid2gamepath[gameuid], self.__statistictime - 1, _t, False + ) else: self.__statistictime = time.time() self.__currentexe = name_ self.traceplaytime( - name_, self.__statistictime - 1, self.__statistictime, True + uid2gamepath[gameuid], + self.__statistictime - 1, + self.__statistictime, + True, ) try: @@ -911,13 +930,17 @@ class MAINUI: if len(self.textsource.pids) == 0: raise Exception() if _pid in self.textsource.pids or _pid == os.getpid(): - isok(self.textsource.pname) + isok(self.textsource.gameuid) else: self.__currentexe = None except: name_ = getpidexe(_pid) - if name_ and name_ in savehook_new_list: - isok(name_) + if ( + name_ + and name_ in gamepath2uid + and gamepath2uid[name_] in savehook_new_list + ): + isok(gamepath2uid[name_]) else: self.__currentexe = None except: diff --git a/LunaTranslator/LunaTranslator/cishu/goo.py b/LunaTranslator/LunaTranslator/cishu/goo.py index 65c38a5d..ed217088 100644 --- a/LunaTranslator/LunaTranslator/cishu/goo.py +++ b/LunaTranslator/LunaTranslator/cishu/goo.py @@ -1,6 +1,6 @@ import requests from urllib.parse import quote -import re, os +import re, os, gobject from cishu.cishubase import cishubase @@ -12,15 +12,15 @@ class goo(cishubase): xx = re.findall("
([\\s\\S]*?)
", x) xx = "".join(xx).replace('href="/', 'href="https://dictionary.goo.ne.jp/') - if os.path.exists("cache/temp/goo.css") == False: + temp = gobject.gettempdir("goo.css") + if os.path.exists(temp) == False: stl = requests.get( "https://dictionary.goo.ne.jp/mix/css/app.css", proxies=self.proxy ).text - os.makedirs("cache/temp", exist_ok=True) - with open("cache/temp/goo.css", "w", encoding="utf8") as ff: + with open(temp, "w", encoding="utf8") as ff: ff.write(stl) else: - with open("cache/temp/goo.css", "r", encoding="utf8") as ff: + with open(temp, "r", encoding="utf8") as ff: stl = ff.read() if len(xx): diff --git a/LunaTranslator/LunaTranslator/cishu/mdict.py b/LunaTranslator/LunaTranslator/cishu/mdict.py index 1c626eb4..295bbcd4 100644 --- a/LunaTranslator/LunaTranslator/cishu/mdict.py +++ b/LunaTranslator/LunaTranslator/cishu/mdict.py @@ -1,4 +1,4 @@ -import math, base64, uuid +import math, base64, uuid, gobject import threading, time @@ -341,270 +341,12 @@ def rol(s, x): return (x << s | x >> (32 - s)) & 0xFFFFFFFF -r = [ - 0, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 7, - 4, - 13, - 1, - 10, - 6, - 15, - 3, - 12, - 0, - 9, - 5, - 2, - 14, - 11, - 8, - 3, - 10, - 14, - 4, - 9, - 15, - 8, - 1, - 2, - 7, - 0, - 6, - 13, - 11, - 5, - 12, - 1, - 9, - 11, - 10, - 0, - 8, - 12, - 4, - 13, - 3, - 7, - 15, - 14, - 5, - 6, - 2, -] -rp = [ - 5, - 14, - 7, - 0, - 9, - 2, - 11, - 4, - 13, - 6, - 15, - 8, - 1, - 10, - 3, - 12, - 6, - 11, - 3, - 7, - 0, - 13, - 5, - 10, - 14, - 15, - 8, - 12, - 4, - 9, - 1, - 2, - 15, - 5, - 1, - 3, - 7, - 14, - 6, - 9, - 11, - 8, - 12, - 2, - 10, - 0, - 4, - 13, - 8, - 6, - 4, - 1, - 3, - 11, - 15, - 0, - 5, - 12, - 2, - 13, - 9, - 7, - 10, - 14, -] -s = [ - 11, - 14, - 15, - 12, - 5, - 8, - 7, - 9, - 11, - 13, - 14, - 15, - 6, - 7, - 9, - 8, - 7, - 6, - 8, - 13, - 11, - 9, - 7, - 15, - 7, - 12, - 15, - 9, - 11, - 7, - 13, - 12, - 11, - 13, - 6, - 7, - 14, - 9, - 13, - 15, - 14, - 8, - 13, - 6, - 5, - 12, - 7, - 5, - 11, - 12, - 14, - 15, - 14, - 15, - 9, - 8, - 9, - 14, - 5, - 6, - 8, - 6, - 5, - 12, -] -sp = [ - 8, - 9, - 9, - 11, - 13, - 15, - 15, - 5, - 7, - 7, - 8, - 11, - 14, - 14, - 12, - 6, - 9, - 13, - 15, - 7, - 12, - 8, - 9, - 11, - 7, - 7, - 12, - 7, - 6, - 15, - 13, - 11, - 9, - 7, - 15, - 11, - 8, - 6, - 6, - 14, - 12, - 13, - 5, - 14, - 13, - 13, - 7, - 5, - 15, - 5, - 8, - 11, - 14, - 14, - 6, - 14, - 6, - 9, - 12, - 9, - 12, - 5, - 15, - 8, -] +# fmt: off +r = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2] +rp = [ 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14] +s = [ 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12] +sp = [ 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8] +# fmt: on def ripemd128(message): @@ -1962,13 +1704,12 @@ class IndexBuilder(object): _filename, _file_extension = os.path.splitext(fname) assert _file_extension == ".mdx" assert os.path.isfile(fname) - os.makedirs("cache/mdict/index", exist_ok=True) _mdxmd5 = ( os.path.basename(_filename) + "_" + hashlib.md5(_filename.encode("utf8")).hexdigest() ) - _targetfilenamebase = os.path.join("cache/mdict/index", _mdxmd5) + _targetfilenamebase = gobject.getcachedir("mdict/index/" + _mdxmd5) self._mdx_db = _targetfilenamebase + ".mdx.db" # make index anyway if force_rebuild: @@ -2363,7 +2104,9 @@ class mdict(cishubase): self.init_once_mdx(f) try: - with open("userconfig/mdict_config.json", "w", encoding="utf8") as ff: + with open( + gobject.getuserconfigdir("mdict_config.json"), "w", encoding="utf8" + ) as ff: ff.write(json.dumps(self.extraconf, ensure_ascii=False, indent=4)) except: pass diff --git a/LunaTranslator/LunaTranslator/gobject.py b/LunaTranslator/LunaTranslator/gobject.py index 44c6e02b..c266f69b 100644 --- a/LunaTranslator/LunaTranslator/gobject.py +++ b/LunaTranslator/LunaTranslator/gobject.py @@ -15,6 +15,30 @@ def GetDllpath(_, base=None): return os.path.join(base, _[isbit64]) +def getcachedir(name, basedir="cache"): + + fd = os.path.dirname(name) + fn = os.path.basename(name) + fn1 = os.path.abspath(basedir) + fn1 = os.path.join(fn1, fd) + os.makedirs(fn1, exist_ok=True) + fn1 = os.path.join(fn1, fn) + return fn1 + + +def getuserconfigdir(name): + return getcachedir(name, "userconfig") + + +def gettranslationrecorddir(name): + return getcachedir(name, "translation_record") + + +def gettempdir(filename): + tgt = getcachedir(os.path.join(f"temp{os.getpid()}", filename)) + return tgt + + def dopathexists(file): if not file: return False diff --git a/LunaTranslator/LunaTranslator/gui/dialog_memory.py b/LunaTranslator/LunaTranslator/gui/dialog_memory.py index 062ee16e..70412f5f 100644 --- a/LunaTranslator/LunaTranslator/gui/dialog_memory.py +++ b/LunaTranslator/LunaTranslator/gui/dialog_memory.py @@ -1,5 +1,5 @@ from qtsymbols import * -import os +import os, gobject from myutils.config import _TR, globalconfig from myutils.wrapper import Singleton_close from gui.usefulwidget import saveposwindow @@ -30,8 +30,7 @@ class dialog_memory(saveposwindow): self.gamemd5 = gamemd5 formLayout = QVBoxLayout() # self.showtext = QTextEdit() - os.makedirs("./userconfig/memory", exist_ok=True) - self.rwpath = "./userconfig/memory/{}.html".format(gamemd5) + self.rwpath = gobject.getuserconfigdir("memory/{}.html".format(gamemd5)) try: with open(self.rwpath, "r", encoding="utf8") as ff: text = ff.read() diff --git a/LunaTranslator/LunaTranslator/gui/dialog_savedgame.py b/LunaTranslator/LunaTranslator/gui/dialog_savedgame.py index cf22cb05..426bd489 100644 --- a/LunaTranslator/LunaTranslator/gui/dialog_savedgame.py +++ b/LunaTranslator/LunaTranslator/gui/dialog_savedgame.py @@ -6,7 +6,9 @@ import windows, gobject, winsharedutils from myutils.config import ( savehook_new_list, savehook_new_data, + gamepath2uid, savegametaged, + uid2gamepath, _TR, _TRL, postprocessconfig, @@ -57,6 +59,7 @@ from gui.usefulwidget import ( tabadd_lazy, getsimpleswitch, threebuttons, + getsimplekeyseq, getspinbox, selectcolor, listediter, @@ -87,7 +90,7 @@ class ItemWidget(QWidget): if self != ItemWidget.globallashfocus: ItemWidget.clearfocus() ItemWidget.globallashfocus = self - self.focuschanged.emit(True, self.exe) + self.focuschanged.emit(True, self.gameuid) except: print_exc() @@ -96,16 +99,16 @@ class ItemWidget(QWidget): def focusOut(self): self.bottommask.setStyleSheet("background-color: rgba(255,255,255, 0);") - self.focuschanged.emit(False, self.exe) + self.focuschanged.emit(False, self.gameuid) def mouseDoubleClickEvent(self, e): - self.doubleclicked.emit(self.exe) + self.doubleclicked.emit(self.gameuid) def resizeEvent(self, a0: QResizeEvent) -> None: self.bottommask.resize(a0.size()) self.maskshowfileexists.resize(a0.size()) - def __init__(self, exe, pixmap, file) -> None: + def __init__(self, gameuid, pixmap, file) -> None: super().__init__() self.itemw = globalconfig["dialog_savegame_layout"]["itemw"] self.itemh = globalconfig["dialog_savegame_layout"]["itemh"] @@ -147,9 +150,11 @@ class ItemWidget(QWidget): self._lb.setAlignment(Qt.AlignmentFlag.AlignHCenter) layout.addWidget(self._lb) self.setLayout(layout) - self.exe = exe + self.gameuid = gameuid c = globalconfig["dialog_savegame_layout"][ - ("onfilenoexistscolor1", "backcolor1")[os.path.exists(exe)] + ("onfilenoexistscolor1", "backcolor1")[ + os.path.exists(uid2gamepath[gameuid]) + ] ] c = str2rgba(c, globalconfig["dialog_savegame_layout"]["transparent"]) self.maskshowfileexists.setStyleSheet(f"background-color:{c};") @@ -387,39 +392,34 @@ class TagWidget(QWidget): class browserdialog(saveposwindow): seturlsignal = pyqtSignal(str) - def parsehtml(self, newpath): - if newpath[:4].lower() != "http": - newpath = os.path.abspath(newpath) - return newpath + def startupsettitle(self, gameuid): - def startupsettitle(self, exepath): - - if exepath: - title = savehook_new_data[exepath]["title"] + if gameuid: + title = savehook_new_data[gameuid]["title"] else: title = "LunaTranslator" self.setWindowTitle(title) - def loadalllinks(self, exepath): + def loadalllinks(self, gameuid): items = [] - if exepath: - self.setWindowTitle(savehook_new_data[exepath]["title"]) + if gameuid: + self.setWindowTitle(savehook_new_data[gameuid]["title"]) for link in globalconfig["relationlinks"]: items.append((link[0], tagitem.TYPE_GLOABL_LIKE, link[1])) - if exepath: - for link in savehook_new_data[self.exepath]["relationlinks"]: + if gameuid: + for link in savehook_new_data[self.gameuid]["relationlinks"]: items.append((link[0], tagitem.TYPE_GAME_LIKE, link[1])) self.tagswidget.clearTag(False) self.tagswidget.addTags(items) - def startupnavi(self, exepath): + def startupnavi(self, gameuid): for idx in range(2, 100): if idx == 2: - if exepath: - if len(savehook_new_data[exepath]["relationlinks"]): - navitarget = savehook_new_data[exepath]["relationlinks"][-1][1] + if gameuid: + if len(savehook_new_data[gameuid]["relationlinks"]): + navitarget = savehook_new_data[gameuid]["relationlinks"][-1][1] break elif idx == 3: if len(globalconfig["relationlinks"]): @@ -452,8 +452,8 @@ class browserdialog(saveposwindow): text = [] for _t in _dia.text: text.append(_t.text()) - if self.exepath: - savehook_new_data[self.exepath]["relationlinks"].append(text) + if self.gameuid: + savehook_new_data[self.gameuid]["relationlinks"].append(text) self.tagswidget.addTag(text[0], tagitem.TYPE_GAME_LIKE, text[1]) else: globalconfig["relationlinks"].append(text) @@ -468,20 +468,20 @@ class browserdialog(saveposwindow): elif _type == tagitem.TYPE_GAME_LIKE: __2.append([_name, _url]) globalconfig["relationlinks"] = __ - if self.exepath: - savehook_new_data[self.exepath]["relationlinks"] = __2 + if self.gameuid: + savehook_new_data[self.gameuid]["relationlinks"] = __2 - def reinit(self, exepath=None): + def reinit(self, gameuid=None): - self.exepath = exepath - self.loadalllinks(exepath) - self.startupnavi(exepath) - self.startupsettitle(exepath) + self.gameuid = gameuid + self.loadalllinks(gameuid) + self.startupnavi(gameuid) + self.startupsettitle(gameuid) - def __init__(self, parent, exepath=None) -> None: + def __init__(self, parent, gameuid=None) -> None: super().__init__(parent, poslist=globalconfig["browserwidget"]) - if exepath: - self.setWindowIcon(getExeIcon(exepath, cache=True)) + if gameuid: + self.setWindowIcon(getExeIcon(uid2gamepath[gameuid], cache=True)) self.browser = auto_select_webview(self) self.tagswidget = TagWidget(self) @@ -513,13 +513,13 @@ class browserdialog(saveposwindow): __w.setLayout(layout) self.setCentralWidget(__w) - self.reinit(exepath) + self.reinit(gameuid) self.show() def urlclicked(self, _): tag, _, url = _ - if url.startswith("./cache/vndb"): - url = self.parsehtml(url) + if url[:4].lower() != "http": + url = os.path.abspath(url) self.browser.navigate(url) def showmenu(self, p): @@ -533,7 +533,7 @@ class browserdialog(saveposwindow): if action == shanchu: self.nettab.setCurrentIndex(0) self.nettab.removeTab(tab_index) - savehook_new_data[self.exepath]["relationlinks"].pop( + savehook_new_data[self.gameuid]["relationlinks"].pop( tab_index - self.hasvndb ) @@ -550,15 +550,15 @@ def calculate_centered_rect(original_rect: QRect, size: QSize) -> QRect: return new_rect -def maybehavebutton(self, game, post): +def maybehavebutton(self, gameuid, post): if post == "_11": - savehook_new_data[game]["save_text_process_info"]["mypost"] = str( + savehook_new_data[gameuid]["save_text_process_info"]["mypost"] = str( uuid.uuid4() ).replace("-", "_") return getIconButton( callback=functools.partial( selectdebugfile, - savehook_new_data[game]["save_text_process_info"]["mypost"], + savehook_new_data[gameuid]["save_text_process_info"]["mypost"], ismypost=True, ), icon="fa.gear", @@ -575,14 +575,14 @@ def maybehavebutton(self, game, post): callback = functools.partial( postconfigdialog, self, - savehook_new_data[game]["save_text_process_info"][ + savehook_new_data[gameuid]["save_text_process_info"][ "postprocessconfig" ][post]["args"], postprocessconfig[post]["name"], ) else: items = autoinitdialog_items( - savehook_new_data[game]["save_text_process_info"][ + savehook_new_data[gameuid]["save_text_process_info"][ "postprocessconfig" ][post] ) @@ -600,32 +600,29 @@ def maybehavebutton(self, game, post): class dialog_setting_game_internal(QWidget): def selectexe(self): - # 修改exe之后不要去动列表,否则会有一致性问题,很难搞,就这样吧。 - f = QFileDialog.getOpenFileName(directory=self.exepath) + f = QFileDialog.getOpenFileName(directory=uid2gamepath[self.gameuid]) res = f[0] if res == "": return - res = os.path.normpath(res) - if res in savehook_new_list: + if res in gamepath2uid: return - _origin = savehook_new_list[savehook_new_list.index(self.exepath)] - savehook_new_list[savehook_new_list.index(self.exepath)] = res - savehook_new_data[res] = savehook_new_data[self.exepath] - gobject.baseobject.resetgameinternal(_origin, res) + originpath = uid2gamepath[self.gameuid] + gamepath2uid[res] = gamepath2uid.pop(originpath) + uid2gamepath[self.gameuid] = res + gobject.baseobject.resetgameinternal(originpath, res) _icon = getExeIcon(res, cache=True) self.setWindowIcon(_icon) self.editpath.setText(res) - self.exepath = res - def __init__(self, parent, exepath) -> None: + def __init__(self, parent, gameuid) -> None: super().__init__(parent) vbox = QVBoxLayout(self) formLayout = QFormLayout() self.setLayout(vbox) - self.exepath = exepath - self.editpath = QLineEdit(exepath) + self.gameuid = gameuid + self.editpath = QLineEdit(uid2gamepath[gameuid]) self.editpath.setReadOnly(True) formLayout.addRow( _TR("路径"), @@ -634,21 +631,23 @@ class dialog_setting_game_internal(QWidget): self.editpath, getIconButton(functools.partial(self.selectexe), icon="fa.gear"), getIconButton( - lambda: browserdialog(gobject.baseobject.commonstylebase, exepath), + lambda: browserdialog( + gobject.baseobject.commonstylebase, gameuid + ), icon="fa.book", ), ] ), ) - titleedit = QLineEdit(savehook_new_data[exepath]["title"]) + titleedit = QLineEdit(savehook_new_data[gameuid]["title"]) def _titlechange(): x = titleedit.text() - titlechangedtask(exepath, x) + titlechangedtask(gameuid, x) self.setWindowTitle(x) titleedit.textEdited.connect( - functools.partial(savehook_new_data[exepath].__setitem__, "title") + functools.partial(savehook_new_data[gameuid].__setitem__, "title") ) titleedit.returnPressed.connect(_titlechange) @@ -661,31 +660,21 @@ class dialog_setting_game_internal(QWidget): ] ), ) + functs = [ + ("启动", self.starttab), + ("HOOK", self.gethooktab), + ("语言", self.getlangtab), + ("文本处理", self.gettextproc), + ("标签", self.getlabelsetting), + ("元数据", self.metadataorigin), + ("统计", self.getstatistic), + ("语音", self.getttssetting), + ("预翻译", self.getpretranstab), + ("Anki", self.maketabforanki), + ] methodtab, do = makesubtab_lazy( - _TRL( - [ - "启动", - "HOOK", - "语言", - "文本处理", - "标签", - "元数据", - "统计", - "语音", - "预翻译", - ] - ), - [ - functools.partial(self.doaddtab, self.starttab, exepath), - functools.partial(self.doaddtab, self.gethooktab, exepath), - functools.partial(self.doaddtab, self.getlangtab, exepath), - functools.partial(self.doaddtab, self.gettextproc, exepath), - functools.partial(self.doaddtab, self.getlabelsetting, exepath), - functools.partial(self.doaddtab, self.metadataorigin, exepath), - functools.partial(self.doaddtab, self.getstatistic, exepath), - functools.partial(self.doaddtab, self.getttssetting, exepath), - functools.partial(self.doaddtab, self.getpretranstab, exepath), - ], + _TRL([_[0] for _ in functs]), + [functools.partial(self.doaddtab, _[1], gameuid) for _ in functs], delay=True, ) self.methodtab = methodtab @@ -693,13 +682,13 @@ class dialog_setting_game_internal(QWidget): vbox.addWidget(methodtab) do() - def openrefmainpage(self, key, idname, exepath): + def openrefmainpage(self, key, idname, gameuid): try: - os.startfile(targetmod[key].refmainpage(savehook_new_data[exepath][idname])) + os.startfile(targetmod[key].refmainpage(savehook_new_data[gameuid][idname])) except: print_exc() - def metadataorigin(self, exepath): + def metadataorigin(self, gameuid): formLayout = QFormLayout() _w = QWidget() _w.setLayout(formLayout) @@ -714,24 +703,24 @@ class dialog_setting_game_internal(QWidget): ) for key in globalconfig["metadata"]: idname = globalconfig["metadata"][key]["target"] - vndbid = QLineEdit(str(savehook_new_data[exepath][idname])) + vndbid = QLineEdit(str(savehook_new_data[gameuid][idname])) if globalconfig["metadata"][key]["idtype"] == 0: vndbid.setValidator(QIntValidator()) vndbid.setSizePolicy(QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Fixed) vndbid.textEdited.connect( - functools.partial(savehook_new_data[exepath].__setitem__, idname) + functools.partial(savehook_new_data[gameuid].__setitem__, idname) ) vndbid.returnPressed.connect( - functools.partial(gamdidchangedtask, key, idname, exepath) + functools.partial(gamdidchangedtask, key, idname, gameuid) ) _vbox_internal = [ vndbid, getIconButton( - functools.partial(self.openrefmainpage, key, idname, exepath), + functools.partial(self.openrefmainpage, key, idname, gameuid), icon="fa.chrome", ), getIconButton( - functools.partial(gamdidchangedtask, key, idname, exepath), + functools.partial(gamdidchangedtask, key, idname, gameuid), icon="fa.search", ), ] @@ -754,26 +743,26 @@ class dialog_setting_game_internal(QWidget): w = wfunct(exe) layout.addWidget(w) - def starttab(self, exepath): + def starttab(self, gameuid): _w = QWidget() formLayout = QFormLayout() _w.setLayout(formLayout) - b = windows.GetBinaryType(exepath) + b = windows.GetBinaryType(uid2gamepath[gameuid]) if b == 6: _methods = ["", "Locale_Remulator", "Ntleas"] else: _methods = ["Locale-Emulator", "Locale_Remulator", "Ntleas"] - if b == 6 and savehook_new_data[exepath]["localeswitcher"] == 0: - savehook_new_data[exepath]["localeswitcher"] = 1 + if b == 6 and savehook_new_data[gameuid]["localeswitcher"] == 0: + savehook_new_data[gameuid]["localeswitcher"] = 1 formLayout.addRow( _TR("转区启动"), getboxlayout( [ - getsimpleswitch(savehook_new_data[exepath], "leuse"), + getsimpleswitch(savehook_new_data[gameuid], "leuse"), getsimplecombobox( - _TRL(_methods), savehook_new_data[exepath], "localeswitcher" + _TRL(_methods), savehook_new_data[gameuid], "localeswitcher" ), ] ), @@ -783,8 +772,8 @@ class dialog_setting_game_internal(QWidget): _TR("命令行启动"), getboxlayout( [ - getsimpleswitch(savehook_new_data[exepath], "startcmduse"), - getlineedit(savehook_new_data[exepath], "startcmd"), + getsimpleswitch(savehook_new_data[gameuid], "startcmduse"), + getlineedit(savehook_new_data[gameuid], "startcmd"), ] ), ) @@ -793,13 +782,13 @@ class dialog_setting_game_internal(QWidget): _TR("自动切换到模式"), getsimplecombobox( _TRL(["不切换", "HOOK", "剪贴板", "OCR"]), - savehook_new_data[exepath], + savehook_new_data[gameuid], "onloadautochangemode2", ), ) return _w - def getstatistic(self, exepath): + def getstatistic(self, gameuid): _w = QWidget() formLayout = QVBoxLayout() @@ -867,12 +856,12 @@ class dialog_setting_game_internal(QWidget): return lists def refresh(self): - __ = gobject.baseobject.querytraceplaytime_v4(self.exepath) + __ = gobject.baseobject.querytraceplaytime_v4(self.gameuid) _cnt = sum([_[1] - _[0] for _ in __]) - savehook_new_data[self.exepath]["statistic_playtime"] = _cnt + savehook_new_data[self.gameuid]["statistic_playtime"] = _cnt self._timelabel.setText(self.formattime(_cnt)) self._wordlabel.setText( - str(savehook_new_data[self.exepath]["statistic_wordcount"]) + str(savehook_new_data[self.gameuid]["statistic_wordcount"]) ) self.chart.setdata(self.split_range_into_days(__)) @@ -897,7 +886,7 @@ class dialog_setting_game_internal(QWidget): string = "0" return string - def getlabelsetting(self, exepath): + def getlabelsetting(self, gameuid): _w = QWidget() formLayout = QVBoxLayout() _w.setLayout(formLayout) @@ -910,9 +899,9 @@ class dialog_setting_game_internal(QWidget): def __(_qw, _): t, _type, _ = _ _qw.remove() - i = savehook_new_data[exepath]["usertags"].index(t) + i = savehook_new_data[gameuid]["usertags"].index(t) self.labelflow.removeidx(i) - savehook_new_data[exepath]["usertags"].remove(t) + savehook_new_data[gameuid]["usertags"].remove(t) if removeable: qw.removesignal.connect(functools.partial(__, qw)) @@ -929,11 +918,11 @@ class dialog_setting_game_internal(QWidget): else: self.labelflow.addwidget(qw) - for tag in savehook_new_data[exepath]["usertags"]: + for tag in savehook_new_data[gameuid]["usertags"]: newitem(tag, True, _type=tagitem.TYPE_USERTAG) - for tag in savehook_new_data[exepath]["developers"]: + for tag in savehook_new_data[gameuid]["developers"]: newitem(tag, False, _type=tagitem.TYPE_DEVELOPER) - for tag in savehook_new_data[exepath]["webtags"]: + for tag in savehook_new_data[gameuid]["webtags"]: newitem(tag, False, _type=tagitem.TYPE_TAG) formLayout.addWidget(self.labelflow) _dict = {"new": 0} @@ -949,8 +938,8 @@ class dialog_setting_game_internal(QWidget): tag = combo.currentText() # tag = globalconfig["labelset"][_dict["new"]] - if tag and tag not in savehook_new_data[exepath]["usertags"]: - savehook_new_data[exepath]["usertags"].insert(0, tag) + if tag and tag not in savehook_new_data[gameuid]["usertags"]: + savehook_new_data[gameuid]["usertags"].insert(0, tag) newitem(tag, True, True, _type=tagitem.TYPE_USERTAG) combo.clearEditText() @@ -966,62 +955,135 @@ class dialog_setting_game_internal(QWidget): ) return _w - def getttssetting(self, exepath): + def getttssetting(self, gameuid): _w = QWidget() - formLayout = QVBoxLayout() - formLayout.setAlignment(Qt.AlignmentFlag.AlignTop) + formLayout = QFormLayout() _w.setLayout(formLayout) - formLayout.addLayout( - getboxlayout( - [ - QLabel(_TR("禁止自动朗读的人名")), - listediterline( - _TR("禁止自动朗读的人名"), - _TR("人名"), - savehook_new_data[exepath]["allow_tts_auto_names_v4"], - ), - ] - ) + formLayout.addRow( + _TR("禁止自动朗读的人名"), + listediterline( + _TR("禁止自动朗读的人名"), + _TR("人名"), + savehook_new_data[gameuid]["allow_tts_auto_names_v4"], + ), ) - formLayout.addLayout( + formLayout.addRow( + _TR("语音修正"), getboxlayout( [ - QLabel(_TR("语音修正")), - getsimpleswitch(savehook_new_data[exepath], "tts_repair"), + getsimpleswitch(savehook_new_data[gameuid], "tts_repair"), getIconButton( - callback=lambda : noundictconfigdialog1( + callback=lambda: noundictconfigdialog1( self, - savehook_new_data[exepath]["tts_repair_regex"], + savehook_new_data[gameuid]["tts_repair_regex"], "语音修正", ["正则", "原文", "替换"], ), icon="fa.gear", ), - ] - ) + QLabel(), + ], + makewidget=True, + ), ) return _w - def getpretranstab(self, exepath): + def maketabforanki(self, gameuid): + _w = QWidget() + formLayout = QFormLayout() + _w.setLayout(formLayout) + __extraw = QWidget() + + formLayout.addRow( + _TR("跟随默认"), + getsimpleswitch( + savehook_new_data[gameuid], + "follow_default_ankisettings", + callback=lambda _: __extraw.setEnabled(not _), + ), + ) + __extraw.setEnabled( + not savehook_new_data[gameuid]["follow_default_ankisettings"] + ) + savehook_new_data[gameuid]["anki_DeckName"] = globalconfig["ankiconnect"][ + "DeckName" + ] + savehook_new_data[gameuid]["anki_simulate_key_1_use"] = globalconfig[ + "ankiconnect" + ]["simulate_key"]["1"]["use"] + savehook_new_data[gameuid]["anki_simulate_key_1_keystring"] = globalconfig[ + "ankiconnect" + ]["simulate_key"]["1"]["keystring"] + savehook_new_data[gameuid]["anki_simulate_key_2_use"] = globalconfig[ + "ankiconnect" + ]["simulate_key"]["2"]["use"] + savehook_new_data[gameuid]["anki_simulate_key_2_keystring"] = globalconfig[ + "ankiconnect" + ]["simulate_key"]["2"]["keystring"] + + formLayout.addRow(__extraw) + formLayout2 = QFormLayout() + formLayout2.setContentsMargins(0, 0, 0, 0) + __extraw.setLayout(formLayout2) + formLayout2.addRow( + _TR("DeckName"), + getlineedit( + savehook_new_data[gameuid], + "anki_DeckName", + ), + ) + formLayout2.addRow( + _TR("录音时模拟按键"), + getboxlayout( + [ + getsimpleswitch( + savehook_new_data[gameuid], "anki_simulate_key_1_use" + ), + getsimplekeyseq( + savehook_new_data[gameuid], "anki_simulate_key_1_keystring" + ), + ], + margin0=True, + makewidget=True, + ), + ) + formLayout2.addRow( + _TR("录音时模拟按键_例句"), + getboxlayout( + [ + getsimpleswitch( + savehook_new_data[gameuid], "anki_simulate_key_2_use" + ), + getsimplekeyseq( + savehook_new_data[gameuid], "anki_simulate_key_2_keystring" + ), + ], + margin0=True, + makewidget=True, + ), + ) + return _w + + def getpretranstab(self, gameuid): _w = QWidget() formLayout = QFormLayout() _w.setLayout(formLayout) - def selectimg(exepath, key, res): - savehook_new_data[exepath][key] = res + def selectimg(gameuid, key, res): + savehook_new_data[gameuid][key] = res for showname, key, filt in [ ("json翻译文件", "gamejsonfile", "*.json"), ]: - if isinstance(savehook_new_data[exepath][key], str): - savehook_new_data[exepath][key] = [savehook_new_data[exepath][key]] + if isinstance(savehook_new_data[gameuid][key], str): + savehook_new_data[gameuid][key] = [savehook_new_data[gameuid][key]] formLayout.addRow( _TR(showname), listediterline( showname, showname, - savehook_new_data[exepath][key], + savehook_new_data[gameuid][key], ispathsedit=dict(filter1=filt), ), ) @@ -1032,17 +1094,17 @@ class dialog_setting_game_internal(QWidget): formLayout.addRow( _TR(showname), getsimplepatheditor( - savehook_new_data[exepath][key], + savehook_new_data[gameuid][key], False, False, filt, - functools.partial(selectimg, exepath, key), + functools.partial(selectimg, gameuid, key), True, ), ) return _w - def gettextproc(self, exepath): + def gettextproc(self, gameuid): _w = QWidget() formLayout = QFormLayout() _w.setLayout(formLayout) @@ -1054,19 +1116,19 @@ class dialog_setting_game_internal(QWidget): formLayout.addRow( _TR("跟随默认"), getsimpleswitch( - savehook_new_data[exepath], + savehook_new_data[gameuid], "textproc_follow_default", callback=__function, ), ) - __extra.setEnabled(not savehook_new_data[exepath]["textproc_follow_default"]) + __extra.setEnabled(not savehook_new_data[gameuid]["textproc_follow_default"]) vbox = QVBoxLayout() vbox.setContentsMargins(0, 0, 0, 0) __extra.setLayout(vbox) formLayout.addRow(__extra) model = QStandardItemModel() - model.setHorizontalHeaderLabels(_TRL(["使用", "预处理方法", "设置"])) + model.setHorizontalHeaderLabels(_TRL(["预处理方法", "使用", "设置"])) table = QTableView() @@ -1081,9 +1143,9 @@ class dialog_setting_game_internal(QWidget): table.customContextMenuRequested.connect(self.__privatetextproc_showmenu) self.__textprocinternaltable = table self.__textprocinternalmodel = model - self.__privatetextproc_exe = exepath + self.__privatetextproc_gameuid = gameuid for row, k in enumerate( - savehook_new_data[exepath]["save_text_process_info"]["rank"] + savehook_new_data[gameuid]["save_text_process_info"]["rank"] ): # 2 self.__checkaddnewmethod(row, k) vbox.addWidget(table) @@ -1116,7 +1178,7 @@ class dialog_setting_game_internal(QWidget): def __privatetextproc_moverank(self, dy): __row = self.__textprocinternaltable.currentIndex().row() - __list = savehook_new_data[self.__privatetextproc_exe][ + __list = savehook_new_data[self.__privatetextproc_gameuid][ "save_text_process_info" ]["rank"] game = __list[__row] @@ -1133,21 +1195,21 @@ class dialog_setting_game_internal(QWidget): self.__textprocinternalmodel.insertRow( row, [ - QStandardItem(), QStandardItem(postprocessconfig[_internal]["name"]), QStandardItem(), + QStandardItem(), ], ) - __dict = savehook_new_data[self.__privatetextproc_exe][ + __dict = savehook_new_data[self.__privatetextproc_gameuid][ "save_text_process_info" ]["postprocessconfig"] if _internal not in __dict: __dict[_internal] = postprocessconfig[_internal] __dict[_internal]["use"] = True - btn = maybehavebutton(self, self.__privatetextproc_exe, _internal) + btn = maybehavebutton(self, self.__privatetextproc_gameuid, _internal) self.__textprocinternaltable.setIndexWidget( - self.__textprocinternalmodel.index(row, 0), + self.__textprocinternalmodel.index(row, 1), getsimpleswitch(__dict[_internal], "use"), ) if btn: @@ -1161,7 +1223,9 @@ class dialog_setting_game_internal(QWidget): if row < 0: return self.__textprocinternalmodel.removeRow(row) - _dict = savehook_new_data[self.__privatetextproc_exe]["save_text_process_info"] + _dict = savehook_new_data[self.__privatetextproc_gameuid][ + "save_text_process_info" + ] post = _dict["rank"][row] _dict["rank"].pop(row) if post in _dict["postprocessconfig"]: @@ -1174,7 +1238,7 @@ class dialog_setting_game_internal(QWidget): def __callback(d): __ = list(postprocessconfig.keys())[d["k"]] - __list = savehook_new_data[self.__privatetextproc_exe][ + __list = savehook_new_data[self.__privatetextproc_gameuid][ "save_text_process_info" ]["rank"] if __ in __list: @@ -1202,7 +1266,7 @@ class dialog_setting_game_internal(QWidget): ], ) - def getlangtab(self, exepath): + def getlangtab(self, gameuid): _w = QWidget() formLayout = QFormLayout() _w.setLayout(formLayout) @@ -1211,16 +1275,16 @@ class dialog_setting_game_internal(QWidget): formLayout.addRow( _TR("跟随默认"), getsimpleswitch( - savehook_new_data[exepath], + savehook_new_data[gameuid], "lang_follow_default", callback=lambda _: __extraw.setEnabled(not _), ), ) - __extraw.setEnabled(not savehook_new_data[exepath]["lang_follow_default"]) - savehook_new_data[exepath]["private_tgtlang"] = savehook_new_data[exepath].get( + __extraw.setEnabled(not savehook_new_data[gameuid]["lang_follow_default"]) + savehook_new_data[gameuid]["private_tgtlang"] = savehook_new_data[gameuid].get( "private_tgtlang", globalconfig["tgtlang3"] ) - savehook_new_data[exepath]["private_srclang"] = savehook_new_data[exepath].get( + savehook_new_data[gameuid]["private_srclang"] = savehook_new_data[gameuid].get( "private_srclang", globalconfig["srclang3"] ) @@ -1232,7 +1296,7 @@ class dialog_setting_game_internal(QWidget): _TR("源语言"), getsimplecombobox( _TRL(static_data["language_list_translator"]), - savehook_new_data[exepath], + savehook_new_data[gameuid], "private_srclang", ), ) @@ -1240,13 +1304,13 @@ class dialog_setting_game_internal(QWidget): _TR("目标语言"), getsimplecombobox( _TRL(static_data["language_list_translator"]), - savehook_new_data[exepath], + savehook_new_data[gameuid], "private_tgtlang", ), ) return _w - def gethooktab(self, exepath): + def gethooktab(self, gameuid): _w = QWidget() formLayout = QFormLayout() _w.setLayout(formLayout) @@ -1255,13 +1319,13 @@ class dialog_setting_game_internal(QWidget): listediterline( _TR("特殊码"), _TR("特殊码"), - savehook_new_data[exepath]["needinserthookcode"], + savehook_new_data[gameuid]["needinserthookcode"], ), ) formLayout.addRow( _TR("插入特殊码延迟(ms)"), - getspinbox(0, 1000000, savehook_new_data[exepath], "inserthooktimeout"), + getspinbox(0, 1000000, savehook_new_data[gameuid], "inserthooktimeout"), ) __extraw = QWidget() @@ -1275,13 +1339,13 @@ class dialog_setting_game_internal(QWidget): formLayout.addRow( _TR("跟随默认"), getsimpleswitch( - savehook_new_data[exepath], + savehook_new_data[gameuid], "hooksetting_follow_default", callback=__function, ), ) __extraw.setEnabled( - not savehook_new_data[exepath]["hooksetting_follow_default"] + not savehook_new_data[gameuid]["hooksetting_follow_default"] ) for k in [ @@ -1295,8 +1359,8 @@ class dialog_setting_game_internal(QWidget): "allow_set_text_name", "use_yapi", ]: - if k not in savehook_new_data[exepath]["hooksetting_private"]: - savehook_new_data[exepath]["hooksetting_private"][k] = globalconfig[k] + if k not in savehook_new_data[gameuid]["hooksetting_private"]: + savehook_new_data[gameuid]["hooksetting_private"][k] = globalconfig[k] formLayout.addRow(__extraw) formLayout2 = QFormLayout() formLayout2.setContentsMargins(0, 0, 0, 0) @@ -1305,7 +1369,7 @@ class dialog_setting_game_internal(QWidget): _TR("代码页"), getsimplecombobox( _TRL(static_data["codepage_display"]), - savehook_new_data[exepath]["hooksetting_private"], + savehook_new_data[gameuid]["hooksetting_private"], "codepage_index", lambda x: gobject.baseobject.textsource.setsettings(), ), @@ -1313,7 +1377,7 @@ class dialog_setting_game_internal(QWidget): formLayout2.addRow( _TR("过滤反复刷新的句子"), getsimpleswitch( - savehook_new_data[exepath]["hooksetting_private"], + savehook_new_data[gameuid]["hooksetting_private"], "direct_filterrepeat", callback=lambda x: gobject.baseobject.textsource.setsettings(), ), @@ -1322,7 +1386,7 @@ class dialog_setting_game_internal(QWidget): formLayout2.addRow( _TR("移除非选定hook"), getsimpleswitch( - savehook_new_data[exepath]["hooksetting_private"], "removeuseless" + savehook_new_data[gameuid]["hooksetting_private"], "removeuseless" ), ) formLayout2.addRow( @@ -1330,7 +1394,7 @@ class dialog_setting_game_internal(QWidget): getspinbox( 0, 10000, - savehook_new_data[exepath]["hooksetting_private"], + savehook_new_data[gameuid]["hooksetting_private"], "textthreaddelay", callback=lambda x: gobject.baseobject.textsource.setsettings(), ), @@ -1340,7 +1404,7 @@ class dialog_setting_game_internal(QWidget): getspinbox( 0, 1000000, - savehook_new_data[exepath]["hooksetting_private"], + savehook_new_data[gameuid]["hooksetting_private"], "maxBufferSize", callback=lambda x: gobject.baseobject.textsource.setsettings(), ), @@ -1350,7 +1414,7 @@ class dialog_setting_game_internal(QWidget): getspinbox( 0, 1000000000, - savehook_new_data[exepath]["hooksetting_private"], + savehook_new_data[gameuid]["hooksetting_private"], "maxHistorySize", callback=lambda x: gobject.baseobject.textsource.setsettings(), ), @@ -1358,21 +1422,21 @@ class dialog_setting_game_internal(QWidget): formLayout2.addRow( _TR("过滤包含乱码的文本行"), getsimpleswitch( - savehook_new_data[exepath]["hooksetting_private"], + savehook_new_data[gameuid]["hooksetting_private"], "filter_chaos_code", ), ) formLayout2.addRow( _TR("区分人名和文本"), getsimpleswitch( - savehook_new_data[exepath]["hooksetting_private"], + savehook_new_data[gameuid]["hooksetting_private"], "allow_set_text_name", ), ) formLayout2.addRow( _TR("使用YAPI注入"), getsimpleswitch( - savehook_new_data[exepath]["hooksetting_private"], + savehook_new_data[gameuid]["hooksetting_private"], "use_yapi", ), ) @@ -1383,15 +1447,15 @@ class dialog_setting_game_internal(QWidget): @Singleton_close class dialog_setting_game(QDialog): - def __init__(self, parent, exepath, setindexhook=False) -> None: + def __init__(self, parent, gameuid, setindexhook=False) -> None: super().__init__(parent, Qt.WindowType.WindowCloseButtonHint) global _global_dialog_setting_game _global_dialog_setting_game = self - self.setWindowTitle(savehook_new_data[exepath]["title"]) + self.setWindowTitle(savehook_new_data[gameuid]["title"]) - self.setWindowIcon(getExeIcon(exepath, cache=True)) - _ = dialog_setting_game_internal(self, exepath) + self.setWindowIcon(getExeIcon(uid2gamepath[gameuid], cache=True)) + _ = dialog_setting_game_internal(self, gameuid) if setindexhook: _.methodtab.setCurrentIndex(1) _.setMinimumSize(QSize(600, 500)) @@ -1504,10 +1568,11 @@ class dialog_syssetting(QDialog): @threader -def startgame(game): +def startgame(gameuid): try: + game = uid2gamepath[gameuid] if os.path.exists(game): - mode = savehook_new_data[game]["onloadautochangemode2"] + mode = savehook_new_data[gameuid]["onloadautochangemode2"] if mode > 0: _ = {1: "texthook", 2: "copy", 3: "ocr"} if globalconfig["sourcestatus2"][_[mode]]["use"] == False: @@ -1525,8 +1590,8 @@ def startgame(game): dirpath = os.path.dirname(game) - if savehook_new_data[game]["startcmduse"]: - usearg = savehook_new_data[game]["startcmd"].format(exepath=game) + if savehook_new_data[gameuid]["startcmduse"]: + usearg = savehook_new_data[gameuid]["startcmd"].format(exepath=game) windows.CreateProcess( None, usearg, @@ -1539,7 +1604,7 @@ def startgame(game): windows.STARTUPINFO(), ) return - if savehook_new_data[game]["leuse"] == False or ( + if savehook_new_data[gameuid]["leuse"] == False or ( game.lower()[-4:] not in [".lnk", ".exe"] ): # 对于其他文件,需要AssocQueryStringW获取命令行才能正确le,太麻烦,放弃。 @@ -1562,7 +1627,7 @@ def startgame(game): if dirp != "": dirpath = dirp - localeswitcher = savehook_new_data[game]["localeswitcher"] + localeswitcher = savehook_new_data[gameuid]["localeswitcher"] b = windows.GetBinaryType(execheck3264) if b == 6 and localeswitcher == 0: localeswitcher = 1 @@ -1587,7 +1652,8 @@ def startgame(game): print_exc() -def opendir(f): +def opendirforgameuid(gameuid): + f = uid2gamepath[gameuid] f = os.path.dirname(f) if os.path.exists(f) and os.path.isdir(f): os.startfile(f) @@ -1605,20 +1671,20 @@ def _getpixfunction(kk): _pix = QPixmap(_) if _pix and not _pix.isNull(): return _pix - _pix = getExeIcon(kk, False, cache=True) + _pix = getExeIcon(uid2gamepath[kk], False, cache=True) return _pix -def startgamecheck(self, game): - if not game: +def startgamecheck(self, gameuid): + if not gameuid: return - if not os.path.exists(game): + if not os.path.exists(uid2gamepath[gameuid]): return if globalconfig["startgamenototop"] == False: - idx = savehook_new_list.index(game) + idx = savehook_new_list.index(gameuid) savehook_new_list.insert(0, savehook_new_list.pop(idx)) self.parent().parent().close() - startgame(game) + startgame(gameuid) def addgamesingle(callback, targetlist): @@ -1628,8 +1694,9 @@ def addgamesingle(callback, targetlist): if res == "": return res = os.path.normpath(res) - if checkifnewgame(targetlist, res): - callback(res) + uid = checkifnewgame(targetlist, res) + if uid: + callback(uid) def addgamebatch(callback, targetlist): @@ -1643,8 +1710,9 @@ def addgamebatch(callback, targetlist): path = os.path.normpath(os.path.abspath(os.path.join(_dir, _f))) if path.lower().endswith(".exe") == False: continue - if checkifnewgame(targetlist, path): - callback(path) + uid = checkifnewgame(targetlist, path) + if uid: + callback(uid) @Singleton_close @@ -1704,9 +1772,9 @@ class dialog_savedgame_integrated(saveposwindow): self.internallayout.addWidget(QWidget()) self.setCentralWidget(w) - self.layout1btn = MySwitch(self, icon="fa.th", ) - self.layout2btn = MySwitch(self, icon="fa.th-list", ) - self.layout3btn = MySwitch(self, icon="fa.list" , ) + self.layout1btn = MySwitch(self, icon="fa.th") + self.layout2btn = MySwitch(self, icon="fa.th-list") + self.layout3btn = MySwitch(self, icon="fa.list") self.layout1btn.clicked.connect(functools.partial(self.selectlayout, 0)) self.layout2btn.clicked.connect(functools.partial(self.selectlayout, 1)) self.layout3btn.clicked.connect(functools.partial(self.selectlayout, 2)) @@ -1755,7 +1823,7 @@ def getreflist(reftagid): class dialog_savedgame_new(QWidget): def clicked2(self): try: - game = self.currentfocuspath + game = self.currentfocusuid idx2 = self.reflist.index(game) self.reflist.pop(idx2) @@ -1772,13 +1840,13 @@ class dialog_savedgame_new(QWidget): print_exc() def clicked4(self): - opendir(self.currentfocuspath) + opendirforgameuid(self.currentfocusuid) def clicked3_batch(self): - addgamebatch(lambda res: self.newline(res, True), self.reflist) + addgamebatch(lambda uid: self.newline(uid, True), self.reflist) def clicked3(self): - addgamesingle(lambda res: self.newline(res, True), self.reflist) + addgamesingle(lambda uid: self.newline(uid, True), self.reflist) def tagschanged(self, tags): self.currtags = tags @@ -1798,7 +1866,7 @@ class dialog_savedgame_new(QWidget): notshow = False for tag, _type, _ in tags: if _type == tagitem.TYPE_EXISTS: - if os.path.exists(k) == False: + if os.path.exists(uid2gamepath[k]) == False: notshow = True break elif _type == tagitem.TYPE_DEVELOPER: @@ -1838,8 +1906,8 @@ class dialog_savedgame_new(QWidget): batchadd = QAction(_TR("批量添加")) othersetting = QAction(_TR("其他设置")) - if self.currentfocuspath: - exists = os.path.exists(self.currentfocuspath) + if self.currentfocusuid: + exists = os.path.exists(uid2gamepath[self.currentfocusuid]) if exists: menu.addAction(startgame) menu.addAction(delgame) @@ -1852,7 +1920,7 @@ class dialog_savedgame_new(QWidget): menu.addAction(othersetting) action = menu.exec(self.mapToGlobal(p)) if action == startgame: - startgamecheck(self, self.currentfocuspath) + startgamecheck(self, self.currentfocusuid) elif action == gamesetting: self.showsettingdialog() elif action == delgame: @@ -1897,7 +1965,7 @@ class dialog_savedgame_new(QWidget): layout.addWidget( getIconButton( - lambda : listediter( + lambda: listediter( parent, _TR("标签集"), _TR("标签"), @@ -1939,7 +2007,7 @@ class dialog_savedgame_new(QWidget): self.buttonlayout = buttonlayout self.savebutton = [] self.simplebutton( - "开始游戏", True, lambda: startgamecheck(self, self.currentfocuspath), True + "开始游戏", True, lambda: startgamecheck(self, self.currentfocusuid), True ) self.simplebutton("游戏设置", True, self.showsettingdialog, False) self.simplebutton("删除游戏", True, self.clicked2, False) @@ -1975,7 +2043,7 @@ class dialog_savedgame_new(QWidget): self.installEventFilter(self.__filter) def moverank(self, dx): - game = self.currentfocuspath + game = self.currentfocusuid idx1 = self.idxsave.index(game) idx2 = (idx1 + dx) % len(self.idxsave) @@ -1989,7 +2057,7 @@ class dialog_savedgame_new(QWidget): def showsettingdialog(self): try: - dialog_setting_game(self.parent(), self.currentfocuspath) + dialog_setting_game(self.parent(), self.currentfocusuid) except: print_exc() @@ -2006,15 +2074,15 @@ class dialog_savedgame_new(QWidget): def itemfocuschanged(self, b, k): if b: - self.currentfocuspath = k + self.currentfocusuid = k else: - self.currentfocuspath = None + self.currentfocusuid = None for _btn, exists in self.savebutton: _able1 = b and ( (not exists) - or (self.currentfocuspath) - and (os.path.exists(self.currentfocuspath)) + or (self.currentfocusuid) + and (os.path.exists(uid2gamepath[self.currentfocusuid])) ) _btn.setEnabled(_able1) @@ -2139,8 +2207,8 @@ class dialog_savedgame_lagacy(QWidget): pass def clicked3(self): - def call(res): - self.newline(0, res) + def call(uid): + self.newline(0, uid) self.table.setCurrentIndex(self.model.index(0, 0)) addgamesingle(call) @@ -2152,13 +2220,15 @@ class dialog_savedgame_lagacy(QWidget): def delayloadicon(self, k): return getcolorbutton( - "", "", functools.partial(opendir, k), qicon=getExeIcon(k, cache=True) + "", + "", + functools.partial(opendirforgameuid, k), + qicon=getExeIcon(uid2gamepath[k], cache=True), ) def newline(self, row, k): keyitem = QStandardItem() keyitem.savetext = k - k = k.replace("/", "\\") self.model.insertRow( row, [ @@ -2248,7 +2318,7 @@ class clickitem(QWidget): clickitem.globallashfocus = None def mouseDoubleClickEvent(self, e): - self.doubleclicked.emit(self.exe) + self.doubleclicked.emit(self.uid) def click(self): try: @@ -2259,7 +2329,7 @@ class clickitem(QWidget): if self != clickitem.globallashfocus: clickitem.clearfocus() clickitem.globallashfocus = self - self.focuschanged.emit(True, self.exe) + self.focuschanged.emit(True, self.uid) except: print_exc() @@ -2268,17 +2338,17 @@ class clickitem(QWidget): def focusOut(self): self.bottommask.setStyleSheet("background-color: rgba(255,255,255, 0);") - self.focuschanged.emit(False, self.exe) + self.focuschanged.emit(False, self.uid) def resizeEvent(self, a0: QResizeEvent) -> None: self.bottommask.resize(a0.size()) self.maskshowfileexists.resize(a0.size()) self.bottomline.resize(a0.size()) - def __init__(self, exe): + def __init__(self, uid): super().__init__() - self.exe = exe + self.uid = uid self.lay = QHBoxLayout() self.lay.setSpacing(0) self.lay.setContentsMargins(0, 0, 0, 0) @@ -2286,7 +2356,7 @@ class clickitem(QWidget): self.maskshowfileexists = QLabel(self) c = globalconfig["dialog_savegame_layout"][ - ("onfilenoexistscolor1", "backcolor1")[os.path.exists(exe)] + ("onfilenoexistscolor1", "backcolor1")[os.path.exists(uid2gamepath[uid])] ] c = str2rgba(c, globalconfig["dialog_savegame_layout"]["transparent"]) self.maskshowfileexists.setStyleSheet(f"background-color:{c};") @@ -2302,11 +2372,11 @@ class clickitem(QWidget): _.setFixedSize(QSize(size, size)) _.setScaledContents(True) _.setStyleSheet("background-color: rgba(255,255,255, 0);") - icon = getExeIcon(exe, icon=False, cache=True) + icon = getExeIcon(uid2gamepath[uid], icon=False, cache=True) icon.setDevicePixelRatio(self.devicePixelRatioF()) _.setPixmap(icon) self.lay.addWidget(_) - _ = QLabel(savehook_new_data[exe]["title"]) + _ = QLabel(savehook_new_data[uid]["title"]) _.setWordWrap(True) _.setFixedHeight(size + 1) self.lay.addWidget(_) @@ -2314,10 +2384,30 @@ class clickitem(QWidget): _.setStyleSheet("""background-color: rgba(255,255,255, 0);""") +class fadeoutlabel(QLabel): + def __init__(self, p=None): + super().__init__(p) + + effect = QGraphicsOpacityEffect(self) + self.setGraphicsEffect(effect) + + self.animation = QPropertyAnimation(effect, b"opacity") + self.animation.setDuration(4000) + self.animation.setStartValue(1.0) + self.animation.setEndValue(0.0) + self.animation.setDirection(QPropertyAnimation.Direction.Forward) + + def setText(self, t): + super().setText(t) + self.animation.stop() + self.animation.start() + + class pixwrapper(QWidget): def __init__(self) -> None: super().__init__() self.pixview = QLabel(self) + self.pathview = fadeoutlabel(self) self.pixmaps = [] self.rflist = [] self.iternalpixmaps = [] @@ -2342,13 +2432,14 @@ class pixwrapper(QWidget): def resizeEvent(self, e: QResizeEvent): self.pixview.resize(e.size().width(), e.size().height()) + self.pathview.resize(e.size().width(), self.pathview.height()) self.visidx() def visidx(self): if len(self.pixmaps) == 0: if not self.k: return - pixmap = getExeIcon(self.k, False, cache=True) + pixmap = getExeIcon(uid2gamepath[self.k], False, cache=True) pixmap.setDevicePixelRatio(self.devicePixelRatioF()) self.pixview.setPixmap(self.scalepix(pixmap)) else: @@ -2358,6 +2449,7 @@ class pixwrapper(QWidget): if pixmap is None or pixmap.isNull(): self.pixmaps.pop(self.pixmapi) return self.visidx() + self.pathview.setText(pixmap_) savehook_new_data[self.k]["currentvisimage"] = pixmap_ pixmap.setDevicePixelRatio(self.devicePixelRatioF()) self.pixview.setPixmap(self.scalepix(pixmap)) @@ -2397,7 +2489,7 @@ class dialog_savedgame_v3(QWidget): def viewitem(self, k): try: self.pixview.setpix(k) - self.currentfocuspath = k + self.currentfocusuid = k if self.righttop.count() > 1: self.righttop.removeTab(1) tabadd_lazy( @@ -2413,18 +2505,18 @@ class dialog_savedgame_v3(QWidget): self.reftagid = reftagid if b: - self.currentfocuspath = k + self.currentfocusuid = k else: - self.currentfocuspath = None + self.currentfocusuid = None for _btn, exists in self.savebutton: _able1 = b and ( (not exists) - or (self.currentfocuspath) - and (os.path.exists(self.currentfocuspath)) + or (self.currentfocusuid) + and (os.path.exists(uid2gamepath[self.currentfocusuid])) ) _btn.setEnabled(_able1) - if self.currentfocuspath: + if self.currentfocusuid: self.viewitem(k) def delayitemcreater(self, k, select, reftagid): @@ -2451,7 +2543,7 @@ class dialog_savedgame_v3(QWidget): self.stack.directshow() def stack_showmenu(self, ispixmenu, p): - if not self.currentfocuspath: + if not self.currentfocusuid: return menu = QMenu(self) startgame = QAction(_TR("开始游戏")) @@ -2461,7 +2553,7 @@ class dialog_savedgame_v3(QWidget): setimage = QAction(_TR("设为封面")) deleteimage = QAction(_TR("删除图片")) hualang = QAction(_TR("画廊")) - exists = os.path.exists(self.currentfocuspath) + exists = os.path.exists(uid2gamepath[self.currentfocusuid]) if exists: menu.addAction(startgame) menu.addAction(delgame) @@ -2475,16 +2567,16 @@ class dialog_savedgame_v3(QWidget): menu.addAction(hualang) action = menu.exec(QCursor.pos()) if action == startgame: - startgamecheck(self, self.currentfocuspath) + startgamecheck(self, self.currentfocusuid) elif action == delgame: - self.clicked2() + self.shanchuyouxi() elif action == hualang: listediter( self, _TR("画廊"), _TR("画廊"), - savehook_new_data[self.currentfocuspath]["imagepath_all"], - closecallback=lambda: self.pixview.setpix(self.currentfocuspath), + savehook_new_data[self.currentfocusuid]["imagepath_all"], + closecallback=lambda: self.pixview.setpix(self.currentfocusuid), ispathsedit=dict(), ) @@ -2495,11 +2587,11 @@ class dialog_savedgame_v3(QWidget): elif action == addtolist: self.addtolist() elif action == setimage: - curr = savehook_new_data[self.currentfocuspath]["currentvisimage"] + curr = savehook_new_data[self.currentfocusuid]["currentvisimage"] if curr and os.path.exists(curr): - savehook_new_data[self.currentfocuspath]["currentmainimage"] = curr + savehook_new_data[self.currentfocusuid]["currentmainimage"] = curr - def addtolistcallback(self, __d, __uid, path): + def addtolistcallback(self, __d, __uid, gameuid): if len(__uid) == 0: return @@ -2508,9 +2600,13 @@ class dialog_savedgame_v3(QWidget): __save = self.reftagid self.reftagid = uid - if path not in getreflist(self.reftagid): - getreflist(self.reftagid).insert(0, path) - self.newline(path) + if gameuid not in getreflist(self.reftagid): + getreflist(self.reftagid).insert(0, gameuid) + self.newline(gameuid) + else: + idx = getreflist(self.reftagid).index(gameuid) + getreflist(self.reftagid).insert(0, getreflist(self.reftagid).pop(idx)) + self.stack.w(calculatetagidx(self.reftagid)).torank1(idx) self.reftagid = __save def addtolist(self): @@ -2543,7 +2639,7 @@ class dialog_savedgame_v3(QWidget): { "type": "okcancel", "callback": functools.partial( - self.addtolistcallback, __d, __uid, self.currentfocuspath + self.addtolistcallback, __d, __uid, self.currentfocusuid ), }, ], @@ -2554,7 +2650,7 @@ class dialog_savedgame_v3(QWidget): def __init__(self, parent) -> None: super().__init__(parent) - self.currentfocuspath = None + self.currentfocusuid = None self.reftagid = None self.reallist = {} self.stack = stackedlist() @@ -2588,9 +2684,9 @@ class dialog_savedgame_v3(QWidget): rightlay.addLayout(self.buttonlayout) self.simplebutton( - "开始游戏", True, lambda: startgamecheck(self, self.currentfocuspath), True + "开始游戏", True, lambda: startgamecheck(self, self.currentfocusuid), True ) - self.simplebutton("删除游戏", True, self.clicked2, False) + self.simplebutton("删除游戏", True, self.shanchuyouxi, False) self.simplebutton("打开目录", True, self.clicked4, True) self.simplebutton("添加到列表", False, self.addtolist, 1) if globalconfig["startgamenototop"]: @@ -2622,7 +2718,9 @@ class dialog_savedgame_v3(QWidget): self.stack.insertw(i, group0) rowreal = 0 for row, k in enumerate(lst): - if globalconfig["hide_not_exists"] and not os.path.exists(k): + if globalconfig["hide_not_exists"] and not os.path.exists( + uid2gamepath[k] + ): continue self.reallist[tagid].append(k) group0.insertw( @@ -2643,7 +2741,7 @@ class dialog_savedgame_v3(QWidget): self.stack.switchidx(idx1, idx2) def tagbuttonmenu(self, tagid): - self.currentfocuspath = None + self.currentfocusuid = None self.reftagid = tagid menu = QMenu(self) editname = QAction(_TR("修改名称")) @@ -2724,29 +2822,29 @@ class dialog_savedgame_v3(QWidget): return shrinkableitem(_btn, opened) def moverank(self, dx): - game = self.currentfocuspath - idx1 = self.reallist[self.reftagid].index(game) + uid = self.currentfocusuid + idx1 = self.reallist[self.reftagid].index(uid) idx2 = (idx1 + dx) % len(self.reallist[self.reftagid]) - game2 = self.reallist[self.reftagid][idx2] + uid2 = self.reallist[self.reftagid][idx2] self.reallist[self.reftagid].insert( idx2, self.reallist[self.reftagid].pop(idx1) ) self.stack.w(calculatetagidx(self.reftagid)).switchidx(idx1, idx2) - idx1 = getreflist(self.reftagid).index(game) - idx2 = getreflist(self.reftagid).index(game2) + idx1 = getreflist(self.reftagid).index(uid) + idx2 = getreflist(self.reftagid).index(uid2) getreflist(self.reftagid).insert(idx2, getreflist(self.reftagid).pop(idx1)) - def clicked2(self): - if not self.currentfocuspath: + def shanchuyouxi(self): + if not self.currentfocusuid: return try: - game = self.currentfocuspath - idx2 = getreflist(self.reftagid).index(game) + uid = self.currentfocusuid + idx2 = getreflist(self.reftagid).index(uid) getreflist(self.reftagid).pop(idx2) - idx2 = self.reallist[self.reftagid].index(game) + idx2 = self.reallist[self.reftagid].index(uid) self.reallist[self.reftagid].pop(idx2) clickitem.clearfocus() group0 = self.stack.w(calculatetagidx(self.reftagid)) @@ -2759,16 +2857,16 @@ class dialog_savedgame_v3(QWidget): print_exc() def clicked4(self): - opendir(self.currentfocuspath) + opendirforgameuid(self.currentfocusuid) def clicked3_batch(self): - addgamebatch(lambda res: self.newline(res), getreflist(self.reftagid)) + addgamebatch(lambda uid: self.newline(uid), getreflist(self.reftagid)) def clicked3(self): - addgamesingle(lambda res: self.newline(res), getreflist(self.reftagid)) + addgamesingle(lambda uid: self.newline(uid), getreflist(self.reftagid)) def clicked(self): - startgamecheck(self, self.currentfocuspath) + startgamecheck(self, self.currentfocusuid) def simplebutton(self, text, save, callback, exists): button5 = QPushButton() diff --git a/LunaTranslator/LunaTranslator/gui/pretransfile.py b/LunaTranslator/LunaTranslator/gui/pretransfile.py index 33393d0d..a8d4e692 100644 --- a/LunaTranslator/LunaTranslator/gui/pretransfile.py +++ b/LunaTranslator/LunaTranslator/gui/pretransfile.py @@ -95,7 +95,7 @@ def sqlite2json2(self, sqlitefile, targetjson=None, existsmerge=False): for k in existsjs: if k not in js_format2 or js_format2[k] == "": js_format2[k] = existsjs[k] - + os.makedirs(os.path.dirname(target), exist_ok=True) with open(target, "w", encoding="utf8") as ff: ff.write( json.dumps(js_format2, ensure_ascii=False, sort_keys=False, indent=4) @@ -109,8 +109,7 @@ def sqlite2json2(self, sqlitefile, targetjson=None, existsmerge=False): def sqlite2json(self): - os.makedirs("./translation_record", exist_ok=True) - f = QFileDialog.getOpenFileName(directory="./translation_record", filter="*.sqlite") + f = QFileDialog.getOpenFileName(directory="translation_record", filter="*.sqlite") if f[0] == "": return diff --git a/LunaTranslator/LunaTranslator/gui/selecthook.py b/LunaTranslator/LunaTranslator/gui/selecthook.py index aefd1821..5afc18d4 100644 --- a/LunaTranslator/LunaTranslator/gui/selecthook.py +++ b/LunaTranslator/LunaTranslator/gui/selecthook.py @@ -74,8 +74,7 @@ class QButtonGroup_switch_widegt(QWidget): def listprocessm(): - os.makedirs("cache/temp", exist_ok=True) - cachefname = os.path.abspath("cache/temp/{}.txt".format(time.time())) + cachefname = gobject.gettempdir("{}.txt".format(time.time())) arch = "64" if gobject.baseobject.textsource.is64bit else "32" exe = os.path.abspath("./files/plugins/shareddllproxy{}.exe".format(arch)) pid = " ".join([str(_) for _ in gobject.baseobject.textsource.pids]) @@ -211,7 +210,7 @@ class searchhookparam(QDialog): layout1 = QHBoxLayout() layout1.addWidget(QLabel(_TR("代码页"))) self.codepagesave = { - "spcp": savehook_new_data[gobject.baseobject.textsource.pname].get( + "spcp": savehook_new_data[gobject.baseobject.textsource.gameuid].get( "codepage_index", globalconfig["codepage_index"] ) } @@ -513,7 +512,7 @@ class hookselect(closeashidewindow): gobject.baseobject.textsource.hooktypecollecter, key, callback=functools.partial( - savehook_new_data[gobject.baseobject.textsource.pname][ + savehook_new_data[gobject.baseobject.textsource.gameuid][ "hooktypeasname" ].__setitem__, json.dumps(gobject.baseobject.textsource.serialkey(key)), @@ -537,10 +536,10 @@ class hookselect(closeashidewindow): if hn[:8] == "UserHook": needinserthookcode = savehook_new_data[ - gobject.baseobject.textsource.pname + gobject.baseobject.textsource.gameuid ]["needinserthookcode"] needinserthookcode = list(set(needinserthookcode + [hc])) - savehook_new_data[gobject.baseobject.textsource.pname].update( + savehook_new_data[gobject.baseobject.textsource.gameuid].update( {"needinserthookcode": needinserthookcode} ) else: @@ -552,19 +551,19 @@ class hookselect(closeashidewindow): gobject.baseobject.textsource.useembed(tp.addr, tp.ctx, tp.ctx2, _) _use = self._check_tp_using(key) if _use: - savehook_new_data[gobject.baseobject.textsource.pname][ + savehook_new_data[gobject.baseobject.textsource.gameuid][ "embedablehook" ].append([hc, tp.addr, tp.ctx, tp.ctx2]) else: save = [] - for _ in savehook_new_data[gobject.baseobject.textsource.pname][ + for _ in savehook_new_data[gobject.baseobject.textsource.gameuid][ "embedablehook" ]: hc, ad, c1, c2 = _ if (hc, 0, c1, c2) == (hc, 0, tp.ctx, tp.ctx2): save.append(_) for _ in save: - savehook_new_data[gobject.baseobject.textsource.pname][ + savehook_new_data[gobject.baseobject.textsource.gameuid][ "embedablehook" ].remove(_) @@ -710,7 +709,7 @@ class hookselect(closeashidewindow): def opengamesetting(self): try: - dialog_setting_game(self, gobject.baseobject.textsource.pname, True) + dialog_setting_game(self, gobject.baseobject.textsource.gameuid, True) except: print_exc() @@ -865,16 +864,16 @@ class hookselect(closeashidewindow): if hn[:8] == "UserHook": needinserthookcode = savehook_new_data[ - gobject.baseobject.textsource.pname + gobject.baseobject.textsource.gameuid ]["needinserthookcode"] needinserthookcode = list(set(needinserthookcode + [hc])) - savehook_new_data[gobject.baseobject.textsource.pname].update( + savehook_new_data[gobject.baseobject.textsource.gameuid].update( {"needinserthookcode": needinserthookcode} ) else: pass - savehook_new_data[gobject.baseobject.textsource.pname].update( + savehook_new_data[gobject.baseobject.textsource.gameuid].update( {"hook": gobject.baseobject.textsource.serialselectedhook()} ) except: diff --git a/LunaTranslator/LunaTranslator/gui/setting_about.py b/LunaTranslator/LunaTranslator/gui/setting_about.py index aa7de973..89752b7a 100644 --- a/LunaTranslator/LunaTranslator/gui/setting_about.py +++ b/LunaTranslator/LunaTranslator/gui/setting_about.py @@ -52,8 +52,10 @@ def doupdate(): elif platform.architecture()[0] == "32bit": bit = "_x86" _6432 = "32" - os.makedirs("./cache", exist_ok=True) - shutil.copy(rf".\files\plugins\shareddllproxy{_6432}.exe", rf".\cache\Updater.exe") + shutil.copy( + rf".\files\plugins\shareddllproxy{_6432}.exe", + gobject.getcachedir("Updater.exe"), + ) subprocess.Popen(rf".\cache\Updater.exe update .\cache\update\LunaTranslator{bit}") @@ -82,9 +84,7 @@ def updatemethod(_version, self): _version, bit ) - savep = "./cache/update/LunaTranslator{}.zip".format(bit) - - os.makedirs("./cache/update", exist_ok=True) + savep = gobject.getcachedir("update/LunaTranslator{}.zip".format(bit)) r2 = requests.get( url, stream=True, verify=False, proxies=getproxy(("github", "download")) @@ -124,11 +124,9 @@ def updatemethod(_version, self): def uncompress(self, savep): self.progresssignal.emit("正在解压……", 10000) - os.makedirs("./cache/update", exist_ok=True) - if os.path.exists("./cache/update/LunaTranslator"): - shutil.rmtree("./cache/update/LunaTranslator") + shutil.rmtree(gobject.getcachedir("update/LunaTranslator")) with zipfile.ZipFile(savep) as zipf: - zipf.extractall("./cache/update") + zipf.extractall(gobject.getcachedir("update")) @threader diff --git a/LunaTranslator/LunaTranslator/gui/setting_display_text.py b/LunaTranslator/LunaTranslator/gui/setting_display_text.py index c536abfc..ebaadfde 100644 --- a/LunaTranslator/LunaTranslator/gui/setting_display_text.py +++ b/LunaTranslator/LunaTranslator/gui/setting_display_text.py @@ -72,8 +72,9 @@ class extrahtml(saveposwindow): ) def savehtml(self): - os.makedirs("userconfig", exist_ok=True) - with open("userconfig/extrahtml.html", "w", encoding="utf8") as ff: + with open( + gobject.getuserconfigdir("extrahtml.html"), "w", encoding="utf8" + ) as ff: ff.write(self.vistext.toPlainText()) def __init__(self, parent) -> None: @@ -188,8 +189,7 @@ def doinstallqweb(self, dd, base): getQMessageBox(self, "错误", f"请选择_{base}") return with zipfile.ZipFile(dd["k"]) as zipf: - target = "cache/temp/QWebEngine" - os.makedirs(target, exist_ok=True) + target = gobject.gettempdir("QWebEngine/") zipf.extractall(target) bit = ["x86", "x64"][platform.architecture()[0] == "64bit"] copytree(f"{target}/{bit}/PyQt5", "LunaTranslator/runtime/PyQt5") diff --git a/LunaTranslator/LunaTranslator/gui/setting_textinput.py b/LunaTranslator/LunaTranslator/gui/setting_textinput.py index 51713b4d..6b03f9eb 100644 --- a/LunaTranslator/LunaTranslator/gui/setting_textinput.py +++ b/LunaTranslator/LunaTranslator/gui/setting_textinput.py @@ -7,6 +7,7 @@ from myutils.config import ( _TR, _TRL, savehook_new_data, + uid2gamepath, savehook_new_list, static_data, ) @@ -176,7 +177,7 @@ def gethookgrid(self): return grids -def doexportchspatch(exe, realgame): +def doexportchspatch(exe, gameuid): b = windows.GetBinaryType(exe) is64 = b == 6 @@ -199,10 +200,10 @@ def doexportchspatch(exe, realgame): embedconfig = { "translation_file": "translation.json", "target_exe": os.path.basename(exe), - "target_exe2": os.path.basename(realgame), + "target_exe2": os.path.basename(exe), "startup_argument": None, "inject_timeout": 1000, - "embedhook": savehook_new_data[realgame]["embedablehook"], + "embedhook": savehook_new_data[gameuid]["embedablehook"], "embedsettings": { "font": ( globalconfig["embedded"]["changefont_font"] @@ -219,7 +220,7 @@ def doexportchspatch(exe, realgame): ff.write(json.dumps(embedconfig, ensure_ascii=False, indent=4)) -def getunknowgameexe(self): +def selectgameuid(self): dialog = QDialog(self, Qt.WindowType.WindowCloseButtonHint) # 自定义一个dialog dialog.setWindowTitle(_TR("选择游戏")) @@ -245,10 +246,10 @@ def getunknowgameexe(self): def exportchspatch(self): - realgame = getunknowgameexe(self) - if realgame is None: + gameuid = selectgameuid(self) + if gameuid is None: return - exe = realgame + exe = uid2gamepath[gameuid] if exe.lower().endswith(".exe") == False: f = QFileDialog.getOpenFileName( self, caption=_TR("选择EXE文件"), filter="*.exe" @@ -257,16 +258,15 @@ def exportchspatch(self): if exe == "": return exe = os.path.normpath(exe) - doexportchspatch(exe, realgame) + doexportchspatch(exe, gameuid) md5 = getfilemd5(exe) name = os.path.basename(exe).replace("." + os.path.basename(exe).split(".")[-1], "") - os.makedirs("./translation_record", exist_ok=True) - sqlfname_all = "./translation_record/" + name + "_" + md5 + ".sqlite" + sqlfname_all = gobject.gettranslationrecorddir(name + "_" + md5 + ".sqlite") if os.path.exists(sqlfname_all) == False: f = QFileDialog.getOpenFileName( self, caption=_TR("选择预翻译文件"), - directory="./translation_record/", + directory="translation_record", filter="*.sqlite", ) sqlfname_all = f[0] @@ -388,10 +388,10 @@ def getTabclip(self): grids = [ [ - "排除复制自翻译器的文本", + "排除复制自翻译器的文本", D_getsimpleswitch(globalconfig, "excule_from_self"), "", - "" + "", ] ] return grids diff --git a/LunaTranslator/LunaTranslator/gui/showword.py b/LunaTranslator/LunaTranslator/gui/showword.py index 46d1a7be..d3e63cc5 100644 --- a/LunaTranslator/LunaTranslator/gui/showword.py +++ b/LunaTranslator/LunaTranslator/gui/showword.py @@ -6,7 +6,7 @@ import qtawesome, requests, gobject, windows import myutils.ankiconnect as anki from myutils.hwnd import grabwindow from myutils.utils import parsekeystringtomodvkcode, unsupportkey -from myutils.config import globalconfig, _TR, static_data +from myutils.config import globalconfig, _TR, static_data, savehook_new_data from myutils.subproc import subproc_w from myutils.wrapper import threader from myutils.ocrutil import imageCut, ocr_run @@ -39,12 +39,10 @@ def getimageformat(): return getimageformatlist()[globalconfig["imageformat"]] + class loopbackrecorder: def __init__(self): - os.makedirs("cache/temp", exist_ok=True) - self.file = os.path.abspath( - os.path.join("cache/temp", str(time.time()) + ".wav") - ) + self.file = gobject.gettempdir(str(time.time()) + ".wav") try: self.waitsignal = str(time.time()) self.engine = subproc_w( @@ -112,8 +110,7 @@ class AnkiWindow(QWidget): refreshhtml = pyqtSignal() def callbacktts(self, edit, data): - fname = "cache/temp/" + str(uuid.uuid4()) + ".mp3" - os.makedirs("cache/temp", exist_ok=True) + fname = gobject.gettempdir(str(uuid.uuid4()) + ".mp3") with open(fname, "wb") as ff: ff.write(data) edit.setText(os.path.abspath(fname)) @@ -140,8 +137,7 @@ class AnkiWindow(QWidget): img = imageCut( 0, rect[0][0], rect[0][1], rect[1][0], rect[1][1], False, True ) - fname = "cache/temp/" + str(uuid.uuid4()) + "." + getimageformat() - os.makedirs("cache/temp", exist_ok=True) + fname = gobject.gettempdir(str(uuid.uuid4()) + "." + getimageformat()) img.save(fname) self.editpath.setText(os.path.abspath(fname)) if globalconfig["ankiconnect"]["ocrcroped"]: @@ -337,12 +333,17 @@ class AnkiWindow(QWidget): model_htmlfront = self.fronttext.toPlainText() model_htmlback = self.backtext.toPlainText() model_css = self.csstext.toPlainText() - os.makedirs("userconfig/anki", exist_ok=True) - with open("userconfig/anki/back.html", "w", encoding="utf8") as ff: + with open( + gobject.getuserconfigdir("anki/back.html"), "w", encoding="utf8" + ) as ff: ff.write(model_htmlback) - with open("userconfig/anki/front.html", "w", encoding="utf8") as ff: + with open( + gobject.getuserconfigdir("anki/front.html"), "w", encoding="utf8" + ) as ff: ff.write(model_htmlfront) - with open("userconfig/anki/style.css", "w", encoding="utf8") as ff: + with open( + gobject.getuserconfigdir("anki/style.css"), "w", encoding="utf8" + ) as ff: ff.write(model_css) def creatsetdtab(self, baselay): @@ -431,14 +432,34 @@ class AnkiWindow(QWidget): @threader def simulate_key(self, i): - if not globalconfig["ankiconnect"]["simulate_key"][i]["use"]: + def __internal__keystring(i): + try: + for _ in (0,): + + if not gobject.baseobject.textsource: + break + + gameuid = gobject.baseobject.textsource.gameuid + if not gameuid: + break + if savehook_new_data[gameuid]["follow_default_ankisettings"]: + break + if not savehook_new_data[gameuid][f"anki_simulate_key_{i}_use"]: + return None + return savehook_new_data[gameuid][ + f"anki_simulate_key_{i}_keystring" + ] + except: + pass + return globalconfig["ankiconnect"]["simulate_key"][i]["keystring"] + + keystring = __internal__keystring(i) + if not keystring: return windows.SetForegroundWindow(gobject.baseobject.textsource.hwnd) time.sleep(0.1) try: - modes, vkcode = parsekeystringtomodvkcode( - globalconfig["ankiconnect"]["simulate_key"][i]["keystring"], modes=True - ) + modes, vkcode = parsekeystringtomodvkcode(keystring, modes=True) except unsupportkey as e: print("不支持的键") return @@ -593,7 +614,9 @@ class AnkiWindow(QWidget): or pix.height() > self.viewimagelabel.height() ): pix = pix.scaled( - self.viewimagelabel.size() * rate, Qt.AspectRatioMode.KeepAspectRatio + self.viewimagelabel.size() * rate, + Qt.AspectRatioMode.KeepAspectRatio, + Qt.TransformationMode.SmoothTransformation, ) self.viewimagelabel.setPixmap(pix) @@ -650,11 +673,30 @@ class AnkiWindow(QWidget): return model_htmlfront, model_htmlback, model_css def addanki(self): + + def __internal__DeckName(): + try: + for _ in (0,): + + if not gobject.baseobject.textsource: + break + + gameuid = gobject.baseobject.textsource.gameuid + if not gameuid: + break + if savehook_new_data[gameuid]["follow_default_ankisettings"]: + break + + return savehook_new_data[gameuid]["anki_DeckName"] + except: + pass + return globalconfig["ankiconnect"]["DeckName"] + autoUpdateModel = globalconfig["ankiconnect"]["autoUpdateModel"] allowDuplicate = globalconfig["ankiconnect"]["allowDuplicate"] anki.global_port = globalconfig["ankiconnect"]["port"] ModelName = globalconfig["ankiconnect"]["ModelName5"] - DeckName = globalconfig["ankiconnect"]["DeckName"] + DeckName = __internal__DeckName() model_htmlfront, model_htmlback, model_css = self.tryloadankitemplates() tags = globalconfig["ankiconnect"]["tags"] anki.Deck.create(DeckName) diff --git a/LunaTranslator/LunaTranslator/gui/specialwidget.py b/LunaTranslator/LunaTranslator/gui/specialwidget.py index 10369e03..05f9a73d 100644 --- a/LunaTranslator/LunaTranslator/gui/specialwidget.py +++ b/LunaTranslator/LunaTranslator/gui/specialwidget.py @@ -474,7 +474,6 @@ class delayloadvbox(QWidget): self.lock = threading.Lock() self.nowvisregion = QRect() - def resizeEvent(self, e: QResizeEvent): if e.oldSize().width() != e.size().width(): @@ -483,6 +482,7 @@ class delayloadvbox(QWidget): if isinstance(w, QWidget): w.resize(self.width(), w.height()) return super().resizeEvent(e) + def _dovisinternal(self, procevent, region: QRect): if region.isEmpty(): return @@ -544,6 +544,12 @@ class delayloadvbox(QWidget): # setFixedHeight会导致上面的闪烁 self._dovisinternal(False, self.nowvisregion) + def torank1(self, i): + with self.lock: + self.internal_widgets.insert(0, self.internal_widgets.pop(i)) + self.internal_itemH.insert(0, self.internal_itemH.pop(i)) + self._dovisinternal(False, self.nowvisregion) + def insertw(self, i, wf, height): refresh = True with self.lock: @@ -597,6 +603,9 @@ class shrinkableitem(QWidget): def insertw(self, i, wf, height): self.items.insertw(i, wf, height) + def torank1(self, i): + self.items.torank1(i) + def popw(self, i): return self.items.popw(i) diff --git a/LunaTranslator/LunaTranslator/gui/translatorUI.py b/LunaTranslator/LunaTranslator/gui/translatorUI.py index 9d01be5d..f570a72e 100644 --- a/LunaTranslator/LunaTranslator/gui/translatorUI.py +++ b/LunaTranslator/LunaTranslator/gui/translatorUI.py @@ -3,11 +3,11 @@ import time, functools, threading, os, sys, importlib, shutil from traceback import print_exc import windows, qtawesome, gobject, winsharedutils from myutils.wrapper import threader, trypass -from myutils.config import globalconfig, saveallconfig, _TR, static_data +from myutils.config import globalconfig, saveallconfig, _TR, static_data, gamepath2uid from myutils.subproc import endsubprocs from myutils.ocrutil import ocr_run, imageCut from myutils.utils import loadpostsettingwindowmethod, str2rgba -from myutils.hwnd import mouseselectwindow, grabwindow, getExeIcon +from myutils.hwnd import mouseselectwindow, grabwindow, getExeIcon, getpidexe from gui.setting_about import doupdate from gui.dialog_memory import dialog_memory from gui.textbrowser import Textbrowser @@ -381,7 +381,7 @@ class QUnFrameWindow(resizableframeless): "open_relative_link", lambda: browserdialog( gobject.baseobject.commonstylebase, - trypass(lambda: gobject.baseobject.textsource.pname)(), + trypass(lambda: gobject.baseobject.textsource.gameuid)(), ), ), ( @@ -797,6 +797,9 @@ class QUnFrameWindow(resizableframeless): gobject.baseobject.textsource.hwnd = hwnd if pid != _pid else None if not globalconfig["sourcestatus2"]["texthook"]["use"]: gobject.baseobject.textsource.pids = [pid] if pid != _pid else None + gameuid = gamepath2uid.get(getpidexe(pid), None) + if gameuid: + gobject.baseobject.textsource.gameuid = gameuid self.isbindedwindow = pid != _pid self.refreshtoolicon() @@ -1007,7 +1010,7 @@ class QUnFrameWindow(resizableframeless): def tryremoveuseless(self): try: - shutil.rmtree("./cache/temp") + shutil.rmtree(gobject.gettempdir('')) except: pass try: diff --git a/LunaTranslator/LunaTranslator/gui/usefulwidget.py b/LunaTranslator/LunaTranslator/gui/usefulwidget.py index 3faf5b35..e085ee56 100644 --- a/LunaTranslator/LunaTranslator/gui/usefulwidget.py +++ b/LunaTranslator/LunaTranslator/gui/usefulwidget.py @@ -920,8 +920,7 @@ class abstractwebview(QWidget): if len(html) < self.html_limit: self._setHtml(html) else: - os.makedirs("cache/temp", exist_ok=True) - lastcachehtml = os.path.abspath("cache/temp/" + str(time.time()) + ".html") + lastcachehtml = gobject.gettempdir(str(time.time()) + ".html") with open(lastcachehtml, "w", encoding="utf8") as ff: ff.write(html) self.navigate(lastcachehtml) @@ -1665,9 +1664,9 @@ class listediter(QDialog): if self.closecallback: self.closecallback() - def __cb(self, path): - - self.hcmodel.insertRow(0, [QStandardItem(path)]) + def __cb(self, paths): + for path in paths: + self.hcmodel.insertRow(0, [QStandardItem(path)]) def click1(self): @@ -1676,7 +1675,7 @@ class listediter(QDialog): else: openfiledirectory( "", - multi=False, + multi=True, edit=None, isdir=self.ispathsedit.get("isdir", False), filter1=self.ispathsedit.get("filter1", "*.*"), diff --git a/LunaTranslator/LunaTranslator/metadata/abstract.py b/LunaTranslator/LunaTranslator/metadata/abstract.py index 85d293fb..375e7e70 100644 --- a/LunaTranslator/LunaTranslator/metadata/abstract.py +++ b/LunaTranslator/LunaTranslator/metadata/abstract.py @@ -45,19 +45,24 @@ class common: Thread(target=self.__autodownloadimage).start() def __autodownloadimage(self): + def tryremove(pair): + try: + globalconfig["metadata"][self.typename]["downloadtasks"].remove( + list(pair) + ) + except: + pass + while True: - url, save = self.__tasks.get() + pair = self.__tasks.get() + url, save = pair if os.path.exists(save): + tryremove(pair) continue if self.__realdodownload(url, save): - try: - globalconfig["metadata"][self.typename]["downloadtasks"].remove( - (url, save) - ) - except: - pass + tryremove(pair) else: - self.__tasks.put((url, save)) + self.__tasks.put(pair) time.sleep(1) def __realdodownload(self, url, save): @@ -73,36 +78,27 @@ class common: } try: _content = self.proxysession.get(url, headers=headers).content + os.makedirs(os.path.dirname(save), exist_ok=True) with open(save, "wb") as ff: ff.write(_content) return True except: return False - def dispatchdownloadtask(self, url, ishtml=False, delay=True): + def dispatchdownloadtask(self, url): __routine = f"cache/metadata/{self.typename}" if self.typename == "vndb": __routine = "cache/vndb" - os.makedirs(__routine, exist_ok=True) - if ishtml: - __ = ".html" + + if "." in url[5:]: + __ = url[url.rfind(".") :] else: - if "." in url[5:]: - __ = url[url.rfind(".") :] - else: - __ = ".jpg" + __ = ".jpg" savepath = f"{__routine}/{self.b64string(url)}{__}" - if delay: - globalconfig["metadata"][self.typename]["downloadtasks"].append( - (url, savepath) - ) - self.__tasks.put((url, savepath)) - return savepath - else: - if self.__realdodownload(url, savepath): - return savepath - else: - return None + + globalconfig["metadata"][self.typename]["downloadtasks"].append((url, savepath)) + self.__tasks.put((url, savepath)) + return savepath def b64string(self, a): return hashlib.md5(a.encode("utf8")).hexdigest() diff --git a/LunaTranslator/LunaTranslator/metadata/vndb.py b/LunaTranslator/LunaTranslator/metadata/vndb.py index 72f8781a..2afdf606 100644 --- a/LunaTranslator/LunaTranslator/metadata/vndb.py +++ b/LunaTranslator/LunaTranslator/metadata/vndb.py @@ -1,7 +1,7 @@ import requests, re, os from myutils.config import tryreadconfig, safesave import gzip, json -import shutil +import shutil, gobject from metadata.abstract import common @@ -156,14 +156,12 @@ def safedownload(proxy): "https://dl.vndb.org/dump/vndb-tags-latest.json.gz", proxies=proxy, ) - os.makedirs("cache/temp", exist_ok=True) - with open("cache/temp/vndb-tags-latest.json.gz", "wb") as ff: + jsongz = gobject.gettempdir("vndb-tags-latest.json.gz") + jsonfile = gobject.gettempdir("vndb-tags-latest.json") + with open(jsongz, "wb") as ff: ff.write(resp.content) - decompress_gzip_file( - "cache/temp/vndb-tags-latest.json.gz", - "cache/temp/vndb-tags-latest.json", - ) - with open("cache/temp/vndb-tags-latest.json", "r", encoding="utf8") as ff: + decompress_gzip_file(jsongz, jsonfile) + with open(jsonfile, "r", encoding="utf8") as ff: js = json.load(ff) newjs = {} for item in js: @@ -215,18 +213,6 @@ def getvntagsbyid(proxy, vid): return tags - -def gettagfromhtml(path): - if path and os.path.exists(path): - with open(path, "r", encoding="utf8") as ff: - html = ff.read() - find = re.search('
([\\s\\S]*?)
', html) - if find: - html = find.groups()[0] - return [_[1] for _ in re.findall("(.*?)", html)] - return [] - - class searcher(common): def refmainpage(self, _id): @@ -238,8 +224,27 @@ class searcher(common): return int(vid[1:]) return None + def gettagfromhtml(self, _vid): + + headers = { + "sec-ch-ua": '"Microsoft Edge";v="113", "Chromium";v="113", "Not-A.Brand";v="24"', + "Referer": "https://vndb.org/", + "sec-ch-ua-mobile": "?0", + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36 Edg/113.0.1774.42", + "sec-ch-ua-platform": '"Windows"', + } + try: + html = self.proxysession.get(self.refmainpage(_vid), headers=headers).text + except: + return [] + find = re.search('
([\\s\\S]*?)
', html) + if find: + html = find.groups()[0] + return [_[1] for _ in re.findall("(.*?)", html)] + else: + return [] + def searchfordata(self, _vid): - os.makedirs("./cache/vndb", exist_ok=True) vid = "v{}".format(_vid) img = getimgbyid(self.proxy, vid) title = gettitlebyid(self.proxy, vid) @@ -247,11 +252,7 @@ class searcher(common): vndbtags = [] # getvntagsbyid(self.proxy, vid) #这个东西谜之慢 if len(vndbtags) == 0: # 没代理时下不动那个tag的json - vndbtags = gettagfromhtml( - self.dispatchdownloadtask( - self.refmainpage(_vid), ishtml=True, delay=False - ) - ) + vndbtags = self.gettagfromhtml(_vid) developers = getdevelopersbyid(self.proxy, vid) try: imagepath_much2 = [ diff --git a/LunaTranslator/LunaTranslator/myutils/config.py b/LunaTranslator/LunaTranslator/myutils/config.py index 99b15bb3..8d5add2e 100644 --- a/LunaTranslator/LunaTranslator/myutils/config.py +++ b/LunaTranslator/LunaTranslator/myutils/config.py @@ -4,22 +4,23 @@ from traceback import print_exc def tryreadconfig(path, default=None): + path = os.path.join("userconfig", path) + if not os.path.exists(path): + path += ".tmp" + dfret = default if default else {} + if not os.path.exists(path): + return dfret try: - path = os.path.join("./userconfig/", path) - if os.path.exists(path) == False: - path += ".tmp" - if os.path.exists(path): - with open(path, "r", encoding="utf-8") as ff: - x = json.load(ff) - else: - x = default if default else {} + with open(path, "r", encoding="utf-8") as ff: + x = json.load(ff) + return x except: - return {} + return dfret def tryreadconfig2(path): - path = os.path.join("./files/defaultconfig/", path) + path = os.path.join("files/defaultconfig", path) with open(path, "r", encoding="utf-8") as ff: x = json.load(ff) return x @@ -41,25 +42,67 @@ magpie_config = tryreadconfig("magpie_config.json") postprocessconfig = tryreadconfig("postprocessconfig.json") noundictconfig = tryreadconfig("noundictconfig.json") transerrorfixdictconfig = tryreadconfig("transerrorfixdictconfig.json") -_savehook = tryreadconfig("savehook_new_1.39.4.json", default=[[], {}]) -try: +_savehook = tryreadconfig("savegamedata_5.3.1.json") +if _savehook: + # 新版 + # savehook_new_list: [uid,...] + # savehook_new_data:{uid:dict,...} + # savegametaged:[ None, {'games':[uid,...],'title':str,'opened':bool,'uid':str},...] + # gamepath2uid:{gamepath:uid} savehook_new_list = _savehook[0] savehook_new_data = _savehook[1] -except: - savehook_new_list = [] - savehook_new_data = {} - -try: savegametaged = _savehook[2] -except: - savegametaged = [None] + gamepath2uid = _savehook[3] +else: + _savehook = tryreadconfig("savehook_new_1.39.4.json", default=[[], {}]) + + # savehook_new_list: [gamepath,...] + # savehook_new_data:{gamepath:dict,...} + # savegametaged: 可能没有该项 [ None, {'games':[gamepath,...],'title':str,'opened':bool,'uid':str},...] + try: + savehook_new_list = _savehook[0] + savehook_new_data = _savehook[1] + except: + savehook_new_list = [] + savehook_new_data = {} + + try: + savegametaged = _savehook[2] + except: + savegametaged = [None] + + # 将savehook_new_data转换为新的格式 + gamepath2uid = {} + __savehook_new_data = {} + for k in savehook_new_data: + uid = f"{time.time()}_{uuid.uuid4()}" + + __savehook_new_data[uid] = savehook_new_data[k] + __savehook_new_data[uid].update(gamepath=k) + gamepath2uid[k] = uid + savehook_new_data = __savehook_new_data + + # 将global游戏表和自定义子列表都转换成新格式 + def parselist(ls): + for i in range(len(ls)): + ori = ls[i] + if ori not in gamepath2uid: + continue + ls[i] = gamepath2uid[ori] + + parselist(savehook_new_list) + for sub in savegametaged: + if sub is None: + continue + parselist(sub["games"]) translatorsetting = tryreadconfig("translatorsetting.json") ocrsetting = tryreadconfig("ocrsetting.json") def getdefaultsavehook(gamepath, title=None): default = { + # "gamepath": gamepath, "hooksetting_follow_default": True, "hooksetting_private": {}, # 显示时再加载,缺省用global中的键 "textproc_follow_default": True, @@ -71,6 +114,8 @@ def getdefaultsavehook(gamepath, title=None): "lang_follow_default": True, # "private_srclang": 0,# 显示时再加载,缺省用global中的键 # "private_tgtlang": 0, + "follow_default_ankisettings": True, + # "anki_DeckName":str "localeswitcher": 0, "onloadautochangemode2": 0, "needinserthookcode": [], @@ -132,19 +177,31 @@ def getdefaultsavehook(gamepath, title=None): _dfsavehook = getdefaultsavehook("") -for game in savehook_new_data: +for uid in savehook_new_data: if ( - ("allow_tts_auto_names_v4" not in savehook_new_data[game]) - and ("allow_tts_auto_names" in savehook_new_data[game]) - and len(savehook_new_data[game]["allow_tts_auto_names"]) + ("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"]) ): - savehook_new_data[game]["allow_tts_auto_names_v4"] = savehook_new_data[game][ + savehook_new_data[uid]["allow_tts_auto_names_v4"] = savehook_new_data[uid][ "allow_tts_auto_names" ].split("|") for k in _dfsavehook: - if k not in savehook_new_data[game]: - savehook_new_data[game][k] = _dfsavehook[k] + if k not in savehook_new_data[uid]: + savehook_new_data[uid][k] = _dfsavehook[k] + + +class __uid2gamepath: + def __setitem__(self, uid, value): + + savehook_new_data[uid]["gamepath"] = value + + def __getitem__(self, uid): + return savehook_new_data.get(uid, {}).get("gamepath", None) + + +uid2gamepath = __uid2gamepath() def syncconfig(config1, default, drop=False, deep=0, skipdict=False): @@ -367,8 +424,8 @@ def saveallconfig(): safesave("./userconfig/ocrerrorfix.json", ocrerrorfix) safesave("./userconfig/ocrsetting.json", ocrsetting) safesave( - "./userconfig/savehook_new_1.39.4.json", - [savehook_new_list, savehook_new_data, savegametaged], + "./userconfig/savegamedata_5.3.1.json", + [savehook_new_list, savehook_new_data, savegametaged, gamepath2uid], ) safesave( "./files/lang/{}.json".format(getlanguse()), diff --git a/LunaTranslator/LunaTranslator/myutils/hwnd.py b/LunaTranslator/LunaTranslator/myutils/hwnd.py index b73fe923..d3d39d1f 100644 --- a/LunaTranslator/LunaTranslator/myutils/hwnd.py +++ b/LunaTranslator/LunaTranslator/myutils/hwnd.py @@ -10,21 +10,19 @@ from myutils.wrapper import threader @threader def grabwindow(app="PNG", callback=None): if callback: - fnamebase = "cache/temp" + fname = gobject.gettempdir(time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime())) else: - fnamebase = "cache/screenshot/{}".format(0) + dirname = "0" + try: if gobject.baseobject.textsource.md5 != "0": - fnamebase = "cache/screenshot/{}".format( - gobject.baseobject.textsource.basename - ) + dirname = gobject.baseobject.textsource.basename except: pass - if os.path.exists(fnamebase) == False: - os.mkdir(fnamebase) - fname = "{}/{}".format( - fnamebase, time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime()) - ) + fname = gobject.getcachedir( + f"screenshot/{dirname}/" + + time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime()), + ) hwnd = windows.FindWindow( "Window_Magpie_967EB565-6F73-4E94-AE53-00CC42592A22", None @@ -154,8 +152,9 @@ def getExeIcon(name, icon=True, cache=False): name = exepath data = winsharedutils.extracticon2data(name) if cache: - os.makedirs("./cache/icon", exist_ok=True) - fn = "./cache/icon/{}.bmp".format(hashlib.md5(name.encode("utf8")).hexdigest()) + fn = gobject.getcachedir( + "icon/{}.bmp".format(hashlib.md5(name.encode("utf8")).hexdigest()) + ) if data: pixmap = QPixmap() pixmap.loadFromData(data) diff --git a/LunaTranslator/LunaTranslator/myutils/post.py b/LunaTranslator/LunaTranslator/myutils/post.py index 98ad0269..7b0c25b4 100644 --- a/LunaTranslator/LunaTranslator/myutils/post.py +++ b/LunaTranslator/LunaTranslator/myutils/post.py @@ -373,22 +373,24 @@ def POSTSOLVE(line): usemypostpath = "./userconfig/mypost.py" usemodule = "mypost" try: - if gobject.baseobject.textsource and ("pname" in dir(gobject.baseobject.textsource)): - exepath = gobject.baseobject.textsource.pname - if not savehook_new_data[exepath]["textproc_follow_default"]: - useranklist = savehook_new_data[exepath]["save_text_process_info"][ + if gobject.baseobject.textsource: + gameuid = gobject.baseobject.textsource.gameuid + if gameuid and not savehook_new_data[gameuid]["textproc_follow_default"]: + useranklist = savehook_new_data[gameuid]["save_text_process_info"][ "rank" ] - usedpostprocessconfig = savehook_new_data[exepath][ + usedpostprocessconfig = savehook_new_data[gameuid][ "save_text_process_info" ]["postprocessconfig"] - if savehook_new_data[exepath]["save_text_process_info"]["mypost"]: + if savehook_new_data[gameuid]["save_text_process_info"].get( + "mypost", None + ): usemodule = ( "posts." - + savehook_new_data[exepath]["save_text_process_info"]["mypost"] + + savehook_new_data[gameuid]["save_text_process_info"]["mypost"] ) usemypostpath = "./userconfig/posts/{}.py".format( - savehook_new_data[exepath]["save_text_process_info"]["mypost"] + savehook_new_data[gameuid]["save_text_process_info"]["mypost"] ) except: print_exc() diff --git a/LunaTranslator/LunaTranslator/myutils/utils.py b/LunaTranslator/LunaTranslator/myutils/utils.py index 6642bf54..1f2b629e 100644 --- a/LunaTranslator/LunaTranslator/myutils/utils.py +++ b/LunaTranslator/LunaTranslator/myutils/utils.py @@ -3,7 +3,7 @@ import os, time from traceback import print_exc import codecs, hashlib import os, time -import socket, gobject +import socket, gobject, uuid import ctypes, importlib import time import ctypes.wintypes @@ -15,7 +15,8 @@ from myutils.config import ( static_data, getlanguse, savehook_new_data, - _TR, + uid2gamepath, + gamepath2uid, getdefaultsavehook, ) from ctypes import c_float, pointer, c_void_p @@ -30,14 +31,15 @@ def __internal__getlang(k1, k2): if not gobject.baseobject.textsource: break - if "pname" not in dir(gobject.baseobject.textsource): + + gameuid = gobject.baseobject.textsource.gameuid + if not gameuid: break - exepath = gobject.baseobject.textsource.pname - if savehook_new_data[exepath]["lang_follow_default"]: + if savehook_new_data[gameuid]["lang_follow_default"]: break return static_data["language_list_translator_inner"][ - savehook_new_data[exepath][k1] + savehook_new_data[gameuid][k1] ] except: pass @@ -116,16 +118,18 @@ class PriorityQueue: searchvndbqueue = PriorityQueue() -def guessmaybetitle(gamepath): +def guessmaybetitle(gamepath, title): __t = [] print(gamepath) for _ in [ - savehook_new_data[gamepath]["title"], + title, os.path.basename(os.path.dirname(gamepath)), os.path.basename(gamepath)[:-4], ]: + if not title: + continue _ = _.replace("(同人ゲーム)", "").replace("(18禁ゲーム)", "") _ = re.sub(r"\[RJ(.*?)\]", "", _) _ = re.sub(r"\[\d{4}-?\d{2}\-?\d{2}\]", "", _) @@ -150,7 +154,7 @@ def guessmaybetitle(gamepath): targetmod = {} -def trysearchforid(gamepath, searchargs: list): +def trysearchforid(gameuid, searchargs: list): infoid = None primitivtemetaorigin = globalconfig["primitivtemetaorigin"] __ = list(targetmod.keys()) @@ -168,17 +172,17 @@ def trysearchforid(gamepath, searchargs: list): if not vid: continue idname = globalconfig["metadata"][key]["target"] - savehook_new_data[gamepath][idname] = vid + savehook_new_data[gameuid][idname] = vid if infoid is None or key == primitivtemetaorigin: infoid = key, vid if key == primitivtemetaorigin: break if infoid: - searchvndbqueue.put((1, gamepath, infoid)) + searchvndbqueue.put((1, gameuid, infoid)) return infoid -def trysearchfordata(gamepath, key, vid): +def trysearchfordata(gameuid, key, vid): try: data = targetmod[key].searchfordata(vid) except: @@ -193,34 +197,34 @@ def trysearchfordata(gamepath, key, vid): for _ in imagepath_all: if _ is None: continue - if _ not in savehook_new_data[gamepath]["imagepath_all"]: - savehook_new_data[gamepath]["imagepath_all"].append(_) + if _ not in savehook_new_data[gameuid]["imagepath_all"]: + savehook_new_data[gameuid]["imagepath_all"].append(_) if title: - if not savehook_new_data[gamepath]["istitlesetted"]: - savehook_new_data[gamepath]["title"] = title + if not savehook_new_data[gameuid]["istitlesetted"]: + savehook_new_data[gameuid]["title"] = title _vis = globalconfig["metadata"][key]["name"] _url = targetmod[key].refmainpage(vid) - _urls = [_[1] for _ in savehook_new_data[gamepath]["relationlinks"]] + _urls = [_[1] for _ in savehook_new_data[gameuid]["relationlinks"]] if _url not in _urls: - savehook_new_data[gamepath]["relationlinks"].append( + savehook_new_data[gameuid]["relationlinks"].append( (_vis, targetmod[key].refmainpage(vid)) ) if namemap: - savehook_new_data[gamepath]["namemap"] = namemap + savehook_new_data[gameuid]["namemap"] = namemap if len(webtags): - savehook_new_data[gamepath]["webtags"] = webtags + savehook_new_data[gameuid]["webtags"] = webtags if len(developers): - savehook_new_data[gamepath]["developers"] = developers + savehook_new_data[gameuid]["developers"] = developers return True def everymethodsthread(): while True: _ = searchvndbqueue.get() - _type, gamepath, arg = _ + _type, gameuid, arg = _ try: if _type == 0: - infoid = trysearchforid(gamepath, arg) + infoid = trysearchforid(gameuid, arg) key, vid = infoid gobject.baseobject.translation_ui.displayglobaltooltip.emit( f"{key}: found {vid}" @@ -228,7 +232,7 @@ def everymethodsthread(): elif _type == 1: key, vid = arg - if trysearchfordata(gamepath, key, vid): + if trysearchfordata(gameuid, key, vid): gobject.baseobject.translation_ui.displayglobaltooltip.emit( f"{key}: {vid} data loaded" ) @@ -241,8 +245,8 @@ def everymethodsthread(): print_exc() -def gamdidchangedtask(key, idname, gamepath): - vid = savehook_new_data[gamepath][idname] +def gamdidchangedtask(key, idname, gameuid): + vid = savehook_new_data[gameuid][idname] if vid == "": return else: @@ -253,26 +257,34 @@ def gamdidchangedtask(key, idname, gamepath): except: print(vid) return - savehook_new_data[gamepath][idname] = vid - searchvndbqueue.put((1, gamepath, (key, vid)), 1) + savehook_new_data[gameuid][idname] = vid + searchvndbqueue.put((1, gameuid, (key, vid)), 1) except: print_exc() -def titlechangedtask(gamepath, title): - savehook_new_data[gamepath]["title"] = title - savehook_new_data[gamepath]["istitlesetted"] = True - searchvndbqueue.put((0, gamepath, [title]), 1) +def titlechangedtask(gameuid, title): + savehook_new_data[gameuid]["title"] = title + savehook_new_data[gameuid]["istitlesetted"] = True + searchvndbqueue.put((0, gameuid, [title]), 1) def checkifnewgame(targetlist, gamepath, title=None): - isnew = gamepath not in targetlist + if gamepath not in gamepath2uid: + uid = f"{time.time()}_{uuid.uuid4()}" + gamepath2uid[gamepath] = uid + savehook_new_data[uid] = getdefaultsavehook(gamepath, title) + + uid2gamepath[uid] = gamepath + searchvndbqueue.put((0, uid, [title] + guessmaybetitle(gamepath, title))) + else: + uid = gamepath2uid[gamepath] + isnew = uid not in targetlist if isnew: - targetlist.insert(0, gamepath) - if gamepath not in savehook_new_data: - savehook_new_data[gamepath] = getdefaultsavehook(gamepath, title) - searchvndbqueue.put((0, gamepath, [title] + guessmaybetitle(gamepath))) - return isnew + targetlist.insert(0, uid) + return uid + else: + return None kanjichs2ja = str.maketrans(static_data["kanjichs2ja"]) diff --git a/LunaTranslator/LunaTranslator/ocrengines/mangaocr.py b/LunaTranslator/LunaTranslator/ocrengines/mangaocr.py index bd6ec799..2586c7cb 100644 --- a/LunaTranslator/LunaTranslator/ocrengines/mangaocr.py +++ b/LunaTranslator/LunaTranslator/ocrengines/mangaocr.py @@ -1,15 +1,12 @@ import requests from ocrengines.baseocrclass import baseocr -import os, uuid -from myutils.ocrutil import binary2qimage - +import os, uuid, gobject class OCR(baseocr): def ocr(self, imagebinary): - os.makedirs("cache/temp", exist_ok=True) - fname = "cache/temp/" + str(uuid.uuid4()) + ".png" + fname = gobject.gettempdir(str(uuid.uuid4()) + ".png") with open(fname, "wb") as ff: ff.write(imagebinary) self.checkempty(["Port"]) diff --git a/LunaTranslator/LunaTranslator/ocrengines/tesseract5.py b/LunaTranslator/LunaTranslator/ocrengines/tesseract5.py index 9821ffaf..a44bd4b0 100644 --- a/LunaTranslator/LunaTranslator/ocrengines/tesseract5.py +++ b/LunaTranslator/LunaTranslator/ocrengines/tesseract5.py @@ -1,4 +1,4 @@ -import os, uuid +import os, uuid, gobject from myutils.config import _TR, ocrsetting from ocrengines.baseocrclass import baseocr from myutils.subproc import subproc_w @@ -24,8 +24,7 @@ class OCR(baseocr): if os.path.exists(path) == False: raise Exception(_TR("路径不存在")) - os.makedirs("cache/temp", exist_ok=True) - fname = "cache/temp/" + str(uuid.uuid4()) + ".png" + fname = gobject.gettempdir(str(uuid.uuid4()) + ".png") with open(fname, "wb") as ff: ff.write(imagebinary) imgfile = os.path.abspath(fname) diff --git a/LunaTranslator/LunaTranslator/qtsymbols.py b/LunaTranslator/LunaTranslator/qtsymbols.py index 32f241c2..1de72275 100644 --- a/LunaTranslator/LunaTranslator/qtsymbols.py +++ b/LunaTranslator/LunaTranslator/qtsymbols.py @@ -1,8 +1,8 @@ try: from PyQt5 import QtSvg - from PyQt5.QtWidgets import QFrame,QListView,QCheckBox,QAbstractItemView,QTextEdit,QTableView,QHeaderView,QColorDialog,QSpinBox,QDoubleSpinBox,QComboBox,QDialogButtonBox,QMainWindow,QMessageBox,QDialog,QGridLayout,QTextBrowser,QGraphicsDropShadowEffect,QWidget,QSizePolicy,QScrollArea,QApplication,QPushButton,QSystemTrayIcon,QPlainTextEdit,QAction,QMenu,QFileDialog,QKeySequenceEdit,QLabel,QSpacerItem,QWidgetItem,QLayout,QTextBrowser,QLineEdit,QFormLayout,QSizePolicy,QTabWidget,QTabBar,QSplitter,QListWidget,QListWidgetItem,QHBoxLayout,QVBoxLayout,QSizeGrip,QFontComboBox,QProgressBar,QRadioButton,QButtonGroup,QSlider,QToolTip,QGroupBox + from PyQt5.QtWidgets import QFrame,QListView,QCheckBox,QAbstractItemView,QTextEdit,QTableView,QHeaderView,QColorDialog,QSpinBox,QDoubleSpinBox,QComboBox,QDialogButtonBox,QMainWindow,QMessageBox,QDialog,QGridLayout,QTextBrowser,QGraphicsDropShadowEffect,QWidget,QSizePolicy,QScrollArea,QApplication,QPushButton,QSystemTrayIcon,QPlainTextEdit,QAction,QMenu,QFileDialog,QKeySequenceEdit,QLabel,QSpacerItem,QWidgetItem,QLayout,QTextBrowser,QLineEdit,QFormLayout,QSizePolicy,QTabWidget,QTabBar,QSplitter,QListWidget,QListWidgetItem,QHBoxLayout,QVBoxLayout,QSizeGrip,QFontComboBox,QProgressBar,QRadioButton,QButtonGroup,QSlider,QToolTip,QGroupBox,QGraphicsOpacityEffect from PyQt5.QtGui import QIconEngine,QIntValidator,QStandardItem,QStandardItemModel,QImageWriter,QIcon,QTextCharFormat,QTextBlockFormat,QResizeEvent,QTextCursor,QFontMetricsF,QMouseEvent,QImage,QPainter,QRegion,QCloseEvent,QFontDatabase,QKeySequence,QPixmap,QCursor,QColor,QFont,QPen,QPainterPath,QBrush,QFontMetrics,QShowEvent,QWheelEvent,QPaintEvent - from PyQt5.QtCore import QObject,pyqtSignal,Qt,QSize,QByteArray,QBuffer,QPointF,QPoint,QRect,QEvent,QModelIndex,QTimer,QRectF,QVariantAnimation,QUrl + from PyQt5.QtCore import QObject,pyqtSignal,Qt,QSize,QByteArray,QBuffer,QPointF,QPoint,QRect,QEvent,QModelIndex,QTimer,QRectF,QVariantAnimation,QUrl,QPropertyAnimation isqt5 = True class LineHeightTypes: LineDistanceHeight=QTextBlockFormat.LineHeightTypes.LineDistanceHeight @@ -11,9 +11,9 @@ except: #from traceback import print_exc #print_exc() from PyQt6 import QtSvg - from PyQt6.QtWidgets import QFrame,QListView,QCheckBox,QAbstractItemView,QTextEdit,QTableView,QHeaderView,QColorDialog,QSpinBox,QDoubleSpinBox,QComboBox,QDialogButtonBox,QMainWindow,QMessageBox,QDialog,QGridLayout,QTextBrowser,QGraphicsDropShadowEffect,QWidget,QSizePolicy,QScrollArea,QApplication,QPushButton,QSystemTrayIcon,QPlainTextEdit,QMenu,QFileDialog,QKeySequenceEdit,QLabel,QSpacerItem,QWidgetItem,QLayout,QTextBrowser,QLineEdit,QFormLayout,QSizePolicy,QTabWidget,QTabBar,QSplitter,QListWidget,QListWidgetItem,QHBoxLayout,QVBoxLayout,QSizeGrip,QFontComboBox,QProgressBar,QRadioButton,QButtonGroup,QSlider,QToolTip,QGroupBox + from PyQt6.QtWidgets import QFrame,QListView,QCheckBox,QAbstractItemView,QTextEdit,QTableView,QHeaderView,QColorDialog,QSpinBox,QDoubleSpinBox,QComboBox,QDialogButtonBox,QMainWindow,QMessageBox,QDialog,QGridLayout,QTextBrowser,QGraphicsDropShadowEffect,QWidget,QSizePolicy,QScrollArea,QApplication,QPushButton,QSystemTrayIcon,QPlainTextEdit,QMenu,QFileDialog,QKeySequenceEdit,QLabel,QSpacerItem,QWidgetItem,QLayout,QTextBrowser,QLineEdit,QFormLayout,QSizePolicy,QTabWidget,QTabBar,QSplitter,QListWidget,QListWidgetItem,QHBoxLayout,QVBoxLayout,QSizeGrip,QFontComboBox,QProgressBar,QRadioButton,QButtonGroup,QSlider,QToolTip,QGroupBox,QGraphicsOpacityEffect from PyQt6.QtGui import QIconEngine,QIntValidator,QAction,QStandardItem,QStandardItemModel,QImageWriter,QIcon,QTextCharFormat,QTextBlockFormat,QResizeEvent,QTextCursor,QFontMetricsF,QMouseEvent,QImage,QPainter,QRegion,QCloseEvent,QFontDatabase,QKeySequence,QPixmap,QCursor,QColor,QFont,QPen,QPainterPath,QBrush,QFontMetrics,QShowEvent,QWheelEvent,QPaintEvent - from PyQt6.QtCore import QObject,pyqtSignal,Qt,QSize,QByteArray,QBuffer,QPointF,QPoint,QRect,QEvent,QModelIndex,QTimer,QRectF,QVariantAnimation,QUrl + from PyQt6.QtCore import QObject,pyqtSignal,Qt,QSize,QByteArray,QBuffer,QPointF,QPoint,QRect,QEvent,QModelIndex,QTimer,QRectF,QVariantAnimation,QUrl,QPropertyAnimation isqt5 = False class LineHeightTypes: diff --git a/LunaTranslator/LunaTranslator/scalemethod/magpie_builtin.py b/LunaTranslator/LunaTranslator/scalemethod/magpie_builtin.py index 5da0684e..1c788802 100644 --- a/LunaTranslator/LunaTranslator/scalemethod/magpie_builtin.py +++ b/LunaTranslator/LunaTranslator/scalemethod/magpie_builtin.py @@ -1,6 +1,6 @@ from scalemethod.base import scalebase import os, json -import windows +import windows, gobject from myutils.config import globalconfig, magpie_config from myutils.subproc import subproc_w from myutils.wrapper import threader @@ -25,8 +25,7 @@ class Method(scalebase): def init(self): self.statuslistener() - os.makedirs("cache/temp", exist_ok=True) - self.jspath = os.path.abspath("cache/temp/magpie.config.json") + self.jspath = gobject.gettempdir("magpie.config.json") self.engine = subproc_w( './files/plugins/Magpie/Magpie.Core.exe "{}"'.format(self.jspath), cwd="./files/plugins/Magpie/", diff --git a/LunaTranslator/LunaTranslator/textsource/texthook.py b/LunaTranslator/LunaTranslator/textsource/texthook.py index e8f2e582..cb05095f 100644 --- a/LunaTranslator/LunaTranslator/textsource/texthook.py +++ b/LunaTranslator/LunaTranslator/textsource/texthook.py @@ -10,6 +10,8 @@ from textsource.textsourcebase import basetext from myutils.utils import checkchaos from myutils.hwnd import injectdll from myutils.wrapper import threader +from myutils.utils import getfilemd5 + from ctypes import ( CDLL, CFUNCTYPE, @@ -85,7 +87,7 @@ EmbedCallback = CFUNCTYPE(None, c_wchar_p, ThreadParam) class texthook(basetext): @property def config(self): - if savehook_new_data[self.pname]["hooksetting_follow_default"]: + if savehook_new_data[self.gameuid]["hooksetting_follow_default"]: return globalconfig else: @@ -96,22 +98,24 @@ class texthook(basetext): else: return globalconfig[key] - return __shitdict(savehook_new_data[self.pname]["hooksetting_private"]) + return __shitdict(savehook_new_data[self.gameuid]["hooksetting_private"]) def __init__( - self, pids, hwnd, pname, autostarthookcode=None, needinserthookcode=None + self, + pids, + hwnd, + gamepath, + gameuid, + autostarthookcode=None, + needinserthookcode=None, ): if autostarthookcode is None: autostarthookcode = [] if needinserthookcode is None: needinserthookcode = [] - self.pname = pname - self.pids = pids - self.hwnd = hwnd self.keepref = [] self.newline = Queue() self.newline_delaywait = Queue() - self.is64bit = Is64bit(pids[0]) self.hookdatacollecter = OrderedDict() self.hooktypecollecter = OrderedDict() self.currentname = None @@ -119,30 +123,41 @@ class texthook(basetext): self.forward = [] self.selectinghook = None self.selectedhook = [] + self.showonce = False self.selectedhookidx = [] - self.allow_set_text_name = self.config["allow_set_text_name"] self.connectedpids = [] self.runonce_line = "" self.autostarthookcode = [self.deserial(__) for __ in autostarthookcode] - self.isremoveuseless = self.config["removeuseless"] and len( - self.autostarthookcode - ) + self.needinserthookcode = needinserthookcode self.removedaddress = [] + super(texthook, self).__init__(*self.checkmd5prefix(gamepath)) + self.gamepath = gamepath + self.gameuid = gameuid + self.pids = pids + self.is64bit = Is64bit(pids[0]) + self.hwnd = hwnd gobject.baseobject.hookselectdialog.changeprocessclearsignal.emit(self.config) + self.allow_set_text_name = self.config["allow_set_text_name"] + self.isremoveuseless = self.config["removeuseless"] and len( + self.autostarthookcode + ) if ( len(autostarthookcode) == 0 - and len(savehook_new_data[self.pname]["embedablehook"]) == 0 + and len(savehook_new_data[self.gameuid]["embedablehook"]) == 0 ): gobject.baseobject.hookselectdialog.realshowhide.emit(True) - self.delaycollectallselectedoutput() - - super(texthook, self).__init__(*self.checkmd5prefix(pname)) self.declare() - self.start() + + def checkmd5prefix(self, gamepath): + md5 = getfilemd5(gamepath) + name = os.path.basename(gamepath).replace( + "." + os.path.basename(gamepath).split(".")[-1], "" + ) + return md5, name def declare(self): LunaHost = CDLL( @@ -254,14 +269,24 @@ class texthook(basetext): def onprocconnect(self, pid): self.connectedpids.append(pid) - time.sleep(savehook_new_data[self.pname]["inserthooktimeout"] / 1000) + time.sleep(savehook_new_data[self.gameuid]["inserthooktimeout"] / 1000) for hookcode in self.needinserthookcode: self.Luna_InsertHookCode(pid, hookcode) self.showgamename() self.flashembedsettings(pid) + def showgamename(self): + if self.showonce: + return + self.showonce = False + gobject.baseobject.textgetmethod( + "" + savehook_new_data[self.gameuid]["title"] + ) + def newhookinsert(self, addr, hcode): - for _hc, _addr, _ctx1, _ctx2 in savehook_new_data[self.pname]["embedablehook"]: + for _hc, _addr, _ctx1, _ctx2 in savehook_new_data[self.gameuid][ + "embedablehook" + ]: if hcode == _hc: self.useembed(addr, _ctx1, _ctx2, True) @@ -339,8 +364,8 @@ class texthook(basetext): self.hookdatacollecter[key] = [] self.hooktypecollecter[key] = 0 if self.allow_set_text_name: - for jskey in savehook_new_data[self.pname]["hooktypeasname"]: - if savehook_new_data[self.pname]["hooktypeasname"][jskey] == 0: + for jskey in savehook_new_data[self.gameuid]["hooktypeasname"]: + if savehook_new_data[self.gameuid]["hooktypeasname"][jskey] == 0: continue if self.match_compatibility(self.deserial(json.loads(jskey)), key): self.hooktypecollecter[key] = 1 @@ -396,7 +421,7 @@ class texthook(basetext): usestruct.searchTime = 30000 usestruct.maxRecords = 100000 usestruct.codepage = self.codepage() - usestruct.boundaryModule = os.path.basename(self.pname) + usestruct.boundaryModule = os.path.basename(self.gamepath) usestruct.jittype = 0 return usestruct @@ -462,8 +487,6 @@ class texthook(basetext): self.newline.put(_collector) self.runonce_line = _collector collector.clear() - - def handle_output(self, hc, hn, tp, output): diff --git a/LunaTranslator/LunaTranslator/textsource/textsourcebase.py b/LunaTranslator/LunaTranslator/textsource/textsourcebase.py index 2ad94a1e..03845fa2 100644 --- a/LunaTranslator/LunaTranslator/textsource/textsourcebase.py +++ b/LunaTranslator/LunaTranslator/textsource/textsourcebase.py @@ -2,28 +2,30 @@ import threading, gobject, queue import time, sqlite3, json, os from traceback import print_exc from myutils.config import globalconfig, savehook_new_data -from myutils.utils import getfilemd5, autosql +from myutils.utils import autosql class basetext: + def __init__(self, md5, basename): - self.textgetmethod = gobject.baseobject.textgetmethod - self.ending = False - self.sqlqueue = queue.Queue() - if "hwnd" not in dir(self): - self.hwnd = 0 - if "pids" not in dir(self): - self.pids = [] self.md5 = md5 self.basename = basename - os.makedirs("./translation_record", exist_ok=True) - sqlfname_all_old = ( - "./translation_record/" + md5 + "_" + basename + ".pretrans_common.sqlite" + self.hwnd = None + self.pids = [] + self.gameuid = None + # + + self.textgetmethod = gobject.baseobject.textgetmethod + + self.ending = False + self.sqlqueue = queue.Queue() + + sqlfname_all_old = gobject.gettranslationrecorddir( + md5 + "_" + basename + ".pretrans_common.sqlite" ) - sqlfname_all = "./translation_record/" + basename + "_" + md5 + ".sqlite" + sqlfname_all = gobject.gettranslationrecorddir(basename + "_" + md5 + ".sqlite") if os.path.exists(sqlfname_all_old): sqlfname_all = sqlfname_all_old - self.uuname = basename + "_" + md5 try: # self.sqlwrite=sqlite3.connect(self.sqlfname,check_same_thread = False, isolation_level=None) @@ -74,7 +76,7 @@ class basetext: "SELECT * FROM artificialtrans WHERE source = ?", (src,) ).fetchone() try: - savehook_new_data[self.pname]["statistic_wordcount"] += lensrc + savehook_new_data[self.gameuid]["statistic_wordcount"] += lensrc except: pass if ret is None: @@ -89,7 +91,7 @@ class basetext: (src, json.dumps({})), ) try: - savehook_new_data[self.pname][ + savehook_new_data[self.gameuid][ "statistic_wordcount_nodump" ] += lensrc except: @@ -111,20 +113,6 @@ class basetext: except: print_exc() - def checkmd5prefix(self, pname): - md5 = getfilemd5(pname) - name = os.path.basename(pname).replace( - "." + os.path.basename(pname).split(".")[-1], "" - ) - return md5, name - - def showgamename(self): - if "showonce" not in dir(self): - gobject.baseobject.textgetmethod( - "" + savehook_new_data[self.pname]["title"] - ) - self.showonce = 1 - def gettextthread_(self): while True: if self.ending: diff --git a/LunaTranslator/LunaTranslator/translator/DeepLX.py b/LunaTranslator/LunaTranslator/translator/DeepLX.py index fb6ff85b..e41880e0 100644 --- a/LunaTranslator/LunaTranslator/translator/DeepLX.py +++ b/LunaTranslator/LunaTranslator/translator/DeepLX.py @@ -10,7 +10,7 @@ class TS(basetrans): return x # {"zh":"ZH","ja":"JA","en":"EN","es":"ES","fr":"FR","ru":"RU"} def translate(self, query): - + self.checkempty(["api"]) payload = { "text": query, "source_lang": self.srclang, diff --git a/LunaTranslator/LunaTranslator/translator/basetranslator.py b/LunaTranslator/LunaTranslator/translator/basetranslator.py index 1bfa1aef..70acc06f 100644 --- a/LunaTranslator/LunaTranslator/translator/basetranslator.py +++ b/LunaTranslator/LunaTranslator/translator/basetranslator.py @@ -109,10 +109,12 @@ class basetrans(commonbase): if self.transtype != "pre": try: - os.makedirs("./translation_record/cache", exist_ok=True) + self.sqlwrite2 = autosql( sqlite3.connect( - "./translation_record/cache/{}.sqlite".format(self.typename), + gobject.gettranslationrecorddir( + "cache/{}.sqlite".format(self.typename) + ), check_same_thread=False, isolation_level=None, ) diff --git a/LunaTranslator/LunaTranslator/translator/premt.py b/LunaTranslator/LunaTranslator/translator/premt.py index 28e9c3e5..418a5d04 100644 --- a/LunaTranslator/LunaTranslator/translator/premt.py +++ b/LunaTranslator/LunaTranslator/translator/premt.py @@ -11,8 +11,8 @@ import winsharedutils class TS(basetrans): def unsafegetcurrentgameconfig(self): try: - _path = gobject.baseobject.textsource.pname - _path = savehook_new_data[_path]["gamesqlitefile"] + gameuid = gobject.baseobject.textsource.gameuid + _path = savehook_new_data[gameuid]["gamesqlitefile"] return _path except: return None diff --git a/LunaTranslator/LunaTranslator/translator/rengong.py b/LunaTranslator/LunaTranslator/translator/rengong.py index d9dfc7e5..990ce45f 100644 --- a/LunaTranslator/LunaTranslator/translator/rengong.py +++ b/LunaTranslator/LunaTranslator/translator/rengong.py @@ -24,8 +24,8 @@ class TS(basetrans): def unsafegetcurrentgameconfig(self): try: - _path = gobject.baseobject.textsource.pname - _path = savehook_new_data[_path]["gamejsonfile"] + gameuid = gobject.baseobject.textsource.gameuid + _path = savehook_new_data[gameuid]["gamejsonfile"] if isinstance(_path, str): _path = [_path] return tuple(_path) diff --git a/LunaTranslator/LunaTranslator/transoptimi/vndbnamemap.py b/LunaTranslator/LunaTranslator/transoptimi/vndbnamemap.py index 0c9371e3..71098467 100644 --- a/LunaTranslator/LunaTranslator/transoptimi/vndbnamemap.py +++ b/LunaTranslator/LunaTranslator/transoptimi/vndbnamemap.py @@ -6,8 +6,8 @@ class Process: def process_before(self, s): - exepath = gobject.baseobject.textsource.pname - namemap = savehook_new_data[exepath]["namemap"] + gameuid = gobject.baseobject.textsource.gameuid + namemap = savehook_new_data[gameuid]["namemap"] bettermap = {} for k, v in namemap.items(): for sp in ["・", " "]: diff --git a/LunaTranslator/LunaTranslator/tts/NeoSpeech.py b/LunaTranslator/LunaTranslator/tts/NeoSpeech.py index b9ce997c..8a123d26 100644 --- a/LunaTranslator/LunaTranslator/tts/NeoSpeech.py +++ b/LunaTranslator/LunaTranslator/tts/NeoSpeech.py @@ -2,7 +2,7 @@ import time import os import windows from tts.basettsclass import TTSbase -import ctypes, subprocess +import ctypes, subprocess, gobject from myutils.subproc import subproc_w, autoproc from ctypes import cast, POINTER, c_char, c_int32 @@ -69,8 +69,7 @@ class TTS(TTSbase): return self.mapx[(hk, idx)] def getvoicelist(self): - os.makedirs("cache/temp", exist_ok=True) - cachefname = os.path.abspath("cache/temp/{}.txt".format(time.time())) + cachefname = gobject.gettempdir(f"{time.time()}.txt") exe = os.path.abspath("./files/plugins/shareddllproxy32.exe") subprocess.run('"{}" neospeechlist "{}"'.format(exe, cachefname)) diff --git a/LunaTranslator/files/defaultconfig/translatorsetting.json b/LunaTranslator/files/defaultconfig/translatorsetting.json index 4dc4bc8b..92fd383a 100644 --- a/LunaTranslator/files/defaultconfig/translatorsetting.json +++ b/LunaTranslator/files/defaultconfig/translatorsetting.json @@ -6,7 +6,7 @@ }, "DeepLX": { "args": { - "api": "https://api.deeplx.org/translate" + "api": "" } }, "baiduapi": { diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index c889945c..47e6f503 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -29,7 +29,7 @@ include(generate_product_version) set(VERSION_MAJOR 5) set(VERSION_MINOR 3) -set(VERSION_PATCH 0) +set(VERSION_PATCH 1) add_library(pch pch.cpp) target_precompile_headers(pch PUBLIC pch.h)