issues 622/623

This commit is contained in:
恍兮惚兮 2024-04-04 16:24:33 +08:00
parent 018797c905
commit cabf20e785
28 changed files with 210 additions and 88 deletions

View File

@ -451,16 +451,22 @@ class MAINUI:
# print_exc()
self.readcurrent()
def ttsrepair(self, text, usedict):
if usedict["tts_repair"]:
text = self.parsemayberegexreplace(usedict["tts_repair_regex"], text)
return text
def readcurrent(self, force=False):
try:
if force or globalconfig["autoread"]:
if globalconfig["ttscommon"]["tts_repair"]:
text = self.parsemayberegexreplace(
globalconfig["ttscommon"]["tts_repair_regex"], self.currentread
text = self.ttsrepair(self.currentread, globalconfig["ttscommon"])
try:
text = self.ttsrepair(
text, savehook_new_data[self.textsource.pname]
)
else:
text = self.currentread
self.reader.read(text)
except:
print_exc()
self.reader.read(text, force)
except:
print_exc()

View File

@ -58,6 +58,7 @@ from myutils.utils import checkifnewgame
from myutils.proxy import getproxy
from gui.usefulwidget import yuitsu_switch, saveposwindow, getboxlayout
from myutils.vndb import parsehtmlmethod
from gui.inputdialog import noundictconfigdialog1
class ItemWidget(QWidget):
@ -691,10 +692,47 @@ class dialog_setting_game(QDialog):
methodtab = QTabWidget()
methodtab.addTab(self.gethooktab(exepath), "HOOK")
methodtab.addTab(self.getpretranstab(exepath), "预翻译")
methodtab.addTab(self.getttssetting(exepath), "语音")
formLayout.addWidget(methodtab)
self.show()
def getttssetting(self, exepath):
_w = QWidget()
formLayout = QVBoxLayout()
formLayout.setAlignment(Qt.AlignTop)
_w.setLayout(formLayout)
edit = QLineEdit(savehook_new_data[exepath]["allow_tts_auto_names"])
edit.textChanged.connect(
lambda x: savehook_new_data[exepath].__setitem__("allow_tts_auto_names", x)
)
formLayout.addLayout(
getboxlayout([QLabel(_TR("禁止自动朗读的人名(以|分隔多个)")), edit])
)
formLayout.addLayout(
getboxlayout(
[
QLabel(_TR("语音修正")),
getsimpleswitch(savehook_new_data[exepath], "tts_repair"),
getcolorbutton(
globalconfig,
"",
callback=lambda x: noundictconfigdialog1(
self,
savehook_new_data[exepath],
"tts_repair_regex",
"语音修正",
["正则", "原文", "替换"],
),
icon="fa.gear",
constcolor="#FF69B4",
),
]
)
)
return _w
def getpretranstab(self, exepath):
_w = QWidget()
formLayout = QVBoxLayout()
@ -813,16 +851,6 @@ class dialog_setting_game(QDialog):
]
)
)
if globalconfig["allow_set_text_name"]:
edit = QLineEdit(savehook_new_data[exepath]["allow_tts_auto_names"])
edit.textChanged.connect(
lambda x: savehook_new_data[exepath].__setitem__(
"allow_tts_auto_names", x
)
)
formLayout.addLayout(
getboxlayout([QLabel(_TR("禁止自动朗读的人名(以|分隔多个)")), edit])
)
return _w
def clicked2(self):

View File

