mirror of
https://github.com/HIllya51/LunaTranslator.git
synced 2024-12-27 15:44:12 +08:00
many
This commit is contained in:
parent
aac082cf45
commit
70aa8e78dc
10
.github/ISSUE_TEMPLATE/01_bug.yaml
vendored
10
.github/ISSUE_TEMPLATE/01_bug.yaml
vendored
@ -29,13 +29,3 @@ body:
|
||||
尽可能详细描述错误产生的细节。
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Log file 日志文件
|
||||
description: >
|
||||
Run LunaTranslator_debug.exe to reproduce the error, and then upload the generated log_*.txt file.
|
||||
|
||||
运行LunaTranslator_debug.exe复现错误,然后上传产生的log_*.txt文件。
|
||||
validations:
|
||||
required: true
|
@ -60,10 +60,12 @@ Some buttons have two icons to indicate two different states. Some buttons only
|
||||
However, the select text window will automatically pop up after selecting the process, and this button is actually used to replace the selected text or modify some settings.
|
||||
1. #### <i class="fa fa-crop"></i> <i class="fa fa-icon fa-rotate-right"></i> Select OCR Range
|
||||
**This button is only available in OCR mode**<br>
|
||||
In OCR mode, select the OCR area, or change the OCR area, or when activating `OCR Settings` -> `Other` -> `Multiple Area Mode`, add a new OCR area
|
||||
In OCR mode, select the OCR area, or change the OCR area, or when activating `OCR Settings` -> `Other` -> `Multiple Area Mode`, add a new OCR area<br>
|
||||
When the right button is pressed, all selected ranges will be cleared before adding new areas.
|
||||
1. #### <i class="fa fa-square"></i> <i class="fa fa-icon fa-rotate-right"></i> Show/Hide Range Box
|
||||
**This button is only available in OCR mode**<br>
|
||||
When no OCR range is selected, use this button to display the OCR range, which will automatically set the OCR range to the last selected OCR.
|
||||
When no OCR range is selected, use this button to display the OCR range, which will automatically set the OCR range to the last selected OCR.<br>
|
||||
When the right button is pressed, all selected ranges will be cleared
|
||||
1. #### <i class="fa fa-crop"></i> <i class="fa fa-icon fa-rotate-right"></i> Perform OCR Once
|
||||
This button is similar to `Read Clipboard`, regardless of the current default text input source, it will first select the OCR range, then perform OCR once, and then proceed with the translation process.<br>
|
||||
This button is generally used in HOOK mode, when encountering choices, to temporarily use OCR for translation of choices. Or in OCR mode, to temporarily recognize a new position that occasionally appears.<br>
|
||||
|
@ -57,15 +57,19 @@
|
||||
### **OCR**
|
||||
|
||||
1. #### Select OCR Range
|
||||
**Available only in OCR mode**
|
||||
**Available only in OCR mode**<br>
|
||||
In OCR mode, selects the OCR area, or changes the OCR area, or when `OCR Settings` -> `Other` -> `Multi-region Mode` is activated, adds a new OCR area.
|
||||
|
||||
1. #### Show/Hide Range Box
|
||||
**Available only in OCR mode**
|
||||
**Available only in OCR mode**<br>
|
||||
When no OCR range is selected, using this shortcut key will display the OCR range and automatically set the OCR range to the last selected OCR.
|
||||
|
||||
1. ###### Clear OCR range
|
||||
**Only available in OCR mode**<br>
|
||||
Clear all selected ranges
|
||||
|
||||
1. #### Select OCR Range - Immediate
|
||||
**Available only in OCR mode**
|
||||
**Available only in OCR mode**<br>
|
||||
The difference from `Select OCR Range` is that it requires one less mouse click.
|
||||
|
||||
1. #### Perform OCR Once
|
||||
|
@ -157,14 +157,14 @@ Replace `{endpoint}` and `{deployName}` with your endpoint and deployName.
|
||||
|
||||
>Some large model platforms are not fully compatible with the ChatGPT interface, please fill in the parameters to use in the dedicated interface.
|
||||
|
||||
#### Foreign Large Model Interfaces
|
||||
|
||||
<!-- tabs:start -->
|
||||
|
||||
### **gemini**
|
||||
|
||||
<a id="gemini"></a>
|
||||
|
||||
**BASE_URL** `https://generativelanguage.googleapis.com`
|
||||
|
||||
**model** https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models
|
||||
|
||||
**API Key** https://aistudio.google.com/app/apikey
|
||||
@ -183,12 +183,6 @@ Replace `{endpoint}` and `{deployName}` with your endpoint and deployName.
|
||||
|
||||
**model** https://docs.cohere.com/docs/models
|
||||
|
||||
<!-- tabs:end -->
|
||||
|
||||
#### Domestic Large Model Interfaces
|
||||
|
||||
<!-- tabs:start -->
|
||||
|
||||
### **Tencent Hunyuan Large Model**
|
||||
|
||||
**SecretId** & **SecretKey** https://console.cloud.tencent.com/cam/capi
|
||||
|
@ -15,7 +15,7 @@ Make sure not to download the source code by mistake!
|
||||
|
||||
**LunaTranslator_admin.exe** will start with administrator privileges. Some games require administrator privileges to HOOK, so use this only when necessary; otherwise, start in normal mode.
|
||||
|
||||
**LunaTranslator_debug.exe** will generate log file. When submitting bug feedback, please be sure to run the program and reproduce the bug, and then submit the generated log file.
|
||||
**LunaTranslator_debug.exe** will display a command line window
|
||||
|
||||
#### Note
|
||||
|
||||
|
@ -63,12 +63,12 @@
|
||||
|
||||
1. #### <i class="fa fa-crop"></i> <i class="fa fa-icon fa-rotate-right"></i> Выбор области OCR
|
||||
**Эта кнопка доступна только в режиме OCR**<br>
|
||||
В режиме OCR выбирать область OCR, изменять область OCR или добавлять новую область OCR при активации `OCR настройки` -> `Другие` -> `Многообластный режим`.
|
||||
|
||||
В режиме OCR выбирать область OCR, изменять область OCR или добавлять новую область OCR при активации `OCR настройки` -> `Другие` -> `Многообластный режим`.<br>
|
||||
При нажатии правой кнопки мыши все выбранные области сначала будут очищены, а затем добавлены новые.
|
||||
1. #### <i class="fa fa-square"></i> <i class="fa fa-icon fa-rotate-right"></i> Показать/Скрыть рамку области
|
||||
**Эта кнопка доступна только в режиме OCR**<br>
|
||||
Когда никакая область OCR не выбрана, используйте эту кнопку, чтобы отобразить область OCR, автоматически устанавливая область OCR в последний выбранный OCR.
|
||||
|
||||
Когда никакая область OCR не выбрана, используйте эту кнопку, чтобы отобразить область OCR, автоматически устанавливая область OCR в последний выбранный OCR.<br>
|
||||
При нажатии правой кнопки будет очищен весь выбранный диапазон
|
||||
1. #### <i class="fa fa-crop"></i> <i class="fa fa-icon fa-rotate-right"></i> Выполнить одинOCR
|
||||
Эта кнопка аналогична кнопке `Прочитать буфер обмена`, независимо от текущего источника текстового ввода, сначала выбирается область OCR, затем выполняется один OCR, а затем процесс перевода.<br>
|
||||
Обычно эта кнопка используется в режиме HOOK, когда при выборе ветвей, временно используется OCR для перевода ветвей. Или в режиме OCR, чтобы временно распознать новый случайный появляющийся раз в другом месте.<br>
|
||||
|
@ -63,6 +63,10 @@
|
||||
**Доступно только в режиме OCR**<br>
|
||||
Если никакая область OCR не выбрана, при использовании этого горячего клавиша для отображения области OCR, автоматически устанавливается область OCR в последний выбранный OCR.
|
||||
|
||||
1. #### Очистить диапазон OCR
|
||||
**Доступно только в режиме OCR**<br>
|
||||
Очистить все выбранные диапазоны
|
||||
|
||||
1. #### Выбор области OCR — немедленно
|
||||
**Доступно только в режиме OCR**<br>
|
||||
Разница от `Выбор области OCR` заключается только в том, что требуется нажатие мыши меньше раз.
|
||||
|
@ -157,14 +157,14 @@
|
||||
|
||||
>Некоторые платформы больших моделей не полностью совместимы с интерфейсом ChatGPT, пожалуйста, заполните параметры в специальном интерфейсе для использования.
|
||||
|
||||
#### Зарубежные интерфейсы больших моделей
|
||||
|
||||
<!-- tabs:start -->
|
||||
|
||||
### **gemini**
|
||||
|
||||
<a id="gemini"></a>
|
||||
|
||||
**BASE_URL** `https://generativelanguage.googleapis.com`
|
||||
|
||||
**model** https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models
|
||||
|
||||
**API Key** https://aistudio.google.com/app/apikey
|
||||
@ -183,12 +183,6 @@
|
||||
|
||||
**model** https://docs.cohere.com/docs/models
|
||||
|
||||
<!-- tabs:end -->
|
||||
|
||||
#### Китайские интерфейсы больших моделей
|
||||
|
||||
<!-- tabs:start -->
|
||||
|
||||
### **Tencent Hunyuan Large Model**
|
||||
|
||||
**SecretId** & **SecretKey** https://console.cloud.tencent.com/cam/capi
|
||||
|
@ -15,7 +15,7 @@
|
||||
|
||||
**LunaTranslator_admin.exe** запускается с правами администратора, некоторые игры требуют прав администратора для HOOK, используйте его только в этом случае, в остальных случаях запускайте в обычном режиме.
|
||||
|
||||
**LunaTranslator_debug.exe** создаст файлы журналов. Отправляя отзыв об ошибке, обязательно используйте эту программу для запуска и воспроизведения ошибки, а затем отправьте созданный файл журнала.
|
||||
**LunaTranslator_debug.exe** Показать окно командной строки
|
||||
|
||||
#### Внимание
|
||||
|
||||
|
@ -60,10 +60,12 @@
|
||||
不过,选择文本窗口在选择进程后会自动弹出,这个按钮实际上是用来更换选择的文本,或修改一些设置用的。
|
||||
1. #### <i class="fa fa-crop"></i> <i class="fa fa-icon fa-rotate-right"></i> 选取OCR范围
|
||||
**该按钮仅在OCR模式下可用**<br>
|
||||
OCR模式下,选取OCR区域,或者更换OCR区域,或者当激活`OCR设置`->`其他`->`多重区域模式`时增加新的OCR区域
|
||||
OCR模式下,选取OCR区域,或者更换OCR区域,或者当激活`OCR设置`->`其他`->`多重区域模式`时增加新的OCR区域<br>
|
||||
当按下右键时,会先清除所有已选取范围,再添加新的区域。
|
||||
1. #### <i class="fa fa-square"></i> <i class="fa fa-icon fa-rotate-right"></i> 显示/隐藏范围框
|
||||
**该按钮仅在OCR模式下可用**<br>
|
||||
当未选择任何OCR范围时,使用该按钮显示OCR范围,会自动设置OCR范围为上一次选择的OCR。
|
||||
当未选择任何OCR范围时,使用该按钮显示OCR范围,会自动设置OCR范围为上一次选择的OCR。<br>
|
||||
当按下右键时,会清除所有已选取范围
|
||||
1. #### <i class="fa fa-crop"></i> <i class="fa fa-icon fa-rotate-right"></i> 进行一次OCR
|
||||
该按钮和`读取剪贴板`类似,不管当前的默认文本输入源是什么,都会先进行OCR范围选择,然后进行一次OCR,然后进行翻译流程。<br>
|
||||
该按钮一般用于,在HOOK模式下,遇到选择支时,临时使用一次OCR进行翻译选择支。或者在OCR模式下,临时去识别一次其他偶尔出现的新的位置。<br>
|
||||
|
@ -65,6 +65,10 @@
|
||||
**仅在OCR模式下可用**<br>
|
||||
当未选择任何OCR范围时,使用该快捷键显示OCR范围,会自动设置OCR范围为上一次选择的OCR。
|
||||
|
||||
1. #### 清除OCR范围
|
||||
**仅在OCR模式下可用**<br>
|
||||
清除所有已选取范围
|
||||
|
||||
1. #### 选取OCR范围——立即
|
||||
**仅在OCR模式下可用**<br>
|
||||
和`选取OCR范围`的区别仅是少按一次鼠标
|
||||
|
@ -162,15 +162,14 @@
|
||||
|
||||
>部分大模型平台不完全兼容ChatGPT接口,请在专用接口中填写参数使用。
|
||||
|
||||
#### 外国大模型接口
|
||||
|
||||
|
||||
<!-- tabs:start -->
|
||||
|
||||
### **gemini**
|
||||
|
||||
<a id="gemini"></a>
|
||||
|
||||
**BASE_URL** `https://generativelanguage.googleapis.com`
|
||||
|
||||
**model** https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models
|
||||
|
||||
**API Key** https://aistudio.google.com/app/apikey
|
||||
@ -189,14 +188,6 @@
|
||||
|
||||
**model** https://docs.cohere.com/docs/models
|
||||
|
||||
|
||||
<!-- tabs:end -->
|
||||
|
||||
|
||||
#### 国产大模型接口
|
||||
|
||||
<!-- tabs:start -->
|
||||
|
||||
### **腾讯混元大模型**
|
||||
|
||||
**SecretId** & **SecretKey** https://console.cloud.tencent.com/cam/capi
|
||||
|
@ -24,7 +24,7 @@
|
||||
|
||||
**LunaTranslator_admin.exe** 会以管理员权限启动,部分游戏需要管理员权限才能HOOK,仅这时需要使用这个,其他时候普通模式启动即可。
|
||||
|
||||
**LunaTranslator_debug.exe** 会生成log文件。提交bug反馈时,务必请使用该程序运行并复现bug,然后提交生成的log文件。
|
||||
**LunaTranslator_debug.exe** 会显示命令行窗口
|
||||
|
||||
|
||||
|
||||
|
@ -44,7 +44,7 @@ import windows
|
||||
import winsharedutils
|
||||
from winsharedutils import collect_running_pids
|
||||
from myutils.post import POSTSOLVE
|
||||
from myutils.utils import nowisdark
|
||||
from myutils.utils import nowisdark, dynamicapiname
|
||||
from myutils.traceplaytime import playtimemanager
|
||||
from myutils.audioplayer import series_audioplayer
|
||||
from gui.dynalang import LAction, LMenu
|
||||
@ -516,7 +516,7 @@ class MAINUI:
|
||||
if iserror:
|
||||
if currentsignature == self.currentsignature:
|
||||
self.translation_ui.displaystatus.emit(
|
||||
globalconfig["fanyi"][classname]["name"] + " " + res,
|
||||
dynamicapiname(classname) + " " + res,
|
||||
True,
|
||||
False,
|
||||
)
|
||||
@ -540,7 +540,7 @@ class MAINUI:
|
||||
iter_res_status in (0, 1)
|
||||
):
|
||||
displayreskwargs = dict(
|
||||
name=globalconfig["fanyi"][classname]["name"],
|
||||
name=dynamicapiname(classname),
|
||||
color=globalconfig["fanyi"][classname]["color"],
|
||||
res=res,
|
||||
iter_context=(iter_res_status, classname),
|
||||
@ -548,9 +548,7 @@ class MAINUI:
|
||||
self.translation_ui.displayres.emit(displayreskwargs)
|
||||
if iter_res_status in (0, 2): # 0为普通,1为iter,2为iter终止
|
||||
|
||||
self.transhis.getnewtranssignal.emit(
|
||||
globalconfig["fanyi"][classname]["name"], res
|
||||
)
|
||||
self.transhis.getnewtranssignal.emit(dynamicapiname(classname), res)
|
||||
if not waitforresultcallback:
|
||||
if (
|
||||
globalconfig["read_trans"]
|
||||
@ -822,7 +820,7 @@ class MAINUI:
|
||||
return aclass(classname)
|
||||
except Exception as e:
|
||||
self.displayinfomessage(
|
||||
globalconfig["fanyi"][classname]["name"]
|
||||
dynamicapiname(classname)
|
||||
+ " import failed : "
|
||||
+ str(stringfyerror(e)),
|
||||
"<msg_error_not_refresh>",
|
||||
|
@ -2,7 +2,7 @@ from qtsymbols import *
|
||||
import gobject, os
|
||||
from myutils.config import globalconfig, uid2gamepath
|
||||
from myutils.wrapper import Singleton_close
|
||||
from myutils.utils import getfilemd5
|
||||
from myutils.utils import getfilemd5, getimagefilefilter
|
||||
from gui.usefulwidget import saveposwindow
|
||||
from gui.dynalang import LPushButton
|
||||
|
||||
@ -15,7 +15,7 @@ class dialog_memory(saveposwindow):
|
||||
ff.write(self.showtext.toHtml())
|
||||
|
||||
def insertpic(self):
|
||||
f = QFileDialog.getOpenFileName()
|
||||
f = QFileDialog.getOpenFileName(filter=getimagefilefilter())
|
||||
res = f[0]
|
||||
if res != "":
|
||||
self.showtext.insertHtml('<img src="{}">'.format(res))
|
||||
|
@ -11,7 +11,7 @@ from myutils.config import (
|
||||
globalconfig,
|
||||
)
|
||||
from myutils.hwnd import clipboard_set_image
|
||||
from myutils.utils import str2rgba, get_time_stamp, loopbackrecorder
|
||||
from myutils.utils import str2rgba, get_time_stamp, loopbackrecorder, getimagefilefilter
|
||||
from myutils.audioplayer import playonce
|
||||
from gui.inputdialog import autoinitdialog
|
||||
from gui.specialwidget import stackedlist, shrinkableitem, shownumQPushButton
|
||||
@ -613,7 +613,7 @@ class pixwrapper(QWidget):
|
||||
("画廊"),
|
||||
savehook_new_data[self.k]["imagepath_all"],
|
||||
closecallback=lambda: self.setpix(self.k),
|
||||
ispathsedit=dict(),
|
||||
ispathsedit=dict(filter1=getimagefilefilter()),
|
||||
)
|
||||
elif action == setimage:
|
||||
savehook_new_data[self.k]["currentmainimage"] = curr
|
||||
|
@ -2,7 +2,7 @@ from qtsymbols import *
|
||||
import threading, windows
|
||||
import gobject, qtawesome, os, json
|
||||
from myutils.config import globalconfig, savehook_new_data, translatorsetting
|
||||
from myutils.utils import translate_exits
|
||||
from myutils.utils import translate_exits, dynamicapiname
|
||||
from myutils.wrapper import Singleton_close
|
||||
from gui.usefulwidget import saveposwindow, getsimplecombobox
|
||||
from gui.dynalang import LPushButton, LMainWindow
|
||||
@ -160,7 +160,7 @@ class edittrans(LMainWindow):
|
||||
if not translate_exits(fanyi):
|
||||
continue
|
||||
inter.append(fanyi)
|
||||
vis.append(globalconfig["fanyi"][fanyi]["name"])
|
||||
vis.append(dynamicapiname(fanyi))
|
||||
qv.addWidget(self.textOutput)
|
||||
qv.addWidget(
|
||||
getsimplecombobox(
|
||||
|
@ -2,7 +2,7 @@ from qtsymbols import *
|
||||
import sqlite3, os, json, functools
|
||||
from traceback import print_exc
|
||||
from myutils.config import globalconfig, _TR
|
||||
from myutils.utils import autosql
|
||||
from myutils.utils import autosql, dynamicapiname
|
||||
from gui.usefulwidget import getQMessageBox, LFocusCombo
|
||||
from gui.dynalang import LFormLayout, LPushButton, LDialog
|
||||
from textsource.texthook import splitembedlines
|
||||
@ -51,7 +51,7 @@ def sqlite2json2(
|
||||
dialog.setLayout(formLayout)
|
||||
|
||||
combo = LFocusCombo()
|
||||
combo.addItems([globalconfig["fanyi"][_]["name"] for _ in collect])
|
||||
combo.addItems([dynamicapiname(_) for _ in collect])
|
||||
|
||||
formLayout.addRow("首选翻译", combo)
|
||||
e = QLineEdit(sqlitefile[: -(len(".sqlite"))])
|
||||
|
@ -1,5 +1,5 @@
|
||||
from qtsymbols import *
|
||||
import functools, json, subprocess, os, time, binascii
|
||||
import functools, binascii
|
||||
from collections import OrderedDict
|
||||
from traceback import print_exc
|
||||
import qtawesome, windows, winsharedutils, gobject
|
||||
@ -125,6 +125,33 @@ class dialog_showinfo(QDialog):
|
||||
self.show()
|
||||
|
||||
|
||||
class HexValidator(QValidator):
|
||||
def validate(self, input_str, pos):
|
||||
# 检查输入是否是有效的16进制数
|
||||
if all(c in "0123456789abcdefABCDEF" for c in input_str):
|
||||
return QValidator.State.Acceptable, input_str, pos
|
||||
elif input_str == "" or (
|
||||
len(input_str) == 1 and input_str in "0123456789abcdefABCDEF"
|
||||
):
|
||||
return QValidator.State.Intermediate, input_str, pos
|
||||
else:
|
||||
return QValidator.State.Invalid, input_str, pos
|
||||
|
||||
|
||||
class PatternValidator(QValidator):
|
||||
def validate(self, input_str, pos):
|
||||
# 检查输入是否是有效的16进制数
|
||||
if all(c in "0123456789abcdefABCDEF ?" for c in input_str):
|
||||
return QValidator.State.Acceptable, input_str, pos
|
||||
elif input_str == "" or (
|
||||
len(input_str) == 1 and input_str in "0123456789abcdefABCDEF ?"
|
||||
):
|
||||
return QValidator.State.Intermediate, input_str, pos
|
||||
else:
|
||||
return QValidator.State.Invalid, input_str, pos
|
||||
|
||||
|
||||
|
||||
class searchhookparam(LDialog):
|
||||
def safehex(self, string, default):
|
||||
try:
|
||||
@ -149,11 +176,11 @@ class searchhookparam(LDialog):
|
||||
elif idx == 2:
|
||||
dumpvalues = {}
|
||||
for k, widget in self.regists.items():
|
||||
if type(widget) == QLineEdit:
|
||||
if isinstance(widget, QLineEdit):
|
||||
dumpvalues[k] = widget.text()
|
||||
if type(widget) == FocusSpin:
|
||||
elif isinstance(widget, QSpinBox):
|
||||
dumpvalues[k] = widget.value()
|
||||
if callable(widget):
|
||||
elif callable(widget):
|
||||
dumpvalues[k] = widget()
|
||||
pattern = dumpvalues["pattern"]
|
||||
if "." in pattern:
|
||||
@ -161,9 +188,11 @@ class searchhookparam(LDialog):
|
||||
usestruct.exportModule = pattern[:120]
|
||||
else:
|
||||
try:
|
||||
bs = bytes.fromhex(
|
||||
pattern.replace(" ", "").replace("0x", "").replace("??", "11")
|
||||
)
|
||||
p = pattern.replace(" ", "").replace("??", "11")
|
||||
if ("?" in p) or (len(p) % 2 != 0):
|
||||
getQMessageBox(self, "警告", "无效", True)
|
||||
raise
|
||||
bs = bytes.fromhex(p)
|
||||
usestruct.pattern = bs[:30]
|
||||
usestruct.length = len(bs)
|
||||
except:
|
||||
@ -186,7 +215,7 @@ class searchhookparam(LDialog):
|
||||
usestruct.maxAddress = self.safehex(
|
||||
dumpvalues["offstopaddr"], usestruct.maxAddress
|
||||
)
|
||||
usestruct.padding = 0 # self.safehex(dumpvalues[4], usestruct.padding)
|
||||
usestruct.padding = dumpvalues["stroffset"]
|
||||
usestruct.offset = dumpvalues["offset"]
|
||||
usestruct.codepage = static_data["codepage_real"][
|
||||
self.codepagesave["spcp"]
|
||||
@ -266,7 +295,19 @@ class searchhookparam(LDialog):
|
||||
):
|
||||
if _type == 0:
|
||||
line = QLineEdit(_val)
|
||||
line.setValidator(HexValidator())
|
||||
regwid = addwid = line
|
||||
elif _type == -2:
|
||||
line = QLineEdit(_val)
|
||||
line.setValidator(PatternValidator())
|
||||
regwid = addwid = line
|
||||
elif _type == -1:
|
||||
sp = FocusSpin()
|
||||
sp.setDisplayIntegerBase(16)
|
||||
sp.setMaximum(0x7FFFFFFF)
|
||||
sp.setMinimum(-0x7FFFFFFF)
|
||||
sp.setValue(_val)
|
||||
regwid = addwid = sp
|
||||
elif _type == 1:
|
||||
sp = FocusSpin()
|
||||
sp.setMaximum(10000000)
|
||||
@ -364,13 +405,14 @@ class searchhookparam(LDialog):
|
||||
"pattern",
|
||||
"搜索匹配的特征(hex)",
|
||||
self.hex2str(usestruct.pattern),
|
||||
0,
|
||||
-2,
|
||||
uselayout=patternWl,
|
||||
)
|
||||
autoaddline(
|
||||
"offset", "相对特征地址的偏移", usestruct.offset, 1, uselayout=patternWl
|
||||
)
|
||||
|
||||
autoaddline("stroffset", "字符串地址偏移", usestruct.padding, -1)
|
||||
autoaddline("time", "搜索持续时间(s)", usestruct.searchTime // 1000, 1)
|
||||
autoaddline("maxrecords", "搜索结果数上限", usestruct.maxRecords, 1)
|
||||
|
||||
|
@ -4,7 +4,7 @@ import gobject, os, zipfile
|
||||
from myutils.config import globalconfig, static_data
|
||||
from gui.inputdialog import multicolorset, autoinitdialog
|
||||
from myutils.wrapper import tryprint
|
||||
from myutils.utils import dynamiclink, translate_exits, copytree
|
||||
from myutils.utils import dynamiclink, translate_exits, copytree, dynamicapiname
|
||||
from gui.usefulwidget import (
|
||||
D_getsimplecombobox,
|
||||
getsimplecombobox,
|
||||
@ -333,7 +333,7 @@ def vistranslate_rank(self):
|
||||
("显示顺序"),
|
||||
globalconfig["fix_translate_rank_rank"],
|
||||
isrankeditor=True,
|
||||
namemapfunction=lambda k: globalconfig["fanyi"][k]["name"],
|
||||
namemapfunction=lambda k: dynamicapiname(k),
|
||||
)
|
||||
|
||||
|
||||
|
@ -62,6 +62,7 @@ def registrhotkeys(self):
|
||||
"_12": lambda: gobject.baseobject.hookselectdialog.showsignal.emit(),
|
||||
"_13": lambda: gobject.baseobject.translation_ui.clickRange_signal.emit(False),
|
||||
"_14": gobject.baseobject.translation_ui.showhide_signal.emit,
|
||||
"_14_1": gobject.baseobject.translation_ui.clear_signal_1.emit,
|
||||
"_15": gobject.baseobject.translation_ui.bindcropwindow_signal.emit,
|
||||
"_16": gobject.baseobject.translation_ui.showhideuisignal.emit,
|
||||
"_17": gobject.baseobject.translation_ui.quitf_signal.emit,
|
||||
|
@ -1,7 +1,7 @@
|
||||
from qtsymbols import *
|
||||
import functools, os, json
|
||||
import windows, gobject
|
||||
from myutils.utils import translate_exits
|
||||
from myutils.utils import translate_exits, dynamicapiname
|
||||
from myutils.config import (
|
||||
globalconfig,
|
||||
_TR,
|
||||
@ -272,7 +272,7 @@ def loadvalidtss():
|
||||
for x in globalconfig["fanyi"]:
|
||||
if not translate_exits(x):
|
||||
continue
|
||||
alltransvis.append(globalconfig["fanyi"][x]["name"])
|
||||
alltransvis.append(dynamicapiname(x))
|
||||
alltrans.append(x)
|
||||
return alltrans, alltransvis
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
from qtsymbols import *
|
||||
import functools, os
|
||||
from myutils.config import globalconfig, ocrsetting, ocrerrorfix, static_data
|
||||
from myutils.utils import splitocrtypes, dynamiclink
|
||||
from myutils.utils import splitocrtypes, dynamiclink, getimagefilefilter
|
||||
from gui.inputdialog import autoinitdialogx, postconfigdialog, autoinitdialog_items
|
||||
from gui.usefulwidget import (
|
||||
D_getsimplecombobox,
|
||||
@ -297,13 +297,7 @@ class showocrimage(saveposwindow):
|
||||
super().closeEvent(e)
|
||||
|
||||
def openff(self):
|
||||
f = QFileDialog.getOpenFileName(
|
||||
filter="image ("
|
||||
+ " ".join(
|
||||
["*" + _.data().decode() for _ in QImageWriter.supportedImageFormats()]
|
||||
)
|
||||
+ ")"
|
||||
)
|
||||
f = QFileDialog.getOpenFileName(filter=getimagefilefilter())
|
||||
res = f[0]
|
||||
if not res:
|
||||
return
|
||||
@ -531,7 +525,11 @@ def getocrgrid(self):
|
||||
grid=[
|
||||
[
|
||||
"多重区域模式",
|
||||
D_getsimpleswitch(globalconfig, "multiregion"),
|
||||
D_getsimpleswitch(
|
||||
globalconfig,
|
||||
"multiregion",
|
||||
callback=lambda _: gobject.baseobject.textsource.leaveone(),
|
||||
),
|
||||
],
|
||||
[
|
||||
"范围框颜色",
|
||||
|
@ -7,6 +7,7 @@ from myutils.utils import (
|
||||
splittranslatortypes,
|
||||
dynamiclink,
|
||||
translate_exits,
|
||||
dynamicapiname,
|
||||
)
|
||||
from gui.pretransfile import sqlite2json
|
||||
from gui.inputdialog import autoinitdialog, autoinitdialog_items, autoinitdialogx
|
||||
@ -14,6 +15,7 @@ from gui.usefulwidget import (
|
||||
D_getspinbox,
|
||||
getIconButton,
|
||||
D_getcolorbutton,
|
||||
Prompt_dialog,
|
||||
getcolorbutton,
|
||||
getsimpleswitch,
|
||||
D_getIconButton,
|
||||
@ -25,7 +27,7 @@ from gui.usefulwidget import (
|
||||
getvboxwidget,
|
||||
)
|
||||
from traceback import print_exc
|
||||
from gui.dynalang import LPushButton, LLabel
|
||||
from gui.dynalang import LPushButton, LLabel, LAction, LMenu
|
||||
|
||||
|
||||
def deepcopydict(d):
|
||||
@ -74,7 +76,7 @@ def loadvisinternal(btnplus, copy):
|
||||
else:
|
||||
if not translate_exits(_):
|
||||
continue
|
||||
__vis.append(globalconfig["fanyi"][_]["name"])
|
||||
__vis.append(dynamicapiname(_))
|
||||
__uid.append(_)
|
||||
return __vis, __uid
|
||||
|
||||
@ -123,6 +125,39 @@ def getalistname(parent, copy, btnplus, callback):
|
||||
)
|
||||
|
||||
|
||||
def renameapi(qlabel: QLabel, apiuid, _):
|
||||
menu = QMenu(qlabel)
|
||||
editname = LAction("重命名")
|
||||
menu.addAction(editname)
|
||||
action = menu.exec(qlabel.mapToGlobal(_))
|
||||
if action == editname:
|
||||
before = dynamicapiname(apiuid)
|
||||
_dia = Prompt_dialog(
|
||||
qlabel,
|
||||
"重命名",
|
||||
"",
|
||||
[
|
||||
[
|
||||
"名称",
|
||||
before,
|
||||
],
|
||||
],
|
||||
)
|
||||
|
||||
if _dia.exec():
|
||||
title = _dia.text[0].text()
|
||||
if title not in ("", before):
|
||||
globalconfig["fanyi"][apiuid]["name_self_set"] = title
|
||||
qlabel.setText(title)
|
||||
|
||||
|
||||
def getrenameablellabel(uid):
|
||||
name = LLabel(dynamicapiname(uid))
|
||||
name.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
|
||||
name.customContextMenuRequested.connect(functools.partial(renameapi, name, uid))
|
||||
return name
|
||||
|
||||
|
||||
def selectllmcallback(self, countnum, btnplus, fanyi, name):
|
||||
uid = str(uuid.uuid4())
|
||||
_f11 = "./Lunatranslator/translator/{}.py".format(fanyi)
|
||||
@ -153,7 +188,7 @@ def selectllmcallback(self, countnum, btnplus, fanyi, name):
|
||||
autoinitdialogx,
|
||||
self,
|
||||
translatorsetting[uid]["args"],
|
||||
(globalconfig["fanyi"][uid]["name"]),
|
||||
dynamicapiname(uid),
|
||||
800,
|
||||
items,
|
||||
"userconfig.copyed." + uid,
|
||||
@ -162,7 +197,7 @@ def selectllmcallback(self, countnum, btnplus, fanyi, name):
|
||||
icon="fa.gear",
|
||||
)
|
||||
|
||||
name = LLabel(globalconfig["fanyi"][uid]["name"])
|
||||
name = getrenameablellabel(uid)
|
||||
swc = getsimpleswitch(
|
||||
globalconfig["fanyi"][uid],
|
||||
"use",
|
||||
@ -329,7 +364,7 @@ def initsome11(self, l, label=None, btnplus=False):
|
||||
autoinitdialogx,
|
||||
self,
|
||||
translatorsetting[fanyi]["args"],
|
||||
globalconfig["fanyi"][fanyi]["name"],
|
||||
dynamicapiname(fanyi),
|
||||
800,
|
||||
items,
|
||||
aclass,
|
||||
@ -345,7 +380,7 @@ def initsome11(self, l, label=None, btnplus=False):
|
||||
else:
|
||||
last = ""
|
||||
line += [
|
||||
globalconfig["fanyi"][fanyi]["name"],
|
||||
functools.partial(getrenameablellabel, fanyi),
|
||||
D_getsimpleswitch(
|
||||
globalconfig["fanyi"][fanyi],
|
||||
"use",
|
||||
|
@ -5,8 +5,13 @@ from traceback import print_exc
|
||||
import qtawesome, requests, gobject, windows, winsharedutils
|
||||
import myutils.ankiconnect as anki
|
||||
from myutils.hwnd import grabwindow
|
||||
from myutils.config import globalconfig, _TR, static_data
|
||||
from myutils.utils import loopbackrecorder, parsekeystringtomodvkcode
|
||||
from myutils.config import globalconfig, static_data
|
||||
from myutils.utils import (
|
||||
loopbackrecorder,
|
||||
parsekeystringtomodvkcode,
|
||||
getimageformatlist,
|
||||
getimagefilefilter,
|
||||
)
|
||||
from myutils.wrapper import threader, tryprint
|
||||
from myutils.ocrutil import imageCut, ocr_run
|
||||
from gui.rangeselect import rangeselct_function
|
||||
@ -42,15 +47,7 @@ from gui.dynalang import (
|
||||
)
|
||||
|
||||
|
||||
def getimageformatlist():
|
||||
_ = [_.data().decode() for _ in QImageWriter.supportedImageFormats()]
|
||||
if globalconfig["imageformat"] == -1 or globalconfig["imageformat"] >= len(_):
|
||||
globalconfig["imageformat"] = _.index("png")
|
||||
return _
|
||||
|
||||
|
||||
def getimageformat():
|
||||
|
||||
return getimageformatlist()[globalconfig["imageformat"]]
|
||||
|
||||
|
||||
@ -496,7 +493,7 @@ class AnkiWindow(QWidget):
|
||||
functools.partial(self.selecfile, self.audiopath_sentence)
|
||||
)
|
||||
folder_open3 = QPushButton(qtawesome.icon("fa.folder-open"), "")
|
||||
folder_open3.clicked.connect(functools.partial(self.selecfile, self.editpath))
|
||||
folder_open3.clicked.connect(functools.partial(self.selecfile2, self.editpath))
|
||||
layout.addLayout(
|
||||
getboxlayout(
|
||||
[
|
||||
@ -622,6 +619,12 @@ class AnkiWindow(QWidget):
|
||||
pix = QPixmap.fromImage(QImage(src))
|
||||
self.viewimagelabel.showpixmap(pix)
|
||||
|
||||
def selecfile2(self, item):
|
||||
f = QFileDialog.getOpenFileName(filter=getimagefilefilter())
|
||||
res = f[0]
|
||||
if res != "":
|
||||
item.setText(res)
|
||||
|
||||
def selecfile(self, item):
|
||||
f = QFileDialog.getOpenFileName()
|
||||
res = f[0]
|
||||
|
@ -247,6 +247,7 @@ class TranslatorWindow(resizableframeless):
|
||||
showsavegame_signal = pyqtSignal()
|
||||
clickRange_signal = pyqtSignal(bool)
|
||||
showhide_signal = pyqtSignal()
|
||||
clear_signal_1 = pyqtSignal()
|
||||
bindcropwindow_signal = pyqtSignal()
|
||||
fullsgame_signal = pyqtSignal()
|
||||
quitf_signal = pyqtSignal()
|
||||
@ -627,8 +628,20 @@ class TranslatorWindow(resizableframeless):
|
||||
"selecttext",
|
||||
lambda: gobject.baseobject.hookselectdialog.showsignal.emit(),
|
||||
),
|
||||
("selectocrrange", lambda: self.clickRange(False)),
|
||||
("hideocrrange", self.showhideocrrange, None, lambda: self.showhidestate),
|
||||
(
|
||||
"selectocrrange",
|
||||
lambda: self.clickRange(False),
|
||||
None,
|
||||
None,
|
||||
lambda: self.clickRangeclear(False),
|
||||
),
|
||||
(
|
||||
"hideocrrange",
|
||||
self.showhideocrrange,
|
||||
None,
|
||||
lambda: self.showhidestate,
|
||||
self.clear_signal_1.emit,
|
||||
),
|
||||
(
|
||||
"bindwindow",
|
||||
self.bindcropwindow_signal.emit,
|
||||
@ -877,6 +890,9 @@ class TranslatorWindow(resizableframeless):
|
||||
)
|
||||
self.clickRange_signal.connect(self.clickRange)
|
||||
self.showhide_signal.connect(self.showhideocrrange)
|
||||
self.clear_signal_1.connect(
|
||||
lambda: self.clearstate() or gobject.baseobject.textsource.clearrange()
|
||||
)
|
||||
self.bindcropwindow_signal.connect(
|
||||
functools.partial(mouseselectwindow, self.bindcropwindowcallback)
|
||||
)
|
||||
@ -1127,6 +1143,13 @@ class TranslatorWindow(resizableframeless):
|
||||
except:
|
||||
pass
|
||||
|
||||
def clearstate(self):
|
||||
try:
|
||||
self.showhidestate = False
|
||||
self.refreshtoolicon()
|
||||
except:
|
||||
pass
|
||||
|
||||
def bindcropwindowcallback(self, pid, hwnd):
|
||||
_pid = os.getpid()
|
||||
gobject.baseobject.hwnd = hwnd if pid != _pid else None
|
||||
@ -1197,10 +1220,18 @@ class TranslatorWindow(resizableframeless):
|
||||
return
|
||||
self.showhidestate = False
|
||||
|
||||
rangeselct_function(self.afterrange, auto)
|
||||
rangeselct_function(functools.partial(self.afterrange, False), auto)
|
||||
|
||||
def clickRangeclear(self, auto):
|
||||
if globalconfig["sourcestatus2"]["ocr"]["use"] == False:
|
||||
return
|
||||
self.showhidestate = False
|
||||
rangeselct_function(functools.partial(self.afterrange, True), auto)
|
||||
|
||||
@tryprint
|
||||
def afterrange(self, rect):
|
||||
def afterrange(self, clear, rect):
|
||||
if clear or not globalconfig["multiregion"]:
|
||||
gobject.baseobject.textsource.clearrange()
|
||||
gobject.baseobject.textsource.newrangeadjustor()
|
||||
gobject.baseobject.textsource.setrect(rect)
|
||||
self.showhideocrrange()
|
||||
|
@ -1025,3 +1025,20 @@ def get_element_by(attr, attrv, html):
|
||||
if res is None:
|
||||
return ""
|
||||
return res
|
||||
|
||||
|
||||
def getimageformatlist():
|
||||
_ = [_.data().decode() for _ in QImageWriter.supportedImageFormats()]
|
||||
if globalconfig["imageformat"] == -1 or globalconfig["imageformat"] >= len(_):
|
||||
globalconfig["imageformat"] = _.index("png")
|
||||
return _
|
||||
|
||||
|
||||
def getimagefilefilter():
|
||||
return " ".join(("*." + _ for _ in getimageformatlist()))
|
||||
|
||||
|
||||
def dynamicapiname(apiuid):
|
||||
return globalconfig["fanyi"][apiuid].get(
|
||||
"name_self_set", globalconfig["fanyi"][apiuid]["name"]
|
||||
)
|
||||
|
@ -1,7 +1,7 @@
|
||||
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,QGraphicsOpacityEffect,QStackedWidget,QStyledItemDelegate,QStyleOptionViewItem,QFontDialog,QTreeView
|
||||
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,QTextLayout, QTextOption,QDragEnterEvent, QDropEvent,QTransform,QKeyEvent,QInputMethodEvent
|
||||
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,QTextLayout, QTextOption,QDragEnterEvent, QDropEvent,QTransform,QKeyEvent,QInputMethodEvent,QValidator
|
||||
from PyQt5.QtCore import QObject,pyqtSignal,Qt,QSize,QByteArray,QBuffer,QPointF,QPoint,QRect,QEvent,QModelIndex,QTimer,QRectF,QVariantAnimation,QUrl,QPropertyAnimation,QLocale,QSignalBlocker
|
||||
isqt5 = True
|
||||
class LineHeightTypes:
|
||||
@ -12,7 +12,7 @@ except:
|
||||
#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,QGraphicsOpacityEffect,QStackedWidget,QTreeView
|
||||
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,QTextLayout, QTextOption,QKeyEvent,QInputMethodEvent
|
||||
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,QTextLayout, QTextOption,QKeyEvent,QInputMethodEvent,QValidator
|
||||
from PyQt6.QtCore import QObject,pyqtSignal,Qt,QSize,QByteArray,QBuffer,QPointF,QPoint,QRect,QEvent,QModelIndex,QTimer,QRectF,QVariantAnimation,QUrl,QPropertyAnimation,QLocale
|
||||
isqt5 = False
|
||||
|
||||
|
@ -35,6 +35,24 @@ class ocrtext(basetext):
|
||||
self.range_ui = []
|
||||
self.gettextthread()
|
||||
|
||||
def clearrange(self):
|
||||
for _ in self.range_ui:
|
||||
_.close()
|
||||
self.range_ui.clear()
|
||||
self.savelastimg.clear()
|
||||
self.savelastrecimg.clear()
|
||||
self.lastocrtime.clear()
|
||||
self.savelasttext.clear()
|
||||
|
||||
def leaveone(self):
|
||||
for _ in self.range_ui[:-1]:
|
||||
_.close()
|
||||
self.range_ui = self.range_ui[-1:]
|
||||
self.savelastimg = self.savelastimg[-1:]
|
||||
self.savelastrecimg = self.savelastrecimg[-1:]
|
||||
self.lastocrtime = self.lastocrtime[-1:]
|
||||
self.savelasttext = self.savelasttext[-1:]
|
||||
|
||||
def newrangeadjustor(self):
|
||||
if len(self.range_ui) == 0 or globalconfig["multiregion"]:
|
||||
self.range_ui.append(rangeadjust(gobject.baseobject.settin_ui))
|
||||
|
@ -35,6 +35,7 @@ from ctypes import (
|
||||
c_char_p,
|
||||
c_wchar_p,
|
||||
c_uint64,
|
||||
c_int64,
|
||||
c_void_p,
|
||||
cast,
|
||||
c_wchar,
|
||||
@ -79,7 +80,7 @@ class SearchParam(Structure):
|
||||
("searchTime", c_int),
|
||||
("maxRecords", c_int),
|
||||
("codepage", c_int),
|
||||
("padding", c_uint64),
|
||||
("padding", c_int64),
|
||||
("minAddress", c_uint64),
|
||||
("maxAddress", c_uint64),
|
||||
("boundaryModule", c_wchar * 120),
|
||||
|
@ -6,7 +6,13 @@ import zhconv, gobject
|
||||
import sqlite3, json
|
||||
import functools
|
||||
from myutils.config import globalconfig, translatorsetting
|
||||
from myutils.utils import stringfyerror, autosql, PriorityQueue, SafeFormatter
|
||||
from myutils.utils import (
|
||||
stringfyerror,
|
||||
autosql,
|
||||
PriorityQueue,
|
||||
SafeFormatter,
|
||||
dynamicapiname,
|
||||
)
|
||||
from myutils.commonbase import ArgsEmptyExc, commonbase
|
||||
from myutils.languageguesser import guess
|
||||
|
||||
@ -86,6 +92,7 @@ class basetrans(commonbase):
|
||||
_globalconfig_key = "fanyi"
|
||||
_setting_dict = translatorsetting
|
||||
using_gpt_dict = False
|
||||
_compatible_flag_is_sakura_less_than_5_52_3 = True
|
||||
|
||||
def level2init(self):
|
||||
if (self.transtype == "offline") and (not self.is_gpt_like):
|
||||
@ -97,7 +104,7 @@ class basetrans(commonbase):
|
||||
self._private_init()
|
||||
except Exception as e:
|
||||
gobject.baseobject.displayinfomessage(
|
||||
globalconfig["fanyi"][self.typename]["name"]
|
||||
dynamicapiname(self.typename)
|
||||
+ " init translator failed : "
|
||||
+ str(stringfyerror(e)),
|
||||
"<msg_error_not_refresh>",
|
||||
@ -245,12 +252,6 @@ class basetrans(commonbase):
|
||||
return res
|
||||
return None
|
||||
|
||||
def maybecachetranslate(self, contentsolved, is_auto_run):
|
||||
res = self.shortorlongcacheget(contentsolved, is_auto_run)
|
||||
if res:
|
||||
return res
|
||||
return self.intervaledtranslate(contentsolved)
|
||||
|
||||
def intervaledtranslate(self, content):
|
||||
interval = globalconfig["requestinterval"]
|
||||
current = time.time()
|
||||
@ -298,33 +299,48 @@ class basetrans(commonbase):
|
||||
messages.append(context[i * 2])
|
||||
messages.append(context[i * 2 + 1])
|
||||
|
||||
def reinitandtrans(self, contentsolved, is_auto_run):
|
||||
if self.needreinit or self.initok == False:
|
||||
self.needreinit = False
|
||||
self.renewsesion()
|
||||
try:
|
||||
self._private_init()
|
||||
except Exception as e:
|
||||
raise Exception("init translator failed : " + str(stringfyerror(e)))
|
||||
return self.maybecachetranslate(contentsolved, is_auto_run)
|
||||
def maybeneedreinit(self):
|
||||
if not (self.needreinit or not self.initok):
|
||||
return
|
||||
self.needreinit = False
|
||||
self.renewsesion()
|
||||
try:
|
||||
self._private_init()
|
||||
except Exception as e:
|
||||
raise Exception("init translator failed : " + str(stringfyerror(e)))
|
||||
|
||||
def translate_and_collect(
|
||||
self,
|
||||
contentsolved,
|
||||
is_auto_run,
|
||||
callback,
|
||||
):
|
||||
def maybezhconvwrapper(self, callback):
|
||||
def __maybeshow(callback, res, is_iter_res):
|
||||
|
||||
if self.needzhconv:
|
||||
res = zhconv.convert(res, "zh-tw")
|
||||
callback(res, is_iter_res)
|
||||
|
||||
callback = functools.partial(__maybeshow, callback)
|
||||
return functools.partial(__maybeshow, callback)
|
||||
|
||||
res = self.reinitandtrans(contentsolved, is_auto_run)
|
||||
def translate_and_collect(
|
||||
self,
|
||||
contentsolved: str | dict,
|
||||
is_auto_run,
|
||||
callback,
|
||||
):
|
||||
if isinstance(contentsolved, dict):
|
||||
if self._compatible_flag_is_sakura_less_than_5_52_3:
|
||||
query_use = json.dumps(contentsolved)
|
||||
cache_use = contentsolved["text"]
|
||||
else:
|
||||
query_use = contentsolved
|
||||
cache_use = contentsolved["contentraw"]
|
||||
else:
|
||||
cache_use = query_use = contentsolved
|
||||
|
||||
res = self.shortorlongcacheget(cache_use, is_auto_run)
|
||||
if not res:
|
||||
res = self.intervaledtranslate(query_use)
|
||||
# 不能因为被打断而放弃后面的操作,发出的请求不会因为不再处理而无效,所以与其浪费不如存下来
|
||||
# gettranslationcallback里已经有了是否为当前请求的校验,这里无脑输出就行了
|
||||
|
||||
callback = self.maybezhconvwrapper(callback)
|
||||
if isinstance(res, types.GeneratorType):
|
||||
collectiterres = ""
|
||||
for _res in res:
|
||||
@ -348,8 +364,25 @@ class basetrans(commonbase):
|
||||
# 不管是否使用翻译缓存,都存下来
|
||||
if self.transtype == "pre":
|
||||
return
|
||||
self.shorttermcacheset(contentsolved, res)
|
||||
self.longtermcacheset(contentsolved, res)
|
||||
self.shorttermcacheset(cache_use, res)
|
||||
self.longtermcacheset(cache_use, res)
|
||||
|
||||
def __parse_gpt_dict(self, contentsolved, optimization_params):
|
||||
gpt_dict = None
|
||||
contentraw = contentsolved
|
||||
for _ in optimization_params:
|
||||
if isinstance(_, dict):
|
||||
_gpt_dict = _.get("gpt_dict", None)
|
||||
if _gpt_dict is None:
|
||||
continue
|
||||
gpt_dict = _gpt_dict
|
||||
contentraw = _.get("gpt_dict_origin")
|
||||
|
||||
return {
|
||||
"text": contentsolved,
|
||||
"gpt_dict": gpt_dict,
|
||||
"contentraw": contentraw,
|
||||
}
|
||||
|
||||
def _fythread(self):
|
||||
self.needreinit = False
|
||||
@ -376,23 +409,12 @@ class basetrans(commonbase):
|
||||
if not checktutukufunction():
|
||||
# 检查请求队列是否空,请求队列有新的请求,则放弃当前请求。但对于内嵌翻译请求,不可以放弃。
|
||||
continue
|
||||
if self.transtype == "pre" or self.using_gpt_dict:
|
||||
gpt_dict = None
|
||||
contentraw = contentsolved
|
||||
for _ in optimization_params:
|
||||
if isinstance(_, dict):
|
||||
_gpt_dict = _.get("gpt_dict", None)
|
||||
if _gpt_dict is None:
|
||||
continue
|
||||
gpt_dict = _gpt_dict
|
||||
contentraw = _.get("gpt_dict_origin")
|
||||
|
||||
contentsolved = json.dumps(
|
||||
{
|
||||
"text": contentsolved,
|
||||
"gpt_dict": gpt_dict,
|
||||
"contentraw": contentraw,
|
||||
}
|
||||
self.maybeneedreinit()
|
||||
|
||||
if self.using_gpt_dict:
|
||||
contentsolved = self.__parse_gpt_dict(
|
||||
contentsolved, optimization_params
|
||||
)
|
||||
|
||||
func = functools.partial(
|
||||
|
@ -5,6 +5,6 @@ class TS(commonllmdev):
|
||||
target_url = "https://chatgpt.com/"
|
||||
jsfile = "commonhookfetchstream.js"
|
||||
function1 = 'url.includes("conversation")'
|
||||
function2 = r"""thistext = chunk.message.content.parts[0]"""
|
||||
function2 = r"""thistext += typeof(chunk.v)=='string'?chunk.v:(chunk.v[0]?(chunk.v[0].o=='append'?chunk.v[0].v:''):'')"""
|
||||
textarea_selector = "#prompt-textarea"
|
||||
button_selector = 'button[data-testid="send-button"]'
|
||||
|
@ -8,7 +8,11 @@ from myutils.utils import urlpathjoin
|
||||
|
||||
|
||||
class TS(basetrans):
|
||||
using_gpt_dict = True
|
||||
_compatible_flag_is_sakura_less_than_5_52_3 = False
|
||||
|
||||
@property
|
||||
def using_gpt_dict(self):
|
||||
return self.config["prompt_version"] in [1, 2]
|
||||
|
||||
def langmap(self):
|
||||
return {"zh": "zh-CN"}
|
||||
@ -31,8 +35,6 @@ class TS(basetrans):
|
||||
# self.client = OpenAI(api_key="114514", base_url=api_url)
|
||||
|
||||
def make_gpt_dict_text(self, gpt_dict):
|
||||
if gpt_dict is None:
|
||||
return ""
|
||||
gpt_dict_text_list = []
|
||||
for gpt in gpt_dict:
|
||||
src = gpt["src"]
|
||||
@ -112,11 +114,10 @@ class TS(basetrans):
|
||||
}
|
||||
]
|
||||
self._gpt_common_parse_context_2(messages, self.context, contextnum, True)
|
||||
gpt_dict_raw_text = self.make_gpt_dict_text(gpt_dict)
|
||||
if gpt_dict_raw_text:
|
||||
if gpt_dict:
|
||||
content = (
|
||||
"根据以下术语表(可以为空):\n"
|
||||
+ gpt_dict_raw_text
|
||||
+ self.make_gpt_dict_text(gpt_dict)
|
||||
+ "\n"
|
||||
+ "将下面的日文文本根据对应关系和备注翻译成中文:"
|
||||
+ query
|
||||
@ -211,17 +212,16 @@ class TS(basetrans):
|
||||
|
||||
yield res
|
||||
|
||||
def translate(self, query):
|
||||
query = json.loads(query)
|
||||
gpt_dict = query["gpt_dict"]
|
||||
contentraw = query["contentraw"]
|
||||
query = query["text"]
|
||||
if (
|
||||
(gpt_dict is not None)
|
||||
and len(gpt_dict)
|
||||
and self.config["prompt_version"] in [1, 2]
|
||||
):
|
||||
query = contentraw
|
||||
def translate(self, query: str | dict):
|
||||
if isinstance(query, dict):
|
||||
gpt_dict = query["gpt_dict"]
|
||||
contentraw = query["contentraw"]
|
||||
query = query["text"]
|
||||
if gpt_dict and self.using_gpt_dict:
|
||||
query = contentraw
|
||||
else:
|
||||
gpt_dict = None
|
||||
contentraw = query
|
||||
self.checkempty(["API接口地址"])
|
||||
self.get_client(self.config["API接口地址"])
|
||||
frequency_penalty = float(self.config["frequency_penalty"])
|
||||
|
@ -985,6 +985,11 @@
|
||||
"name": "显示/隐藏范围框",
|
||||
"keystring": ""
|
||||
},
|
||||
"_14_1": {
|
||||
"use": false,
|
||||
"name": "清除OCR范围",
|
||||
"keystring": ""
|
||||
},
|
||||
"_15": {
|
||||
"use": false,
|
||||
"name": "绑定窗口_(点击自己取消)",
|
||||
|
@ -2056,6 +2056,7 @@
|
||||
[
|
||||
"_13",
|
||||
"_14",
|
||||
"_14_1",
|
||||
"_23",
|
||||
"_26",
|
||||
"_26_1"
|
||||
|
@ -804,5 +804,9 @@
|
||||
"日志": "سجل .",
|
||||
"查看": "عرض .",
|
||||
"标记": "علامة",
|
||||
"当前OCR引擎不支持设置语言为自动": "التعرف الضوئي على الحروف المحرك الحالي لا يدعم وضع اللغة التلقائي"
|
||||
"当前OCR引擎不支持设置语言为自动": "التعرف الضوئي على الحروف المحرك الحالي لا يدعم وضع اللغة التلقائي",
|
||||
"字符串地址偏移": "سلسلة عنوان الإزاحة",
|
||||
"无效": "باطل",
|
||||
"清除OCR范围": "مسح نطاق التعرف الضوئي على الحروف",
|
||||
"重命名": "إعادة تسمية"
|
||||
}
|
@ -804,5 +804,9 @@
|
||||
"日志": "日誌",
|
||||
"查看": "查看",
|
||||
"标记": "標記",
|
||||
"当前OCR引擎不支持设置语言为自动": "當前OCR引擎不支持設定語言為自動"
|
||||
"当前OCR引擎不支持设置语言为自动": "當前OCR引擎不支持設定語言為自動",
|
||||
"字符串地址偏移": "字串地址偏移",
|
||||
"无效": "無效",
|
||||
"清除OCR范围": "清除OCR範圍",
|
||||
"重命名": "重命名"
|
||||
}
|
@ -804,5 +804,9 @@
|
||||
"日志": "deník",
|
||||
"查看": "viz",
|
||||
"标记": "značka",
|
||||
"当前OCR引擎不支持设置语言为自动": "Aktuální OCR engine nepodporuje nastavení jazyka na automatické"
|
||||
"当前OCR引擎不支持设置语言为自动": "Aktuální OCR engine nepodporuje nastavení jazyka na automatické",
|
||||
"字符串地址偏移": "Posun adresy řetězce",
|
||||
"无效": "neplatné",
|
||||
"清除OCR范围": "Vymazat rozsah OCR",
|
||||
"重命名": "přejmenovat"
|
||||
}
|
@ -804,5 +804,9 @@
|
||||
"日志": "Journal",
|
||||
"查看": "siehe",
|
||||
"标记": "Zeichen",
|
||||
"当前OCR引擎不支持设置语言为自动": "Die aktuelle OCR-Engine unterstützt die Einstellung der Sprache auf automatisch nicht"
|
||||
"当前OCR引擎不支持设置语言为自动": "Die aktuelle OCR-Engine unterstützt die Einstellung der Sprache auf automatisch nicht",
|
||||
"字符串地址偏移": "String Adresse Offset",
|
||||
"无效": "ungültig",
|
||||
"清除OCR范围": "OCR-Bereich löschen",
|
||||
"重命名": "umbenennen"
|
||||
}
|
@ -804,5 +804,9 @@
|
||||
"日志": "journal",
|
||||
"查看": "see",
|
||||
"标记": "sign",
|
||||
"当前OCR引擎不支持设置语言为自动": "The current OCR engine does not support setting the language to automatic"
|
||||
"当前OCR引擎不支持设置语言为自动": "The current OCR engine does not support setting the language to automatic",
|
||||
"字符串地址偏移": "String address offset",
|
||||
"无效": "invalid",
|
||||
"清除OCR范围": "Clear OCR range",
|
||||
"重命名": "rename"
|
||||
}
|
@ -804,5 +804,9 @@
|
||||
"日志": "Diario",
|
||||
"查看": "Ver",
|
||||
"标记": "Marcado",
|
||||
"当前OCR引擎不支持设置语言为自动": "El motor OCR actual no admite configurar el lenguaje a automático"
|
||||
"当前OCR引擎不支持设置语言为自动": "El motor OCR actual no admite configurar el lenguaje a automático",
|
||||
"字符串地址偏移": "Desplazamiento de la dirección de la cadena",
|
||||
"无效": "Inválido",
|
||||
"清除OCR范围": "Eliminar el rango OCR",
|
||||
"重命名": "Cambiar el nombre"
|
||||
}
|
@ -804,5 +804,9 @@
|
||||
"日志": "Logs",
|
||||
"查看": "Voir",
|
||||
"标记": "Marquage",
|
||||
"当前OCR引擎不支持设置语言为自动": "Le moteur OCR actuel ne prend pas en charge le réglage de la langue sur auto"
|
||||
"当前OCR引擎不支持设置语言为自动": "Le moteur OCR actuel ne prend pas en charge le réglage de la langue sur auto",
|
||||
"字符串地址偏移": "Décalage d'adresse de chaîne",
|
||||
"无效": "Invalide",
|
||||
"清除OCR范围": "Effacer la plage ocr",
|
||||
"重命名": "Renommer"
|
||||
}
|
@ -804,5 +804,9 @@
|
||||
"日志": "diario",
|
||||
"查看": "vedi",
|
||||
"标记": "segno",
|
||||
"当前OCR引擎不支持设置语言为自动": "Il motore OCR corrente non supporta l'impostazione automatica della lingua"
|
||||
"当前OCR引擎不支持设置语言为自动": "Il motore OCR corrente non supporta l'impostazione automatica della lingua",
|
||||
"字符串地址偏移": "Spostamento indirizzo stringa",
|
||||
"无效": "non valido",
|
||||
"清除OCR范围": "Cancella intervallo OCR",
|
||||
"重命名": "rinomina"
|
||||
}
|
@ -804,5 +804,9 @@
|
||||
"日志": "ログ#ログ#",
|
||||
"查看": "表示#ヒョウジ#",
|
||||
"标记": "マークアップ",
|
||||
"当前OCR引擎不支持设置语言为自动": "現在のOCRエンジンでは言語の自動設定はサポートされていません"
|
||||
"当前OCR引擎不支持设置语言为自动": "現在のOCRエンジンでは言語の自動設定はサポートされていません",
|
||||
"字符串地址偏移": "文字列アドレスオフセット",
|
||||
"无效": "無効です",
|
||||
"清除OCR范围": "OCR範囲のクリア",
|
||||
"重命名": "名前を変更"
|
||||
}
|
@ -804,5 +804,9 @@
|
||||
"日志": "로그",
|
||||
"查看": "보기",
|
||||
"标记": "태그",
|
||||
"当前OCR引擎不支持设置语言为自动": "현재 OCR 엔진은 자동 언어 설정을 지원하지 않습니다."
|
||||
"当前OCR引擎不支持设置语言为自动": "현재 OCR 엔진은 자동 언어 설정을 지원하지 않습니다.",
|
||||
"字符串地址偏移": "문자열 주소 오프셋",
|
||||
"无效": "유효하지 않음",
|
||||
"清除OCR范围": "OCR 범위 지우기",
|
||||
"重命名": "이름 바꾸기"
|
||||
}
|
@ -804,5 +804,9 @@
|
||||
"日志": "dagboek",
|
||||
"查看": "zie",
|
||||
"标记": "teken",
|
||||
"当前OCR引擎不支持设置语言为自动": "De huidige OCR-engine ondersteunt niet het instellen van de taal op automatisch"
|
||||
"当前OCR引擎不支持设置语言为自动": "De huidige OCR-engine ondersteunt niet het instellen van de taal op automatisch",
|
||||
"字符串地址偏移": "Tekenadres offset",
|
||||
"无效": "ongeldig",
|
||||
"清除OCR范围": "OCR-bereik wissen",
|
||||
"重命名": "hernoemen"
|
||||
}
|
@ -804,5 +804,9 @@
|
||||
"日志": "dziennik",
|
||||
"查看": "zobacz",
|
||||
"标记": "znak",
|
||||
"当前OCR引擎不支持设置语言为自动": "Obecny silnik OCR nie obsługuje ustawienia języka na automatyczne"
|
||||
"当前OCR引擎不支持设置语言为自动": "Obecny silnik OCR nie obsługuje ustawienia języka na automatyczne",
|
||||
"字符串地址偏移": "Przesunięcie adresu ciągu",
|
||||
"无效": "nieprawidłowe",
|
||||
"清除OCR范围": "Wyczyść zakres OCR",
|
||||
"重命名": "zmień nazwę"
|
||||
}
|
@ -804,5 +804,9 @@
|
||||
"日志": "diário",
|
||||
"查看": "ver",
|
||||
"标记": "signo",
|
||||
"当前OCR引擎不支持设置语言为自动": "O mecanismo OCR atual não suporta configurar o idioma para automático"
|
||||
"当前OCR引擎不支持设置语言为自动": "O mecanismo OCR atual não suporta configurar o idioma para automático",
|
||||
"字符串地址偏移": "Deslocamento do endereço do string",
|
||||
"无效": "inválido",
|
||||
"清除OCR范围": "Limpar o intervalo de OCR",
|
||||
"重命名": "renomear"
|
||||
}
|
@ -804,5 +804,9 @@
|
||||
"日志": "Журнал",
|
||||
"查看": "Посмотреть",
|
||||
"标记": "Маркировка",
|
||||
"当前OCR引擎不支持设置语言为自动": "Текущий движок OCR не поддерживает настройку языка автоматически"
|
||||
"当前OCR引擎不支持设置语言为自动": "Текущий движок OCR не поддерживает настройку языка автоматически",
|
||||
"字符串地址偏移": "Смещение адреса строки",
|
||||
"无效": "Неверный",
|
||||
"清除OCR范围": "Очистить диапазон OCR",
|
||||
"重命名": "Переименовать"
|
||||
}
|
@ -804,5 +804,9 @@
|
||||
"日志": "journal",
|
||||
"查看": "se",
|
||||
"标记": "tecken",
|
||||
"当前OCR引擎不支持设置语言为自动": "Den aktuella OCR-motorn stöder inte inställning av språket till automatiskt"
|
||||
"当前OCR引擎不支持设置语言为自动": "Den aktuella OCR-motorn stöder inte inställning av språket till automatiskt",
|
||||
"字符串地址偏移": "Strängadressförskjutning",
|
||||
"无效": "ogiltig",
|
||||
"清除OCR范围": "Rensa OCR-område",
|
||||
"重命名": "Byt namn"
|
||||
}
|
@ -804,5 +804,9 @@
|
||||
"日志": "บันทึกประจำวัน",
|
||||
"查看": "ดู",
|
||||
"标记": "เครื่องหมาย",
|
||||
"当前OCR引擎不支持设置语言为自动": "เครื่องยนต์ OCR ปัจจุบันไม่รองรับการตั้งค่าภาษาเป็นอัตโนมัติ"
|
||||
"当前OCR引擎不支持设置语言为自动": "เครื่องยนต์ OCR ปัจจุบันไม่รองรับการตั้งค่าภาษาเป็นอัตโนมัติ",
|
||||
"字符串地址偏移": "การชดเชยที่อยู่สตริง",
|
||||
"无效": "ไม่ถูกต้อง",
|
||||
"清除OCR范围": "ล้างช่วง OCR",
|
||||
"重命名": "เปลี่ยนชื่อ"
|
||||
}
|
@ -804,5 +804,9 @@
|
||||
"日志": "Günlük",
|
||||
"查看": "Gördün mü?",
|
||||
"标记": "imza",
|
||||
"当前OCR引擎不支持设置语言为自动": "Ağımdaki OCR motoru dili otomatik olarak ayarlamasını desteklemez"
|
||||
"当前OCR引擎不支持设置语言为自动": "Ağımdaki OCR motoru dili otomatik olarak ayarlamasını desteklemez",
|
||||
"字符串地址偏移": "Kelime adresi",
|
||||
"无效": "Keçersiz",
|
||||
"清除OCR范围": "OCR aralığını temizle",
|
||||
"重命名": "Yeniden Adlandır"
|
||||
}
|
@ -804,5 +804,9 @@
|
||||
"日志": "журнал",
|
||||
"查看": "див.",
|
||||
"标记": "знак",
|
||||
"当前OCR引擎不支持设置语言为自动": "Поточний рушій OCR не підтримує встановлення мови як автоматичного"
|
||||
"当前OCR引擎不支持设置语言为自动": "Поточний рушій OCR не підтримує встановлення мови як автоматичного",
|
||||
"字符串地址偏移": "Вирівнювання адреси рядків",
|
||||
"无效": "некоректний",
|
||||
"清除OCR范围": "Очистити діапазон OCR",
|
||||
"重命名": "перейменувати"
|
||||
}
|
@ -804,5 +804,9 @@
|
||||
"日志": "Đăng nhập",
|
||||
"查看": "Xem thêm",
|
||||
"标记": "Đánh dấu",
|
||||
"当前OCR引擎不支持设置语言为自动": "Công cụ OCR hiện tại không hỗ trợ thiết lập ngôn ngữ tự động"
|
||||
"当前OCR引擎不支持设置语言为自动": "Công cụ OCR hiện tại không hỗ trợ thiết lập ngôn ngữ tự động",
|
||||
"字符串地址偏移": "Thay đổi địa chỉ chuỗi",
|
||||
"无效": "Không hợp lệ",
|
||||
"清除OCR范围": "Xóa dải OCR",
|
||||
"重命名": "Thay tên"
|
||||
}
|
@ -804,5 +804,9 @@
|
||||
"日志": "",
|
||||
"查看": "",
|
||||
"标记": "",
|
||||
"当前OCR引擎不支持设置语言为自动": ""
|
||||
"当前OCR引擎不支持设置语言为自动": "",
|
||||
"字符串地址偏移": "",
|
||||
"无效": "",
|
||||
"清除OCR范围": "",
|
||||
"重命名": ""
|
||||
}
|
@ -28,8 +28,8 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/version)
|
||||
include(generate_product_version)
|
||||
|
||||
set(VERSION_MAJOR 5)
|
||||
set(VERSION_MINOR 52)
|
||||
set(VERSION_PATCH 3)
|
||||
set(VERSION_MINOR 53)
|
||||
set(VERSION_PATCH 0)
|
||||
|
||||
add_library(pch pch.cpp)
|
||||
target_precompile_headers(pch PUBLIC pch.h)
|
||||
|
@ -271,7 +271,7 @@ def MessageBox(msg, info = 'Message'):
|
||||
ctypes.windll.user32.MessageBoxW(None, str(msg), str(info), 0)
|
||||
return 0
|
||||
os.MessageBox = MessageBox
|
||||
sys.stdout=sys.stderr
|
||||
#sys.stdout=sys.stderr
|
||||
sys.path.insert(0, './LunaTranslator')
|
||||
)"
|
||||
#ifndef PYSTAND_CONSOLE
|
||||
@ -365,6 +365,7 @@ int main()
|
||||
}
|
||||
#else
|
||||
SetConsoleOutputCP(CP_UTF8);
|
||||
/*
|
||||
auto getCurrentTimestamp = []
|
||||
{
|
||||
auto now = std::chrono::system_clock::now();
|
||||
@ -376,6 +377,7 @@ int main()
|
||||
};
|
||||
auto curr = getCurrentTimestamp();
|
||||
freopen(curr.c_str(), "a", stderr);
|
||||
*/
|
||||
#endif
|
||||
int hr = ps.RunString(init_script);
|
||||
return hr;
|
||||
|
Loading…
x
Reference in New Issue
Block a user