mirror of
https://github.com/HIllya51/LunaTranslator.git
synced 2025-01-12 15:19:30 +08:00
.
This commit is contained in:
parent
f982f96af6
commit
9f038b3c1e
1
.gitignore
vendored
1
.gitignore
vendored
@ -49,3 +49,4 @@ cpp/LunaHook/.vscode/settings.json
|
||||
cpp/LunaHook/scripts/YY-Thunks-1.0.7-Binary.zip
|
||||
cpp/libs/YY-Thunks
|
||||
py/LunaTranslator/.vscode/settings.json
|
||||
py/files/yearsummary/yearsummary.value.js
|
||||
|
@ -1517,6 +1517,8 @@ namespace ppsspp
|
||||
{0x88F09F4, {CODEC_UTF16, 0, 0, 0, ULJM05976, "ULJM05976"}},
|
||||
// オメルタ~沈黙の掟~ THE LEGACY
|
||||
{0x88861C8, {0, 3, 0, 0, 0, "ULJM06393"}},
|
||||
{0x8885fd8, {0, 0, 0, 0, 0, "ULJM06393"}},
|
||||
{0x88ac3a8, {0, 1, 0, 0, 0, "ULJM06393"}},
|
||||
// L.G.S~新説 封神演義~
|
||||
{0x888A358, {0, 0, 0, 0, ULJM05943F, "ULJM06131"}}, // NAME+TEXT
|
||||
{0x88DB214, {0, 0, 0, 0, ULJM05943F, "ULJM06131"}}, // TEXT
|
||||
@ -1534,6 +1536,7 @@ namespace ppsspp
|
||||
{0x886E094, {0, 0, 0, 0, ULJM06129, "ULJM06129"}}, // name+text
|
||||
// 十鬼の絆 花結綴り
|
||||
{0x886E354, {0, 0, 0, 0, ULJM06289, "ULJM06301"}}, // name+text
|
||||
{0x88f878c, {0, 0, 0, 0, ULJM06289, "ULJM06301"}},
|
||||
// ティンクル☆くるせいだーす STARLIT BRAVE!!
|
||||
{0x88A94BC, {0, 4, 0, 0, 0, "ULJS00315"}}, // text
|
||||
// ティンクル☆くるせいだーす GoGo!
|
||||
|
@ -236,8 +236,7 @@ int PyStand::DetectScript()
|
||||
//---------------------------------------------------------------------
|
||||
const auto init_script =
|
||||
LR"(
|
||||
import sys
|
||||
import os
|
||||
import os,functools, locale, sys
|
||||
PYSTAND = os.environ['PYSTAND']
|
||||
PYSTAND_HOME = os.environ['PYSTAND_HOME']
|
||||
PYSTAND_RUNTIME = os.environ['PYSTAND_RUNTIME']
|
||||
@ -253,26 +252,40 @@ def MessageBox(msg, info = 'Message'):
|
||||
os.MessageBox = MessageBox
|
||||
#sys.stdout=sys.stderr
|
||||
sys.path.insert(0, './LunaTranslator')
|
||||
)"
|
||||
#ifndef PYSTAND_CONSOLE
|
||||
LR"(
|
||||
|
||||
|
||||
def fuckwrite(origin, message):
|
||||
try:
|
||||
if isinstance(message, str):
|
||||
code=locale.getpreferredencoding()
|
||||
origin(message.encode(encoding=code, errors='replace').decode(encoding=code, errors='replace'))
|
||||
else:
|
||||
origin(message)
|
||||
except:
|
||||
return
|
||||
import traceback, io
|
||||
sio = io.StringIO()
|
||||
traceback.print_exc(file = sio)
|
||||
os.MessageBox(sio.getvalue(), message)
|
||||
|
||||
try:
|
||||
fd = os.open('CONOUT$', os.O_RDWR | os.O_BINARY)
|
||||
fp = os.fdopen(fd, 'w')
|
||||
sys.stdout = fp
|
||||
sys.stderr = fp
|
||||
attached = True
|
||||
sys.stdout.write = functools.partial(fuckwrite,sys.stdout.write)
|
||||
sys.stderr.write = functools.partial(fuckwrite,sys.stderr.write)
|
||||
|
||||
except Exception as e:
|
||||
try:
|
||||
fp = open(os.devnull, 'w', errors='ignore') # sometimes FileNotFound Error: [Errno 2]No such file or directory: 'nul'
|
||||
fp = open(os.devnull, 'w', errors='replace') # sometimes FileNotFound Error: [Errno 2]No such file or directory: 'nul'
|
||||
sys.stdout = fp
|
||||
sys.stderr = fp
|
||||
attached = False
|
||||
except:
|
||||
pass
|
||||
)"
|
||||
#endif
|
||||
LR"(
|
||||
|
||||
sys.argv = [PYSTAND_SCRIPT] + sys.argv[1:]
|
||||
text = open(PYSTAND_SCRIPT, 'rb').read()
|
||||
environ = {'__file__': PYSTAND_SCRIPT, '__name__': '__main__'}
|
||||
@ -324,41 +337,13 @@ int main()
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
#ifndef PYSTAND_CONSOLE
|
||||
// winmain下的stderr没有任何卵用,对于崩溃时的stderr根本显示不出来,所以还是用控制台来保存log吧。
|
||||
// print cmd无法显示的字符时,如果使用cmd打开,不论debug还是普通,都会error31崩溃。如果双击打开debug,却不会崩溃
|
||||
// 但因为无法区分是使用cmd打开debug还是双击打开debug,所以干脆都这样吧。
|
||||
if (AttachConsole(ATTACH_PARENT_PROCESS))
|
||||
{
|
||||
freopen("CONOUT$", "w", stdout);
|
||||
freopen("CONOUT$", "w", stderr);
|
||||
int fd = _fileno(stdout);
|
||||
if (fd >= 0)
|
||||
{
|
||||
std::string fn = std::to_string(fd);
|
||||
SetEnvironmentVariableA("PYSTAND_STDOUT", fn.c_str());
|
||||
}
|
||||
fd = _fileno(stdin);
|
||||
if (fd >= 0)
|
||||
{
|
||||
std::string fn = std::to_string(fd);
|
||||
SetEnvironmentVariableA("PYSTAND_STDIN", fn.c_str());
|
||||
}
|
||||
}
|
||||
#else
|
||||
SetConsoleOutputCP(CP_UTF8);
|
||||
/*
|
||||
auto getCurrentTimestamp = []
|
||||
{
|
||||
auto now = std::chrono::system_clock::now();
|
||||
std::time_t now_time_t = std::chrono::system_clock::to_time_t(now);
|
||||
std::tm now_tm = *std::localtime(&now_time_t);
|
||||
std::ostringstream oss;
|
||||
oss << std::put_time(&now_tm, "log_%Y-%m-%d-%H-%M-%S.txt");
|
||||
return oss.str();
|
||||
};
|
||||
auto curr = getCurrentTimestamp();
|
||||
freopen(curr.c_str(), "a", stderr);
|
||||
*/
|
||||
#endif
|
||||
int hr = ps.RunString(init_script);
|
||||
return hr;
|
||||
}
|
||||
|
@ -531,28 +531,8 @@ wchar_t *TranslateFullLog(wchar_t *otext)
|
||||
|
||||
struct AtlasConfig atlcfg;
|
||||
|
||||
static void writestring(wchar_t *text, HANDLE hPipe)
|
||||
{
|
||||
DWORD _;
|
||||
auto len = text ? (2 * wcslen(text)) : 0;
|
||||
if (!WriteFile(hPipe, &len, 4, &_, NULL))
|
||||
return;
|
||||
if (text)
|
||||
if (!WriteFile(hPipe, text, len, &_, NULL))
|
||||
return;
|
||||
}
|
||||
static wchar_t *readstring(HANDLE hPipe)
|
||||
{
|
||||
DWORD _;
|
||||
int len;
|
||||
if (!ReadFile(hPipe, &len, 4, &_, NULL))
|
||||
return nullptr;
|
||||
wchar_t *otext = new wchar_t[len / 2 + 1];
|
||||
if (!ReadFile(hPipe, otext, len, &_, NULL))
|
||||
return nullptr;
|
||||
otext[len / 2] = 0;
|
||||
return otext;
|
||||
}
|
||||
void writestring(const wchar_t *text, HANDLE hPipe);
|
||||
wchar_t *readstring(HANDLE hPipe);
|
||||
HANDLE mutex = NULL;
|
||||
int atlaswmain(int argc, wchar_t *argv[])
|
||||
{
|
||||
|
@ -678,6 +678,7 @@ std::optional<std::wstring> CTextProcess::eztrans_proc(const std::wstring &input
|
||||
output = HangulDecode(output);
|
||||
return output;
|
||||
}
|
||||
void writestring(const wchar_t *text, HANDLE hPipe);
|
||||
|
||||
int eztrans(int argc, wchar_t *argv[])
|
||||
{
|
||||
@ -700,12 +701,10 @@ int eztrans(int argc, wchar_t *argv[])
|
||||
if (!ReadFile(hPipe, buff, 12000, &_, NULL))
|
||||
break;
|
||||
auto trans = CTextProcess::eztrans_proc(buff);
|
||||
std::wstring res;
|
||||
if (trans)
|
||||
res = trans.value();
|
||||
writestring(trans.value().c_str(), hPipe);
|
||||
else
|
||||
res = L"translate failed";
|
||||
WriteFile(hPipe, res.data(), 2 * res.size(), &_, NULL);
|
||||
writestring(0, hPipe);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -149,7 +149,7 @@ void SetUpLEC()
|
||||
RegCloseKey(key);
|
||||
}
|
||||
}
|
||||
static void writestring(wchar_t *text, HANDLE hPipe)
|
||||
void writestring(const wchar_t *text, HANDLE hPipe)
|
||||
{
|
||||
DWORD _;
|
||||
auto len = text ? (2 * wcslen(text)) : 0;
|
||||
@ -159,7 +159,7 @@ static void writestring(wchar_t *text, HANDLE hPipe)
|
||||
if (!WriteFile(hPipe, text, len, &_, NULL))
|
||||
return;
|
||||
}
|
||||
static wchar_t *readstring(HANDLE hPipe)
|
||||
wchar_t *readstring(HANDLE hPipe)
|
||||
{
|
||||
DWORD _;
|
||||
int len;
|
||||
|
@ -1,7 +1,7 @@
|
||||
|
||||
set(VERSION_MAJOR 6)
|
||||
set(VERSION_MINOR 14)
|
||||
set(VERSION_PATCH 13)
|
||||
set(VERSION_MINOR 15)
|
||||
set(VERSION_PATCH 0)
|
||||
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)
|
||||
|
@ -223,26 +223,7 @@ def urlprotocol():
|
||||
print_exc()
|
||||
|
||||
|
||||
def is64_bit_os():
|
||||
import ctypes
|
||||
|
||||
is64bit = ctypes.c_bool()
|
||||
handle = ctypes.windll.kernel32.GetCurrentProcess()
|
||||
success = ctypes.windll.kernel32.IsWow64Process(handle, ctypes.byref(is64bit))
|
||||
return (success and is64bit).value
|
||||
|
||||
|
||||
def disablestdio():
|
||||
import platform
|
||||
|
||||
if (int(platform.version().split(".")[0]) <= 6) and (not is64_bit_os()):
|
||||
# win7 32位,有时候print会谜之报错PermissionError WinError 31
|
||||
sys.stdout = None
|
||||
sys.stderr = None
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
disablestdio()
|
||||
switchdir()
|
||||
prepareqtenv()
|
||||
from qtsymbols import QApplication
|
||||
|
@ -4,11 +4,11 @@ from qtsymbols import *
|
||||
import os, functools, uuid
|
||||
from traceback import print_exc
|
||||
import gobject, qtawesome
|
||||
from gui.dynalang import LPushButton, LAction
|
||||
from gui.dynalang import LAction
|
||||
from gui.dialog_savedgame_v3 import dialog_savedgame_v3
|
||||
from gui.dialog_savedgame_legacy import dialog_savedgame_legacy
|
||||
from gui.dialog_savedgame_setting import dialog_setting_game, userlabelset
|
||||
from myutils.wrapper import Singleton_close
|
||||
from myutils.wrapper import Singleton_close, tryprint
|
||||
from gui.specialwidget import lazyscrollflow
|
||||
from myutils.utils import str2rgba
|
||||
from myutils.config import (
|
||||
@ -25,12 +25,13 @@ from gui.usefulwidget import (
|
||||
Prompt_dialog,
|
||||
IconButton,
|
||||
getsimplecombobox,
|
||||
FQLineEdit,
|
||||
FocusCombo,
|
||||
)
|
||||
from gui.dialog_savedgame_common import (
|
||||
ItemWidget,
|
||||
dialog_syssetting,
|
||||
tagitem,
|
||||
TagWidget,
|
||||
startgamecheck,
|
||||
loadvisinternal,
|
||||
getalistname,
|
||||
@ -150,6 +151,108 @@ class dialog_savedgame_integrated(saveposwindow):
|
||||
)
|
||||
|
||||
|
||||
class TagWidget(QWidget):
|
||||
tagschanged = pyqtSignal(tuple) # ((tag,type,refdata),)
|
||||
linepressedenter = pyqtSignal(str)
|
||||
tagclicked = pyqtSignal(tuple) # tag,type,refdata
|
||||
|
||||
def __init__(self, parent=None, exfoucus=True):
|
||||
super().__init__(parent)
|
||||
tagitem.setstyles(self)
|
||||
layout = QHBoxLayout()
|
||||
layout.setContentsMargins(0, 0, 0, 0)
|
||||
|
||||
self.setLayout(layout)
|
||||
|
||||
self.lineEdit = FocusCombo()
|
||||
if exfoucus:
|
||||
self.lineEdit.setLineEdit(FQLineEdit())
|
||||
# FQLineEdit导致游戏管理页面里,点击编辑框后,下边界消失。
|
||||
# FQLineEdit仅用于和webview同一窗口内焦点缺失问题,所以既然用不到那就不要多此一举了
|
||||
else:
|
||||
self.lineEdit.setEditable(True)
|
||||
self.lineEdit.lineEdit().returnPressed.connect(
|
||||
lambda: self.linepressedenter.emit(self.lineEdit.currentText())
|
||||
)
|
||||
|
||||
self.lineEdit.setSizePolicy(
|
||||
QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Maximum
|
||||
)
|
||||
self.tagtypes = ["usertags", "developers", "webtags", "usertags"]
|
||||
self.tagtypes_zh = ["全部", "开发商", "标签", "自定义"]
|
||||
self.tagtypes_1 = [
|
||||
tagitem.TYPE_SEARCH,
|
||||
tagitem.TYPE_DEVELOPER,
|
||||
tagitem.TYPE_TAG,
|
||||
tagitem.TYPE_USERTAG,
|
||||
]
|
||||
layout.addWidget(self.lineEdit)
|
||||
|
||||
def __(idx):
|
||||
t = self.lineEdit.currentText()
|
||||
self.lineEdit.clear()
|
||||
self.lineEdit.addItems(userlabelset(self.tagtypes[idx]))
|
||||
self.lineEdit.setCurrentText(t)
|
||||
|
||||
self.typecombo = getsimplecombobox(self.tagtypes_zh, callback=__)
|
||||
layout.addWidget(self.typecombo)
|
||||
self.setSizePolicy(QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Fixed)
|
||||
|
||||
self.tag2widget = {}
|
||||
|
||||
def callback(t):
|
||||
if not t:
|
||||
return
|
||||
self.addTag(t, self.tagtypes_1[self.typecombo.currentIndex()])
|
||||
self.lineEdit.clearEditText()
|
||||
|
||||
self.linepressedenter.connect(callback)
|
||||
self.typecombo.currentIndexChanged.emit(0)
|
||||
|
||||
def addTags(self, tags, signal=True):
|
||||
for key in tags:
|
||||
self.__addTag(key)
|
||||
self.__calltagschanged(signal)
|
||||
|
||||
@tryprint
|
||||
def __addTag(self, key):
|
||||
tag, _type, refdata = key
|
||||
if not tag:
|
||||
return
|
||||
if key in self.tag2widget:
|
||||
return
|
||||
qw = tagitem(tag, _type=_type, refdata=refdata)
|
||||
qw.removesignal.connect(self.removeTag)
|
||||
qw.labelclicked.connect(self.tagclicked.emit)
|
||||
layout = self.layout()
|
||||
layout.insertWidget(layout.count() - 2, qw)
|
||||
self.tag2widget[key] = qw
|
||||
self.lineEdit.setFocus()
|
||||
|
||||
def addTag(self, tag, _type, refdata=None, signal=True):
|
||||
self.__addTag((tag, _type, refdata))
|
||||
self.__calltagschanged(signal)
|
||||
|
||||
@tryprint
|
||||
def __removeTag(self, key):
|
||||
_w = self.tag2widget[key]
|
||||
self.layout().removeWidget(_w)
|
||||
self.tag2widget.pop(key)
|
||||
|
||||
def removeTag(self, key, signal=True):
|
||||
self.__removeTag(key)
|
||||
self.__calltagschanged(signal)
|
||||
|
||||
def __calltagschanged(self, signal):
|
||||
if signal:
|
||||
self.tagschanged.emit(tuple(self.tag2widget.keys()))
|
||||
|
||||
def clearTag(self, signal=True):
|
||||
for key in self.tag2widget.copy():
|
||||
self.__removeTag(key)
|
||||
self.__calltagschanged(signal)
|
||||
|
||||
|
||||
class dialog_savedgame_new(QWidget):
|
||||
|
||||
def dragEnterEvent(self, event: QDragEnterEvent):
|
||||
@ -222,6 +325,10 @@ class dialog_savedgame_new(QWidget):
|
||||
if newtags != self.currtags:
|
||||
break
|
||||
notshow = False
|
||||
webtags = [
|
||||
globalconfig["tagNameRemap"].get(tag, tag)
|
||||
for tag in savehook_new_data[k]["webtags"]
|
||||
]
|
||||
for tag, _type, _ in tags:
|
||||
if _type == tagitem.TYPE_EXISTS:
|
||||
if os.path.exists(get_launchpath(k)) == False:
|
||||
@ -232,16 +339,16 @@ class dialog_savedgame_new(QWidget):
|
||||
notshow = True
|
||||
break
|
||||
elif _type == tagitem.TYPE_TAG:
|
||||
if tag not in savehook_new_data[k]["webtags"]:
|
||||
if tag not in webtags:
|
||||
notshow = True
|
||||
break
|
||||
elif _type == tagitem.TYPE_USERTAG:
|
||||
if tag not in savehook_new_data[k]["usertags"]:
|
||||
notshow = True
|
||||
break
|
||||
elif _type == tagitem.TYPE_RAND:
|
||||
elif _type == tagitem.TYPE_SEARCH:
|
||||
if (
|
||||
tag not in savehook_new_data[k]["webtags"]
|
||||
tag not in webtags
|
||||
and tag not in savehook_new_data[k]["usertags"]
|
||||
and tag not in savehook_new_data[k]["title"]
|
||||
and tag not in savehook_new_data[k]["developers"]
|
||||
@ -431,24 +538,8 @@ class dialog_savedgame_new(QWidget):
|
||||
self.reflist = getreflist(globalconfig["currvislistuid"])
|
||||
self.reftagid = globalconfig["currvislistuid"]
|
||||
|
||||
def callback(t):
|
||||
if not t:
|
||||
return
|
||||
labelset = userlabelset()
|
||||
if t in labelset:
|
||||
tp = tagitem.TYPE_USERTAG
|
||||
else:
|
||||
tp = tagitem.TYPE_RAND
|
||||
self.tagswidget.addTag(t, tp)
|
||||
|
||||
self.tagswidget.lineEdit.clear()
|
||||
self.tagswidget.lineEdit.addItems(labelset)
|
||||
self.tagswidget.lineEdit.clearEditText()
|
||||
|
||||
self.tagswidget = TagWidget(self, exfoucus=False)
|
||||
self.tagswidget.lineEdit.addItems(userlabelset())
|
||||
self.tagswidget.lineEdit.setCurrentText("")
|
||||
self.tagswidget.linepressedenter.connect(callback)
|
||||
|
||||
self.currtags = tuple()
|
||||
self.tagswidget.tagschanged.connect(self.tagschanged)
|
||||
_ = QLabel()
|
||||
@ -500,16 +591,40 @@ class dialog_savedgame_new(QWidget):
|
||||
getreflist(uid).insert(0, getreflist(uid).pop(idx))
|
||||
|
||||
def keyPressEvent(self, e: QKeyEvent):
|
||||
if e.key() == Qt.Key.Key_Return:
|
||||
startgamecheck(self, getreflist(self.reftagid), self.currentfocusuid)
|
||||
elif e.key() == Qt.Key.Key_Delete:
|
||||
self.clicked2()
|
||||
elif e.key() == Qt.Key.Key_Left:
|
||||
self.moverank(-1)
|
||||
elif e.key() == Qt.Key.Key_Right:
|
||||
self.moverank(1)
|
||||
if self.currentfocusuid:
|
||||
if e.key() == Qt.Key.Key_Return:
|
||||
startgamecheck(self, getreflist(self.reftagid), self.currentfocusuid)
|
||||
elif e.key() == Qt.Key.Key_Delete:
|
||||
self.clicked2()
|
||||
elif e.key() == Qt.Key.Key_Left:
|
||||
if e.modifiers() == Qt.KeyboardModifier.ControlModifier:
|
||||
self.moverank(-1)
|
||||
else:
|
||||
self.movefocus(-1)
|
||||
elif e.key() == Qt.Key.Key_Right:
|
||||
if e.modifiers() == Qt.KeyboardModifier.ControlModifier:
|
||||
self.moverank(1)
|
||||
else:
|
||||
self.movefocus(1)
|
||||
super().keyPressEvent(e)
|
||||
|
||||
def movefocus(self, dx):
|
||||
game = self.currentfocusuid
|
||||
|
||||
idx1 = self.idxsave.index(game)
|
||||
idx2 = (idx1 + dx) % len(self.idxsave)
|
||||
|
||||
if idx1 == 0 and dx == -1:
|
||||
self.flow.verticalScrollBar().setValue(
|
||||
self.flow.verticalScrollBar().maximum()
|
||||
)
|
||||
else:
|
||||
self.flow.ensureWidgetVisible(self.flow.widget(idx2))
|
||||
try:
|
||||
self.flow.widget(idx2).click()
|
||||
except:
|
||||
pass
|
||||
|
||||
def moverank(self, dx):
|
||||
game = self.currentfocusuid
|
||||
|
||||
@ -518,7 +633,7 @@ class dialog_savedgame_new(QWidget):
|
||||
game2 = self.idxsave[idx2]
|
||||
self.idxsave.insert(idx2, self.idxsave.pop(idx1))
|
||||
self.flow.switchidx(idx1, idx2)
|
||||
|
||||
# self.flow.ensureWidgetVisible(self.flow.widget(idx2))
|
||||
idx1 = self.reflist.index(game)
|
||||
idx2 = self.reflist.index(game2)
|
||||
self.reflist.insert(idx2, self.reflist.pop(idx1))
|
||||
|
@ -1,8 +1,8 @@
|
||||
from qtsymbols import *
|
||||
import os, functools
|
||||
from traceback import print_exc
|
||||
from myutils.wrapper import tryprint, threader, Singleton_close
|
||||
from myutils.utils import str2rgba, find_or_create_uid, duplicateconfig
|
||||
from myutils.wrapper import threader, Singleton_close
|
||||
from myutils.utils import find_or_create_uid, duplicateconfig
|
||||
from myutils.hwnd import getExeIcon
|
||||
import gobject, hashlib
|
||||
from gui.inputdialog import autoinitdialog
|
||||
@ -19,13 +19,11 @@ from myutils.config import (
|
||||
)
|
||||
from gui.usefulwidget import (
|
||||
getIconButton,
|
||||
FocusCombo,
|
||||
getsimplecombobox,
|
||||
getspinbox,
|
||||
getcolorbutton,
|
||||
getsimpleswitch,
|
||||
getsimplepatheditor,
|
||||
FQLineEdit,
|
||||
getspinbox,
|
||||
selectcolor,
|
||||
SplitLine,
|
||||
@ -211,12 +209,9 @@ class ClickableLabel(QLabel):
|
||||
clicked = pyqtSignal()
|
||||
|
||||
|
||||
class tagitem(QWidget):
|
||||
# website
|
||||
TYPE_GLOABL_LIKE = 3
|
||||
TYPE_GAME_LIKE = 1
|
||||
class tagitem(QFrame):
|
||||
# search game
|
||||
TYPE_RAND = 0
|
||||
TYPE_SEARCH = 0
|
||||
TYPE_DEVELOPER = 1
|
||||
TYPE_TAG = 2
|
||||
TYPE_USERTAG = 3
|
||||
@ -224,132 +219,58 @@ class tagitem(QWidget):
|
||||
removesignal = pyqtSignal(tuple)
|
||||
labelclicked = pyqtSignal(tuple)
|
||||
|
||||
def remove(self):
|
||||
self.hide()
|
||||
_lay = self.layout()
|
||||
_ws = []
|
||||
for i in range(_lay.count()):
|
||||
witem = _lay.itemAt(i)
|
||||
_ws.append(witem.widget())
|
||||
for w in _ws:
|
||||
_lay.removeWidget(w)
|
||||
@staticmethod
|
||||
def setstyles(parent: QWidget):
|
||||
parent.setStyleSheet(
|
||||
"""
|
||||
tagitem#red {
|
||||
border: 1px solid red;
|
||||
}
|
||||
tagitem#black {
|
||||
border: 1px solid black;
|
||||
}
|
||||
tagitem#green {
|
||||
border: 1px solid green;
|
||||
}
|
||||
tagitem#blue {
|
||||
border: 1px solid blue;
|
||||
}
|
||||
tagitem#yellow {
|
||||
border: 1px solid yellow;
|
||||
}
|
||||
"""
|
||||
)
|
||||
|
||||
def paintEvent(self, event):
|
||||
painter = QPainter(self)
|
||||
painter.setRenderHint(QPainter.RenderHint.Antialiasing)
|
||||
if self._type == tagitem.TYPE_RAND:
|
||||
border_color = Qt.GlobalColor.black
|
||||
elif self._type == tagitem.TYPE_DEVELOPER:
|
||||
border_color = Qt.GlobalColor.red
|
||||
elif self._type == tagitem.TYPE_TAG:
|
||||
border_color = Qt.GlobalColor.green
|
||||
elif self._type == tagitem.TYPE_USERTAG:
|
||||
border_color = Qt.GlobalColor.blue
|
||||
elif self._type == tagitem.TYPE_EXISTS:
|
||||
border_color = Qt.GlobalColor.yellow
|
||||
border_width = 1
|
||||
pen = QPen(border_color)
|
||||
pen.setWidth(border_width)
|
||||
painter.setPen(pen)
|
||||
painter.drawRect(self.rect())
|
||||
|
||||
def __init__(self, tag, removeable=True, _type=TYPE_RAND, refdata=None) -> None:
|
||||
def __init__(self, tag, removeable=True, _type=TYPE_SEARCH, refdata=None) -> None:
|
||||
super().__init__()
|
||||
if _type == tagitem.TYPE_SEARCH:
|
||||
border_color = "black"
|
||||
elif _type == tagitem.TYPE_DEVELOPER:
|
||||
border_color = "red"
|
||||
elif _type == tagitem.TYPE_TAG:
|
||||
border_color = "green"
|
||||
elif _type == tagitem.TYPE_USERTAG:
|
||||
border_color = "blue"
|
||||
elif _type == tagitem.TYPE_EXISTS:
|
||||
border_color = "yellow"
|
||||
self.setObjectName(border_color)
|
||||
|
||||
tagLayout = QHBoxLayout()
|
||||
tagLayout.setContentsMargins(0, 0, 0, 0)
|
||||
tagLayout.setSpacing(0)
|
||||
self._type = _type
|
||||
|
||||
key = (tag, _type, refdata)
|
||||
self.setLayout(tagLayout)
|
||||
lb = ClickableLabel()
|
||||
lb.setStyleSheet("background: transparent;")
|
||||
lb.setText(tag)
|
||||
lb.clicked.connect(functools.partial(self.labelclicked.emit, key))
|
||||
tagLayout.addWidget(lb)
|
||||
if removeable:
|
||||
button = getIconButton(
|
||||
functools.partial(self.removesignal.emit, key), icon="fa.times"
|
||||
)
|
||||
tagLayout.addWidget(button)
|
||||
|
||||
|
||||
class TagWidget(QWidget):
|
||||
tagschanged = pyqtSignal(tuple) # ((tag,type,refdata),)
|
||||
linepressedenter = pyqtSignal(str)
|
||||
tagclicked = pyqtSignal(tuple) # tag,type,refdata
|
||||
|
||||
def __init__(self, parent=None, exfoucus=True):
|
||||
super().__init__(parent)
|
||||
|
||||
layout = QHBoxLayout()
|
||||
layout.setContentsMargins(0, 0, 0, 0)
|
||||
|
||||
self.setLayout(layout)
|
||||
|
||||
self.lineEdit = FocusCombo()
|
||||
if exfoucus:
|
||||
self.lineEdit.setLineEdit(FQLineEdit())
|
||||
# FQLineEdit导致游戏管理页面里,点击编辑框后,下边界消失。
|
||||
# FQLineEdit仅用于和webview同一窗口内焦点缺失问题,所以既然用不到那就不要多此一举了
|
||||
else:
|
||||
self.lineEdit.setEditable(True)
|
||||
self.lineEdit.lineEdit().returnPressed.connect(
|
||||
lambda: self.linepressedenter.emit(self.lineEdit.currentText())
|
||||
)
|
||||
|
||||
self.lineEdit.setSizePolicy(
|
||||
QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Maximum
|
||||
)
|
||||
|
||||
layout.addWidget(self.lineEdit)
|
||||
self.setSizePolicy(QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Fixed)
|
||||
|
||||
self.tag2widget = {}
|
||||
|
||||
def addTags(self, tags, signal=True):
|
||||
for key in tags:
|
||||
self.__addTag(key)
|
||||
self.__calltagschanged(signal)
|
||||
|
||||
@tryprint
|
||||
def __addTag(self, key):
|
||||
tag, _type, refdata = key
|
||||
if not tag:
|
||||
return
|
||||
if key in self.tag2widget:
|
||||
return
|
||||
qw = tagitem(tag, _type=_type, refdata=refdata)
|
||||
qw.removesignal.connect(self.removeTag)
|
||||
qw.labelclicked.connect(self.tagclicked.emit)
|
||||
layout = self.layout()
|
||||
layout.insertWidget(layout.count() - 1, qw)
|
||||
self.tag2widget[key] = qw
|
||||
self.lineEdit.setFocus()
|
||||
|
||||
def addTag(self, tag, _type, refdata=None, signal=True):
|
||||
self.__addTag((tag, _type, refdata))
|
||||
self.__calltagschanged(signal)
|
||||
|
||||
@tryprint
|
||||
def __removeTag(self, key):
|
||||
_w = self.tag2widget[key]
|
||||
_w.remove()
|
||||
|
||||
self.layout().removeWidget(_w)
|
||||
self.tag2widget.pop(key)
|
||||
|
||||
def removeTag(self, key, signal=True):
|
||||
self.__removeTag(key)
|
||||
self.__calltagschanged(signal)
|
||||
|
||||
def __calltagschanged(self, signal):
|
||||
if signal:
|
||||
self.tagschanged.emit(tuple(self.tag2widget.keys()))
|
||||
|
||||
def clearTag(self, signal=True):
|
||||
for key in self.tag2widget.copy():
|
||||
self.__removeTag(key)
|
||||
self.__calltagschanged(signal)
|
||||
tagLayout.addWidget(lb)
|
||||
|
||||
|
||||
def opendirforgameuid(gameuid):
|
||||
|
@ -4,7 +4,7 @@ from qtsymbols import *
|
||||
import functools, uuid
|
||||
from datetime import datetime, timedelta
|
||||
from traceback import print_exc
|
||||
import gobject
|
||||
import gobject, winsharedutils
|
||||
from myutils.config import (
|
||||
savehook_new_data,
|
||||
uid2gamepath,
|
||||
@ -16,7 +16,7 @@ from myutils.config import (
|
||||
)
|
||||
from myutils.localetools import getgamecamptools, maycreatesettings
|
||||
from myutils.hwnd import getExeIcon
|
||||
from myutils.wrapper import Singleton, Singleton_close, trypass
|
||||
from myutils.wrapper import Singleton, Singleton_close
|
||||
from myutils.utils import (
|
||||
gamdidchangedtask,
|
||||
checkpostlangmatch,
|
||||
@ -34,9 +34,10 @@ from gui.inputdialog import (
|
||||
autoinitdialog_items,
|
||||
postconfigdialog,
|
||||
)
|
||||
from gui.specialwidget import ScrollFlow, chartwidget
|
||||
from gui.specialwidget import chartwidget
|
||||
from gui.usefulwidget import (
|
||||
TableViewW,
|
||||
FlowWidget,
|
||||
getsimpleswitch,
|
||||
getsimplepatheditor,
|
||||
getboxlayout,
|
||||
@ -50,6 +51,8 @@ from gui.usefulwidget import (
|
||||
getspinbox,
|
||||
getsmalllabel,
|
||||
listediterline,
|
||||
editswitchTextBrowser,
|
||||
FocusCombo,
|
||||
)
|
||||
from gui.dynalang import (
|
||||
LFormLayout,
|
||||
@ -61,6 +64,7 @@ from gui.dynalang import (
|
||||
LGroupBox,
|
||||
)
|
||||
from gui.dialog_savedgame_common import tagitem
|
||||
from gui.inputdialog import postconfigdialog_
|
||||
|
||||
|
||||
@Singleton
|
||||
@ -183,11 +187,11 @@ def maybehavebutton(self, gameuid, post):
|
||||
return None
|
||||
|
||||
|
||||
def userlabelset():
|
||||
def userlabelset(key="usertags"):
|
||||
s = set()
|
||||
for gameuid in savehook_new_data:
|
||||
s = s.union(savehook_new_data[gameuid]["usertags"])
|
||||
return list(s)
|
||||
s = s.union(savehook_new_data[gameuid][key])
|
||||
return sorted(list(s))
|
||||
|
||||
|
||||
class dialog_setting_game_internal(QWidget):
|
||||
@ -199,8 +203,9 @@ class dialog_setting_game_internal(QWidget):
|
||||
if self.lauchpath:
|
||||
self.lauchpath.clear.clicked.emit()
|
||||
|
||||
def __init__(self, parent, gameuid) -> None:
|
||||
def __init__(self, parent, gameuid, keepindexobject=None) -> None:
|
||||
super().__init__(parent)
|
||||
self.keepindexobject = keepindexobject
|
||||
vbox = QVBoxLayout(self)
|
||||
self.lauchpath = None
|
||||
formLayout = LFormLayout()
|
||||
@ -253,6 +258,11 @@ class dialog_setting_game_internal(QWidget):
|
||||
[_[0] for _ in functs],
|
||||
[functools.partial(self.doaddtab, _[1], gameuid) for _ in functs],
|
||||
delay=True,
|
||||
initial=(
|
||||
(self.keepindexobject, "p1")
|
||||
if (self.keepindexobject is not None)
|
||||
else None
|
||||
),
|
||||
)
|
||||
vbox.addLayout(formLayout)
|
||||
vbox.addWidget(methodtab)
|
||||
@ -285,12 +295,17 @@ class dialog_setting_game_internal(QWidget):
|
||||
functs = [
|
||||
("元数据", functools.partial(self.___tabf, self.metadataorigin)),
|
||||
("统计", functools.partial(self.___tabf2, self.getstatistic)),
|
||||
("标签", functools.partial(self.___tabf2, self.getlabelsetting)),
|
||||
("信息", functools.partial(self.___tabf2, self.getlabelsetting)),
|
||||
]
|
||||
methodtab, do = makesubtab_lazy(
|
||||
[_[0] for _ in functs],
|
||||
[functools.partial(self.doaddtab, _[1], gameuid) for _ in functs],
|
||||
delay=True,
|
||||
initial=(
|
||||
(self.keepindexobject, "gamedata")
|
||||
if (self.keepindexobject is not None)
|
||||
else None
|
||||
),
|
||||
)
|
||||
vbox.addWidget(methodtab)
|
||||
do()
|
||||
@ -310,6 +325,11 @@ class dialog_setting_game_internal(QWidget):
|
||||
[_[0] for _ in functs],
|
||||
[functools.partial(self.doaddtab, _[1], gameuid) for _ in functs],
|
||||
delay=True,
|
||||
initial=(
|
||||
(self.keepindexobject, "gamesetting")
|
||||
if (self.keepindexobject is not None)
|
||||
else None
|
||||
),
|
||||
)
|
||||
|
||||
self.methodtab = methodtab
|
||||
@ -556,74 +576,106 @@ class dialog_setting_game_internal(QWidget):
|
||||
string = "0"
|
||||
return string
|
||||
|
||||
def tagenewitem(
|
||||
self,
|
||||
gameuid,
|
||||
text,
|
||||
refkey,
|
||||
first=False,
|
||||
_type=tagitem.TYPE_SEARCH,
|
||||
):
|
||||
if _type == tagitem.TYPE_TAG:
|
||||
text = globalconfig["tagNameRemap"].get(text, text)
|
||||
qw = tagitem(text, True, _type)
|
||||
|
||||
def __(gameuid, _qw, refkey, _):
|
||||
t, _, _ = _
|
||||
try:
|
||||
savehook_new_data[gameuid][refkey].remove(t)
|
||||
self.flowwidget.removeWidget(_qw)
|
||||
except:
|
||||
print_exc()
|
||||
|
||||
qw.removesignal.connect(functools.partial(__, gameuid, qw, refkey))
|
||||
|
||||
def safeaddtags(_):
|
||||
try:
|
||||
gobject.global_dialog_savedgame_new.tagswidget.addTag(*_)
|
||||
except:
|
||||
winsharedutils.clipboard_set(_[0])
|
||||
|
||||
qw.labelclicked.connect(safeaddtags)
|
||||
if first:
|
||||
self.flowwidget.insertWidget(self.labelflowmap[refkey], 1, qw)
|
||||
else:
|
||||
self.flowwidget.addWidget(self.labelflowmap[refkey], qw)
|
||||
|
||||
def getlabelsetting(self, formLayout: QVBoxLayout, gameuid):
|
||||
self.labelflow = ScrollFlow()
|
||||
self.labelflowmap = {}
|
||||
flowwidget = FlowWidget(groups=4)
|
||||
tagitem.setstyles(flowwidget)
|
||||
self.flowwidget = flowwidget
|
||||
scroll = QScrollArea()
|
||||
scroll.setWidgetResizable(True)
|
||||
scroll.setWidget(flowwidget)
|
||||
formLayout.addWidget(scroll)
|
||||
self.tagtypes = ["developers", "webtags", "usertags"]
|
||||
self.tagtypes_zh = ["开发商", "标签", "自定义"]
|
||||
self.tagtypes_1 = [
|
||||
tagitem.TYPE_DEVELOPER,
|
||||
tagitem.TYPE_TAG,
|
||||
tagitem.TYPE_USERTAG,
|
||||
]
|
||||
|
||||
def newitem(text, refkey, first=False, _type=tagitem.TYPE_RAND):
|
||||
qw = tagitem(text, True, _type)
|
||||
def createflows(label, key, _t, index):
|
||||
self.labelflowmap[key] = index
|
||||
flowwidget.addWidget(index, LLabel(label))
|
||||
for tag in savehook_new_data[gameuid][key]:
|
||||
self.tagenewitem(gameuid, tag, key, _type=_t)
|
||||
|
||||
def __(gameuid, _qw, refkey, _):
|
||||
t, _type, _ = _
|
||||
try:
|
||||
_qw.remove()
|
||||
savehook_new_data[gameuid][refkey].remove(t)
|
||||
self.labelflow.removewidget(_qw)
|
||||
except:
|
||||
print_exc()
|
||||
for i in range(len(self.tagtypes)):
|
||||
createflows(self.tagtypes_zh[i], self.tagtypes[i], self.tagtypes_1[i], i)
|
||||
flowwidget.addWidget(3, LLabel("简介"))
|
||||
edit = editswitchTextBrowser()
|
||||
edit.settext(savehook_new_data[gameuid].get("description", ""))
|
||||
|
||||
qw.removesignal.connect(functools.partial(__, gameuid, qw, refkey))
|
||||
|
||||
def safeaddtags(_):
|
||||
try:
|
||||
gobject.global_dialog_savedgame_new.tagswidget.addTag(*_)
|
||||
except:
|
||||
pass
|
||||
|
||||
qw.labelclicked.connect(safeaddtags)
|
||||
if first:
|
||||
self.labelflow.insertwidget(0, qw)
|
||||
def __():
|
||||
if not edit.text().strip():
|
||||
savehook_new_data[gameuid]["description"] = ""
|
||||
else:
|
||||
self.labelflow.addwidget(qw)
|
||||
savehook_new_data[gameuid]["description"] = edit.text().strip()
|
||||
|
||||
for tag in savehook_new_data[gameuid]["usertags"]:
|
||||
newitem(tag, "usertags", _type=tagitem.TYPE_USERTAG)
|
||||
for tag in savehook_new_data[gameuid]["developers"]:
|
||||
newitem(tag, "developers", _type=tagitem.TYPE_DEVELOPER)
|
||||
for tag in savehook_new_data[gameuid]["webtags"]:
|
||||
newitem(tag, "webtags", _type=tagitem.TYPE_TAG)
|
||||
formLayout.addWidget(self.labelflow)
|
||||
_dict = {"new": 0}
|
||||
edit.textChanged.connect(__)
|
||||
flowwidget.addWidget(3, edit)
|
||||
|
||||
formLayout.addWidget(self.labelflow)
|
||||
button = LPushButton("添加")
|
||||
|
||||
combo = getsimplecombobox(userlabelset(), _dict, "new", static=True)
|
||||
typecombo = getsimplecombobox(self.tagtypes_zh, initial=2)
|
||||
combo = FocusCombo()
|
||||
combo.setEditable(True)
|
||||
combo.clearEditText()
|
||||
|
||||
def __(idx):
|
||||
t = combo.currentText()
|
||||
combo.clear()
|
||||
combo.addItems(userlabelset(self.tagtypes[idx]))
|
||||
combo.setCurrentText(t)
|
||||
|
||||
typecombo.currentIndexChanged.connect(__)
|
||||
__(2)
|
||||
|
||||
def _add(_):
|
||||
labelset = userlabelset()
|
||||
tag = combo.currentText()
|
||||
if (not tag) or (tag in savehook_new_data[gameuid]["usertags"]):
|
||||
tp = self.tagtypes[typecombo.currentIndex()]
|
||||
if (not tag) or (tag in savehook_new_data[gameuid][tp]):
|
||||
return
|
||||
savehook_new_data[gameuid]["usertags"].insert(0, tag)
|
||||
newitem(tag, "usertags", first=True, _type=tagitem.TYPE_USERTAG)
|
||||
savehook_new_data[gameuid][tp].insert(0, tag)
|
||||
self.tagenewitem(
|
||||
gameuid,
|
||||
tag,
|
||||
tp,
|
||||
first=True,
|
||||
_type=self.tagtypes_1[typecombo.currentIndex()],
|
||||
)
|
||||
combo.clearEditText()
|
||||
combo.clear()
|
||||
combo.addItems(labelset)
|
||||
try:
|
||||
_ = (
|
||||
gobject.global_dialog_savedgame_new.tagswidget.lineEdit.currentText()
|
||||
)
|
||||
gobject.global_dialog_savedgame_new.tagswidget.lineEdit.clear()
|
||||
gobject.global_dialog_savedgame_new.tagswidget.lineEdit.addItems(
|
||||
labelset
|
||||
)
|
||||
gobject.global_dialog_savedgame_new.tagswidget.lineEdit.setCurrentText(
|
||||
_
|
||||
)
|
||||
except:
|
||||
pass
|
||||
|
||||
button.clicked.connect(_add)
|
||||
|
||||
@ -631,11 +683,18 @@ class dialog_setting_game_internal(QWidget):
|
||||
getboxlayout(
|
||||
[
|
||||
combo,
|
||||
typecombo,
|
||||
button,
|
||||
getIconButton(callback=self.edittagremap, icon="fa.gear"),
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
def edittagremap(self):
|
||||
postconfigdialog_(
|
||||
self, globalconfig["tagNameRemap"], "标签映射", ["From", "To"]
|
||||
)
|
||||
|
||||
def createfollowdefault(
|
||||
self,
|
||||
dic: dict,
|
||||
@ -1111,7 +1170,7 @@ def calculate_centered_rect(original_rect: QRect, size: QSize) -> QRect:
|
||||
|
||||
|
||||
@Singleton_close
|
||||
class dialog_setting_game(LDialog):
|
||||
class dialog_setting_game(QDialog):
|
||||
|
||||
def __init__(self, parent, gameuid, setindexhook=0) -> None:
|
||||
super().__init__(parent, Qt.WindowType.WindowCloseButtonHint)
|
||||
|
@ -669,7 +669,11 @@ class dialog_savedgame_v3(QWidget):
|
||||
tabadd_lazy(
|
||||
self.righttop,
|
||||
"设置",
|
||||
lambda v: v.addWidget(dialog_setting_game_internal(self, k)),
|
||||
lambda v: v.addWidget(
|
||||
dialog_setting_game_internal(
|
||||
self, k, keepindexobject=self.keepindexobject
|
||||
)
|
||||
),
|
||||
)
|
||||
self.righttop.setCurrentIndex(currvis)
|
||||
except:
|
||||
@ -835,6 +839,22 @@ class dialog_savedgame_v3(QWidget):
|
||||
)
|
||||
self.setStyleSheet(style)
|
||||
|
||||
def movefocus(self, dx):
|
||||
uid = self.currentfocusuid
|
||||
idx1 = self.reallist[self.reftagid].index(uid)
|
||||
idx2 = (idx1 + dx) % len(self.reallist[self.reftagid])
|
||||
group0 = self.stack.w(calculatetagidx(self.reftagid))
|
||||
if idx1 == 0 and dx == -1:
|
||||
self.stack.verticalScrollBar().setValue(
|
||||
self.stack.verticalScrollBar().maximum()
|
||||
)
|
||||
else:
|
||||
self.stack.ensureWidgetVisible(group0.w(idx2))
|
||||
try:
|
||||
group0.w(idx2).click()
|
||||
except:
|
||||
pass
|
||||
|
||||
def __init__(self, parent) -> None:
|
||||
super().__init__(parent)
|
||||
parent.setWindowTitle("游戏管理")
|
||||
@ -842,21 +862,29 @@ class dialog_savedgame_v3(QWidget):
|
||||
self.currentfocusuid = None
|
||||
self.reftagid = None
|
||||
self.reallist = {}
|
||||
self.keepindexobject = {}
|
||||
|
||||
class ___(stackedlist):
|
||||
def keyPressEvent(self, e: QKeyEvent):
|
||||
if e.key() == Qt.Key.Key_Return:
|
||||
startgamecheck(
|
||||
self.ref,
|
||||
getreflist(self.ref.reftagid),
|
||||
self.ref.currentfocusuid,
|
||||
)
|
||||
elif e.key() == Qt.Key.Key_Delete:
|
||||
self.ref.shanchuyouxi()
|
||||
elif e.key() == Qt.Key.Key_Left:
|
||||
self.ref.moverank(-1)
|
||||
elif e.key() == Qt.Key.Key_Right:
|
||||
self.ref.moverank(1)
|
||||
if self.ref.currentfocusuid:
|
||||
if e.key() == Qt.Key.Key_Return:
|
||||
startgamecheck(
|
||||
self.ref,
|
||||
getreflist(self.ref.reftagid),
|
||||
self.ref.currentfocusuid,
|
||||
)
|
||||
elif e.key() == Qt.Key.Key_Delete:
|
||||
self.ref.shanchuyouxi()
|
||||
elif e.key() == Qt.Key.Key_Left:
|
||||
self.ref.moverank(-1)
|
||||
elif e.key() == Qt.Key.Key_Right:
|
||||
self.ref.moverank(1)
|
||||
elif e.key() == Qt.Key.Key_Down:
|
||||
self.ref.movefocus(1)
|
||||
return e.ignore()
|
||||
elif e.key() == Qt.Key.Key_Up:
|
||||
self.ref.movefocus(-1)
|
||||
return e.ignore()
|
||||
super().keyPressEvent(e)
|
||||
|
||||
self.stack = ___()
|
||||
@ -1047,6 +1075,9 @@ class dialog_savedgame_v3(QWidget):
|
||||
)
|
||||
|
||||
self.stack.w(calculatetagidx(self.reftagid)).switchidx(idx1, idx2)
|
||||
self.stack.ensureWidgetVisible(
|
||||
self.stack.w(calculatetagidx(self.reftagid)).w(idx2)
|
||||
)
|
||||
idx1 = getreflist(self.reftagid).index(uid)
|
||||
idx2 = getreflist(self.reftagid).index(uid2)
|
||||
getreflist(self.reftagid).insert(idx2, getreflist(self.reftagid).pop(idx1))
|
||||
|
@ -452,19 +452,6 @@ class autoinitdialog__(LDialog):
|
||||
super().__init__(parent, Qt.WindowType.WindowCloseButtonHint)
|
||||
self.setWindowTitle(title)
|
||||
self.resize(QSize(width, 10))
|
||||
for line in lines:
|
||||
if line["type"] != "program":
|
||||
continue
|
||||
try:
|
||||
func = getattr(
|
||||
importlib.import_module(line["route"][0]),
|
||||
line["route"][1],
|
||||
)
|
||||
func(self)
|
||||
except:
|
||||
print_exc()
|
||||
self.show()
|
||||
return
|
||||
formLayout = VisLFormLayout()
|
||||
self.setLayout(formLayout)
|
||||
regist = {}
|
||||
|
@ -5,7 +5,7 @@ from myutils.config import globalconfig, static_data, _TR, get_platform
|
||||
from myutils.wrapper import threader, tryprint
|
||||
from myutils.hwnd import getcurrexe
|
||||
from myutils.utils import makehtml, getlanguse, dynamiclink
|
||||
import requests, sys
|
||||
import requests, importlib
|
||||
import shutil, gobject
|
||||
from myutils.proxy import getproxy
|
||||
import zipfile, os
|
||||
@ -13,12 +13,15 @@ import subprocess
|
||||
from gui.usefulwidget import (
|
||||
D_getsimpleswitch,
|
||||
makescrollgrid,
|
||||
CollapsibleBox,
|
||||
makesubtab_lazy,
|
||||
D_getsimplecombobox,
|
||||
makegrid,
|
||||
D_getIconButton,
|
||||
WebivewWidget,
|
||||
)
|
||||
from gui.dynalang import LLabel
|
||||
from gui.setting_year import yearsummary
|
||||
|
||||
versionchecktask = queue.Queue()
|
||||
|
||||
@ -248,39 +251,6 @@ def versionlabelmaybesettext(self, x):
|
||||
self.versionlabel_cache = x
|
||||
|
||||
|
||||
def solvelinkitems(grid, source):
|
||||
name = source["name"]
|
||||
link = source["link"]
|
||||
grid.append([name, (makehtml(link), 2, "link")])
|
||||
|
||||
|
||||
def resourcegrid(self, l):
|
||||
titles = []
|
||||
makewidgetsfunctions = []
|
||||
for sourcetype in static_data["aboutsource"]:
|
||||
titles.append(sourcetype["name"])
|
||||
sources = sourcetype["sources"]
|
||||
grid = []
|
||||
for source in sources:
|
||||
|
||||
__grid = []
|
||||
for link in source["links"]:
|
||||
__grid.append([link["name"], (makehtml(link["link"]), 2, "link")])
|
||||
grid.append(
|
||||
[
|
||||
(
|
||||
dict(title=source.get("name", None), type="grid", grid=__grid),
|
||||
0,
|
||||
"group",
|
||||
)
|
||||
]
|
||||
)
|
||||
makewidgetsfunctions.append(functools.partial(makescrollgrid, grid))
|
||||
tab, dotab = makesubtab_lazy(titles, makewidgetsfunctions, delay=True)
|
||||
l.addWidget(tab)
|
||||
dotab()
|
||||
|
||||
|
||||
def createimageview(self):
|
||||
lb = QLabel()
|
||||
img = QPixmap.fromImage(QImage("./files/zan.jpg"))
|
||||
@ -295,17 +265,60 @@ def createimageview(self):
|
||||
return lb
|
||||
|
||||
|
||||
def setTab_aboutlazy(self, basel):
|
||||
|
||||
resourcegrid(self, basel)
|
||||
|
||||
|
||||
def changelog(self, basel: QHBoxLayout):
|
||||
_ = WebivewWidget(self)
|
||||
_.navigate(dynamiclink("{main_server}/ChangeLog"))
|
||||
basel.addWidget(_)
|
||||
|
||||
|
||||
def delayloadlinks(key, box):
|
||||
sources = static_data["aboutsource"][key]
|
||||
grid = []
|
||||
for source in sources:
|
||||
__grid = []
|
||||
function = source.get("function")
|
||||
if function:
|
||||
func = getattr(
|
||||
importlib.import_module(function[0]),
|
||||
function[1],
|
||||
)
|
||||
__grid.append([(func, 0)])
|
||||
else:
|
||||
for link in source["links"]:
|
||||
__grid.append(
|
||||
[link["name"], (makehtml(link["link"]), 2, "link")]
|
||||
+ ([link.get("about")] if link.get("about") else [])
|
||||
)
|
||||
grid.append(
|
||||
[
|
||||
(
|
||||
dict(title=source.get("name", None), type="grid", grid=__grid),
|
||||
0,
|
||||
"group",
|
||||
)
|
||||
]
|
||||
)
|
||||
grid = [
|
||||
[
|
||||
(
|
||||
dict(type="grid", grid=grid),
|
||||
0,
|
||||
"group",
|
||||
)
|
||||
]
|
||||
]
|
||||
w, do = makegrid(grid, delay=True, w=False)
|
||||
w.setContentsMargins(0, 0, 0, 0)
|
||||
box.content_area.setLayout(w)
|
||||
do()
|
||||
|
||||
|
||||
def offlinelinks(key):
|
||||
box = CollapsibleBox("下载")
|
||||
box.setdelayload(functools.partial(delayloadlinks, key))
|
||||
return box
|
||||
|
||||
|
||||
def setTab_about1(self, basel):
|
||||
|
||||
shuominggrid = [
|
||||
@ -363,12 +376,12 @@ def setTab_about1(self, basel):
|
||||
|
||||
def setTab_about(self, basel):
|
||||
tab_widget, do = makesubtab_lazy(
|
||||
["关于软件", "其他设置", "资源下载", "更新记录"],
|
||||
["关于软件", "其他设置", "更新记录", "年度总结"],
|
||||
[
|
||||
functools.partial(setTab_about1, self),
|
||||
functools.partial(setTab_update, self),
|
||||
functools.partial(setTab_aboutlazy, self),
|
||||
functools.partial(changelog, self),
|
||||
functools.partial(yearsummary, self),
|
||||
],
|
||||
delay=True,
|
||||
)
|
||||
@ -384,6 +397,7 @@ def changeUIlanguage(_):
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
def setTab_update(self, basel):
|
||||
version = winsharedutils.queryversion(getcurrexe())
|
||||
if version is None:
|
||||
|
@ -22,6 +22,7 @@ from gui.usefulwidget import (
|
||||
D_getsimplecombobox,
|
||||
)
|
||||
from gui.showword import showdiction
|
||||
from gui.setting_about import offlinelinks
|
||||
|
||||
|
||||
def setTabcishu(self, basel):
|
||||
@ -217,6 +218,7 @@ def setTabcishu_l(self):
|
||||
)
|
||||
]
|
||||
grids = [
|
||||
[(functools.partial(offlinelinks, "dict"), 0)],
|
||||
grids_1,
|
||||
grids2,
|
||||
[],
|
||||
|
@ -11,6 +11,7 @@ from gui.usefulwidget import (
|
||||
makescrollgrid,
|
||||
D_getsimpleswitch,
|
||||
)
|
||||
from gui.setting_about import offlinelinks
|
||||
|
||||
|
||||
def makescalew(self, lay: QVBoxLayout):
|
||||
@ -333,6 +334,7 @@ def makescalew(self, lay: QVBoxLayout):
|
||||
),
|
||||
("", 10),
|
||||
],
|
||||
[(functools.partial(offlinelinks, "magpie"),0)],
|
||||
]
|
||||
|
||||
commonfsgrid = [
|
||||
|
@ -98,7 +98,7 @@ def makegridW(grid, lay, save=False, savelist=None, savelay=None):
|
||||
|
||||
def makeproxytab():
|
||||
|
||||
lixians, pre, mianfei, develop, shoufei = splittranslatortypes()
|
||||
lixians, pre, mianfei, shoufei = splittranslatortypes()
|
||||
|
||||
mianfei = getall(l=mianfei, item="fanyi", name="./Lunatranslator/translator/%s.py")
|
||||
shoufei = getall(l=shoufei, item="fanyi", name=translate_exits)
|
||||
|
@ -28,6 +28,7 @@ import gobject, qtawesome
|
||||
from gui.dynalang import LFormLayout, LDialog, LAction
|
||||
from myutils.ocrutil import ocr_end, ocr_init, ocr_run
|
||||
from myutils.wrapper import threader, Singleton_close
|
||||
from gui.setting_about import offlinelinks
|
||||
|
||||
|
||||
def __label1(self):
|
||||
@ -385,14 +386,17 @@ class showocrimage(saveposwindow):
|
||||
|
||||
def internal(self):
|
||||
offline, online = splitocrtypes(globalconfig["ocr"])
|
||||
|
||||
offgrids = initgridsources(self, offline)
|
||||
offgrids += [
|
||||
[(functools.partial(offlinelinks, "ocr"), 0)],
|
||||
]
|
||||
engines = [
|
||||
[
|
||||
(
|
||||
dict(
|
||||
title="离线",
|
||||
type="grid",
|
||||
grid=initgridsources(self, offline),
|
||||
grid=offgrids,
|
||||
),
|
||||
0,
|
||||
"group",
|
||||
|
@ -1,7 +1,7 @@
|
||||
from qtsymbols import *
|
||||
import functools, os
|
||||
import gobject, qtawesome, uuid, shutil
|
||||
from myutils.config import globalconfig, translatorsetting
|
||||
from myutils.config import globalconfig, translatorsetting, static_data
|
||||
from myutils.utils import (
|
||||
selectdebugfile,
|
||||
splittranslatortypes,
|
||||
@ -26,6 +26,7 @@ from gui.usefulwidget import (
|
||||
makescrollgrid,
|
||||
)
|
||||
from gui.dynalang import LPushButton, LLabel, LAction
|
||||
from gui.setting_about import offlinelinks
|
||||
|
||||
|
||||
def deepcopydict(d):
|
||||
@ -58,7 +59,7 @@ def splitapillm(l):
|
||||
def loadvisinternal(btnplus, copy):
|
||||
__vis = []
|
||||
__uid = []
|
||||
lixians, pre, mianfei, develop, shoufei = splittranslatortypes()
|
||||
lixians, pre, mianfei, shoufei = splittranslatortypes()
|
||||
if btnplus == "api":
|
||||
is_gpt_likes, not_is_gpt_like = splitapillm(shoufei)
|
||||
elif btnplus == "offline":
|
||||
@ -161,6 +162,8 @@ def loadbutton(self, fanyi):
|
||||
aclass = "translator." + fanyi
|
||||
elif which == 1:
|
||||
aclass = "userconfig.copyed." + fanyi
|
||||
else:
|
||||
return
|
||||
return autoinitdialogx(
|
||||
self,
|
||||
translatorsetting[fanyi]["args"],
|
||||
@ -222,18 +225,18 @@ def selectllmcallback(self, countnum, btnplus, fanyi, name):
|
||||
),
|
||||
)
|
||||
|
||||
if len(countnum) % 3 == 0:
|
||||
offset = 5 * (len(countnum) % 3)
|
||||
layout.addWidget(name, layout.rowCount() - 1, offset + 0)
|
||||
layout.addWidget(swc, layout.rowCount() - 1, offset + 1)
|
||||
layout.addWidget(color, layout.rowCount() - 1, offset + 2)
|
||||
layout.addWidget(last, layout.rowCount() - 1, offset + 3)
|
||||
if len(countnum) % 3 != 2:
|
||||
layout.addWidget(QLabel(), layout.rowCount() - 1, offset + 4)
|
||||
|
||||
else:
|
||||
layout.addWidget(
|
||||
getattr(self, "btnmany" + btnplus), layout.rowCount(), 5 * 2, 1, 4
|
||||
)
|
||||
offset = 5 * (len(countnum) % 3)
|
||||
layout.addWidget(name, layout.rowCount() - 2, offset + 0)
|
||||
layout.addWidget(swc, layout.rowCount() - 2, offset + 1)
|
||||
layout.addWidget(color, layout.rowCount() - 2, offset + 2)
|
||||
layout.addWidget(last, layout.rowCount() - 2, offset + 3)
|
||||
if len(countnum) % 3 != 2:
|
||||
layout.addWidget(QLabel(), layout.rowCount() - 2, offset + 4)
|
||||
|
||||
countnum.append(uid)
|
||||
|
||||
|
||||
@ -393,12 +396,12 @@ def initsome11(self, l, label=None, btnplus=False):
|
||||
if len(line):
|
||||
grids.append(line)
|
||||
if btnplus:
|
||||
grids.append(
|
||||
[
|
||||
("", 10),
|
||||
(functools.partial(createmanybtn, self, countnum, btnplus), 4),
|
||||
]
|
||||
)
|
||||
|
||||
if i % 3 == 0:
|
||||
grids.append([])
|
||||
if i % 3 != 2:
|
||||
grids[-1].append(("", 5 * (2 - i % 3)))
|
||||
grids[-1].append((functools.partial(createmanybtn, self, countnum, btnplus), 4))
|
||||
|
||||
return grids
|
||||
|
||||
@ -434,7 +437,6 @@ def initsome2(self, l, label=None, btnplus=None):
|
||||
return grids
|
||||
|
||||
|
||||
|
||||
def createbtnexport(self):
|
||||
|
||||
bt = LPushButton("导出翻译记录为json文件")
|
||||
@ -512,20 +514,11 @@ def setTabTwo_lazy(self, basel: QVBoxLayout):
|
||||
],
|
||||
[],
|
||||
]
|
||||
_items = [
|
||||
{
|
||||
"type": "file",
|
||||
"dir": False,
|
||||
"filter": "*.exe",
|
||||
"name": "Chromium_路径",
|
||||
"k": "chromepath",
|
||||
},
|
||||
{"type": "okcancel"},
|
||||
]
|
||||
|
||||
lixians, pre, mianfei, develop, shoufei = splittranslatortypes()
|
||||
lixians, pre, mianfei, shoufei = splittranslatortypes()
|
||||
|
||||
offlinegrid = initsome2(self, lixians, btnplus="offline")
|
||||
offlinegrid += [[functools.partial(offlinelinks, "translate")]]
|
||||
onlinegrid = initsome11(self, mianfei)
|
||||
online_reg_grid += initsome2(self, shoufei, btnplus="api")
|
||||
pretransgrid += initsome11(self, pre)
|
||||
|
@ -9,6 +9,7 @@ from gui.inputdialog import (
|
||||
autoinitdialog,
|
||||
yuyinzhidingsetting,
|
||||
)
|
||||
from gui.setting_about import offlinelinks
|
||||
from gui.setting_textinput import loadvalidtss
|
||||
from gui.usefulwidget import (
|
||||
D_getsimplecombobox,
|
||||
@ -131,6 +132,10 @@ def setTab5lz(self):
|
||||
grids = []
|
||||
offline, online = splitocrtypes(globalconfig["reader"])
|
||||
alltrans, alltransvis = loadvalidtss()
|
||||
offilesgrid = getttsgrid(self, offline)
|
||||
offilesgrid += [
|
||||
[(functools.partial(offlinelinks, "tts"), 0)],
|
||||
]
|
||||
grids += [
|
||||
[
|
||||
(
|
||||
@ -143,7 +148,7 @@ def setTab5lz(self):
|
||||
dict(
|
||||
title="离线",
|
||||
type="grid",
|
||||
grid=getttsgrid(self, offline),
|
||||
grid=offilesgrid,
|
||||
),
|
||||
0,
|
||||
"group",
|
||||
|
223
py/LunaTranslator/gui/setting_year.py
Normal file
223
py/LunaTranslator/gui/setting_year.py
Normal file
@ -0,0 +1,223 @@
|
||||
from qtsymbols import *
|
||||
import queue
|
||||
import gobject
|
||||
import os
|
||||
from gui.usefulwidget import WebivewWidget
|
||||
from datetime import datetime, timedelta
|
||||
from myutils.config import savehook_new_data, globalconfig
|
||||
|
||||
timestamps = [1609459200, 1672531200, 1704067200, 1720032000]
|
||||
|
||||
|
||||
def split_range_into_days(times):
|
||||
everyday = {}
|
||||
for start, end in times:
|
||||
if start == 0:
|
||||
everyday[0] = end
|
||||
continue
|
||||
|
||||
start_date = datetime.fromtimestamp(start)
|
||||
end_date = datetime.fromtimestamp(end)
|
||||
|
||||
current_date = start_date
|
||||
while current_date <= end_date:
|
||||
end_of_day = current_date.replace(
|
||||
hour=23, minute=59, second=59, microsecond=0
|
||||
)
|
||||
end_of_day = end_of_day.timestamp() + 1
|
||||
|
||||
if end_of_day >= end_date.timestamp():
|
||||
useend = end_date.timestamp()
|
||||
else:
|
||||
useend = end_of_day
|
||||
duration = useend - current_date.timestamp()
|
||||
today = end_of_day - 1
|
||||
if today not in everyday:
|
||||
everyday[today] = 0
|
||||
everyday[today] += duration
|
||||
current_date += timedelta(days=1)
|
||||
current_date = current_date.replace(
|
||||
hour=0, minute=0, second=0, microsecond=0
|
||||
)
|
||||
return everyday
|
||||
|
||||
|
||||
def calc_uid_times(inf):
|
||||
everytimes = {}
|
||||
for uid, ls in inf.items():
|
||||
x = 0
|
||||
for s, e in ls:
|
||||
x += e - s
|
||||
if int(x):
|
||||
everytimes[uid] = x
|
||||
|
||||
return everytimes
|
||||
|
||||
|
||||
def spliteverygameinmothon(yearinfos):
|
||||
allmonths = []
|
||||
for uid in yearinfos:
|
||||
everydays = split_range_into_days(yearinfos, uidx=uid)
|
||||
everymonth = group_by_month(everydays)
|
||||
|
||||
|
||||
def getthisyearinfo(allinfos):
|
||||
current_year = datetime.now().year
|
||||
yearinfos = {}
|
||||
for uid, ls in allinfos.items():
|
||||
yearinfos[uid] = []
|
||||
for s, e in ls:
|
||||
if datetime.fromtimestamp(s).year == current_year:
|
||||
yearinfos[uid].append((s, e))
|
||||
if len(yearinfos[uid]) == 0:
|
||||
yearinfos.pop(uid)
|
||||
return yearinfos
|
||||
|
||||
|
||||
def geteverygameeveryday(yearinfos):
|
||||
x = {}
|
||||
for uid, ls in yearinfos.items():
|
||||
x[uid] = split_range_into_days(ls)
|
||||
return x
|
||||
|
||||
|
||||
def group_by_month(timerangeindays):
|
||||
every = {}
|
||||
for uid, ls in timerangeindays.items():
|
||||
|
||||
inmonths = {}
|
||||
for day, time in ls.items():
|
||||
# 将时间戳转换为日期对象(时间戳为毫秒,需要除以1000)
|
||||
date = datetime.fromtimestamp(day)
|
||||
if date.month not in inmonths:
|
||||
inmonths[date.month] = 0
|
||||
inmonths[date.month] += time
|
||||
every[uid] = inmonths
|
||||
return every
|
||||
|
||||
|
||||
def have_game_days_count(everydays):
|
||||
days = set()
|
||||
for info in everydays.values():
|
||||
for d in info:
|
||||
days.add(d)
|
||||
return len(days)
|
||||
|
||||
|
||||
def everymonths_game_images(everymonth):
|
||||
months = {}
|
||||
for i in range(1, 13):
|
||||
months[i] = {}
|
||||
for uid in everymonth:
|
||||
for m, tm in everymonth[uid].items():
|
||||
months[m][uid] = tm
|
||||
return months
|
||||
|
||||
|
||||
def getuidimage(uid):
|
||||
data = savehook_new_data.get(uid)
|
||||
if not data:
|
||||
return
|
||||
main = savehook_new_data[uid].get("currentmainimage")
|
||||
if (main in savehook_new_data[uid]["imagepath_all"]) and os.path.exists(main):
|
||||
return os.path.abspath(main)
|
||||
else:
|
||||
for _ in savehook_new_data[uid]["imagepath_all"]:
|
||||
if os.path.exists(_):
|
||||
return os.path.abspath(_)
|
||||
|
||||
|
||||
def guji_word(everytimes, alleverytimes):
|
||||
cnt_zishu = 0
|
||||
for uid in everytimes:
|
||||
data = savehook_new_data.get(uid)
|
||||
if not data:
|
||||
continue
|
||||
if not everytimes[uid]:
|
||||
return
|
||||
cnt_zishu += (
|
||||
data.get("statistic_wordcount", 0) * everytimes[uid] / alleverytimes[uid]
|
||||
)
|
||||
return cnt_zishu
|
||||
|
||||
|
||||
def getimages(xx):
|
||||
uids = list(xx.keys())
|
||||
uids.sort(key=lambda x: -xx[x])
|
||||
tu = []
|
||||
for uid in uids:
|
||||
img = getuidimage(uid)
|
||||
if img:
|
||||
tu.append(img)
|
||||
return tu
|
||||
|
||||
|
||||
def getallgamelabels(yearinfos):
|
||||
developers = {}
|
||||
webtags = {}
|
||||
# 可以考虑玩的最多的游戏的标签,和玩的时间最长的标签
|
||||
for uid in yearinfos:
|
||||
data = savehook_new_data.get(uid)
|
||||
if not data:
|
||||
continue
|
||||
img = getuidimage(uid)
|
||||
if not img:
|
||||
continue
|
||||
for dev in data["developers"]:
|
||||
if dev not in developers:
|
||||
developers[dev] = []
|
||||
developers[dev].append(img)
|
||||
for tag in data["webtags"]:
|
||||
tag = globalconfig["tagNameRemap"].get(tag, tag)
|
||||
if tag not in webtags:
|
||||
webtags[tag] = []
|
||||
webtags[tag].append(img)
|
||||
return developers, webtags
|
||||
|
||||
|
||||
def yearsummary(self, basel: QHBoxLayout):
|
||||
allinfos = gobject.baseobject.playtimemanager.all() # {uid:[[s,e]]}
|
||||
yearinfos = getthisyearinfo(allinfos) # {uid:[[s,e]]}
|
||||
alleverytimes = calc_uid_times(allinfos) # {uid:time}
|
||||
everytimes = calc_uid_times(yearinfos) # {uid:time}
|
||||
everydays = geteverygameeveryday(yearinfos) # {uid:{day_tms:time}}
|
||||
everymonth = group_by_month(everydays) # {uid:{month:time}}
|
||||
everymonth_uid_time = everymonths_game_images(everymonth) # {month:{uid:time}}
|
||||
everymonth_time = {
|
||||
k: sum(v.values()) for k, v in everymonth_uid_time.items()
|
||||
} # {month:time}
|
||||
uids = list(everytimes.keys())
|
||||
uids.sort(key=lambda x: -everytimes[x])
|
||||
tu = getimages(everytimes)
|
||||
tu_m = {}
|
||||
for m, info in everymonth_uid_time.items():
|
||||
tu_m[m] = getimages(info)
|
||||
developer, webtags = getallgamelabels(yearinfos)
|
||||
_ = WebivewWidget(self)
|
||||
with open("files/yearsummary/yearsummary.value.js", "w", encoding="utf8") as ff2:
|
||||
ff2.write(
|
||||
r"""
|
||||
GAMES_YEAR_PLAYED={GAMES_YEAR_PLAYED}
|
||||
TIME_YEAR_PLAYED={TIME_YEAR_PLAYED}
|
||||
COUNT_ZISHU_YEAR_PLAYED={COUNT_ZISHU_YEAR_PLAYED}
|
||||
TIME_YEAR_PLAYED_DAY={TIME_YEAR_PLAYED_DAY}
|
||||
TOP25_TIME_IMAGE={TOP25_TIME_IMAGE}
|
||||
TOP25_TIME_IMAGE_M={TOP25_TIME_IMAGE_M}
|
||||
everymonth_time={everymonth_time}
|
||||
developer={developer}
|
||||
webtags={webtags}
|
||||
""".format(
|
||||
developer=developer,
|
||||
webtags=webtags,
|
||||
GAMES_YEAR_PLAYED=len(everytimes),
|
||||
TIME_YEAR_PLAYED=int(sum(everytimes.values()) / 3600),
|
||||
COUNT_ZISHU_YEAR_PLAYED=int(guji_word(everytimes, alleverytimes)),
|
||||
TIME_YEAR_PLAYED_DAY=have_game_days_count(everydays),
|
||||
TOP25_TIME_IMAGE=tu,
|
||||
TOP25_TIME_IMAGE_M=tu_m,
|
||||
everymonth_time=everymonth_time,
|
||||
)
|
||||
)
|
||||
|
||||
_.navigate(os.path.abspath("files/yearsummary/yearsummary.html"))
|
||||
basel.addWidget(_)
|
@ -153,165 +153,6 @@ class ScrollArea(QScrollArea):
|
||||
super().keyPressEvent(e)
|
||||
|
||||
|
||||
class ScrollFlow(QWidget):
|
||||
bgclicked = pyqtSignal()
|
||||
|
||||
def resizeEvent(self, a0) -> None:
|
||||
self.qscrollarea.resize(self.size())
|
||||
return super().resizeEvent(a0)
|
||||
|
||||
def __init__(self):
|
||||
super(ScrollFlow, self).__init__()
|
||||
|
||||
class qw(QWidget):
|
||||
def mousePressEvent(_, _2) -> None:
|
||||
self.bgclicked.emit()
|
||||
|
||||
self.listWidget = qw(self)
|
||||
# self.listWidget.setFixedWidth(600)
|
||||
self.lazyitems = []
|
||||
self.lazydoneidx = []
|
||||
self.l = FlowLayout()
|
||||
|
||||
self.listWidget.setLayout(self.l)
|
||||
|
||||
self.qscrollarea = QScrollArea(self)
|
||||
self.qscrollarea.setWidgetResizable(True)
|
||||
self.qscrollarea.setWidget(self.listWidget)
|
||||
|
||||
@trypass
|
||||
def addwidget(self, wid):
|
||||
self.l.addWidget(wid)
|
||||
|
||||
@trypass
|
||||
def insertwidget(self, idx, wid):
|
||||
self.l.insertWidget(idx, wid)
|
||||
|
||||
@trypass
|
||||
def removewidget(self, wid):
|
||||
self.l.removeWidget(wid)
|
||||
|
||||
@trypass
|
||||
def removeidx(self, index):
|
||||
_ = self.l.takeAt(index)
|
||||
_.widget().hide()
|
||||
|
||||
@trypass
|
||||
def setfocus(self, idx):
|
||||
self.widget(idx).setFocus()
|
||||
|
||||
@trypass
|
||||
def widget(self, idx):
|
||||
idx = min(idx, len(self.l._item_list) - 1)
|
||||
idx = max(idx, 0)
|
||||
return self.l._item_list[idx].widget()
|
||||
|
||||
|
||||
class FlowLayout(QLayout):
|
||||
heightChanged = pyqtSignal(int)
|
||||
|
||||
def __init__(self, parent=None, margin=0, spacing=-1):
|
||||
super().__init__(parent)
|
||||
if parent is not None:
|
||||
self.setContentsMargins(margin, margin, margin, margin)
|
||||
self.setSpacing(spacing)
|
||||
|
||||
self._item_list = []
|
||||
|
||||
def __del__(self):
|
||||
while self.count():
|
||||
self.takeAt(0)
|
||||
|
||||
def insertWidget(self, idx, widget):
|
||||
item = QWidgetItem(widget)
|
||||
widget.setParent(self.parentWidget())
|
||||
widget.adjustSize()
|
||||
widget.setVisible(True)
|
||||
self._item_list.insert(idx, item)
|
||||
|
||||
self._do_layout(self.geometry(), False)
|
||||
|
||||
def addItem(self, item): # pylint: disable=invalid-name
|
||||
self._item_list.append(item)
|
||||
|
||||
def addSpacing(self, size): # pylint: disable=invalid-name
|
||||
self.addItem(
|
||||
QSpacerItem(size, 0, QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Minimum)
|
||||
)
|
||||
|
||||
def count(self):
|
||||
return len(self._item_list)
|
||||
|
||||
def itemAt(self, index): # pylint: disable=invalid-name
|
||||
if 0 <= index < len(self._item_list):
|
||||
return self._item_list[index]
|
||||
return None
|
||||
|
||||
def takeAt(self, index): # pylint: disable=invalid-name
|
||||
if 0 <= index < len(self._item_list):
|
||||
return self._item_list.pop(index)
|
||||
return None
|
||||
|
||||
def setGeometry(self, rect): # pylint: disable=invalid-name
|
||||
super().setGeometry(rect)
|
||||
self._do_layout(rect, False)
|
||||
|
||||
def sizeHint(self): # pylint: disable=invalid-name
|
||||
return self.minimumSize()
|
||||
|
||||
def minimumSize(self): # pylint: disable=invalid-name
|
||||
size = QSize()
|
||||
|
||||
for item in self._item_list:
|
||||
minsize = item.minimumSize()
|
||||
extent = item.geometry().bottomRight()
|
||||
size = size.expandedTo(QSize(minsize.width(), extent.y()))
|
||||
|
||||
margin = self.contentsMargins().left()
|
||||
size += QSize(2 * margin, 2 * margin)
|
||||
return size
|
||||
|
||||
def _do_layout(self, rect, test_only=False):
|
||||
m = self.contentsMargins()
|
||||
effective_rect = rect.adjusted(+m.left(), +m.top(), -m.right(), -m.bottom())
|
||||
x = effective_rect.x()
|
||||
y = effective_rect.y()
|
||||
line_height = 0
|
||||
for item in self._item_list:
|
||||
wid = item.widget()
|
||||
|
||||
space_x = self.spacing()
|
||||
space_y = self.spacing()
|
||||
if wid is not None:
|
||||
space_x += wid.style().layoutSpacing(
|
||||
QSizePolicy.ControlType.PushButton,
|
||||
QSizePolicy.ControlType.PushButton,
|
||||
Qt.Orientation.Horizontal,
|
||||
)
|
||||
space_y += wid.style().layoutSpacing(
|
||||
QSizePolicy.ControlType.PushButton,
|
||||
QSizePolicy.ControlType.PushButton,
|
||||
Qt.Orientation.Vertical,
|
||||
)
|
||||
|
||||
next_x = x + item.sizeHint().width() + space_x
|
||||
if next_x - space_x > effective_rect.right() and line_height > 0:
|
||||
x = effective_rect.x()
|
||||
y = y + line_height + space_y
|
||||
next_x = x + item.sizeHint().width() + space_x
|
||||
line_height = 0
|
||||
|
||||
if not test_only:
|
||||
sz = item.sizeHint()
|
||||
item.setGeometry(QRect(QPoint(x, y), sz))
|
||||
x = next_x
|
||||
line_height = max(line_height, item.sizeHint().height())
|
||||
|
||||
new_height = y + line_height - rect.y()
|
||||
self.heightChanged.emit(new_height)
|
||||
return new_height
|
||||
|
||||
|
||||
class lazyscrollflow(ScrollArea):
|
||||
bgclicked = pyqtSignal()
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
from qtsymbols import *
|
||||
import os, platform, functools, uuid, json, math, csv, io, pickle
|
||||
import os, re, functools, uuid, json, math, csv, io, pickle
|
||||
from traceback import print_exc
|
||||
import windows, qtawesome, winsharedutils, gobject
|
||||
from webviewpy import webview_native_handle_kind_t, Webview
|
||||
from myutils.config import _TR, globalconfig, _TRL
|
||||
from myutils.config import _TR, globalconfig
|
||||
from myutils.wrapper import Singleton_close, tryprint
|
||||
from myutils.utils import nowisdark, checkportavailable, checkisusingwine
|
||||
from gui.dynalang import (
|
||||
@ -913,8 +913,19 @@ def comboboxcallbackwrap(s: SuperCombo, d, k, call, _):
|
||||
|
||||
|
||||
def getsimplecombobox(
|
||||
lst, d, k, callback=None, fixedsize=False, internal=None, static=False, emit=False
|
||||
lst,
|
||||
d=None,
|
||||
k=None,
|
||||
callback=None,
|
||||
fixedsize=False,
|
||||
internal=None,
|
||||
static=False,
|
||||
initial=None,
|
||||
):
|
||||
if d is None:
|
||||
d = {}
|
||||
if initial is not None:
|
||||
d[k] = initial
|
||||
s = SuperCombo(static=static)
|
||||
s.addItems(lst, internal)
|
||||
|
||||
@ -1772,8 +1783,14 @@ def makegroupingrid(args):
|
||||
if title:
|
||||
group.setTitle(title)
|
||||
else:
|
||||
_id = "luna" + str(uuid.uuid4())
|
||||
group.setObjectName(_id)
|
||||
group.setStyleSheet(
|
||||
"QGroupBox{ margin-top:0px;} QGroupBox:title {margin-top: 0px;}"
|
||||
"QGroupBox#"
|
||||
+ _id
|
||||
+ "{ margin-top:0px;} QGroupBox#"
|
||||
+ _id
|
||||
+ ":title {margin-top: 0px;}"
|
||||
)
|
||||
|
||||
if _type == "grid":
|
||||
@ -1858,16 +1875,18 @@ def automakegrid(grid: QGridLayout, lis, save=False, savelist=None):
|
||||
grid.setRowMinimumHeight(nowr, 25)
|
||||
|
||||
|
||||
def makegrid(grid=None, save=False, savelist=None, savelay=None, delay=False):
|
||||
def makegrid(grid=None, save=False, savelist=None, savelay=None, delay=False, w=True):
|
||||
|
||||
class gridwidget(QWidget):
|
||||
pass
|
||||
|
||||
gridlayoutwidget = gridwidget()
|
||||
if w:
|
||||
gridlayoutwidget = gridwidget()
|
||||
gridlay = QGridLayout()
|
||||
gridlay.setAlignment(Qt.AlignmentFlag.AlignTop)
|
||||
gridlayoutwidget.setLayout(gridlay)
|
||||
gridlayoutwidget.setStyleSheet("gridwidget{background-color:transparent;}")
|
||||
if w:
|
||||
gridlayoutwidget.setLayout(gridlay)
|
||||
gridlayoutwidget.setStyleSheet("gridwidget{background-color:transparent;}")
|
||||
|
||||
def do(gridlay, grid, save, savelist, savelay):
|
||||
automakegrid(gridlay, grid, save, savelist)
|
||||
@ -1875,6 +1894,8 @@ def makegrid(grid=None, save=False, savelist=None, savelay=None, delay=False):
|
||||
savelay.append(gridlay)
|
||||
|
||||
__do = functools.partial(do, gridlay, grid, save, savelist, savelay)
|
||||
if not w:
|
||||
gridlayoutwidget = gridlay
|
||||
if not delay:
|
||||
__do()
|
||||
return gridlayoutwidget
|
||||
@ -1899,14 +1920,17 @@ def makescrollgrid(grid, lay, save=False, savelist=None, savelay=None):
|
||||
|
||||
|
||||
def makesubtab_lazy(
|
||||
titles=None, functions=None, klass=None, callback=None, delay=False
|
||||
titles=None, functions=None, klass=None, callback=None, delay=False, initial=None
|
||||
):
|
||||
if klass:
|
||||
tab = klass()
|
||||
tab: LTabWidget = klass()
|
||||
else:
|
||||
tab = LTabWidget()
|
||||
|
||||
def __(t, i):
|
||||
def __(t: LTabWidget, initial, i):
|
||||
if initial:
|
||||
object, key = initial
|
||||
object[key] = i
|
||||
try:
|
||||
w = t.currentWidget()
|
||||
if "lazyfunction" in dir(w):
|
||||
@ -1917,14 +1941,20 @@ def makesubtab_lazy(
|
||||
if callback:
|
||||
callback(i)
|
||||
|
||||
tab.currentChanged.connect(functools.partial(__, tab))
|
||||
can = initial and (initial[1] in initial[0])
|
||||
if not can:
|
||||
tab.currentChanged.connect(functools.partial(__, tab, initial))
|
||||
|
||||
def __do(tab, titles, functions):
|
||||
def __do(tab: LTabWidget, titles, functions, initial):
|
||||
if titles and functions:
|
||||
for i, func in enumerate(functions):
|
||||
tabadd_lazy(tab, titles[i], func)
|
||||
if can:
|
||||
tab.setCurrentIndex(initial[0][initial[1]])
|
||||
tab.currentChanged.connect(functools.partial(__, tab, initial))
|
||||
tab.currentChanged.emit(initial[0][initial[1]])
|
||||
|
||||
___do = functools.partial(__do, tab, titles, functions)
|
||||
___do = functools.partial(__do, tab, titles, functions, initial)
|
||||
if not delay:
|
||||
___do()
|
||||
return tab
|
||||
@ -2561,3 +2591,152 @@ class VisLFormLayout(LFormLayout):
|
||||
label.widget().deleteLater()
|
||||
tres.fieldItem.widget().hide()
|
||||
self._row_vis[row_index] = visible
|
||||
|
||||
|
||||
class CollapsibleBox(QWidget):
|
||||
def setdelayload(self, func):
|
||||
self.func = func
|
||||
|
||||
def __init__(self, title="", parent=None):
|
||||
super(CollapsibleBox, self).__init__(parent)
|
||||
|
||||
self.toggle_button = QToolButton(text=title, checkable=True, checked=False)
|
||||
self.toggle_button.setToolButtonStyle(
|
||||
Qt.ToolButtonStyle.ToolButtonTextBesideIcon
|
||||
)
|
||||
self.toggle_button.toggled.connect(self.on_toggled)
|
||||
self.content_area = QWidget()
|
||||
lay = QVBoxLayout(self)
|
||||
lay.setSpacing(0)
|
||||
lay.setContentsMargins(0, 0, 0, 0)
|
||||
lay.addWidget(self.toggle_button)
|
||||
lay.addWidget(self.content_area)
|
||||
self.func = None
|
||||
self.collapse()
|
||||
|
||||
def on_toggled(self, checked):
|
||||
if checked:
|
||||
if self.func:
|
||||
self.func(self)
|
||||
self.func = None
|
||||
self.toggle_button.setIcon(qtawesome.icon("fa.chevron-down"))
|
||||
self.content_area.setVisible(True)
|
||||
else:
|
||||
self.toggle_button.setIcon(qtawesome.icon("fa.chevron-right"))
|
||||
self.content_area.setVisible(False)
|
||||
|
||||
def expand(self):
|
||||
self.toggle_button.setChecked(True)
|
||||
self.on_toggled(True)
|
||||
|
||||
def collapse(self):
|
||||
self.toggle_button.setChecked(False)
|
||||
self.on_toggled(False)
|
||||
|
||||
|
||||
class editswitchTextBrowser(QWidget):
|
||||
textChanged = pyqtSignal(str)
|
||||
|
||||
def heightForWidth(self, w):
|
||||
return self.browser.heightForWidth(w)
|
||||
|
||||
def resizeEvent(self, a0):
|
||||
self.switch.move(self.width() - self.switch.width(), 0)
|
||||
return super().resizeEvent(a0)
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
stack = QStackedWidget()
|
||||
self.edit = QPlainTextEdit()
|
||||
self.browser = QLabel()
|
||||
self.browser.setAlignment(Qt.AlignmentFlag.AlignTop)
|
||||
self.browser.setWordWrap(True)
|
||||
self.browser.setTextInteractionFlags(
|
||||
Qt.TextInteractionFlag.TextSelectableByMouse
|
||||
)
|
||||
self.edit.textChanged.connect(
|
||||
lambda: (
|
||||
self.browser.setText(
|
||||
"<html>"
|
||||
+ re.sub(
|
||||
r'href="([^"]+)"',
|
||||
"",
|
||||
re.sub(r'src="([^"]+)"', "", self.edit.toPlainText()),
|
||||
)
|
||||
+ "</html>"
|
||||
),
|
||||
self.textChanged.emit(self.edit.toPlainText()),
|
||||
)
|
||||
)
|
||||
stack.addWidget(self.browser)
|
||||
stack.addWidget(self.edit)
|
||||
l = QHBoxLayout()
|
||||
self.setLayout(l)
|
||||
l.setContentsMargins(0, 0, 0, 0)
|
||||
l.addWidget(stack)
|
||||
self.switch = MySwitch(self, icon="fa.edit")
|
||||
self.switch.setFixedSize(QSize(25, 25))
|
||||
self.switch.raise_()
|
||||
self.switch.clicked.connect(lambda c: stack.setCurrentIndex(not c))
|
||||
|
||||
def settext(self, text):
|
||||
self.edit.setPlainText(text)
|
||||
|
||||
def text(self):
|
||||
return self.edit.toPlainText()
|
||||
|
||||
|
||||
class FlowWidget(QWidget):
|
||||
def __init__(self, parent=None, groups=3):
|
||||
super().__init__(parent)
|
||||
self.margin = QMargins(5, 5, 5, 5)
|
||||
self.spacing = 5
|
||||
self._item_list = [[] for _ in range(groups)]
|
||||
|
||||
def insertWidget(self, group, index, w: QWidget):
|
||||
w.setParent(self)
|
||||
w.show()
|
||||
self._item_list[group].insert(index, w)
|
||||
self.doresize()
|
||||
|
||||
def addWidget(self, group, w: QWidget):
|
||||
self.insertWidget(group, len(self._item_list[group]), w)
|
||||
|
||||
def removeWidget(self, w: QWidget):
|
||||
for _ in self._item_list:
|
||||
if w in _:
|
||||
_.remove(w)
|
||||
w.deleteLater()
|
||||
self.doresize()
|
||||
break
|
||||
|
||||
def doresize(self):
|
||||
line_height = 0
|
||||
spacing = self.spacing
|
||||
y = self.margin.left()
|
||||
for listi in self._item_list:
|
||||
x = self.margin.top()
|
||||
for i, item in enumerate(listi):
|
||||
|
||||
next_x = x + item.sizeHint().width() + spacing
|
||||
if (
|
||||
next_x - spacing + self.margin.right() > self.width()
|
||||
and line_height > 0
|
||||
):
|
||||
x = self.margin.top()
|
||||
y = y + line_height + spacing
|
||||
next_x = x + item.sizeHint().width() + spacing
|
||||
|
||||
size = item.sizeHint()
|
||||
if (i == len(listi) - 1) and isinstance(item, editswitchTextBrowser):
|
||||
w = self.width() - self.margin.right() - x
|
||||
size = QSize(w, max(size.height(), item.heightForWidth(w)))
|
||||
|
||||
item.setGeometry(QRect(QPoint(x, y), size))
|
||||
line_height = max(line_height, size.height())
|
||||
x = next_x
|
||||
y = y + line_height + spacing
|
||||
self.setFixedHeight(y + self.margin.bottom() - spacing)
|
||||
|
||||
def resizeEvent(self, a0):
|
||||
self.doresize()
|
||||
|
@ -157,6 +157,7 @@ class common:
|
||||
developers = data.get("developers", [])
|
||||
webtags = data.get("webtags", [])
|
||||
imagepath_all = data.get("imagepath_all", [])
|
||||
description=data.get('description',None)
|
||||
normaled = [
|
||||
os.path.abspath(_) for _ in savehook_new_data[gameuid]["imagepath_all"]
|
||||
]
|
||||
@ -175,6 +176,8 @@ class common:
|
||||
_urls = [_[1] for _ in savehook_new_data[gameuid]["relationlinks"]]
|
||||
if _url not in _urls:
|
||||
savehook_new_data[gameuid]["relationlinks"].append((_vis, _url))
|
||||
if description and not savehook_new_data[gameuid].get('description'):
|
||||
savehook_new_data[gameuid]['description']=description
|
||||
if namemap:
|
||||
dedump = set()
|
||||
for _ in savehook_new_data[gameuid]["namemap2"]:
|
||||
|
@ -346,7 +346,6 @@ class searcher(common):
|
||||
response = self.proxysession.get(
|
||||
"https://api.bgm.tv/v0/subjects/{}".format(sid), headers=headers
|
||||
)
|
||||
print(response.text)
|
||||
try:
|
||||
response = response.json()
|
||||
except:
|
||||
@ -384,4 +383,5 @@ class searcher(common):
|
||||
"imagepath_all": [imagepath],
|
||||
"webtags": vndbtags,
|
||||
"developers": developers,
|
||||
"description": response["summary"].replace("\n", "<br>"),
|
||||
}
|
||||
|
@ -113,10 +113,14 @@ class searcher(common):
|
||||
"https:" + _[0] for _ in re.findall('<div data-src="(.*?)"(.*?)>', inner)
|
||||
]
|
||||
print(imags1)
|
||||
|
||||
description = simplehtmlparser(
|
||||
response.text, "div", '<div itemprop="description"'
|
||||
)
|
||||
print(description)
|
||||
return {
|
||||
"title": title,
|
||||
"imagepath_all": [self.dispatchdownloadtask(_) for _ in imags1 + imags2],
|
||||
"webtags": tags,
|
||||
"developers": [devp],
|
||||
"description": description,
|
||||
}
|
||||
|
@ -170,6 +170,9 @@ class searcher(common):
|
||||
|
||||
inner = simplehtmlparser(response.text, "div", '<div ref="product_slider_data"')
|
||||
|
||||
description = simplehtmlparser(
|
||||
response.text, "div", '<div class="area-detail-read">'
|
||||
)
|
||||
return {
|
||||
"title": title,
|
||||
"imagepath_all": [
|
||||
@ -177,4 +180,5 @@ class searcher(common):
|
||||
],
|
||||
"webtags": tags,
|
||||
"developers": [devp],
|
||||
'description':description
|
||||
}
|
||||
|
@ -172,7 +172,6 @@ class searcher(common):
|
||||
"https://store.steampowered.com/api/appdetails?appids={}".format(_id),
|
||||
proxies=self.proxy,
|
||||
).json()[str(_id)]["data"]
|
||||
|
||||
devs = data.get("developers", []) + data.get("publishers", [])
|
||||
tagsofficial = [
|
||||
_["description"] for _ in data.get("genres", [])
|
||||
@ -191,4 +190,5 @@ class searcher(common):
|
||||
],
|
||||
"webtags": tagsofficial,
|
||||
"developers": devs,
|
||||
"description":data['detailed_description']
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ def getinfosbyvid(proxy, vid):
|
||||
"vn",
|
||||
{
|
||||
"filters": ["id", "=", vid],
|
||||
"fields": "tags.rating,tags.name,title,titles.title,titles.main,screenshots.url,image.url,developers.name,developers.original",
|
||||
"fields": "tags.rating,tags.name,title,titles.title,titles.main,screenshots.url,image.url,developers.name,developers.original,description",
|
||||
},
|
||||
)
|
||||
if js:
|
||||
@ -152,6 +152,7 @@ def getinfosbyvid(proxy, vid):
|
||||
sc=imgs,
|
||||
dev=dev,
|
||||
tags=sorted(tags, key=lambda x: -rates[tags.index(x)]),
|
||||
description=js["results"][0]['description']
|
||||
)
|
||||
|
||||
|
||||
@ -379,4 +380,5 @@ class searcher(common):
|
||||
"imagepath_all": img + sc,
|
||||
"webtags": infos["tags"],
|
||||
"developers": infos["dev"],
|
||||
"description":infos['description']
|
||||
}
|
||||
|
@ -200,6 +200,7 @@ def getdefaultsavehook(title=None):
|
||||
"imagepath_all": [],
|
||||
"developers": [],
|
||||
"webtags": [], # 标签
|
||||
# "description": "", # 简介
|
||||
# "infopath": None, # 离线存储的主页
|
||||
}
|
||||
if title and len(title):
|
||||
|
@ -1,6 +1,6 @@
|
||||
import windows, os, winsharedutils, re, functools
|
||||
from qtsymbols import *
|
||||
from myutils.config import savehook_new_data, get_launchpath, globalconfig, get_platform
|
||||
from myutils.config import savehook_new_data, get_launchpath, globalconfig, get_platform, _TR
|
||||
from gui.usefulwidget import getlineedit, getsimplecombobox, getsimplepatheditor
|
||||
from traceback import print_exc
|
||||
import xml.etree.ElementTree as ET
|
||||
@ -50,9 +50,11 @@ class le_internal(LEbase):
|
||||
LCID=0x11, CodePage=932, RedirectRegistry=False, HookUILanguageAPI=False
|
||||
)
|
||||
|
||||
def getlrpath(self):
|
||||
def getlrpath(self, show=False):
|
||||
LEProc = globalconfig.get("le_extra_path", "")
|
||||
if not (LEProc and os.path.exists(LEProc)):
|
||||
if show:
|
||||
return _TR("内置")
|
||||
LEProc = os.path.abspath("files/plugins/Locale/Locale.Emulator/LEProc.exe")
|
||||
return LEProc
|
||||
|
||||
@ -129,14 +131,12 @@ class le_internal(LEbase):
|
||||
layout.addRow(
|
||||
"路径",
|
||||
getsimplepatheditor(
|
||||
self.getlrpath(),
|
||||
self.getlrpath(show=True),
|
||||
False,
|
||||
False,
|
||||
filter1="LEProc.exe",
|
||||
callback=functools.partial(self.reselect, config, Guids),
|
||||
clearset=lambda: os.path.abspath(
|
||||
"files/plugins/Locale/Locale.Emulator/LEProc.exe"
|
||||
),
|
||||
clearset=lambda: _TR("内置"),
|
||||
icons=("fa.gear", "fa.refresh"),
|
||||
),
|
||||
)
|
||||
@ -167,9 +167,11 @@ class NTLEAS64(LEbase):
|
||||
continue
|
||||
config[k] = v
|
||||
|
||||
def getlrpath(self):
|
||||
def getlrpath(self, show=False):
|
||||
LEProc = globalconfig.get("ntleas_extra_path", "")
|
||||
if not (LEProc and os.path.exists(LEProc)):
|
||||
if show:
|
||||
return _TR("内置")
|
||||
LEProc = os.path.abspath("files/plugins/Locale/ntleas046_x64/Placeholder")
|
||||
return LEProc
|
||||
|
||||
@ -204,14 +206,12 @@ class NTLEAS64(LEbase):
|
||||
layout.addRow(
|
||||
"路径",
|
||||
getsimplepatheditor(
|
||||
self.getlrpath(),
|
||||
self.getlrpath(show=True),
|
||||
False,
|
||||
False,
|
||||
filter1="ntleasWin.exe",
|
||||
callback=self.reselect,
|
||||
clearset=lambda: os.path.abspath(
|
||||
"files/plugins/Locale/ntleas046_x64/Placeholder"
|
||||
),
|
||||
clearset=lambda: _TR("内置"),
|
||||
icons=("fa.gear", "fa.refresh"),
|
||||
),
|
||||
)
|
||||
@ -265,9 +265,11 @@ class lr_internal(LEbase):
|
||||
print_exc()
|
||||
return Names, Guids, run_as_admins
|
||||
|
||||
def getlrpath(self):
|
||||
def getlrpath(self, show=False):
|
||||
LEProc = globalconfig.get("lr_extra_path", "")
|
||||
if not (LEProc and os.path.exists(LEProc)):
|
||||
if show:
|
||||
return _TR("内置")
|
||||
LEProc = os.path.abspath("files/plugins/Locale/Locale_Remulator/LRProc.exe")
|
||||
return LEProc
|
||||
|
||||
@ -303,14 +305,12 @@ class lr_internal(LEbase):
|
||||
layout.addRow(
|
||||
"路径",
|
||||
getsimplepatheditor(
|
||||
self.getlrpath(),
|
||||
self.getlrpath(show=True),
|
||||
False,
|
||||
False,
|
||||
filter1="LRProc.exe",
|
||||
callback=functools.partial(self.reselect, config, Guids),
|
||||
clearset=lambda: os.path.abspath(
|
||||
"files/plugins/Locale/Locale_Remulator/LRProc.exe"
|
||||
),
|
||||
clearset=lambda: _TR("内置"),
|
||||
icons=("fa.gear", "fa.refresh"),
|
||||
),
|
||||
)
|
||||
|
@ -10,6 +10,17 @@ import gobject
|
||||
|
||||
|
||||
class playtimemanager:
|
||||
def all(self):
|
||||
res = self.sqlsavegameinfo.execute(
|
||||
"SELECT gameinternalid_v2.gameuid, trace_strict.timestart, trace_strict.timestop FROM gameinternalid_v2 JOIN trace_strict ON gameinternalid_v2.gameinternalid = trace_strict.gameinternalid "
|
||||
).fetchall()
|
||||
mp = {}
|
||||
for uid, s, e in res:
|
||||
if uid not in mp:
|
||||
mp[uid] = []
|
||||
mp[uid].append((s, e))
|
||||
return mp
|
||||
|
||||
def __init__(self):
|
||||
|
||||
self.sqlsavegameinfo = sqlite3.connect(
|
||||
@ -111,7 +122,9 @@ class playtimemanager:
|
||||
gameinternalid = self.get_gameinternalid(uid)
|
||||
if uid in dic:
|
||||
self.sqlsavegameinfo.execute(
|
||||
"UPDATE {} SET timestop = ? WHERE (gameinternalid = ? and timestart = ?)".format(table),
|
||||
"UPDATE {} SET timestop = ? WHERE (gameinternalid = ? and timestart = ?)".format(
|
||||
table
|
||||
),
|
||||
(_t, gameinternalid, dic[uid]),
|
||||
)
|
||||
|
||||
|
@ -356,7 +356,7 @@ def checkportavailable(port):
|
||||
|
||||
|
||||
def splittranslatortypes():
|
||||
pre, offline, free, dev, api = [], [], [], [], []
|
||||
pre, offline, free, api = [], [], [], []
|
||||
for k in globalconfig["fanyi"]:
|
||||
try:
|
||||
{"pre": pre, "offline": offline, "free": free, "api": api}[
|
||||
@ -365,7 +365,7 @@ def splittranslatortypes():
|
||||
except:
|
||||
pass
|
||||
|
||||
return offline, pre, free, dev, api
|
||||
return offline, pre, free, api
|
||||
|
||||
|
||||
def splitocrtypes(dic):
|
||||
|
@ -13,8 +13,9 @@ class OCR(baseocr):
|
||||
headers = {
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
|
||||
}
|
||||
cookies = {"SOCS": "CAESEwgDEgk0ODE3Nzk3MjQaAmVuIAEaBgiA_LyaBg"}
|
||||
files = {"encoded_image": ("screenshot.png", imagebinary, "image/png")}
|
||||
res = self.proxysession.post(url, files=files, headers=headers)
|
||||
res = self.proxysession.post(url, files=files, headers=headers, cookies=cookies)
|
||||
match = regex.search(res.text)
|
||||
if not match:
|
||||
return
|
||||
|
@ -114,6 +114,8 @@ def getallsupports():
|
||||
|
||||
|
||||
def dodownload(combo: QComboBox, allsupports: list):
|
||||
if not allsupports:
|
||||
return
|
||||
lang = allsupports[combo.currentIndex()]
|
||||
gobject.baseobject.openlink(
|
||||
dynamiclink("{main_server}/Resource/ocr_models/" + lang + ".zip")
|
||||
@ -121,6 +123,8 @@ def dodownload(combo: QComboBox, allsupports: list):
|
||||
|
||||
|
||||
def doinstall(self, combo: QComboBox, allsupports: list, parent, callback):
|
||||
if not allsupports:
|
||||
return
|
||||
lang = allsupports[combo.currentIndex()]
|
||||
f = QFileDialog.getOpenFileName(parent, filter=lang + ".zip")
|
||||
fn = f[0]
|
||||
@ -135,8 +139,10 @@ def doinstall(self, combo: QComboBox, allsupports: list, parent, callback):
|
||||
print_exc()
|
||||
|
||||
|
||||
def question(dialog: QDialog):
|
||||
def question():
|
||||
dialog = QWidget()
|
||||
formLayout = LFormLayout()
|
||||
formLayout.setContentsMargins(0, 0, 0, 0)
|
||||
dialog.setLayout(formLayout)
|
||||
supportlang = LLabel()
|
||||
formLayout.addRow("当前支持的语言", supportlang)
|
||||
@ -166,6 +172,7 @@ def question(dialog: QDialog):
|
||||
"添加语言包",
|
||||
getboxlayout([combo, btndownload, btninstall], makewidget=True),
|
||||
)
|
||||
return dialog
|
||||
|
||||
|
||||
class OCR(baseocr):
|
||||
|
@ -4,8 +4,7 @@ from myutils.config import _TR, static_data, getlang_inner2show
|
||||
from myutils.utils import dynamiclink
|
||||
from ocrengines.baseocrclass import baseocr
|
||||
from qtsymbols import *
|
||||
from gui.usefulwidget import getboxlayout
|
||||
from gui.dynalang import LPushButton, LFormLayout, LLabel
|
||||
from gui.dynalang import LPushButton, LLabel
|
||||
from myutils.utils import getlanguagespace
|
||||
|
||||
|
||||
@ -31,8 +30,10 @@ def initsupports():
|
||||
return supportmap
|
||||
|
||||
|
||||
def question(dialog: QDialog):
|
||||
formLayout = LFormLayout()
|
||||
def question():
|
||||
dialog = QWidget()
|
||||
formLayout = QHBoxLayout()
|
||||
formLayout.setContentsMargins(0, 0, 0, 0)
|
||||
dialog.setLayout(formLayout)
|
||||
_allsupport = initsupports()
|
||||
supportlang = LLabel()
|
||||
@ -43,9 +44,10 @@ def question(dialog: QDialog):
|
||||
dynamiclink("{docs_server}/#/zh/windowsocr")
|
||||
)
|
||||
)
|
||||
formLayout.addRow(
|
||||
"当前支持的语言", getboxlayout([supportlang, btndownload], makewidget=True)
|
||||
)
|
||||
formLayout.addWidget(LLabel("当前支持的语言"))
|
||||
formLayout.addWidget(supportlang)
|
||||
formLayout.addWidget(btndownload)
|
||||
return dialog
|
||||
|
||||
|
||||
class OCR(baseocr):
|
||||
@ -85,7 +87,9 @@ class OCR(baseocr):
|
||||
)
|
||||
else:
|
||||
uselang = self.srclang
|
||||
ret = winrtutils.OCR_f(imagebinary, self.supportmap[uselang], getlanguagespace(uselang))
|
||||
ret = winrtutils.OCR_f(
|
||||
imagebinary, self.supportmap[uselang], getlanguagespace(uselang)
|
||||
)
|
||||
boxs = [_[1:] for _ in ret]
|
||||
texts = [_[0] for _ in ret]
|
||||
return {"box": boxs, "text": texts}
|
||||
|
@ -1,8 +1,8 @@
|
||||
try:
|
||||
from PyQt5 import QtSvg
|
||||
from PyQt5.QtWidgets import QFrame,QListView,QCheckBox,QAbstractItemView,QTextEdit,QTableView,QHeaderView,QColorDialog,QSpinBox,QDoubleSpinBox,QComboBox,QDialogButtonBox,QMainWindow,QMessageBox,QDialog,QGridLayout,QTextBrowser,QGraphicsDropShadowEffect,QWidget,QSizePolicy,QScrollArea,QApplication,QPushButton,QSystemTrayIcon,QPlainTextEdit,QAction,QMenu,QFileDialog,QKeySequenceEdit,QLabel,QSpacerItem,QWidgetItem,QLayout,QTextBrowser,QLineEdit,QFormLayout,QSizePolicy,QTabWidget,QTabBar,QSplitter,QListWidget,QListWidgetItem,QHBoxLayout,QVBoxLayout,QSizeGrip,QFontComboBox,QProgressBar,QRadioButton,QButtonGroup,QSlider,QToolTip,QGroupBox,QGraphicsOpacityEffect,QStackedWidget,QStyledItemDelegate,QStyleOptionViewItem,QFontDialog,QTreeView
|
||||
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
|
||||
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
|
||||
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
|
||||
class LineHeightTypes:
|
||||
LineDistanceHeight=QTextBlockFormat.LineHeightTypes.LineDistanceHeight
|
||||
@ -11,9 +11,9 @@ except:
|
||||
#from traceback import print_exc
|
||||
#print_exc()
|
||||
from PyQt6 import QtSvg
|
||||
from PyQt6.QtWidgets import QFrame,QListView,QCheckBox,QAbstractItemView,QTextEdit,QTableView,QHeaderView,QColorDialog,QSpinBox,QDoubleSpinBox,QComboBox,QDialogButtonBox,QMainWindow,QMessageBox,QDialog,QGridLayout,QTextBrowser,QGraphicsDropShadowEffect,QWidget,QSizePolicy,QScrollArea,QApplication,QPushButton,QSystemTrayIcon,QPlainTextEdit,QMenu,QFileDialog,QKeySequenceEdit,QLabel,QSpacerItem,QWidgetItem,QLayout,QTextBrowser,QLineEdit,QFormLayout,QSizePolicy,QTabWidget,QTabBar,QSplitter,QListWidget,QListWidgetItem,QHBoxLayout,QVBoxLayout,QSizeGrip,QFontComboBox,QProgressBar,QRadioButton,QButtonGroup,QSlider,QToolTip,QGroupBox,QGraphicsOpacityEffect,QStackedWidget,QTreeView
|
||||
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
|
||||
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
|
||||
from PyQt6.QtCore import QObject,pyqtSignal,Qt,QSize,QByteArray,QBuffer,QPointF,QPoint,QRect,QEvent,QModelIndex,QTimer,QRectF,QVariantAnimation,QUrl,QPropertyAnimation,QLocale,QMargins
|
||||
isqt5 = False
|
||||
|
||||
class LineHeightTypes:
|
||||
|
@ -1,6 +1,6 @@
|
||||
from textsource.textsourcebase import basetext
|
||||
from myutils.wrapper import threader
|
||||
import json, time, os, gobject, re
|
||||
import json, time, os, gobject, winsharedutils
|
||||
from myutils.config import globalconfig
|
||||
|
||||
|
||||
@ -29,8 +29,9 @@ class parsejson:
|
||||
|
||||
def load(self):
|
||||
for i, k in enumerate(self.data):
|
||||
if self.data[k]:
|
||||
yield i, None
|
||||
if not isinstance(self.data[k], str):
|
||||
continue
|
||||
if winsharedutils.distance_ratio(self.data[k], k) < 0.2:
|
||||
continue
|
||||
yield i, k
|
||||
|
||||
|
@ -43,7 +43,7 @@ class TS(basetrans):
|
||||
)
|
||||
return True
|
||||
|
||||
def x64(self, content):
|
||||
def translate(self, content):
|
||||
self.checkpath()
|
||||
|
||||
l = content.encode("utf-16-le")
|
||||
@ -53,6 +53,3 @@ class TS(basetrans):
|
||||
if not size:
|
||||
raise Exception("not installed")
|
||||
return windows.ReadFile(self.hPipe, size).decode("utf-16-le")
|
||||
|
||||
def translate(self, content):
|
||||
return self.x64(content)
|
||||
|
@ -62,7 +62,7 @@ class TS(basetrans):
|
||||
)
|
||||
return True
|
||||
|
||||
def x64(self, content):
|
||||
def translate(self, content):
|
||||
|
||||
if self.checkpath() == False:
|
||||
raise Exception(_TR("翻译器加载失败"))
|
||||
@ -74,6 +74,3 @@ class TS(basetrans):
|
||||
windows.WriteFile(self.hPipe, line.encode(codes[self.srclang]))
|
||||
ress.append(windows.ReadFile(self.hPipe, 4096).decode(codes[self.tgtlang]))
|
||||
return "\n".join(ress)
|
||||
|
||||
def translate(self, content):
|
||||
return self.x64(content)
|
||||
|
@ -1,7 +1,7 @@
|
||||
from translator.basetranslator import basetrans
|
||||
from myutils.config import _TR
|
||||
import os, time
|
||||
import windows
|
||||
import windows, ctypes
|
||||
from myutils.subproc import subproc_w, autoproc
|
||||
|
||||
|
||||
@ -54,7 +54,7 @@ class TS(basetrans):
|
||||
)
|
||||
return True
|
||||
|
||||
def x64(self, content: str):
|
||||
def translate(self, content):
|
||||
|
||||
if self.checkpath() == False:
|
||||
raise Exception(_TR("翻译器加载失败"))
|
||||
@ -62,14 +62,7 @@ class TS(basetrans):
|
||||
|
||||
code1 = content.encode("utf-16-le")
|
||||
windows.WriteFile(self.hPipe, code1)
|
||||
xx = windows.ReadFile(self.hPipe, 65535)
|
||||
xx = xx.decode("utf-16-le", errors="ignore")
|
||||
|
||||
return xx
|
||||
|
||||
def translate(self, content):
|
||||
|
||||
return self.x64(content)
|
||||
|
||||
def langmap(self):
|
||||
return {"zh": "936", "cht": "950"}
|
||||
size = ctypes.c_int.from_buffer_copy(windows.ReadFile(self.hPipe, 4)).value
|
||||
if not size:
|
||||
raise Exception("not installed")
|
||||
return windows.ReadFile(self.hPipe, size).decode("utf-16-le")
|
||||
|
@ -67,7 +67,7 @@ class TS(basetrans):
|
||||
)
|
||||
return True
|
||||
|
||||
def x64(self, content: str):
|
||||
def translate(self, content):
|
||||
if self.tgtlang not in ["936", "950"]:
|
||||
return ""
|
||||
if self.checkpath() == False:
|
||||
@ -86,42 +86,5 @@ class TS(basetrans):
|
||||
ress.append(xx)
|
||||
return "\n".join(ress)
|
||||
|
||||
def x86(self, content):
|
||||
CODEPAGE_JA = 932
|
||||
CODEPAGE_GB = 936
|
||||
CODEPAGE_BIG5 = 950
|
||||
BUFFER_SIZE = 3000
|
||||
# if globalconfig['fanjian'] in [0,1,4]:
|
||||
# code=CODEPAGE_GB
|
||||
# else:
|
||||
# code=CODEPAGE_BIG5
|
||||
code = CODEPAGE_GB
|
||||
|
||||
size = BUFFER_SIZE
|
||||
out = ctypes.create_unicode_buffer(size)
|
||||
buf = ctypes.create_unicode_buffer(size)
|
||||
outsz = ctypes.c_int(size)
|
||||
bufsz = ctypes.c_int(size)
|
||||
try:
|
||||
self.dll.JC_Transfer_Unicode(
|
||||
0, # int, unknown
|
||||
CODEPAGE_JA, # uint from, supposed to be 0x3a4 (cp932)
|
||||
code, # uint to, eighter cp950 or cp932
|
||||
1, # int, unknown
|
||||
1, # int, unknown
|
||||
content, # python 默认unicode 所有不用u'
|
||||
out, # wchar_t*
|
||||
ctypes.byref(outsz), # ∫
|
||||
buf, # wchar_t*
|
||||
ctypes.byref(bufsz),
|
||||
) # ∫
|
||||
except:
|
||||
pass
|
||||
return out.value
|
||||
|
||||
def translate(self, content):
|
||||
|
||||
return self.x64(content)
|
||||
|
||||
def langmap(self):
|
||||
return {"zh": "936", "cht": "950"}
|
||||
|
@ -64,7 +64,7 @@ class TS(basetrans):
|
||||
)
|
||||
return True
|
||||
|
||||
def x64(self, content):
|
||||
def translate(self, content):
|
||||
if self.checkpath() == False:
|
||||
raise Exception(_TR("翻译器加载失败"))
|
||||
ress = []
|
||||
@ -77,8 +77,5 @@ class TS(basetrans):
|
||||
|
||||
return "\n".join(ress)
|
||||
|
||||
def translate(self, content):
|
||||
return self.x64(content)
|
||||
|
||||
def langmap(self):
|
||||
return {"zh": "SChinese", "cht": "TChinese", "en": "English", "ja": "Japanese", "auto": "Japanese"}
|
||||
|
@ -49,7 +49,7 @@ class TS(basetrans):
|
||||
)
|
||||
)
|
||||
|
||||
def x64(self, content: str):
|
||||
def translate(self, content):
|
||||
|
||||
self.checkpath()
|
||||
l = content.encode("utf-16-le")
|
||||
@ -59,6 +59,3 @@ class TS(basetrans):
|
||||
if not size:
|
||||
raise Exception("not installed")
|
||||
return windows.ReadFile(self.hPipe, size).decode("utf-16-le")
|
||||
|
||||
def translate(self, content):
|
||||
return self.x64(content)
|
||||
|
@ -10,13 +10,11 @@ from ctypes import (
|
||||
POINTER,
|
||||
c_char,
|
||||
)
|
||||
from ctypes.wintypes import HANDLE
|
||||
import platform, gobject, threading
|
||||
|
||||
try:
|
||||
if platform.system() != "Windows" or int(platform.version().split(".")[0]) <= 6:
|
||||
raise Exception()
|
||||
|
||||
winrtutilsdll = CDLL(gobject.GetDllpath(("winrtutils32.dll", "winrtutils64.dll")))
|
||||
except:
|
||||
winrtutilsdll = 0
|
||||
@ -33,11 +31,6 @@ if winrtutilsdll:
|
||||
_getlanguagelist = winrtutilsdll.getlanguagelist
|
||||
_getlanguagelist.argtypes = (c_void_p,)
|
||||
|
||||
def getlanguagelist():
|
||||
ret = []
|
||||
_getlanguagelist(CFUNCTYPE(None, c_wchar_p)(ret.append))
|
||||
return ret
|
||||
|
||||
def OCR_f(data, lang, space):
|
||||
ret = []
|
||||
|
||||
@ -62,13 +55,24 @@ if winrtutilsdll:
|
||||
_winrt_capture_window = winrtutilsdll.winrt_capture_window
|
||||
_winrt_capture_window.argtypes = c_void_p, c_void_p
|
||||
|
||||
def winrt_capture_window(hwnd):
|
||||
ret = []
|
||||
|
||||
def cb(ptr, size):
|
||||
ret.append(cast(ptr, POINTER(c_char))[:size])
|
||||
def getlanguagelist():
|
||||
if not winrtutilsdll:
|
||||
return []
|
||||
ret = []
|
||||
_getlanguagelist(CFUNCTYPE(None, c_wchar_p)(ret.append))
|
||||
return ret
|
||||
|
||||
_winrt_capture_window(hwnd, CFUNCTYPE(None, c_void_p, c_size_t)(cb))
|
||||
if len(ret):
|
||||
return ret[0]
|
||||
return None
|
||||
|
||||
def winrt_capture_window(hwnd):
|
||||
if not winrtutilsdll:
|
||||
return
|
||||
ret = []
|
||||
|
||||
def cb(ptr, size):
|
||||
ret.append(cast(ptr, POINTER(c_char))[:size])
|
||||
|
||||
_winrt_capture_window(hwnd, CFUNCTYPE(None, c_void_p, c_size_t)(cb))
|
||||
if len(ret):
|
||||
return ret[0]
|
||||
return None
|
||||
|
@ -521,6 +521,7 @@
|
||||
"useproxy": true,
|
||||
"usesysproxy": true,
|
||||
"fullscreenmethod_4": 0,
|
||||
"tagNameRemap": {},
|
||||
"dialog_savegame_layout": {
|
||||
"itemw": 250,
|
||||
"itemh": 350,
|
||||
@ -532,6 +533,7 @@
|
||||
"transparent": 25,
|
||||
"transparentselect": 25,
|
||||
"transparentnotexits": 25,
|
||||
"listitemheight": 30,
|
||||
"listitemwidth_2": [
|
||||
300,
|
||||
500
|
||||
@ -1181,19 +1183,13 @@
|
||||
"use": true,
|
||||
"name": "MeCab",
|
||||
"args": {
|
||||
"path": "",
|
||||
"downloadlink": "{main_server}/Resource/dictionary/Mecab.zip"
|
||||
"path": ""
|
||||
},
|
||||
"argstype": {
|
||||
"path": {
|
||||
"type": "file",
|
||||
"name": "路径",
|
||||
"dir": true
|
||||
},
|
||||
"downloadlink": {
|
||||
"type": "label",
|
||||
"islink": true,
|
||||
"name": "下载"
|
||||
}
|
||||
},
|
||||
"type": "offline"
|
||||
@ -1670,7 +1666,7 @@
|
||||
"type": "offline",
|
||||
"use": false,
|
||||
"color": "#1839f0",
|
||||
"name": "Jbeijing7"
|
||||
"name": "J北京7"
|
||||
},
|
||||
"eztrans": {
|
||||
"type": "offline",
|
||||
|
@ -1,18 +1,4 @@
|
||||
{
|
||||
"local": {
|
||||
"args": {
|
||||
"": ""
|
||||
},
|
||||
"argstype": {
|
||||
"": {
|
||||
"type": "program",
|
||||
"route": [
|
||||
"ocrengines.local",
|
||||
"question"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"youdaodictocr": {
|
||||
"args": {
|
||||
"Translate": false
|
||||
@ -24,20 +10,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"windowsocr": {
|
||||
"args": {
|
||||
"": ""
|
||||
},
|
||||
"argstype": {
|
||||
"": {
|
||||
"type": "program",
|
||||
"route": [
|
||||
"ocrengines.windowsocr",
|
||||
"question"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"baiduocr_X": {
|
||||
"args": {
|
||||
"API Key": "",
|
||||
@ -322,10 +294,7 @@
|
||||
},
|
||||
"mangaocr": {
|
||||
"args": {
|
||||
"Port": 5665,
|
||||
"项目仓库": "https://github.com/kha-white/manga-ocr",
|
||||
"整合包_CPU": "{main_server}/Resource/IntegrationPack/manga_ocr/cpu",
|
||||
"整合包_GPU": "{main_server}/Resource/IntegrationPack/manga_ocr/gpu"
|
||||
"Port": 5665
|
||||
},
|
||||
"argstype": {
|
||||
"Port": {
|
||||
@ -333,18 +302,6 @@
|
||||
"min": 1,
|
||||
"max": 65535,
|
||||
"step": 1
|
||||
},
|
||||
"项目仓库": {
|
||||
"type": "label",
|
||||
"islink": true
|
||||
},
|
||||
"整合包_CPU": {
|
||||
"type": "label",
|
||||
"islink": true
|
||||
},
|
||||
"整合包_GPU": {
|
||||
"type": "label",
|
||||
"islink": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -452,236 +452,295 @@
|
||||
"北欧",
|
||||
"西里尔"
|
||||
],
|
||||
"aboutsource": [
|
||||
{
|
||||
"name": "辞书",
|
||||
"sources": [
|
||||
{
|
||||
"name": "MeCab",
|
||||
"links": [
|
||||
{
|
||||
"name": "MeCab",
|
||||
"link": "{main_server}/Resource/dictionary/Mecab.zip"
|
||||
},
|
||||
{
|
||||
"name": "Unidic",
|
||||
"link": "https://clrd.ninjal.ac.jp/unidic/"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "MDict",
|
||||
"links": [
|
||||
{
|
||||
"name": "论坛",
|
||||
"link": "https://forum.freemdict.com/"
|
||||
},
|
||||
{
|
||||
"name": "freemdict",
|
||||
"link": "https://search.freemdict.com/"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "语音合成",
|
||||
"sources": [
|
||||
{
|
||||
"name": "NeoSpeech",
|
||||
"links": [
|
||||
{
|
||||
"name": "Misaki",
|
||||
"link": "{main_server}/Resource/voice/NeoSpeech.Japanese.Misaki.zip"
|
||||
},
|
||||
{
|
||||
"name": "Show",
|
||||
"link": "{main_server}/Resource/voice/NeoSpeech.TTS.NeoSpeech.Japanese.Show_v3.10.0.0.zip"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "VOICEVOX",
|
||||
"links": [
|
||||
{
|
||||
"name": "Github",
|
||||
"link": "https://github.com/VOICEVOX/voicevox/releases"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "vits-simple-api",
|
||||
"links": [
|
||||
{
|
||||
"name": "Github",
|
||||
"link": "https://github.com/Artrajz/vits-simple-api/releases"
|
||||
},
|
||||
{
|
||||
"name": "整合包_CPU",
|
||||
"link": "{main_server}/Resource/IntegrationPack/vits-simple-api/cpu"
|
||||
},
|
||||
{
|
||||
"name": "整合包_GPU",
|
||||
"link": "{main_server}/Resource/IntegrationPack/vits-simple-api/gpu"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "VoiceRoid+",
|
||||
"links": [
|
||||
{
|
||||
"name": "東北ずん子/东北俊子",
|
||||
"link": "{main_server}/Resource/voice/VOICEROID+zunko.7z"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "VoiceRoid2",
|
||||
"links": [
|
||||
{
|
||||
"name": "SFE_結月ゆかり/结月缘",
|
||||
"link": "{main_server}/Resource/voice/Yukari2.zip"
|
||||
},
|
||||
{
|
||||
"name": "結月ゆかり/结月缘",
|
||||
"link": "{main_server}/Resource/voice/VOICEROID2_Yuzuki_Yukari.zip"
|
||||
},
|
||||
{
|
||||
"name": "紲星あかり/绁星灯",
|
||||
"link": "{main_server}/Resource/voice/VOICEROID2_Kizuna_Akari.zip"
|
||||
},
|
||||
{
|
||||
"name": "琴葉 茜・葵",
|
||||
"link": "{main_server}/Resource/voice/VOICEROID2_Kotonoha_Akane_Aoi.zip"
|
||||
},
|
||||
{
|
||||
"name": "伊織弓鶴",
|
||||
"link": "{main_server}/Resource/voice/VOICEROID2_Iori_Yuzuru.zip"
|
||||
},
|
||||
{
|
||||
"name": "ついなちゃん",
|
||||
"link": "{main_server}/Resource/voice/VOICEROID2_tsuina-chan_dl_e.zip"
|
||||
},
|
||||
{
|
||||
"name": "東北イタコ/东北伊达子",
|
||||
"link": "{main_server}/Resource/voice/VOICEROID2_Tohoku_Itako.zip"
|
||||
},
|
||||
{
|
||||
"name": "附加音源_結月ゆかり",
|
||||
"link": "{main_server}/Resource/voice/yukari_emo_44.zip"
|
||||
},
|
||||
{
|
||||
"name": "附加音源_紲星あかり",
|
||||
"link": "{main_server}/Resource/voice/akari_44.zip"
|
||||
},
|
||||
{
|
||||
"name": "附加音源_東北きりたん",
|
||||
"link": "{main_server}/Resource/voice/kiritan_44.zip"
|
||||
},
|
||||
{
|
||||
"name": "附加音源_東北イタコ",
|
||||
"link": "{main_server}/Resource/voice/itako_emo_44.zip"
|
||||
},
|
||||
{
|
||||
"name": "附加音源_東北ずん子",
|
||||
"link": "{main_server}/Resource/voice/zunko_44.zip"
|
||||
},
|
||||
{
|
||||
"name": "附加音源_伊織弓鶴",
|
||||
"link": "{main_server}/Resource/voice/yuzuru_emo_44.zip"
|
||||
},
|
||||
{
|
||||
"name": "附加音源_ついなちゃん",
|
||||
"link": "{main_server}/Resource/voice/tsuina_44.zip"
|
||||
},
|
||||
{
|
||||
"name": "附加音源_ついなちゃん(関西弁)",
|
||||
"link": "{main_server}/Resource/voice/tsuina_west_44.zip"
|
||||
},
|
||||
{
|
||||
"name": "附加音源_琴葉茜",
|
||||
"link": "{main_server}/Resource/voice/akane_west_emo_44.zip"
|
||||
},
|
||||
{
|
||||
"name": "附加音源_琴葉葵",
|
||||
"link": "{main_server}/Resource/voice/aoi_emo_44.zip"
|
||||
},
|
||||
{
|
||||
"name": "附加音源_水奈瀬コウ",
|
||||
"link": "{main_server}/Resource/voice/kou_44.zip"
|
||||
},
|
||||
{
|
||||
"name": "附加音源_桜乃そら",
|
||||
"link": "{main_server}/Resource/voice/sora_44.zip"
|
||||
},
|
||||
{
|
||||
"name": "附加音源_民安ともえ",
|
||||
"link": "{main_server}/Resource/voice/tamiyasu_44.zip"
|
||||
},
|
||||
{
|
||||
"name": "附加音源_月読アイ",
|
||||
"link": "{main_server}/Resource/voice/ai_44.zip"
|
||||
},
|
||||
{
|
||||
"name": "附加音源_月読ショウタ",
|
||||
"link": "{main_server}/Resource/voice/shouta_44.zip"
|
||||
},
|
||||
{
|
||||
"name": "附加音源_京町セイカ",
|
||||
"link": "{main_server}/Resource/voice/seika_44.zip"
|
||||
},
|
||||
{
|
||||
"name": "附加音源_音街ウナ",
|
||||
"link": "{main_server}/Resource/voice/una_44.zip"
|
||||
},
|
||||
{
|
||||
"name": "附加音源_鷹の爪吉田",
|
||||
"link": "{main_server}/Resource/voice/yoshidakun_44.zip"
|
||||
},
|
||||
{
|
||||
"name": "附加音源_ギャラ子",
|
||||
"link": "{main_server}/Resource/voice/galaco_44.zip"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "其他工具",
|
||||
"sources": [
|
||||
{
|
||||
"name": "转区",
|
||||
"links": [
|
||||
{
|
||||
"name": "Locale-Emulator",
|
||||
"link": "https://github.com/xupefei/Locale-Emulator/releases/download/v2.5.0.1/Locale.Emulator.2.5.0.1.zip"
|
||||
},
|
||||
{
|
||||
"name": "Locale_Remulator",
|
||||
"link": "https://github.com/InWILL/Locale_Remulator/releases/download/v1.5.3-beta.1/Locale_Remulator.1.5.3-beta.1.zip"
|
||||
},
|
||||
{
|
||||
"name": "Ntleas",
|
||||
"link": "https://github.com/zxyacb/ntlea/releases/download/0.46/ntleas046_x64.7z"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Magpie",
|
||||
"links": [
|
||||
{
|
||||
"name": "Github",
|
||||
"link": "https://github.com/Blinue/Magpie/releases"
|
||||
},
|
||||
{
|
||||
"name": "win7适配版",
|
||||
"link": "{main_server}/Resource/Magpie9_Win7"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"aboutsource": {
|
||||
"translate": [
|
||||
{
|
||||
"name": "大模型",
|
||||
"links": [
|
||||
{
|
||||
"name": "Sakura大模型",
|
||||
"link": "https://github.com/SakuraLLM/SakuraLLM",
|
||||
"about": "日语_->_简体中文"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "过时的翻译器",
|
||||
"links": [
|
||||
{
|
||||
"name": "J北京7",
|
||||
"link": "{main_server}/Resource/translate/JBeijing7.zip",
|
||||
"about": "日语_->_简体中文"
|
||||
},
|
||||
{
|
||||
"name": "金山快译",
|
||||
"link": "{main_server}/Resource/translate/FastAIT09_Setup.25269.4101.zip",
|
||||
"about": "日语_->_简体中文"
|
||||
},
|
||||
{
|
||||
"name": "快译通",
|
||||
"link": "{main_server}/Resource/translate/DR.eye.zip",
|
||||
"about": "日语_->_简体中文"
|
||||
},
|
||||
{
|
||||
"name": "Sugoi",
|
||||
"link": "{main_server}/Resource/translate/Sugoi_Translator_V10.1.7z",
|
||||
"about": "日语_->_英语"
|
||||
},
|
||||
{
|
||||
"name": "LEC",
|
||||
"link": "{main_server}/Resource/translate/LEC",
|
||||
"about": "日语_->_英语"
|
||||
},
|
||||
{
|
||||
"name": "Atlas",
|
||||
"link": "{main_server}/Resource/translate/Atlas",
|
||||
"about": "日语_->_英语"
|
||||
},
|
||||
{
|
||||
"name": "ezTrans",
|
||||
"link": "{main_server}/Resource/translate/ezTrans",
|
||||
"about": "日语_->_韩语"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"ocr": [
|
||||
{
|
||||
"name": "本地OCR",
|
||||
"function": [
|
||||
"ocrengines.local",
|
||||
"question"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "WindowsOCR",
|
||||
"function": [
|
||||
"ocrengines.windowsocr",
|
||||
"question"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "manga-ocr",
|
||||
"links": [
|
||||
{
|
||||
"name": "项目仓库",
|
||||
"link": "https://github.com/kha-white/manga-ocr"
|
||||
},
|
||||
{
|
||||
"name": "整合包_CPU",
|
||||
"link": "{main_server}/Resource/IntegrationPack/manga_ocr/cpu"
|
||||
},
|
||||
{
|
||||
"name": "整合包_GPU",
|
||||
"link": "{main_server}/Resource/IntegrationPack/manga_ocr/gpu"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"dict": [
|
||||
{
|
||||
"name": "MeCab",
|
||||
"links": [
|
||||
{
|
||||
"name": "MeCab",
|
||||
"link": "{main_server}/Resource/dictionary/Mecab.zip"
|
||||
},
|
||||
{
|
||||
"name": "Unidic",
|
||||
"link": "https://clrd.ninjal.ac.jp/unidic/"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "MDict",
|
||||
"links": [
|
||||
{
|
||||
"name": "论坛",
|
||||
"link": "https://forum.freemdict.com/"
|
||||
},
|
||||
{
|
||||
"name": "freemdict",
|
||||
"link": "https://search.freemdict.com/"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"tts": [
|
||||
{
|
||||
"name": "NeoSpeech",
|
||||
"links": [
|
||||
{
|
||||
"name": "Misaki",
|
||||
"link": "{main_server}/Resource/voice/NeoSpeech.Japanese.Misaki.zip"
|
||||
},
|
||||
{
|
||||
"name": "Show",
|
||||
"link": "{main_server}/Resource/voice/NeoSpeech.TTS.NeoSpeech.Japanese.Show_v3.10.0.0.zip"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "VOICEVOX",
|
||||
"links": [
|
||||
{
|
||||
"name": "Github",
|
||||
"link": "https://github.com/VOICEVOX/voicevox/releases"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "vits-simple-api",
|
||||
"links": [
|
||||
{
|
||||
"name": "Github",
|
||||
"link": "https://github.com/Artrajz/vits-simple-api/releases"
|
||||
},
|
||||
{
|
||||
"name": "整合包_CPU",
|
||||
"link": "{main_server}/Resource/IntegrationPack/vits-simple-api/cpu"
|
||||
},
|
||||
{
|
||||
"name": "整合包_GPU",
|
||||
"link": "{main_server}/Resource/IntegrationPack/vits-simple-api/gpu"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "VoiceRoid+",
|
||||
"links": [
|
||||
{
|
||||
"name": "東北ずん子/东北俊子",
|
||||
"link": "{main_server}/Resource/voice/VOICEROID+zunko.7z"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "VoiceRoid2",
|
||||
"links": [
|
||||
{
|
||||
"name": "SFE_結月ゆかり/结月缘",
|
||||
"link": "{main_server}/Resource/voice/Yukari2.zip"
|
||||
},
|
||||
{
|
||||
"name": "結月ゆかり/结月缘",
|
||||
"link": "{main_server}/Resource/voice/VOICEROID2_Yuzuki_Yukari.zip"
|
||||
},
|
||||
{
|
||||
"name": "紲星あかり/绁星灯",
|
||||
"link": "{main_server}/Resource/voice/VOICEROID2_Kizuna_Akari.zip"
|
||||
},
|
||||
{
|
||||
"name": "琴葉 茜・葵",
|
||||
"link": "{main_server}/Resource/voice/VOICEROID2_Kotonoha_Akane_Aoi.zip"
|
||||
},
|
||||
{
|
||||
"name": "伊織弓鶴",
|
||||
"link": "{main_server}/Resource/voice/VOICEROID2_Iori_Yuzuru.zip"
|
||||
},
|
||||
{
|
||||
"name": "ついなちゃん",
|
||||
"link": "{main_server}/Resource/voice/VOICEROID2_tsuina-chan_dl_e.zip"
|
||||
},
|
||||
{
|
||||
"name": "東北イタコ/东北伊达子",
|
||||
"link": "{main_server}/Resource/voice/VOICEROID2_Tohoku_Itako.zip"
|
||||
},
|
||||
{
|
||||
"name": "附加音源_結月ゆかり",
|
||||
"link": "{main_server}/Resource/voice/yukari_emo_44.zip"
|
||||
},
|
||||
{
|
||||
"name": "附加音源_紲星あかり",
|
||||
"link": "{main_server}/Resource/voice/akari_44.zip"
|
||||
},
|
||||
{
|
||||
"name": "附加音源_東北きりたん",
|
||||
"link": "{main_server}/Resource/voice/kiritan_44.zip"
|
||||
},
|
||||
{
|
||||
"name": "附加音源_東北イタコ",
|
||||
"link": "{main_server}/Resource/voice/itako_emo_44.zip"
|
||||
},
|
||||
{
|
||||
"name": "附加音源_東北ずん子",
|
||||
"link": "{main_server}/Resource/voice/zunko_44.zip"
|
||||
},
|
||||
{
|
||||
"name": "附加音源_伊織弓鶴",
|
||||
"link": "{main_server}/Resource/voice/yuzuru_emo_44.zip"
|
||||
},
|
||||
{
|
||||
"name": "附加音源_ついなちゃん",
|
||||
"link": "{main_server}/Resource/voice/tsuina_44.zip"
|
||||
},
|
||||
{
|
||||
"name": "附加音源_ついなちゃん(関西弁)",
|
||||
"link": "{main_server}/Resource/voice/tsuina_west_44.zip"
|
||||
},
|
||||
{
|
||||
"name": "附加音源_琴葉茜",
|
||||
"link": "{main_server}/Resource/voice/akane_west_emo_44.zip"
|
||||
},
|
||||
{
|
||||
"name": "附加音源_琴葉葵",
|
||||
"link": "{main_server}/Resource/voice/aoi_emo_44.zip"
|
||||
},
|
||||
{
|
||||
"name": "附加音源_水奈瀬コウ",
|
||||
"link": "{main_server}/Resource/voice/kou_44.zip"
|
||||
},
|
||||
{
|
||||
"name": "附加音源_桜乃そら",
|
||||
"link": "{main_server}/Resource/voice/sora_44.zip"
|
||||
},
|
||||
{
|
||||
"name": "附加音源_民安ともえ",
|
||||
"link": "{main_server}/Resource/voice/tamiyasu_44.zip"
|
||||
},
|
||||
{
|
||||
"name": "附加音源_月読アイ",
|
||||
"link": "{main_server}/Resource/voice/ai_44.zip"
|
||||
},
|
||||
{
|
||||
"name": "附加音源_月読ショウタ",
|
||||
"link": "{main_server}/Resource/voice/shouta_44.zip"
|
||||
},
|
||||
{
|
||||
"name": "附加音源_京町セイカ",
|
||||
"link": "{main_server}/Resource/voice/seika_44.zip"
|
||||
},
|
||||
{
|
||||
"name": "附加音源_音街ウナ",
|
||||
"link": "{main_server}/Resource/voice/una_44.zip"
|
||||
},
|
||||
{
|
||||
"name": "附加音源_鷹の爪吉田",
|
||||
"link": "{main_server}/Resource/voice/yoshidakun_44.zip"
|
||||
},
|
||||
{
|
||||
"name": "附加音源_ギャラ子",
|
||||
"link": "{main_server}/Resource/voice/galaco_44.zip"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"magpie": [
|
||||
{
|
||||
"name": "Magpie",
|
||||
"links": [
|
||||
{
|
||||
"name": "Github",
|
||||
"link": "https://github.com/Blinue/Magpie/releases"
|
||||
},
|
||||
{
|
||||
"name": "win7适配版",
|
||||
"link": "{main_server}/Resource/Magpie9_Win7"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"mod_map": {
|
||||
"CTRL": 2,
|
||||
"SHIFT": 4,
|
||||
|
@ -276,19 +276,7 @@
|
||||
},
|
||||
"sugoix": {
|
||||
"args": {
|
||||
"api": "http://127.0.0.1:14366/",
|
||||
"V8": "{main_server}/Resource/translate/Sugoi_Translator_V8.7z",
|
||||
"V10.1": "{main_server}/Resource/translate/Sugoi_Translator_V10.1.7z"
|
||||
},
|
||||
"argstype": {
|
||||
"V8": {
|
||||
"type": "label",
|
||||
"islink": true
|
||||
},
|
||||
"V10.1": {
|
||||
"type": "label",
|
||||
"islink": true
|
||||
}
|
||||
"api": "http://127.0.0.1:14366/"
|
||||
}
|
||||
},
|
||||
"huoshanapi": {
|
||||
@ -668,36 +656,26 @@
|
||||
},
|
||||
"jb7": {
|
||||
"args": {
|
||||
"path": "",
|
||||
"下载": "{main_server}/Resource/translate/JBeijing7.zip"
|
||||
"path": ""
|
||||
},
|
||||
"argstype": {
|
||||
"path": {
|
||||
"type": "file",
|
||||
"dir": true,
|
||||
"name": "路径"
|
||||
},
|
||||
"下载": {
|
||||
"type": "label",
|
||||
"islink": true
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"kingsoft": {
|
||||
"args": {
|
||||
"path": "",
|
||||
"下载": "{main_server}/Resource/translate/FastAIT09_Setup.25269.4101.zip"
|
||||
"path": ""
|
||||
},
|
||||
"argstype": {
|
||||
"path": {
|
||||
"name": "路径",
|
||||
"type": "file",
|
||||
"dir": true
|
||||
},
|
||||
"下载": {
|
||||
"type": "label",
|
||||
"islink": true
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"eztrans": {
|
||||
@ -715,19 +693,14 @@
|
||||
},
|
||||
"dreye": {
|
||||
"args": {
|
||||
"path": "",
|
||||
"下载": "{main_server}/Resource/translate/DR.eye.zip"
|
||||
"path": ""
|
||||
},
|
||||
"argstype": {
|
||||
"path": {
|
||||
"name": "路径",
|
||||
"type": "file",
|
||||
"dir": true
|
||||
},
|
||||
"下载": {
|
||||
"type": "label",
|
||||
"islink": true
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"rengong": {
|
||||
|
@ -756,5 +756,12 @@
|
||||
"成功": "النجاح .",
|
||||
"Win32通用钩子": "win32 هوك العالمي",
|
||||
"特殊码无效": "رمز خاص غير صالح",
|
||||
"显示模式": "طريقة العرض"
|
||||
"显示模式": "طريقة العرض",
|
||||
"内置": "مدمجة",
|
||||
"信息": "معلومات",
|
||||
"开发商": "المطور",
|
||||
"标签映射": "تسمية الخريطة",
|
||||
"简介": "مقدمة",
|
||||
"全部": "كامل",
|
||||
"年度总结": "ملخص سنوي"
|
||||
}
|
@ -756,5 +756,12 @@
|
||||
"成功": "成功",
|
||||
"Win32通用钩子": "Win32通用鉤子",
|
||||
"特殊码无效": "特殊碼無效",
|
||||
"显示模式": "顯示模式"
|
||||
"显示模式": "顯示模式",
|
||||
"内置": "內寘",
|
||||
"信息": "訊息",
|
||||
"开发商": "開發商",
|
||||
"标签映射": "標籤映射",
|
||||
"简介": "簡介",
|
||||
"全部": "全部",
|
||||
"年度总结": "年度總結"
|
||||
}
|
@ -756,5 +756,12 @@
|
||||
"成功": "úspěch",
|
||||
"Win32通用钩子": "Univerzální hák Win32",
|
||||
"特殊码无效": "Speciální kód je neplatný",
|
||||
"显示模式": "režim zobrazení"
|
||||
"显示模式": "režim zobrazení",
|
||||
"内置": "vestavěné",
|
||||
"信息": "informace",
|
||||
"开发商": "Vývojáři",
|
||||
"标签映射": "Mapování štítků",
|
||||
"简介": "stručný úvod",
|
||||
"全部": "celý",
|
||||
"年度总结": "Roční shrnutí"
|
||||
}
|
@ -756,5 +756,12 @@
|
||||
"成功": "Erfolg",
|
||||
"Win32通用钩子": "Win32 Universal Hook",
|
||||
"特殊码无效": "Der spezielle Code ist ungültig",
|
||||
"显示模式": "Anzeigemodus"
|
||||
"显示模式": "Anzeigemodus",
|
||||
"内置": "eingebaut",
|
||||
"信息": "Informationen",
|
||||
"开发商": "Entwickler",
|
||||
"标签映射": "Beschriftung",
|
||||
"简介": "kurze Einführung",
|
||||
"全部": "ganz",
|
||||
"年度总结": "Jahreszusammenfassung"
|
||||
}
|
@ -756,5 +756,12 @@
|
||||
"成功": "success",
|
||||
"Win32通用钩子": "Win32 Universal Hook",
|
||||
"特殊码无效": "The special code is invalid",
|
||||
"显示模式": "display mode"
|
||||
"显示模式": "display mode",
|
||||
"内置": "built-in",
|
||||
"信息": "information",
|
||||
"开发商": "Developers",
|
||||
"标签映射": "Label Mapping",
|
||||
"简介": "brief introduction",
|
||||
"全部": "all",
|
||||
"年度总结": "Annual Summary"
|
||||
}
|
@ -756,5 +756,12 @@
|
||||
"成功": "éxito",
|
||||
"Win32通用钩子": "Gancho universal Win32",
|
||||
"特殊码无效": "El código especial no es válido",
|
||||
"显示模式": "Modo de visualización"
|
||||
"显示模式": "Modo de visualización",
|
||||
"内置": "Incorporado",
|
||||
"信息": "Información",
|
||||
"开发商": "Desarrolladores",
|
||||
"标签映射": "Mapeo de etiquetas",
|
||||
"简介": "Introducción",
|
||||
"全部": "Todo",
|
||||
"年度总结": "Resumen Anual"
|
||||
}
|
@ -756,5 +756,12 @@
|
||||
"成功": "Succès",
|
||||
"Win32通用钩子": "Win32 crochet universel",
|
||||
"特殊码无效": "Code spécial invalide",
|
||||
"显示模式": "Mode d'affichage"
|
||||
"显示模式": "Mode d'affichage",
|
||||
"内置": "Intégré",
|
||||
"信息": "Informations",
|
||||
"开发商": "Développeur",
|
||||
"标签映射": "Mappage des étiquettes",
|
||||
"简介": "Introduction",
|
||||
"全部": "Tous",
|
||||
"年度总结": "Résumé annuel"
|
||||
}
|
@ -756,5 +756,12 @@
|
||||
"成功": "successo",
|
||||
"Win32通用钩子": "Win32 Universal Hook",
|
||||
"特殊码无效": "Il codice speciale non è valido",
|
||||
"显示模式": "modalità di visualizzazione"
|
||||
"显示模式": "modalità di visualizzazione",
|
||||
"内置": "integrato",
|
||||
"信息": "informazioni",
|
||||
"开发商": "Sviluppatori",
|
||||
"标签映射": "Mappatura etichette",
|
||||
"简介": "breve introduzione",
|
||||
"全部": "intero",
|
||||
"年度总结": "Sintesi annuale"
|
||||
}
|
@ -756,5 +756,12 @@
|
||||
"成功": "成功",
|
||||
"Win32通用钩子": "Win 32汎用フック",
|
||||
"特殊码无效": "特殊コードが無効です",
|
||||
"显示模式": "表示モード"
|
||||
"显示模式": "表示モード",
|
||||
"内置": "組み込み",
|
||||
"信息": "情報#ジョウホウ#",
|
||||
"开发商": "開発者",
|
||||
"标签映射": "ラベルマッピング",
|
||||
"简介": "概要",
|
||||
"全部": "すべて",
|
||||
"年度总结": "年度まとめ"
|
||||
}
|
@ -756,5 +756,12 @@
|
||||
"成功": "성공",
|
||||
"Win32通用钩子": "Win32 범용 갈고리",
|
||||
"特殊码无效": "잘못된 특수 코드",
|
||||
"显示模式": "디스플레이 모드"
|
||||
"显示模式": "디스플레이 모드",
|
||||
"内置": "내장형",
|
||||
"信息": "정보",
|
||||
"开发商": "개발업자",
|
||||
"标签映射": "태그 매핑",
|
||||
"简介": "소개",
|
||||
"全部": "모두",
|
||||
"年度总结": "연간 요약"
|
||||
}
|
@ -756,5 +756,12 @@
|
||||
"成功": "succes",
|
||||
"Win32通用钩子": "Win32 universele haak",
|
||||
"特殊码无效": "De speciale code is ongeldig",
|
||||
"显示模式": "weergavemodus"
|
||||
"显示模式": "weergavemodus",
|
||||
"内置": "ingebouwd",
|
||||
"信息": "informatie",
|
||||
"开发商": "Ontwikkelaars",
|
||||
"标签映射": "Label toewijzing",
|
||||
"简介": "korte inleiding",
|
||||
"全部": "geheel",
|
||||
"年度总结": "Jaarlijkse samenvatting"
|
||||
}
|
@ -756,5 +756,12 @@
|
||||
"成功": "sukces",
|
||||
"Win32通用钩子": "Uniwersalny hak Win32",
|
||||
"特殊码无效": "Kod specjalny jest nieprawidłowy",
|
||||
"显示模式": "tryb wyświetlania"
|
||||
"显示模式": "tryb wyświetlania",
|
||||
"内置": "wbudowany",
|
||||
"信息": "informacje",
|
||||
"开发商": "Deweloperzy",
|
||||
"标签映射": "Mapowanie etykiet",
|
||||
"简介": "krótkie wprowadzenie",
|
||||
"全部": "całość",
|
||||
"年度总结": "Roczne podsumowanie"
|
||||
}
|
@ -756,5 +756,12 @@
|
||||
"成功": "sucesso",
|
||||
"Win32通用钩子": "Gancho Universal Win32",
|
||||
"特殊码无效": "O código especial é inválido",
|
||||
"显示模式": "modo de visualização"
|
||||
"显示模式": "modo de visualização",
|
||||
"内置": "embutido",
|
||||
"信息": "informação",
|
||||
"开发商": "Desenvolvedores",
|
||||
"标签映射": "Mapeamento de Etiquetas",
|
||||
"简介": "breve introdução",
|
||||
"全部": "inteiro",
|
||||
"年度总结": "Resumo anual"
|
||||
}
|
@ -756,5 +756,12 @@
|
||||
"成功": "Успех",
|
||||
"Win32通用钩子": "Win32 Универсальный крюк",
|
||||
"特殊码无效": "Специальный код не работает.",
|
||||
"显示模式": "Показать режим"
|
||||
"显示模式": "Показать режим",
|
||||
"内置": "Встроенные",
|
||||
"信息": "Информация",
|
||||
"开发商": "Разработчики",
|
||||
"标签映射": "Отображение метки",
|
||||
"简介": "Введение",
|
||||
"全部": "Все.",
|
||||
"年度总结": "Ежегодное резюме"
|
||||
}
|
@ -756,5 +756,12 @@
|
||||
"成功": "framgång",
|
||||
"Win32通用钩子": "Win32 universalkrok",
|
||||
"特殊码无效": "Specialkoden är ogiltig",
|
||||
"显示模式": "visningsläge"
|
||||
"显示模式": "visningsläge",
|
||||
"内置": "inbyggd",
|
||||
"信息": "information",
|
||||
"开发商": "Utvecklare",
|
||||
"标签映射": "Etikettmappning",
|
||||
"简介": "kort inledning",
|
||||
"全部": "hela",
|
||||
"年度总结": "Årlig sammanfattning"
|
||||
}
|
@ -756,5 +756,12 @@
|
||||
"成功": "ความสำเร็จ",
|
||||
"Win32通用钩子": "ตะขอสากล Win32",
|
||||
"特殊码无效": "รหัสพิเศษไม่ถูกต้อง",
|
||||
"显示模式": "โหมดการแสดงผล"
|
||||
"显示模式": "โหมดการแสดงผล",
|
||||
"内置": "สร้างขึ้นใน",
|
||||
"信息": "ข้อมูล",
|
||||
"开发商": "นักพัฒนา",
|
||||
"标签映射": "แผนที่ป้ายกำกับ",
|
||||
"简介": "บทนำ",
|
||||
"全部": "ทั้งหมด",
|
||||
"年度总结": "สรุปรายปี"
|
||||
}
|
@ -756,5 +756,12 @@
|
||||
"成功": "başarılı",
|
||||
"Win32通用钩子": "Win32 Universal Hook",
|
||||
"特殊码无效": "Özel kodu geçersiz.",
|
||||
"显示模式": "Görüntü modusu"
|
||||
"显示模式": "Görüntü modusu",
|
||||
"内置": "in şa edilmiş",
|
||||
"信息": "bilgi",
|
||||
"开发商": "Geliştiriciler",
|
||||
"标签映射": "Etiket Haritası",
|
||||
"简介": "kısa tanıtım",
|
||||
"全部": "Tüm",
|
||||
"年度总结": "Yıllık Toplantı"
|
||||
}
|
@ -756,5 +756,12 @@
|
||||
"成功": "успіх",
|
||||
"Win32通用钩子": "Win32 Universal Hook",
|
||||
"特殊码无效": "Некоректний особливий код",
|
||||
"显示模式": "режим показу"
|
||||
"显示模式": "режим показу",
|
||||
"内置": "вбудований",
|
||||
"信息": "інформація",
|
||||
"开发商": "Розробники",
|
||||
"标签映射": "Мапування мітки",
|
||||
"简介": "коротке введення",
|
||||
"全部": "цілий",
|
||||
"年度总结": "Річне резюме"
|
||||
}
|
@ -756,5 +756,12 @@
|
||||
"成功": "Thành công",
|
||||
"Win32通用钩子": "Win32 phổ Hook",
|
||||
"特殊码无效": "Mã đặc biệt không hợp lệ",
|
||||
"显示模式": "Chế độ hiển thị"
|
||||
"显示模式": "Chế độ hiển thị",
|
||||
"内置": "Được xây dựng trong",
|
||||
"信息": "Thông tin",
|
||||
"开发商": "Nhà phát triển",
|
||||
"标签映射": "Bản đồ nhãn",
|
||||
"简介": "Giới thiệu",
|
||||
"全部": "Tất cả",
|
||||
"年度总结": "Tóm tắt hàng năm"
|
||||
}
|
@ -756,5 +756,12 @@
|
||||
"成功": "",
|
||||
"Win32通用钩子": "",
|
||||
"特殊码无效": "",
|
||||
"显示模式": ""
|
||||
"显示模式": "",
|
||||
"内置": "",
|
||||
"信息": "",
|
||||
"开发商": "",
|
||||
"标签映射": "",
|
||||
"简介": "",
|
||||
"全部": "",
|
||||
"年度总结": ""
|
||||
}
|
300
py/files/yearsummary/yearsummary.html
Normal file
300
py/files/yearsummary/yearsummary.html
Normal file
@ -0,0 +1,300 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<title>...</title>
|
||||
<meta charset="UTF-8">
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/wordcloud@1.1.1/src/wordcloud2.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/echarts@latest/dist/echarts.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/echarts-wordcloud@latest/dist/echarts-wordcloud.min.js"></script>
|
||||
<script src="yearsummary.value.js"></script>
|
||||
<style>
|
||||
.page {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.buttons {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
background-color: pink;
|
||||
color: white;
|
||||
text-align: center;
|
||||
padding: 15px 0;
|
||||
border: none;
|
||||
font-size: 18px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.page {
|
||||
height: calc(100vh - 100px);
|
||||
}
|
||||
|
||||
#wordcloud,
|
||||
#wordcloud2 {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.container {
|
||||
overflow: hide;
|
||||
display: flex;
|
||||
padding: 10px;
|
||||
gap: 20px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
|
||||
.left-box h1 {
|
||||
margin: 0;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.left-box p {
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
/* Right Boxes (Detail boxes) */
|
||||
.right-box {
|
||||
height: 100%;
|
||||
flex: 3;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
/* Right Boxes (Detail boxes) */
|
||||
.left-box {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.box {
|
||||
background-color: #ffffff;
|
||||
padding: 15px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.bigbox {
|
||||
background-color: #ffffff;
|
||||
margin-left: 10px;
|
||||
margin-right: 10px;
|
||||
margin-top: 20px;
|
||||
padding: 15px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.right-box .box h3 {
|
||||
margin-top: 0;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.right-box .box p {
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.zitiupup {
|
||||
font-size: 1.5em;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.imagecontainer {
|
||||
width: 20%;
|
||||
height: auto;
|
||||
aspect-ratio: 1 / 1.618;
|
||||
}
|
||||
|
||||
.imagexx {
|
||||
height: 100%;
|
||||
mask-image: linear-gradient(to bottom, rgba(0, 0, 0, 1) 0%, rgba(0, 0, 0, 0) 100%);
|
||||
}
|
||||
|
||||
#imagetop25 {
|
||||
line-height: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div class="page active" id="page1">
|
||||
<div class="container">
|
||||
<!-- Left Box (Main content) -->
|
||||
<div class="left-box">
|
||||
<div class="box">
|
||||
<h1>今年你一共总玩了 <div class="zitiupup" id="GAMES_YEAR_PLAYED"></div> 个游戏
|
||||
</h1>
|
||||
</div>
|
||||
<div class="box" style="flex: 10;">
|
||||
<h3>今年你的累计游戏时长 <div class="zitiupup" id="TIME_YEAR_PLAYED"></div> 小时,有 <div class="zitiupup"
|
||||
id="TIME_YEAR_PLAYED_DAY"></div> 天玩了游戏,累计阅读字数达 <div class="zitiupup"
|
||||
id="COUNT_ZISHU_YEAR_PLAYED"></div>
|
||||
</h3>
|
||||
<canvas id="everymonth" width="100%" height="100%"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Right Box (Detail Boxes) -->
|
||||
<div class="right-box">
|
||||
|
||||
<div class="box" style="height: 100%;">
|
||||
<div class=" imagexx">
|
||||
<div id="imagetop25"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="page bigbox" id="page2" style="display: flex; flex-direction: column;">
|
||||
<h1 style="text-align: center; flex:1">你所玩的游戏的标签</h1>
|
||||
<div style="flex:10;"><div id="wordcloud"></div></div>
|
||||
</div>
|
||||
<div class="page bigbox" id="page3" style="display: flex; flex-direction: column;">
|
||||
<h1 style="text-align: center; flex:1">你所玩的游戏的开发商</h1>
|
||||
<div style="flex:10;"><div id="wordcloud2"></div></div>
|
||||
</div>
|
||||
<div class="buttons"> Next</div>
|
||||
<script>
|
||||
havedatamonth = []
|
||||
havedatamonth_v = []
|
||||
for (let i = 1; i <= 12; i += 1) {
|
||||
if (everymonth_time[i]) {
|
||||
havedatamonth.push(i)
|
||||
havedatamonth_v.push(everymonth_time[i] / 3600)
|
||||
}
|
||||
}
|
||||
var ctx = document.getElementById('everymonth').getContext('2d');
|
||||
let lastshowmonth = 0;
|
||||
TOP25_TIME_IMAGE_M[0] = TOP25_TIME_IMAGE
|
||||
var myChart = new Chart(ctx, {
|
||||
type: 'bar',
|
||||
data: {
|
||||
labels: havedatamonth,
|
||||
datasets: [{
|
||||
label: '每月游戏时长',
|
||||
data: havedatamonth_v,
|
||||
borderWidth: 1
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
scales: {
|
||||
x: {
|
||||
title: {
|
||||
display: true,
|
||||
text: '月'
|
||||
}
|
||||
},
|
||||
y: {
|
||||
display: true,
|
||||
text: '小时',
|
||||
beginAtZero: true
|
||||
}
|
||||
},
|
||||
onHover: function (event, chartElement) {
|
||||
let month = 0
|
||||
if (chartElement.length > 0) {
|
||||
month = havedatamonth[chartElement[0].index]
|
||||
}
|
||||
if (lastshowmonth == month)
|
||||
return
|
||||
lastshowmonth = month
|
||||
document.getElementById('imagetop25').innerHTML = ''
|
||||
TOP25_TIME_IMAGE_M[month].forEach((path) => {
|
||||
let img = document.createElement('img')
|
||||
img.src = path
|
||||
img.classList.add('imagecontainer')
|
||||
document.getElementById('imagetop25').appendChild(img)
|
||||
})
|
||||
},
|
||||
}
|
||||
});
|
||||
document.getElementById('TIME_YEAR_PLAYED_DAY').innerText = TIME_YEAR_PLAYED_DAY
|
||||
document.getElementById('GAMES_YEAR_PLAYED').innerText = GAMES_YEAR_PLAYED
|
||||
document.getElementById('TIME_YEAR_PLAYED').innerText = TIME_YEAR_PLAYED
|
||||
document.getElementById('COUNT_ZISHU_YEAR_PLAYED').innerText = COUNT_ZISHU_YEAR_PLAYED
|
||||
TOP25_TIME_IMAGE.forEach((path) => {
|
||||
let img = document.createElement('img')
|
||||
img.src = path
|
||||
img.classList.add('imagecontainer')
|
||||
document.getElementById('imagetop25').appendChild(img)
|
||||
})
|
||||
</script>
|
||||
<script>
|
||||
document.querySelector('.buttons').addEventListener('click', () => {
|
||||
nextPage()
|
||||
})
|
||||
|
||||
developer_cnt = []
|
||||
webtags_cnt = []
|
||||
for (k in developer) {
|
||||
developer_cnt.push([k,
|
||||
10 * developer[k].length
|
||||
])
|
||||
}
|
||||
for (k in webtags) {
|
||||
webtags_cnt.push([k,
|
||||
webtags[k].length
|
||||
])
|
||||
}
|
||||
let currentPage = 1;
|
||||
const totalPages = 3;
|
||||
|
||||
window.addEventListener('resize', () => {
|
||||
WordCloud(document.getElementById('wordcloud'), {
|
||||
list: webtags_cnt
|
||||
});
|
||||
WordCloud(document.getElementById('wordcloud2'), {
|
||||
list: developer_cnt
|
||||
});
|
||||
});
|
||||
function showPage(page) {
|
||||
// Hide all pages
|
||||
const pages = document.querySelectorAll('.page');
|
||||
pages.forEach(p => p.classList.remove('active'));
|
||||
|
||||
// Show the current page
|
||||
document.getElementById('page' + page).classList.add('active');
|
||||
if (page == 2) {
|
||||
WordCloud(document.getElementById('wordcloud'), {
|
||||
list: webtags_cnt
|
||||
});
|
||||
}
|
||||
if (page == 3) {
|
||||
WordCloud(document.getElementById('wordcloud2'), {
|
||||
list: developer_cnt
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function nextPage() {
|
||||
if (currentPage < totalPages) {
|
||||
currentPage++;
|
||||
showPage(currentPage);
|
||||
}
|
||||
else {
|
||||
const pages = document.querySelectorAll('.page');
|
||||
pages.forEach(p => p.classList.add('active'));
|
||||
|
||||
document.querySelector('.buttons').style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize the first page
|
||||
showPage(currentPage);
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
Loading…
x
Reference in New Issue
Block a user