@ -8,11 +8,13 @@ from PyQt5.QtWidgets import (
QListWidget,
QHBoxLayout,
QListWidgetItem,
QMenu,
QAction,
QApplication,
)
from PyQt5.QtGui import QResizeEvent
from PyQt5.QtWidgets import QTabWidget
import qtawesome, darkdetect, ctypes
import qtawesome, darkdetect, gobject
import functools
from traceback import print_exc
from myutils.config import globalconfig, _TR
@ -29,6 +31,7 @@ from gui.setting_proxy import setTab_proxy
from gui.settingpage7 import setTab7, settab7direct
from gui.settingpage_about import setTab_about, setTab_about_dicrect
from gui.usefulwidget import closeashidewindow
from myutils.hwnd import darkchange
class gridwidget(QWidget):
@ -37,7 +40,7 @@ class gridwidget(QWidget):
class Settin(closeashidewindow):
voicelistsignal = pyqtSignal(list, int)
mp3playsignal = pyqtSignal(str, int)
mp3playsignal = pyqtSignal(str, int, bool)
versiontextsignal = pyqtSignal(str)
progresssignal = pyqtSignal(str, int)
fontbigsmallsignal = pyqtSignal(int)
@ -124,7 +127,7 @@ class Settin(closeashidewindow):
self.usevoice = 0
self.isfirstshow = True
self.inittray()
setTabOne_direct(self)
settab2d(self)
settab7direct(self)
@ -136,6 +139,26 @@ class Settin(closeashidewindow):
self.setstylesheet()
def inittray(self):
showAction = QAction(
_TR("&显示"),
self,
triggered=gobject.baseobject.translation_ui.show_and_enableautohide,
)
settingAction = QAction(
_TR("&设置"),
self,
triggered=lambda: gobject.baseobject.settin_ui.showsignal.emit(),
)
quitAction = QAction(_TR("&退出"), self, triggered=self.close)
self.trayMenu = QMenu(self)
self.trayMenu.addAction(showAction)
self.trayMenu.addAction(settingAction)
self.trayMenu.addSeparator()
self.trayMenu.addAction(quitAction)
gobject.baseobject.translation_ui.tray.setContextMenu(self.trayMenu)
def opensolvetextfun(self):
self.show()
self.tab_widget.setCurrentIndex(3)
@ -219,34 +242,18 @@ class Settin(closeashidewindow):
dark = darkdetect.isDark()
darklight = ["light", "dark"][dark]
top_level_widgets = QApplication.topLevelWidgets()
def ChangeDWMAttrib(hWnd: int, attrib: int, color) -> None:
try:
ctypes.windll.dwmapi.DwmSetWindowAttribute(
hWnd, attrib, ctypes.byref(color), ctypes.sizeof(ctypes.c_int)
)
except:
pass
def darkchange(hwnd):
if dark:
ChangeDWMAttrib(hwnd, 19, ctypes.c_int(1))
ChangeDWMAttrib(hwnd, 20, ctypes.c_int(1))
else:
ChangeDWMAttrib(hwnd, 19, ctypes.c_int(0))
ChangeDWMAttrib(hwnd, 20, ctypes.c_int(0))
class WindowEventFilter(QObject):
def eventFilter(self, obj, event):
if event.type() == QEvent.Type.WindowTitleChange:
darkchange(int(obj.winId()))
if event.type() == QEvent.Type.WinIdChange:
hwnd = obj.winId()
if hwnd: # window create/destroy,when destroy winId is None
darkchange(int(obj.winId()), dark)
return False
self.__filter = WindowEventFilter()
self.__filter = WindowEventFilter() # keep ref
QApplication.instance().installEventFilter(self.__filter)
for widget in top_level_widgets:
darkchange(int(widget.winId()))
for widget in QApplication.topLevelWidgets():
darkchange(int(widget.winId()), dark)
try:
idx = globalconfig[darklight + "theme"] - int(not dark)

View File

