mirror of
https://github.com/HIllya51/LunaTranslator.git
synced 2025-01-12 23:23:54 +08:00
.
This commit is contained in:
parent
d06c29fc59
commit
43349deec5
3
.github/scripts/build_lunatranslator.py
vendored
3
.github/scripts/build_lunatranslator.py
vendored
@ -268,6 +268,9 @@ def downloadbass():
|
||||
"https://www.un4seen.com/files/z/2/bass_spx24.zip",
|
||||
"https://www.un4seen.com/files/z/2/bass_aac24.zip",
|
||||
"https://www.un4seen.com/files/bassopus24.zip",
|
||||
"https://www.un4seen.com/files/bassenc24.zip",
|
||||
"https://www.un4seen.com/files/bassenc_mp324.zip",
|
||||
"https://www.un4seen.com/files/bassenc_opus24.zip",
|
||||
):
|
||||
name = link.split("/")[-1]
|
||||
d = name.split(".")[0]
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -37,6 +37,7 @@ cpp/LunaHook/builds
|
||||
cpp/builds
|
||||
cpp/libs/webview2
|
||||
cpp/.vscode/settings.json
|
||||
cpp/libs/bass
|
||||
cpp/libs/opencv-static/windows-x86
|
||||
cpp/libs/opencv-static/windows-x64
|
||||
cpp/libs/onnxruntime-static/windows-x86
|
||||
|
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -7,9 +7,6 @@
|
||||
[submodule "src/plugins/libs/wechat-ocr"]
|
||||
path = cpp/libs/wechat-ocr
|
||||
url = https://github.com/swigger/wechat-ocr
|
||||
[submodule "src/plugins/libs/tinymp3"]
|
||||
path = cpp/libs/tinymp3
|
||||
url = https://github.com/HIllya51/tinymp3
|
||||
[submodule "src/plugins/libs/Clipper2"]
|
||||
path = cpp/libs/Clipper2
|
||||
url = https://github.com/AngusJohnson/Clipper2
|
||||
|
@ -224,10 +224,6 @@ int PyStand::DetectScript()
|
||||
}
|
||||
SetEnvironmentVariableW(L"PYSTAND_SCRIPT", _script.c_str());
|
||||
|
||||
std::vector<wchar_t> buffer(MAX_PATH);
|
||||
GetModuleFileNameW(GetModuleHandle(0), buffer.data(), MAX_PATH);
|
||||
SetEnvironmentVariableW(L"LUNA_EXE_NAME", buffer.data());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,6 @@ else()
|
||||
add_library(wil INTERFACE)
|
||||
target_include_directories(wil INTERFACE ${CMAKE_CURRENT_LIST_DIR}/wil/include)
|
||||
|
||||
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/tinymp3 ${CMAKE_BINARY_DIR}/tinymp3)
|
||||
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/rapidfuzz-cpp ${CMAKE_BINARY_DIR}/rapidfuzz-cpp)
|
||||
|
||||
|
||||
|
@ -1 +0,0 @@
|
||||
Subproject commit 579726185979f877f2672b956b23538ff00c08ba
|
@ -1,7 +1,7 @@
|
||||
|
||||
set(VERSION_MAJOR 6)
|
||||
set(VERSION_MINOR 16)
|
||||
set(VERSION_PATCH 5)
|
||||
set(VERSION_PATCH 6)
|
||||
set(VERSION_REVISION 0)
|
||||
set(LUNA_VERSION "{${VERSION_MAJOR},${VERSION_MINOR},${VERSION_PATCH},${VERSION_REVISION}}")
|
||||
add_library(VERSION_DEF ${CMAKE_CURRENT_LIST_DIR}/version_def.cpp)
|
||||
|
@ -10,16 +10,15 @@ generate_product_version(
|
||||
VERSION_MINOR ${VERSION_MINOR}
|
||||
VERSION_PATCH ${VERSION_PATCH}
|
||||
)
|
||||
add_library(winsharedutils MODULE mp3enc.cpp webview2_extra.cpp AreoAcrylic.cpp screenshot.cpp ../implsapi.cpp hwnd.cpp globalmessagelistener.cpp theme.cpp version.cpp otsu.cpp clipboard.cpp lnk.cpp levenshtein.cpp muteprocess.cpp sapi_dll.cpp simplemecab.cpp
|
||||
add_library(winsharedutils MODULE webview2_extra.cpp AreoAcrylic.cpp screenshot.cpp ../implsapi.cpp hwnd.cpp globalmessagelistener.cpp theme.cpp version.cpp otsu.cpp clipboard.cpp lnk.cpp levenshtein.cpp muteprocess.cpp sapi_dll.cpp simplemecab.cpp
|
||||
applicationloopbackaudio/runer.cpp applicationloopbackaudio/LoopbackCapture.cpp
|
||||
SimpleBrowser.cpp MWebBrowser.cpp icon.cpp ${versioninfo})
|
||||
target_precompile_headers(winsharedutils REUSE_FROM pch)
|
||||
if(NOT WINXP)
|
||||
target_link_libraries(winsharedutils tinymp3 rapidfuzz wil webview2 Mfplat mfuuid Mmdevapi dwmapi)
|
||||
target_link_libraries(winsharedutils rapidfuzz wil webview2 Mfplat mfuuid Mmdevapi dwmapi)
|
||||
target_link_options(winsharedutils PRIVATE "/DELAYLOAD:Mmdevapi.dll")
|
||||
target_link_options(winsharedutils PRIVATE "/DELAYLOAD:Mfplat.dll")
|
||||
else()
|
||||
target_link_libraries(winsharedutils tinymp3)
|
||||
endif()
|
||||
if(${CMAKE_SIZEOF_VOID_P} EQUAL 8)
|
||||
set_target_properties(winsharedutils PROPERTIES OUTPUT_NAME "winsharedutils64")
|
||||
|
@ -1,82 +0,0 @@
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <timing.h>
|
||||
#include <shine_mp3.h>
|
||||
|
||||
#define DR_WAV_IMPLEMENTATION
|
||||
#include "dr_wav.h"
|
||||
|
||||
int stereo = STEREO;
|
||||
|
||||
DECLARE_API void encodemp3(void *ptr, size_t size, void (*cb)(void *ptr, size_t size), int bitrate)
|
||||
{
|
||||
shine_config_t config;
|
||||
shine_t s;
|
||||
int written;
|
||||
unsigned char *data;
|
||||
/* Set the default MPEG encoding paramters - basically init the struct */
|
||||
shine_set_config_mpeg_defaults(&config.mpeg);
|
||||
|
||||
config.mpeg.bitr = bitrate; // 8-320;
|
||||
|
||||
uint32_t sampleRate = 0;
|
||||
uint64_t totalSampleCount = 0;
|
||||
uint32_t channels = 0;
|
||||
int16_t *data_in = drwav_open_memory_and_read_pcm_frames_s16(ptr, size, &channels, &sampleRate, &totalSampleCount, NULL);
|
||||
if (data_in == NULL)
|
||||
return;
|
||||
totalSampleCount *= channels;
|
||||
double startTime = now();
|
||||
config.wave.samplerate = sampleRate;
|
||||
config.wave.channels = (decltype(config.wave.channels))channels;
|
||||
|
||||
/* See if samplerate and bitrate are valid */
|
||||
if (shine_check_config(config.wave.samplerate, config.mpeg.bitr) < 0)
|
||||
return;
|
||||
// printf("Unsupported samplerate/bitrate configuration.");
|
||||
|
||||
/* Set to stereo mode if wave data is stereo, mono otherwise. */
|
||||
if (config.wave.channels > 1)
|
||||
config.mpeg.mode = (decltype(config.mpeg.mode))stereo;
|
||||
else
|
||||
config.mpeg.mode = MONO;
|
||||
|
||||
/* Initiate encoder */
|
||||
s = shine_initialise(&config);
|
||||
|
||||
int samples_per_pass = shine_samples_per_pass(s) * channels;
|
||||
std::string sdata;
|
||||
/* All the magic happens here */
|
||||
size_t count = totalSampleCount / samples_per_pass;
|
||||
int16_t *buffer = data_in;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
data = shine_encode_buffer_interleaved(s, buffer, &written);
|
||||
sdata += std::string((char *)data, written);
|
||||
buffer += samples_per_pass;
|
||||
}
|
||||
size_t last = totalSampleCount % samples_per_pass;
|
||||
if (last != 0)
|
||||
{
|
||||
int16_t *cache = (int16_t *)calloc(samples_per_pass, sizeof(int16_t));
|
||||
if (cache != NULL)
|
||||
{
|
||||
memcpy(cache, buffer, last * sizeof(int16_t));
|
||||
data = shine_encode_buffer_interleaved(s, cache, &written);
|
||||
free(cache);
|
||||
sdata += std::string((char *)data, written);
|
||||
}
|
||||
}
|
||||
/* Flush and write remaining data. */
|
||||
data = shine_flush(s, &written);
|
||||
sdata += std::string((char *)data, written);
|
||||
/* Close encoder. */
|
||||
shine_close(s);
|
||||
free(data_in);
|
||||
double time_interval = calcElapsed(startTime, now());
|
||||
cb(sdata.data(), sdata.size());
|
||||
}
|
@ -16,11 +16,16 @@ class goo(cishubase):
|
||||
|
||||
xx = "".join(xx).replace('href="/', 'href="https://dictionary.goo.ne.jp/')
|
||||
if not self.style:
|
||||
self.style = requests.get(
|
||||
"https://dictionary.goo.ne.jp/mix/css/app.css", proxies=self.proxy
|
||||
).text
|
||||
self.style = (
|
||||
requests.get(
|
||||
"https://dictionary.goo.ne.jp/mix/css/app.css", proxies=self.proxy
|
||||
)
|
||||
.text.replace("width:1004px", "")
|
||||
.replace("width:1024px", "")
|
||||
.replace("width:644px", "")
|
||||
)
|
||||
|
||||
if len(xx):
|
||||
return '<div style="text-align: center;"><a href="{}">link</a><style>{}</style></div><div id="NR-main-in">{}</div>'.format(
|
||||
return '<div style="text-align: center;"><a href="{}">link</a><style>{}</style></div><div id="NR-wrapper"><div id="NR-wrapper-in" class="cx">{}</div></div>'.format(
|
||||
url, self.style, xx
|
||||
)
|
||||
|
@ -1,8 +1,8 @@
|
||||
import math, base64, uuid, gobject
|
||||
from cishu.cishubase import DictTree
|
||||
from myutils.config import isascii
|
||||
from myutils.config import isascii, globalconfig
|
||||
from traceback import print_exc
|
||||
from myutils.audioplayer import bass_decode
|
||||
from myutils.audioplayer import bass_code_cast
|
||||
import json, os
|
||||
|
||||
cachejson = None
|
||||
@ -2293,18 +2293,14 @@ class mdict(cishubase):
|
||||
file_content = self.parse_url_in_mdd(index, url[8:])
|
||||
if not file_content:
|
||||
return
|
||||
ext = os.path.splitext(url)[1].lower()
|
||||
if ext in (".aac", ".spx", ".opus"):
|
||||
mp3 = bass_decode(file_content, ext)
|
||||
if not mp3:
|
||||
print(ext, "decode error")
|
||||
return
|
||||
file_content = mp3
|
||||
ext = ".mp3"
|
||||
ext = os.path.splitext(url)[1].lower()[1:]
|
||||
if True: # ext in ("aac", "spx", "opus"):
|
||||
new, ext = bass_code_cast(file_content, fr=ext)
|
||||
file_content = new
|
||||
varname = "var_" + hashlib.md5(file_content).hexdigest()
|
||||
audiob64vals[varname] = base64.b64encode(file_content).decode()
|
||||
return 3, "javascript:mdict_play_sound('{}',{})".format(
|
||||
query_mime(ext), varname
|
||||
query_mime("." + ext), varname
|
||||
)
|
||||
file_content = self.parse_url_in_mdd(index, url)
|
||||
if not file_content:
|
||||
@ -2515,7 +2511,7 @@ class mdict(cishubase):
|
||||
)
|
||||
)
|
||||
idx += 1
|
||||
commonstyle = """
|
||||
res = """
|
||||
<script>
|
||||
function onclickbtn_mdict_internal(_id) {
|
||||
tabPanes = document.querySelectorAll('.tab-widget_mdict_internal .tab-pane_mdict_internal');
|
||||
@ -2562,12 +2558,7 @@ function onclickbtn_mdict_internal(_id) {
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
"""
|
||||
|
||||
res = """
|
||||
{commonstyle}
|
||||
<div class="tab-widget_mdict_internal">
|
||||
|
||||
<div class="centerdiv_mdict_internal"><div>
|
||||
{btns}
|
||||
</div>
|
||||
@ -2579,7 +2570,7 @@ function onclickbtn_mdict_internal(_id) {
|
||||
</div>
|
||||
</div>
|
||||
""".format(
|
||||
commonstyle=commonstyle, btns="".join(btns), contents="".join(contents)
|
||||
btns="".join(btns), contents="".join(contents)
|
||||
)
|
||||
return res
|
||||
|
||||
@ -2601,8 +2592,7 @@ function onclickbtn_mdict_internal(_id) {
|
||||
display: none;
|
||||
padding: 10px;
|
||||
border: 1px solid #ddd;
|
||||
}</style>"""
|
||||
content += """
|
||||
}</style>
|
||||
<script>
|
||||
function mdict_flowstyle_clickcallback(_id)
|
||||
{
|
||||
@ -2657,6 +2647,12 @@ for(let i=0;i<elements.length;i++)
|
||||
}
|
||||
var lastmusicplayer=false;
|
||||
function mdict_play_sound(ext, b64){
|
||||
|
||||
if(window.mdict_audio_call)
|
||||
window.mdict_audio_call(b64)
|
||||
else if(window.LUNAJSObject)
|
||||
window.LUNAJSObject.mdict_audio_call(b64)
|
||||
else{
|
||||
const music = new Audio();
|
||||
music.src="data:"+ext+";base64,"+b64
|
||||
if(lastmusicplayer!=false)
|
||||
@ -2665,6 +2661,7 @@ function mdict_play_sound(ext, b64){
|
||||
}
|
||||
lastmusicplayer=music
|
||||
music.play();
|
||||
}
|
||||
}
|
||||
function safe_mdict_entry_call(word){
|
||||
if(window.mdict_entry_call)
|
||||
|
@ -1,5 +1,3 @@
|
||||
from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtWidgets import QWidget
|
||||
from qtsymbols import *
|
||||
import os, functools, uuid
|
||||
from traceback import print_exc
|
||||
@ -26,6 +24,7 @@ from gui.usefulwidget import (
|
||||
IconButton,
|
||||
statusbutton,
|
||||
getsimplecombobox,
|
||||
threeswitch,
|
||||
FQLineEdit,
|
||||
FocusCombo,
|
||||
)
|
||||
@ -50,30 +49,20 @@ from gui.dialog_savedgame_common import (
|
||||
class dialog_savedgame_integrated(saveposwindow):
|
||||
|
||||
def selectlayout(self, type):
|
||||
self.syssettingbtn.setVisible(type != 2)
|
||||
self.syssettingbtn.setVisible(type != 0)
|
||||
try:
|
||||
globalconfig["gamemanager_integrated_internal_layout"] = type
|
||||
klass = [
|
||||
dialog_savedgame_new,
|
||||
dialog_savedgame_v3,
|
||||
dialog_savedgame_legacy,
|
||||
dialog_savedgame_v3,
|
||||
dialog_savedgame_new,
|
||||
][type]
|
||||
btns = [self.layout1btn, self.layout2btn, self.layout3btn]
|
||||
btns[(type + 0) % 3].setEnabled(False)
|
||||
btns[(type + 1) % 3].setEnabled(False)
|
||||
btns[(type + 2) % 3].setEnabled(False)
|
||||
btns[(type + 0) % 3].setChecked(True)
|
||||
btns[(type + 1) % 3].setChecked(False)
|
||||
btns[(type + 2) % 3].setChecked(False)
|
||||
_old = self.internallayout.takeAt(0).widget()
|
||||
_old.hide()
|
||||
_ = klass(self)
|
||||
self.internallayout.addWidget(_)
|
||||
_.directshow()
|
||||
_old.deleteLater()
|
||||
btns[(type + 0) % 3].setEnabled(False)
|
||||
btns[(type + 1) % 3].setEnabled(True)
|
||||
btns[(type + 2) % 3].setEnabled(True)
|
||||
self.__internal = _
|
||||
except:
|
||||
print_exc()
|
||||
@ -95,25 +84,13 @@ class dialog_savedgame_integrated(saveposwindow):
|
||||
self.internallayout.addWidget(QWidget())
|
||||
self.setCentralWidget(w)
|
||||
|
||||
def createbtn(icon, i):
|
||||
btn = statusbutton(
|
||||
p=self,
|
||||
icons=icon,
|
||||
border=False,
|
||||
colors=["", globalconfig["buttoncolor2"]],
|
||||
)
|
||||
btn.clicked.connect(functools.partial(self.selectlayout, i))
|
||||
btn.setFixedSize(QSize(20, 25))
|
||||
return btn
|
||||
|
||||
self.layout1btn = createbtn("fa.th", 0)
|
||||
self.layout2btn = createbtn("fa.th-list", 1)
|
||||
self.layout3btn = createbtn("fa.list", 2)
|
||||
self.switch = threeswitch(self, icons=["fa.list", "fa.th-list", "fa.th"])
|
||||
self.switch.btnclicked.connect(self.selectlayout)
|
||||
self.syssettingbtn = IconButton(icon="fa.gear", parent=self)
|
||||
self.syssettingbtn.setFixedSize(QSize(25, 25))
|
||||
self.syssettingbtn.clicked.connect(self.syssetting)
|
||||
self.show()
|
||||
self.selectlayout(globalconfig["gamemanager_integrated_internal_layout"])
|
||||
self.switch.selectlayout(globalconfig["gamemanager_integrated_internal_layout"])
|
||||
|
||||
def syssetting(self):
|
||||
dialog_syssetting(
|
||||
@ -122,25 +99,10 @@ class dialog_savedgame_integrated(saveposwindow):
|
||||
)
|
||||
|
||||
def resizeEvent(self, e: QResizeEvent):
|
||||
self.layout1btn.move(e.size().width() - self.layout1btn.width(), 0)
|
||||
self.layout2btn.move(
|
||||
e.size().width() - self.layout2btn.width() - self.layout1btn.width(), 0
|
||||
)
|
||||
self.layout3btn.move(
|
||||
e.size().width()
|
||||
- self.layout3btn.width()
|
||||
- self.layout2btn.width()
|
||||
- self.layout1btn.width(),
|
||||
0,
|
||||
)
|
||||
self.syssettingbtn.move(
|
||||
e.size().width()
|
||||
- self.syssettingbtn.width()
|
||||
- self.layout3btn.width()
|
||||
- self.layout2btn.width()
|
||||
- self.layout1btn.width(),
|
||||
0,
|
||||
)
|
||||
x = e.size().width() - self.switch.width()
|
||||
self.switch.move(x, 0)
|
||||
x -= self.syssettingbtn.width()
|
||||
self.syssettingbtn.move(x, 0)
|
||||
|
||||
|
||||
class TagWidget(QWidget):
|
||||
@ -801,7 +763,7 @@ class dialog_savedgame_new(QWidget):
|
||||
game2 = self.idxsave[idx2]
|
||||
self.idxsave.insert(idx2, self.idxsave.pop(idx1))
|
||||
self.flow.switchidx(idx1, idx2)
|
||||
|
||||
|
||||
try:
|
||||
self.flow.ensureWidgetVisible(self.flow.widget(idx2))
|
||||
except:
|
||||
|
@ -33,7 +33,7 @@ from gui.usefulwidget import (
|
||||
|
||||
def showcountgame(window, num):
|
||||
if num:
|
||||
window.setWindowTitle("游戏管理____-_" + str(num))
|
||||
window.setWindowTitle("游戏管理__-__" + str(num))
|
||||
else:
|
||||
window.setWindowTitle("游戏管理")
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
from PyQt5.QtWidgets import QWidget
|
||||
from qtsymbols import *
|
||||
import functools, threading
|
||||
from myutils.config import savehook_new_list, savehook_new_data, get_launchpath
|
||||
|
@ -1,5 +1,3 @@
|
||||
from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtWidgets import QWidget
|
||||
from qtsymbols import *
|
||||
import functools, uuid
|
||||
from datetime import datetime, timedelta
|
||||
|
@ -306,15 +306,6 @@ def mainuisetting(self):
|
||||
),
|
||||
],
|
||||
[
|
||||
"圆角_半径",
|
||||
D_getspinbox(
|
||||
0,
|
||||
100,
|
||||
globalconfig,
|
||||
"yuanjiao_r",
|
||||
callback=lambda _: gobject.baseobject.translation_ui.set_color_transparency(),
|
||||
),
|
||||
"",
|
||||
"可选取的",
|
||||
D_getsimpleswitch(
|
||||
globalconfig,
|
||||
@ -325,6 +316,15 @@ def mainuisetting(self):
|
||||
parent=self,
|
||||
name="selectable_btn",
|
||||
),
|
||||
"",
|
||||
"圆角_半径",
|
||||
D_getspinbox(
|
||||
0,
|
||||
100,
|
||||
globalconfig,
|
||||
"yuanjiao_r",
|
||||
callback=lambda _: gobject.baseobject.translation_ui.set_color_transparency(),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
@ -34,6 +34,7 @@ from gui.usefulwidget import (
|
||||
getIconButton,
|
||||
saveposwindow,
|
||||
tabadd_lazy,
|
||||
VisLFormLayout,
|
||||
)
|
||||
from gui.dynalang import (
|
||||
LPushButton,
|
||||
@ -45,6 +46,7 @@ from gui.dynalang import (
|
||||
LMainWindow,
|
||||
LAction,
|
||||
)
|
||||
from myutils.audioplayer import bass_code_cast
|
||||
|
||||
|
||||
def getimageformat():
|
||||
@ -62,7 +64,8 @@ class AnkiWindow(QWidget):
|
||||
def callbacktts(self, edit, sig, data):
|
||||
if sig != edit.sig:
|
||||
return
|
||||
fname = gobject.gettempdir(str(uuid.uuid4()) + ".mp3")
|
||||
data, ext = bass_code_cast(data, "mp3")
|
||||
fname = gobject.gettempdir(str(uuid.uuid4()) + "." + ext)
|
||||
with open(fname, "wb") as ff:
|
||||
ff.write(data)
|
||||
self.settextsignal.emit(edit, os.path.abspath(fname))
|
||||
@ -330,7 +333,7 @@ class AnkiWindow(QWidget):
|
||||
ff.write(model_css)
|
||||
|
||||
def creatsetdtab(self, baselay):
|
||||
layout = LFormLayout()
|
||||
layout = VisLFormLayout()
|
||||
wid = QWidget()
|
||||
wid.setLayout(layout)
|
||||
baselay.addWidget(wid)
|
||||
@ -384,6 +387,39 @@ class AnkiWindow(QWidget):
|
||||
"成功添加后关闭窗口",
|
||||
getsimpleswitch(globalconfig["ankiconnect"], "addsuccautoclose"),
|
||||
)
|
||||
cnt = layout.rowCount() + 1
|
||||
|
||||
def __(xx):
|
||||
i = ["mp3", "opus"].index(xx)
|
||||
layout.setRowVisible(cnt + 0, False)
|
||||
layout.setRowVisible(cnt + 1, False)
|
||||
layout.setRowVisible(cnt + i, True)
|
||||
|
||||
layout.addRow(
|
||||
"音频编码",
|
||||
getsimplecombobox(
|
||||
["mp3", "opus(ogg)"],
|
||||
globalconfig,
|
||||
"audioformat",
|
||||
internal=["mp3", "opus"],
|
||||
callback=__,
|
||||
),
|
||||
)
|
||||
|
||||
layout.addRow(
|
||||
"MP3 kbps",
|
||||
getsimplecombobox(
|
||||
[str(8 * i) for i in range(1, 320 // 8 + 1)],
|
||||
globalconfig,
|
||||
"mp3kbps",
|
||||
internal=[8 * i for i in range(1, 320 // 8 + 1)],
|
||||
),
|
||||
)
|
||||
layout.addRow(
|
||||
"OPUS bitrate",
|
||||
getspinbox(6, 256, globalconfig, "opusbitrate"),
|
||||
)
|
||||
__(globalconfig["audioformat"])
|
||||
|
||||
def vistranslate_rank(self):
|
||||
listediter(
|
||||
@ -1208,8 +1244,13 @@ class searchwordW(closeashidewindow):
|
||||
self.textOutput.bind(
|
||||
"mdict_entry_call", lambda word: self.search_word.emit(word, False)
|
||||
)
|
||||
self.textOutput.bind(
|
||||
"mdict_audio_call",
|
||||
lambda b64: gobject.baseobject.audioplayer.play(
|
||||
base64.b64decode(b64.encode()), force=True
|
||||
),
|
||||
)
|
||||
self.cache_results = {}
|
||||
self.hiding = True
|
||||
|
||||
self.spliter = QSplitter()
|
||||
|
||||
|
@ -39,7 +39,6 @@ class transhist(closeashidewindow):
|
||||
self.textOutput = textOutput
|
||||
self.setCentralWidget(self.textOutput)
|
||||
|
||||
self.hiding = True
|
||||
|
||||
def showmenu(self, tb, p):
|
||||
menu = QMenu(self)
|
||||
|
@ -48,7 +48,7 @@ class ButtonX(QWidget):
|
||||
super().__init__(*argc)
|
||||
self.reflayout = None
|
||||
self.setMouseTracking(True)
|
||||
self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding)
|
||||
self.setSizePolicy(QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Expanding)
|
||||
|
||||
def showinlayout(self, layout):
|
||||
|
||||
|
@ -1617,6 +1617,43 @@ class auto_select_webview(QWidget):
|
||||
return browser
|
||||
|
||||
|
||||
class threeswitch(QWidget):
|
||||
btnclicked = pyqtSignal(int)
|
||||
|
||||
def selectlayout(self, i):
|
||||
self.btns[(i + 0) % 3].setEnabled(False)
|
||||
self.btns[(i + 1) % 3].setEnabled(False)
|
||||
self.btns[(i + 2) % 3].setEnabled(False)
|
||||
self.btns[(i + 0) % 3].setChecked(True)
|
||||
self.btns[(i + 1) % 3].setChecked(False)
|
||||
self.btns[(i + 2) % 3].setChecked(False)
|
||||
self.btnclicked.emit(i)
|
||||
self.btns[(i + 1) % 3].setEnabled(True)
|
||||
self.btns[(i + 2) % 3].setEnabled(True)
|
||||
|
||||
def __init__(self, p, icons):
|
||||
super().__init__(p)
|
||||
self.btns = []
|
||||
for i, icon in enumerate(icons):
|
||||
btn = statusbutton(
|
||||
p=self,
|
||||
icons=icon,
|
||||
border=False,
|
||||
colors=["", globalconfig["buttoncolor2"]],
|
||||
)
|
||||
btn.clicked.connect(functools.partial(self.selectlayout, i))
|
||||
btn.setFixedSize(QSize(20, 25))
|
||||
self.btns.append(btn)
|
||||
self.setFixedSize(QSize(60, 75))
|
||||
|
||||
def resizeEvent(self, a0):
|
||||
x, y = 0, 0
|
||||
for btn in self.btns:
|
||||
btn.move(x, y)
|
||||
x += btn.width()
|
||||
return super().resizeEvent(a0)
|
||||
|
||||
|
||||
class threebuttons(QWidget):
|
||||
btn1clicked = pyqtSignal()
|
||||
btn2clicked = pyqtSignal()
|
||||
|
@ -1,32 +1,31 @@
|
||||
import time
|
||||
from traceback import print_exc
|
||||
from myutils.config import globalconfig
|
||||
import threading
|
||||
import gobject, winsharedutils
|
||||
from ctypes.wintypes import BOOL, DWORD, HWND, WORD
|
||||
import threading, functools
|
||||
import gobject
|
||||
from ctypes.wintypes import BOOL, DWORD, HWND
|
||||
from ctypes import (
|
||||
WinDLL,
|
||||
WINFUNCTYPE,
|
||||
c_int,
|
||||
c_ulong,
|
||||
c_float,
|
||||
c_int64,
|
||||
c_void_p,
|
||||
c_char_p,
|
||||
Structure,
|
||||
POINTER,
|
||||
pointer,
|
||||
c_void_p,
|
||||
create_string_buffer,
|
||||
sizeof,
|
||||
cast,
|
||||
c_wchar_p,
|
||||
c_char,
|
||||
)
|
||||
|
||||
|
||||
HMUSIC = c_ulong # MOD music handle
|
||||
HSAMPLE = c_ulong # sample handle
|
||||
HPLUGIN = c_ulong # Plugin handle
|
||||
HENCODE = DWORD
|
||||
HMUSIC = DWORD # MOD music handle
|
||||
HSAMPLE = DWORD # sample handle
|
||||
HPLUGIN = DWORD # Plugin handle
|
||||
QWORD = c_int64
|
||||
HSTREAM = c_ulong # sample stream handle
|
||||
HSTREAM = DWORD # sample stream handle
|
||||
BASS_SAMPLE_FLOAT = 0x100
|
||||
BASS_STREAM_DECODE = 0x200000
|
||||
BASS_UNICODE = 0x80000000 # -2147483648
|
||||
@ -34,63 +33,35 @@ BASS_ATTRIB_VOL = 2
|
||||
BASS_ATTRIB_FREQ = 1
|
||||
BASS_SAMPLE_8BITS = 1
|
||||
BASS_POS_BYTE = 0 # byte position
|
||||
bass_module = WinDLL(gobject.GetDllpath("bass.dll"))
|
||||
bass = WinDLL(gobject.GetDllpath("bass.dll"))
|
||||
|
||||
BASS_ChannelSetAttribute = WINFUNCTYPE(BOOL, DWORD, DWORD, c_float)(
|
||||
("BASS_ChannelSetAttribute", bass_module)
|
||||
("BASS_ChannelSetAttribute", bass)
|
||||
)
|
||||
|
||||
BASS_ChannelGetLength = WINFUNCTYPE(QWORD, DWORD, DWORD)(
|
||||
("BASS_ChannelGetLength", bass_module)
|
||||
("BASS_ChannelGetLength", bass)
|
||||
)
|
||||
BASS_ChannelGetPosition = WINFUNCTYPE(QWORD, DWORD, DWORD)(
|
||||
("BASS_ChannelGetPosition", bass_module)
|
||||
)
|
||||
BASS_ChannelPlay = WINFUNCTYPE(BOOL, DWORD, BOOL)(("BASS_ChannelPlay", bass_module))
|
||||
BASS_StreamFree = WINFUNCTYPE(BOOL, HSTREAM)(("BASS_StreamFree", bass_module))
|
||||
BASS_Init = WINFUNCTYPE(BOOL, c_int, DWORD, DWORD, HWND, c_void_p)(
|
||||
("BASS_Init", bass_module)
|
||||
("BASS_ChannelGetPosition", bass)
|
||||
)
|
||||
BASS_ChannelPlay = WINFUNCTYPE(BOOL, DWORD, BOOL)(("BASS_ChannelPlay", bass))
|
||||
BASS_StreamFree = WINFUNCTYPE(BOOL, HSTREAM)(("BASS_StreamFree", bass))
|
||||
BASS_Init = WINFUNCTYPE(BOOL, c_int, DWORD, DWORD, HWND, c_void_p)(("BASS_Init", bass))
|
||||
BASS_StreamCreateFile = WINFUNCTYPE(HSTREAM, BOOL, c_void_p, QWORD, QWORD, DWORD)(
|
||||
("BASS_StreamCreateFile", bass_module)
|
||||
)
|
||||
BASS_Free = WINFUNCTYPE(BOOL)(("BASS_Free", bass_module))
|
||||
BASS_PluginLoad = WINFUNCTYPE(c_ulong, c_char_p, c_ulong)(
|
||||
("BASS_PluginLoad", bass_module)
|
||||
("BASS_StreamCreateFile", bass)
|
||||
)
|
||||
BASS_Free = WINFUNCTYPE(BOOL)(("BASS_Free", bass))
|
||||
BASS_PluginLoad = WINFUNCTYPE(HPLUGIN, c_char_p, DWORD)(("BASS_PluginLoad", bass))
|
||||
|
||||
bassenc = WinDLL(gobject.GetDllpath("bassenc.dll"))
|
||||
|
||||
class WAVEFORMATEX(Structure):
|
||||
_fields_ = [
|
||||
("wFormatTag", WORD),
|
||||
("nChannels", WORD),
|
||||
("nSamplesPerSec", DWORD),
|
||||
("nAvgBytesPerSec", DWORD),
|
||||
("nBlockAlign", WORD),
|
||||
("wBitsPerSample", WORD),
|
||||
("cbSize", WORD),
|
||||
]
|
||||
BASS_Encode_IsActive = WINFUNCTYPE(DWORD, DWORD)(("BASS_Encode_IsActive", bassenc))
|
||||
BASS_Encode_Stop = WINFUNCTYPE(BOOL, DWORD)(("BASS_Encode_Stop", bassenc))
|
||||
|
||||
|
||||
class BASS_CHANNELINFO(Structure):
|
||||
_fields_ = [
|
||||
("freq", DWORD),
|
||||
("chans", DWORD),
|
||||
("flags", DWORD),
|
||||
("ctype", DWORD),
|
||||
("origres", DWORD),
|
||||
("plugin", HPLUGIN),
|
||||
("sample", HSAMPLE),
|
||||
("filename", c_char_p),
|
||||
]
|
||||
|
||||
|
||||
BASS_ChannelGetInfo = WINFUNCTYPE(BOOL, DWORD, POINTER(BASS_CHANNELINFO))(
|
||||
("BASS_ChannelGetInfo", bass_module)
|
||||
)
|
||||
BASS_ChannelIsActive = WINFUNCTYPE(DWORD, DWORD)(("BASS_ChannelIsActive", bass_module))
|
||||
BASS_ChannelIsActive = WINFUNCTYPE(DWORD, DWORD)(("BASS_ChannelIsActive", bass))
|
||||
BASS_ChannelGetData = WINFUNCTYPE(DWORD, DWORD, c_void_p, DWORD)(
|
||||
("BASS_ChannelGetData", bass_module)
|
||||
("BASS_ChannelGetData", bass)
|
||||
)
|
||||
|
||||
|
||||
@ -141,52 +112,83 @@ class playonce:
|
||||
|
||||
BASS_Init(-1, 44100, 0, 0, 0)
|
||||
# https://www.un4seen.com/
|
||||
plugins = {".spx": "bass_spx.dll", ".aac": "bass_aac.dll", ".opus": "bassopus.dll"}
|
||||
|
||||
pluginshandle = {}
|
||||
plugins = ["bass_spx.dll", "bass_aac.dll", "bassopus.dll"]
|
||||
for _ in plugins:
|
||||
BASS_PluginLoad(gobject.GetDllpath(_).encode("utf8"), 0)
|
||||
|
||||
|
||||
def load_ext(ext=None):
|
||||
if ext and plugins.get(ext) and not pluginshandle.get(ext):
|
||||
pluginshandle[ext] = BASS_PluginLoad(
|
||||
gobject.GetDllpath(plugins.get(ext)).encode("utf8"), 0
|
||||
)
|
||||
def ENCODEPROCEXF(ret: list, _, _1, buffer, size, _2, _3):
|
||||
ret.append(cast(buffer, POINTER(c_char))[:size])
|
||||
|
||||
|
||||
def bass_decode(bs, ext=None):
|
||||
load_ext(ext)
|
||||
def ENCODEPROCF(ret: list, _, _1, buffer, size, _2):
|
||||
ret.append(cast(buffer, POINTER(c_char))[:size])
|
||||
|
||||
|
||||
ENCODEPROC = WINFUNCTYPE(None, HENCODE, DWORD, c_void_p, DWORD, c_void_p)
|
||||
ENCODEPROCEX = WINFUNCTYPE(None, HENCODE, DWORD, c_void_p, DWORD, QWORD, c_void_p)
|
||||
encoders = {
|
||||
"mp3": [
|
||||
"bassenc_mp3.dll",
|
||||
"BASS_Encode_MP3_Start",
|
||||
"mp3",
|
||||
ENCODEPROCEXF,
|
||||
ENCODEPROCEX,
|
||||
],
|
||||
"opus": [
|
||||
"bassenc_opus.dll",
|
||||
"BASS_Encode_OPUS_Start",
|
||||
"ogg",
|
||||
ENCODEPROCF,
|
||||
ENCODEPROC,
|
||||
],
|
||||
}
|
||||
BASS_Encode_Start_T = WINFUNCTYPE(HENCODE, DWORD, c_wchar_p, DWORD, c_void_p, c_void_p)
|
||||
|
||||
|
||||
def load_enc_func(ext):
|
||||
_ = encoders.get(ext)
|
||||
if not _:
|
||||
return None
|
||||
dll, fun = _[0], _[1]
|
||||
if isinstance(dll, str):
|
||||
dll = WinDLL(gobject.GetDllpath(dll))
|
||||
_[0] = dll
|
||||
if isinstance(fun, str):
|
||||
fun = BASS_Encode_Start_T((fun, dll))
|
||||
_[1] = fun
|
||||
return _
|
||||
|
||||
|
||||
def bass_code_cast(bs, fr="mp3"):
|
||||
# fr没啥用,仅用来给出编码失败时的用来占位的后缀,以少写代码
|
||||
to = globalconfig["audioformat"]
|
||||
_ = load_enc_func(to)
|
||||
if not _:
|
||||
return bs, fr
|
||||
_, start, ext, func, funct = _
|
||||
stream = BASS_StreamCreateFile(True, bs, 0, len(bs), BASS_STREAM_DECODE)
|
||||
if not stream:
|
||||
return
|
||||
info = BASS_CHANNELINFO()
|
||||
if not BASS_ChannelGetInfo(stream, pointer(info)):
|
||||
return
|
||||
wf = WAVEFORMATEX()
|
||||
wf.wFormatTag = 1
|
||||
wf.nChannels = info.chans
|
||||
wf.wBitsPerSample = 8 if info.flags & BASS_SAMPLE_8BITS else 16
|
||||
wf.nBlockAlign = wf.nChannels * wf.wBitsPerSample // 8
|
||||
wf.nSamplesPerSec = info.freq
|
||||
wf.nAvgBytesPerSec = wf.nSamplesPerSec * wf.nBlockAlign
|
||||
res = []
|
||||
size = 0
|
||||
buff = create_string_buffer(0x10000)
|
||||
return bs, fr
|
||||
ret = []
|
||||
func = funct(functools.partial(func, ret))
|
||||
if to == "mp3":
|
||||
opts = "-b{}".format(globalconfig["mp3kbps"])
|
||||
elif to == "opus":
|
||||
opts = "--bitrate {}".format(globalconfig["opusbitrate"])
|
||||
encoder = start(stream, opts, BASS_UNICODE, func, None)
|
||||
if not encoder:
|
||||
BASS_StreamFree(stream)
|
||||
return bs, fr
|
||||
buff = create_string_buffer(0x10000) # wav,仅用于激活getdata
|
||||
while BASS_ChannelIsActive(stream):
|
||||
get = BASS_ChannelGetData(stream, buff, 0x10000)
|
||||
res.append(buff[:get])
|
||||
size += get
|
||||
header = []
|
||||
header.append(b"RIFF")
|
||||
header.append(bytes(c_int(size + 44)))
|
||||
header.append(b"WAVE")
|
||||
header.append(b"fmt ")
|
||||
header.append(bytes(c_int(sizeof(WAVEFORMATEX))))
|
||||
header.append(bytes(wf))
|
||||
header.append(b"data")
|
||||
header.append(bytes(c_int(size)))
|
||||
header.extend(res)
|
||||
data = b"".join(header)
|
||||
return winsharedutils.encodemp3(data, 64)
|
||||
if not BASS_Encode_IsActive(stream):
|
||||
break
|
||||
_ = BASS_ChannelGetData(stream, buff, 0x10000)
|
||||
BASS_Encode_Stop(stream)
|
||||
BASS_StreamFree(stream)
|
||||
print(len(bs), len(b"".join(ret)))
|
||||
return b"".join(ret), ext
|
||||
|
||||
|
||||
class series_audioplayer:
|
||||
@ -209,11 +211,10 @@ class series_audioplayer:
|
||||
except:
|
||||
pass
|
||||
|
||||
def play(self, binary, volume=100, force=False, timestamp=None, ext=None):
|
||||
def play(self, binary, volume=100, force=False, timestamp=None):
|
||||
if timestamp and (timestamp != self.timestamp):
|
||||
return
|
||||
self.timestamp = timestamp
|
||||
load_ext(ext)
|
||||
try:
|
||||
self.tasks = (binary, volume, force)
|
||||
self.lock.release()
|
||||
|
@ -125,7 +125,7 @@ def getpidexe(pid):
|
||||
|
||||
|
||||
def getcurrexe():
|
||||
return os.environ.get("LUNA_EXE_NAME", "")
|
||||
return getpidexe(os.getpid())
|
||||
|
||||
|
||||
def test_injectable_1(pid):
|
||||
|
@ -21,6 +21,7 @@ import threading, winreg
|
||||
import re, heapq, winsharedutils
|
||||
from myutils.wrapper import tryprint, threader
|
||||
from html.parser import HTMLParser
|
||||
from myutils.audioplayer import bass_code_cast
|
||||
|
||||
|
||||
def qimage2binary(qimage: QImage, fmt="BMP"):
|
||||
@ -839,17 +840,11 @@ class loopbackrecorder:
|
||||
wav = self.capture.stop()
|
||||
if not wav:
|
||||
return callback("")
|
||||
mp3 = winsharedutils.encodemp3(wav)
|
||||
if not mp3:
|
||||
file = gobject.gettempdir(str(time.time()) + ".wav")
|
||||
with open(file, "wb") as ff:
|
||||
ff.write(wav)
|
||||
callback(file)
|
||||
else:
|
||||
file = gobject.gettempdir(str(time.time()) + ".mp3")
|
||||
with open(file, "wb") as ff:
|
||||
ff.write(mp3)
|
||||
callback(file)
|
||||
new, ext = bass_code_cast(wav, "wav")
|
||||
file = gobject.gettempdir(str(time.time()) + "." + ext)
|
||||
with open(file, "wb") as ff:
|
||||
ff.write(new)
|
||||
callback(file)
|
||||
|
||||
|
||||
def copytree(src, dst, copy_function=shutil.copy2):
|
||||
|
@ -1,6 +1,6 @@
|
||||
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,QToolButton,QAbstractSpinBox
|
||||
from PyQt5.QtWidgets import QFrame,QListView,QCheckBox,QAbstractItemView,QTextEdit,QTableView,QHeaderView,QColorDialog,QSpinBox,QDoubleSpinBox,QComboBox,QDialogButtonBox,QMainWindow,QMessageBox,QDialog,QGridLayout,QTextBrowser,QGraphicsDropShadowEffect,QWidget,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,QToolButton,QAbstractSpinBox
|
||||
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,QMargins
|
||||
isqt5 = True
|
||||
@ -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,QGraphicsOpacityEffect,QStackedWidget,QTreeView,QToolButton,QAbstractSpinBox
|
||||
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,QMargins
|
||||
from PyQt6.QtWidgets import QFrame,QListView,QCheckBox,QAbstractItemView,QTextEdit,QTableView,QHeaderView,QColorDialog,QSpinBox,QDoubleSpinBox,QComboBox,QDialogButtonBox,QMainWindow,QMessageBox,QDialog,QGridLayout,QTextBrowser,QGraphicsDropShadowEffect,QWidget,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,QToolButton,QAbstractSpinBox,QStyledItemDelegate,QStyleOptionViewItem,QFontDialog
|
||||
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,QDragEnterEvent,QDropEvent,QTransform
|
||||
from PyQt6.QtCore import QObject,pyqtSignal,Qt,QSize,QByteArray,QBuffer,QPointF,QPoint,QRect,QEvent,QModelIndex,QTimer,QRectF,QVariantAnimation,QUrl,QPropertyAnimation,QLocale,QMargins,QSignalBlocker
|
||||
isqt5 = False
|
||||
|
||||
class LineHeightTypes:
|
||||
|
@ -1,4 +1,3 @@
|
||||
from PyQt5.QtGui import QMouseEvent
|
||||
from qtsymbols import *
|
||||
from myutils.config import globalconfig, static_data
|
||||
from rendertext.somefunctions import dataget
|
||||
@ -459,7 +458,7 @@ class TextBrowser(QWidget, dataget):
|
||||
|
||||
layout = QTextLayout()
|
||||
layout.setFont(font)
|
||||
layout.setTextOption(QTextOption(Qt.AlignLeft))
|
||||
layout.setTextOption(QTextOption(Qt.AlignmentFlag.AlignLeft))
|
||||
layout.setText(linetext)
|
||||
layout.beginLayout()
|
||||
newtag = []
|
||||
|
@ -352,21 +352,6 @@ clipboard_callback_stop = utilsdll.clipboard_callback_stop
|
||||
clipboard_callback_stop.argtypes = (HWND,)
|
||||
clipboard_callback_type = CFUNCTYPE(None, c_wchar_p, c_bool)
|
||||
|
||||
_encodemp3 = utilsdll.encodemp3
|
||||
_encodemp3.argtypes = c_void_p, c_size_t, c_void_p, c_int
|
||||
|
||||
|
||||
def encodemp3(wav, bitr=320):
|
||||
ret = []
|
||||
|
||||
def cb(ptr, size):
|
||||
ret.append(cast(ptr, POINTER(c_char))[:size])
|
||||
|
||||
_encodemp3(wav, len(wav), CFUNCTYPE(None, c_void_p, c_size_t)(cb), bitr)
|
||||
if len(ret):
|
||||
return ret[0]
|
||||
return None
|
||||
|
||||
|
||||
GetMonitorDpiScaling = utilsdll.GetMonitorDpiScaling
|
||||
GetMonitorDpiScaling.argtypes = (HWND,)
|
||||
|
@ -484,6 +484,9 @@
|
||||
"tags": []
|
||||
},
|
||||
"imageformat": -1,
|
||||
"mp3kbps": 64,
|
||||
"opusbitrate": 10,
|
||||
"audioformat": "mp3",
|
||||
"ankiwindow": [
|
||||
100,
|
||||
100,
|
||||
@ -1250,29 +1253,29 @@
|
||||
},
|
||||
"cishu": {
|
||||
"mojidict": {
|
||||
"use": false,
|
||||
"use": true,
|
||||
"name": "Moji辞书",
|
||||
"useproxy": false
|
||||
},
|
||||
"youdao": {
|
||||
"use": false,
|
||||
"use": true,
|
||||
"name": "有道词典",
|
||||
"useproxy": false
|
||||
},
|
||||
"jisho": {
|
||||
"use": false,
|
||||
"use": true,
|
||||
"name": "jisho"
|
||||
},
|
||||
"japandict": {
|
||||
"use": false,
|
||||
"use": true,
|
||||
"name": "JapanDict"
|
||||
},
|
||||
"weblio": {
|
||||
"use": false,
|
||||
"use": true,
|
||||
"name": "weblio"
|
||||
},
|
||||
"goo": {
|
||||
"use": false,
|
||||
"use": true,
|
||||
"name": "goo"
|
||||
},
|
||||
"gemini": {
|
||||
|
@ -765,5 +765,6 @@
|
||||
"全部": "كامل",
|
||||
"年度总结": "ملخص سنوي",
|
||||
"取词翻译": "اختيار الترجمة",
|
||||
"取词查词": "كلمة البحث"
|
||||
"取词查词": "كلمة البحث",
|
||||
"音频编码": "ترميز الصوت"
|
||||
}
|
@ -765,5 +765,6 @@
|
||||
"全部": "全部",
|
||||
"年度总结": "年度總結",
|
||||
"取词翻译": "取詞翻譯",
|
||||
"取词查词": "取詞查詞"
|
||||
"取词查词": "取詞查詞",
|
||||
"音频编码": "音訊編碼"
|
||||
}
|
@ -765,5 +765,6 @@
|
||||
"全部": "celý",
|
||||
"年度总结": "Roční shrnutí",
|
||||
"取词翻译": "Překlad výběru slova",
|
||||
"取词查词": "Načíst a vyhledávat slova"
|
||||
"取词查词": "Načíst a vyhledávat slova",
|
||||
"音频编码": "Kódování zvuku"
|
||||
}
|
@ -765,5 +765,6 @@
|
||||
"全部": "ganz",
|
||||
"年度总结": "Jahreszusammenfassung",
|
||||
"取词翻译": "Übersetzung der Wortauswahl",
|
||||
"取词查词": "Wörter abrufen und suchen"
|
||||
"取词查词": "Wörter abrufen und suchen",
|
||||
"音频编码": "Audio-Codierung"
|
||||
}
|
@ -765,5 +765,6 @@
|
||||
"全部": "all",
|
||||
"年度总结": "Annual Summary",
|
||||
"取词翻译": "Word selection translation",
|
||||
"取词查词": "Retrieve and search for words"
|
||||
"取词查词": "Retrieve and search for words",
|
||||
"音频编码": "audio coding"
|
||||
}
|
@ -765,5 +765,6 @@
|
||||
"全部": "Todo",
|
||||
"年度总结": "Resumen Anual",
|
||||
"取词翻译": "Traducción de palabras",
|
||||
"取词查词": "Buscar palabras"
|
||||
"取词查词": "Buscar palabras",
|
||||
"音频编码": "Codificación de audio"
|
||||
}
|
@ -765,5 +765,6 @@
|
||||
"全部": "Tous",
|
||||
"年度总结": "Résumé annuel",
|
||||
"取词翻译": "Traduction des mots",
|
||||
"取词查词": "Recherche de mots"
|
||||
"取词查词": "Recherche de mots",
|
||||
"音频编码": "Codage audio"
|
||||
}
|
@ -765,5 +765,6 @@
|
||||
"全部": "intero",
|
||||
"年度总结": "Sintesi annuale",
|
||||
"取词翻译": "Traduzione della selezione delle parole",
|
||||
"取词查词": "Recupera e cerca parole"
|
||||
"取词查词": "Recupera e cerca parole",
|
||||
"音频编码": "Codificazione audio"
|
||||
}
|
@ -765,5 +765,6 @@
|
||||
"全部": "すべて",
|
||||
"年度总结": "年度まとめ",
|
||||
"取词翻译": "単語の翻訳",
|
||||
"取词查词": "単語を取って単語を調べる"
|
||||
"取词查词": "単語を取って単語を調べる",
|
||||
"音频编码": "オーディオコーディング"
|
||||
}
|
@ -765,5 +765,6 @@
|
||||
"全部": "모두",
|
||||
"年度总结": "연간 요약",
|
||||
"取词翻译": "취사 번역",
|
||||
"取词查词": "취사 조사"
|
||||
"取词查词": "취사 조사",
|
||||
"音频编码": "오디오 인코딩"
|
||||
}
|
@ -765,5 +765,6 @@
|
||||
"全部": "geheel",
|
||||
"年度总结": "Jaarlijkse samenvatting",
|
||||
"取词翻译": "Woordselectie vertaling",
|
||||
"取词查词": "Woorden ophalen en zoeken"
|
||||
"取词查词": "Woorden ophalen en zoeken",
|
||||
"音频编码": "Audiocodering"
|
||||
}
|
@ -765,5 +765,6 @@
|
||||
"全部": "całość",
|
||||
"年度总结": "Roczne podsumowanie",
|
||||
"取词翻译": "Tłumaczenie wyboru słowa",
|
||||
"取词查词": "Pobieranie i wyszukiwanie słów"
|
||||
"取词查词": "Pobieranie i wyszukiwanie słów",
|
||||
"音频编码": "Kodowanie dźwięku"
|
||||
}
|
@ -765,5 +765,6 @@
|
||||
"全部": "inteiro",
|
||||
"年度总结": "Resumo anual",
|
||||
"取词翻译": "Tradução da selecção de palavras",
|
||||
"取词查词": "Obter e procurar palavras"
|
||||
"取词查词": "Obter e procurar palavras",
|
||||
"音频编码": "Codificação de áudio"
|
||||
}
|
@ -765,5 +765,6 @@
|
||||
"全部": "Все.",
|
||||
"年度总结": "Ежегодное резюме",
|
||||
"取词翻译": "Перевод",
|
||||
"取词查词": "Поиск слов"
|
||||
"取词查词": "Поиск слов",
|
||||
"音频编码": "Звуковое кодирование"
|
||||
}
|
@ -765,5 +765,6 @@
|
||||
"全部": "hela",
|
||||
"年度总结": "Årlig sammanfattning",
|
||||
"取词翻译": "Ordmarkeringsöversättning",
|
||||
"取词查词": "Hämta och sök efter ord"
|
||||
"取词查词": "Hämta och sök efter ord",
|
||||
"音频编码": "Ljudkodning"
|
||||
}
|
@ -765,5 +765,6 @@
|
||||
"全部": "ทั้งหมด",
|
||||
"年度总结": "สรุปรายปี",
|
||||
"取词翻译": "คำแปล",
|
||||
"取词查词": "ค้นหาคำ"
|
||||
"取词查词": "ค้นหาคำ",
|
||||
"音频编码": "การเข้ารหัสเสียง"
|
||||
}
|
@ -765,5 +765,6 @@
|
||||
"全部": "Tüm",
|
||||
"年度总结": "Yıllık Toplantı",
|
||||
"取词翻译": "Kelime seçimi çevirimi",
|
||||
"取词查词": "Kelimeleri alın ve arayın"
|
||||
"取词查词": "Kelimeleri alın ve arayın",
|
||||
"音频编码": "Ses Kodlama"
|
||||
}
|
@ -765,5 +765,6 @@
|
||||
"全部": "цілий",
|
||||
"年度总结": "Річне резюме",
|
||||
"取词翻译": "Переклад вибору слів",
|
||||
"取词查词": "Отримати і шукати слова"
|
||||
"取词查词": "Отримати і шукати слова",
|
||||
"音频编码": "Аудіокодування"
|
||||
}
|
@ -765,5 +765,6 @@
|
||||
"全部": "Tất cả",
|
||||
"年度总结": "Tóm tắt hàng năm",
|
||||
"取词翻译": "Dịch thuật lấy từ",
|
||||
"取词查词": "Tìm kiếm từ"
|
||||
"取词查词": "Tìm kiếm từ",
|
||||
"音频编码": "Mã hóa âm thanh"
|
||||
}
|
@ -765,5 +765,6 @@
|
||||
"全部": "",
|
||||
"年度总结": "",
|
||||
"取词翻译": "",
|
||||
"取词查词": ""
|
||||
"取词查词": "",
|
||||
"音频编码": ""
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
PyQt5==5.15.10
|
||||
PyQt5==5.15.11
|
||||
PyQt5-Qt5==5.15.2
|
||||
webviewpy==1.4.0
|
||||
tinycss2
|
Loading…
x
Reference in New Issue
Block a user