@ -101,6 +101,7 @@ def setTab5lz(self):
(getspinbox(0, 100, globalconfig["ttscommon"], "volume"), 3),
],
[("自动朗读", 6), (getsimpleswitch(globalconfig, "autoread"), 1)],
[("不被打断", 6), (getsimpleswitch(globalconfig, "ttsnointerrupt"), 1)],
[
("朗读原文", 6),
(getsimpleswitch(globalconfig, "read_raw"), 1),

View File

@ -100,7 +100,7 @@ class searchwordW(closeashidewindow):
def langdu(self):
if gobject.baseobject.reader:
gobject.baseobject.reader.read(self.searchtext.text())
gobject.baseobject.reader.read(self.searchtext.text(), True)
def getnewsentence(self, sentence):
self.showNormal()

View File

@ -531,28 +531,8 @@ class QUnFrameWindow(resizableframeless):
if self.isfirstshow:
self.showline(clear=True, text=_TR("欢迎使用"), origin=False)
showAction = QAction(
_TR("&显示"), self, triggered=self.show_and_enableautohide
)
settingAction = QAction(
_TR("&设置"),
self,
triggered=lambda: gobject.baseobject.settin_ui.showsignal.emit(),
)
quitAction = QAction(_TR("&退出"), self, triggered=self.close)
self.tray.activated.connect(self.leftclicktray)
# 创建菜单对象
self.trayMenu = QMenu(self)
# 将动作对象添加到菜单
self.trayMenu.addAction(showAction)
self.trayMenu.addAction(settingAction)
# 增加分割线
self.trayMenu.addSeparator()
self.trayMenu.addAction(quitAction)
# 将菜单栏加入到右键按钮中
self.tray.setContextMenu(self.trayMenu)
self.tray.show()
windows.SetForegroundWindow(int(self.winId()))
self.isfirstshow = False

View File

@ -74,6 +74,8 @@ def getdefaultsavehook(gamepath, title=None):
"removeuseless": False,
"codepage_index": 0,
"allow_tts_auto_names": "",
"tts_repair": False,
"tts_repair_regex": [],
"hooktypeasname": {},
"use_saved_text_process": False,
"searchnoresulttime": 0,

View File

@ -2,7 +2,7 @@ import windows
import threading
from PyQt5.QtGui import QPixmap, QColor, QIcon
from PyQt5.QtWidgets import QApplication
import gobject
import gobject, ctypes
import os, subprocess
import time, winrtutils, winsharedutils, hashlib
from myutils.wrapper import threader
@ -338,3 +338,44 @@ def showintab(hwnd, show):
style_ex &= ~windows.WS_EX_APPWINDOW
style_ex |= windows.WS_EX_TOOLWINDOW
windows.SetWindowLong(hwnd, windows.GWL_EXSTYLE, style_ex)
def darkchange(hwnd, dark):
def ChangeDWMAttrib(hWnd: int, attrib: int, color) -> None:
try:
ctypes.windll.dwmapi.DwmSetWindowAttribute(
hWnd, attrib, ctypes.byref(color), ctypes.sizeof(ctypes.c_int)
)
except:
pass
def systemmenu(mode):
try:
# https://stackoverflow.com/questions/53501268/win10-dark-theme-how-to-use-in-winapi
# https://gist.github.com/rounk-ctrl/b04e5622e30e0d62956870d5c22b7017
LoadLibrary = ctypes.windll.Kernel32.LoadLibraryW
LoadLibrary.argtypes = (ctypes.c_wchar_p,)
LoadLibrary.restype = ctypes.c_void_p
GetProcAddress = ctypes.windll.Kernel32.GetProcAddress
GetProcAddress.argtypes = ctypes.c_void_p, ctypes.c_void_p
GetProcAddress.restype = ctypes.c_void_p
uxtheme = LoadLibrary("uxtheme.dll")
SetPreferredAppMode = GetProcAddress(uxtheme, 135)
FlushMenuThemes = GetProcAddress(uxtheme, 136)
SetPreferredAppMode = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_int)(
SetPreferredAppMode
)
FlushMenuThemes = ctypes.CFUNCTYPE(None)(FlushMenuThemes)
SetPreferredAppMode(mode)
FlushMenuThemes()
except:
pass
if dark:
ChangeDWMAttrib(hwnd, 19, ctypes.c_int(1))
ChangeDWMAttrib(hwnd, 20, ctypes.c_int(1))
systemmenu(2)
else:
ChangeDWMAttrib(hwnd, 19, ctypes.c_int(0))
ChangeDWMAttrib(hwnd, 20, ctypes.c_int(0))
systemmenu(3)

View File

@ -173,11 +173,42 @@ class wavmp3player:
def __init__(self):
self.i = 0
self.lastfile = None
self.tasks = None
self.lock = threading.Lock()
self.lock.acquire()
threading.Thread(target=self.dotasks).start()
def mp3playfunction(self, path, volume):
if os.path.exists(path) == False:
return
self._playsoundWin(path, volume)
def mp3playfunction(self, path, volume, force):
try:
self.tasks = (path, volume, force)
self.lock.release()
except:
pass
def dotasks(self):
durationms = 0
try:
while True:
self.lock.acquire()
task = self.tasks
self.tasks = None
if task is None:
continue
path, volume, force = task
if os.path.exists(path) == False:
continue
durationms = self._playsoundWin(path, volume)
if durationms and globalconfig["ttsnointerrupt"]:
while durationms > 0:
durationms -= 100
time.sleep(0.1)
if self.tasks and self.tasks[-1]:
break
# time.sleep(durationms / 1000)
except:
print_exc()
def _playsoundWin(self, sound, volume):
try:
@ -193,6 +224,11 @@ class wavmp3player:
sound, self.i
)
)
durationms = int(
windows.mciSendString(
"status lunatranslator_mci_{} length".format(self.i)
)
)
windows.mciSendString(
"setaudio lunatranslator_mci_{} volume to {}".format(
self.i, volume * 10
@ -200,7 +236,9 @@ class wavmp3player:
)
windows.mciSendString(("play lunatranslator_mci_{}".format(self.i)))
except:
pass
durationms = 0
return durationms
def selectdebugfile(path):

View File

@ -51,7 +51,7 @@ class ocrtext(basetext):
def newrangeadjustor(self):
if len(self.range_ui) == 0 or globalconfig["multiregion"]:
self.range_ui.append(rangeadjust(gobject.baseobject.translation_ui))
self.range_ui.append(rangeadjust(gobject.baseobject.settin_ui))
self.savelastimg.append(None)
self.savelastrecimg.append(None)
self.lastocrtime.append(0)

View File

@ -50,7 +50,7 @@ class TTSbase:
threading.Thread(target=_).start()
def read(self, content):
def read(self, content, force=False):
if self.loadok == False:
return
@ -67,6 +67,6 @@ class TTSbase:
def _():
fname = self.speak(content, rate, voice, voice_index)
if fname:
self.mp3playsignal.emit(fname, volume)
self.mp3playsignal.emit(fname, volume, force)
threading.Thread(target=_).start()

View File

@ -756,7 +756,10 @@ def mciSendString(s):
_winmm = windll.winmm
_mciSendStringW = _winmm.mciSendStringW
_mciSendStringW.argtypes = c_wchar_p, c_wchar_p, c_uint, c_void_p
return _mciSendStringW(s, None, 0, None)
bf = create_unicode_buffer(1024)
if _mciSendStringW(s, bf, 1024, None) != 0:
return None
return bf.value
# _RegOpenKeyExW=_Advapi32.RegOpenKeyExW

View File

@ -130,6 +130,7 @@
"use_yapi":true,
"showfanyi":true,
"autoread": false,
"ttsnointerrupt":false,
"show_fenci": false,
"jiamingcolor": "black",
"settingfonttype": "Arial",

View File

@ -741,5 +741,6 @@
"解析效果时保存源代码": "تحليل تأثير عند حفظ شفرة المصدر",
"编译效果时将警告视为错误": "تحذير خطأ عند تجميع تأثير",
"检测重复帧": "الكشف عن تكرار الإطار",
"启用动态检测统计": "يمكن الكشف عن الإحصاءات الحيوية"
"启用动态检测统计": "يمكن الكشف عن الإحصاءات الحيوية",
"不被打断": "لا يقاطع"
}

View File

@ -741,5 +741,6 @@
"解析效果时保存源代码": "解析效果時保存原始程式碼",
"编译效果时将警告视为错误": "編譯效果時將警告視為錯誤",
"检测重复帧": "檢測重複幀",
"启用动态检测统计": "啟用動態檢測統計"
"启用动态检测统计": "啟用動態檢測統計",
"不被打断": "不被打斷"
}

View File

@ -741,5 +741,6 @@
"解析效果时保存源代码": "Save source code when parsing effects",
"编译效果时将警告视为错误": "Treat warnings as errors when compiling effects",
"检测重复帧": "Detect duplicate frames",
"启用动态检测统计": "Enable dynamic detection statistics"
"启用动态检测统计": "Enable dynamic detection statistics",
"不被打断": "Not interrupted"
}

View File

@ -741,5 +741,6 @@
"解析效果时保存源代码": "Guardar el código fuente al analizar el efecto",
"编译效果时将警告视为错误": "Tratar la advertencia como un error al compilar el efecto",
"检测重复帧": "Detección de cuadros duplicados",
"启用动态检测统计": "Activar estadísticas de detección dinámica"
"启用动态检测统计": "Activar estadísticas de detección dinámica",
"不被打断": "Sin ser interrumpido"
}

View File

@ -741,5 +741,6 @@
"解析效果时保存源代码": "Enregistrer le code source lors de l'analyse des effets",
"编译效果时将警告视为错误": "Traiter les avertissements comme des erreurs lors de la compilation des effets",
"检测重复帧": "Détection de trames répétitives",
"启用动态检测统计": "Activer les statistiques de détection dynamique"
"启用动态检测统计": "Activer les statistiques de détection dynamique",
"不被打断": "Ne pas être interrompu"
}

View File

@ -741,5 +741,6 @@
"解析效果时保存源代码": "Salva il codice sorgente durante l'analisi degli effetti",
"编译效果时将警告视为错误": "Tratta gli avvisi come errori durante la compilazione degli effetti",
"检测重复帧": "Rileva quadri duplicati",
"启用动态检测统计": "Abilita statistiche di rilevamento dinamico"
"启用动态检测统计": "Abilita statistiche di rilevamento dinamico",
"不被打断": "Non interrotto"
}

View File

@ -741,5 +741,6 @@
"解析效果时保存源代码": "効果解析時にソースコードを保存する",
"编译效果时将警告视为错误": "効果のコンパイル時に警告をエラーとして扱う",
"检测重复帧": "重複フレームの検出",
"启用动态检测统计": "動的検出統計の有効化"
"启用动态检测统计": "動的検出統計の有効化",
"不被打断": "中断されない"
}

View File

@ -741,5 +741,6 @@
"解析效果时保存源代码": "효과 확인 시 소스 코드 저장",
"编译效果时将警告视为错误": "효과를 컴파일할 때 경고가 오류로 간주됨",
"检测重复帧": "중복 프레임 체크",
"启用动态检测统计": "동적 검색 통계 사용"
"启用动态检测统计": "동적 검색 통계 사용",
"不被打断": "끊기지 않음"
}

View File

@ -741,5 +741,6 @@
"解析效果时保存源代码": "Zapisz kod źródłowy podczas analizy efektów",
"编译效果时将警告视为错误": "Traktuj ostrzeżenia jako błędy podczas kompilowania efektów",
"检测重复帧": "Wykryj duplikaty klatek",
"启用动态检测统计": "Włącz dynamiczne statystyki wykrywania"
"启用动态检测统计": "Włącz dynamiczne statystyki wykrywania",
"不被打断": "Bez przerwy"
}

View File

@ -741,5 +741,6 @@
"解析效果时保存源代码": "Сохранить исходный код при анализе эффектов",
"编译效果时将警告视为错误": "Предупреждение считается ошибкой при компиляции",
"检测重复帧": "Обнаружение повторяющихся кадров",
"启用动态检测统计": "Включить статистику динамического обнаружения"
"启用动态检测统计": "Включить статистику динамического обнаружения",
"不被打断": "Не прерывать."
}

View File

@ -741,5 +741,6 @@
"解析效果时保存源代码": "บันทึกซอร์สโค้ดเมื่อวิเคราะห์ผลกระทบ",
"编译效果时将警告视为错误": "ถือว่าคำเตือนเป็นข้อผิดพลาดเมื่อรวบรวมเอฟเฟกต์",
"检测重复帧": "ตรวจจับเฟรมที่ซ้ำกัน",
"启用动态检测统计": "เปิดใช้งานสถิติการตรวจจับแบบไดนามิก"
"启用动态检测统计": "เปิดใช้งานสถิติการตรวจจับแบบไดนามิก",
"不被打断": "ไม่ถูกขัดจังหวะ"
}

View File

@ -741,5 +741,6 @@
"解析效果时保存源代码": "Efektleri ayırıştığında kaynak kodu kaydet",
"编译效果时将警告视为错误": "Efektleri birleştirirken uyarımları hata olarak tedavi edin",
"检测重复帧": "Çiftleri keşfet",
"启用动态检测统计": "Dinamik tanıma istatistiklerini etkinleştir"
"启用动态检测统计": "Dinamik tanıma istatistiklerini etkinleştir",
"不被打断": "Bırakılmadı"
}

View File

@ -741,5 +741,6 @@
"解析效果时保存源代码": "Зберегти код джерела під час аналізу ефектів",
"编译效果时将警告视为错误": "Вважати попередження помилками під час збирання ефектів",
"检测重复帧": "Визначити дублікатні рамки",
"启用动态检测统计": "Увімкнути статистику динамічного виявлення"
"启用动态检测统计": "Увімкнути статистику динамічного виявлення",
"不被打断": "Не перервано"
}

View File

@ -741,5 +741,6 @@
"解析效果时保存源代码": "Lưu mã nguồn khi phân tích hiệu ứng",
"编译效果时将警告视为错误": "Xem cảnh báo là lỗi khi biên dịch hiệu ứng",
"检测重复帧": "Phát hiện các khung lặp lại",
"启用动态检测统计": "Bật thống kê phát hiện động"
"启用动态检测统计": "Bật thống kê phát hiện động",
"不被打断": "Không bị gián đoạn"
}

View File

@ -741,5 +741,6 @@
"解析效果时保存源代码": "",
"编译效果时将警告视为错误": "",
"检测重复帧": "",
"启用动态检测统计": ""
"启用动态检测统计": "",
"不被打断": ""
}