From c2af20424a3eddabe923f9a6177476eb67416aee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=81=8D=E5=85=AE=E6=83=9A=E5=85=AE?= <101191390+HIllya51@users.noreply.github.com> Date: Sat, 13 Apr 2024 22:03:02 +0800 Subject: [PATCH] speed up Update specialwidget.py Update specialwidget.py Update specialwidget.py Update dialog_savedgame.py Update dialog_savedgame.py --- .../LunaTranslator/gui/dialog_savedgame.py | 61 +++-- .../LunaTranslator/gui/specialwidget.py | 214 ++++++++++++++++-- .../LunaTranslator/myutils/utils.py | 11 +- .../files/defaultconfig/static_data.json | 2 +- 4 files changed, 230 insertions(+), 58 deletions(-) diff --git a/LunaTranslator/LunaTranslator/gui/dialog_savedgame.py b/LunaTranslator/LunaTranslator/gui/dialog_savedgame.py index 2c6b65b1..d79e0c7d 100644 --- a/LunaTranslator/LunaTranslator/gui/dialog_savedgame.py +++ b/LunaTranslator/LunaTranslator/gui/dialog_savedgame.py @@ -1,6 +1,6 @@ import functools, time, qtawesome from datetime import datetime, timedelta -from gui.specialwidget import ScrollFlow, chartwidget +from gui.specialwidget import ScrollFlow, chartwidget, lazyscrollflow from PyQt5.QtWidgets import ( QPushButton, QDialog, @@ -114,24 +114,7 @@ class ItemWidget(QWidget): def setimg(self, pixmap): self._img.setimg(pixmap) - def connectexepath(self, exe): - self.exe = exe - self.latershowfileexits(exe) - - @threader - def latershowfileexits(self, exe): - if os.path.exists(exe): - self.maskshowfileexists.setStyleSheet( - "QLabel { background-color: rgba(255,255,255, 0); }" - ) - else: - self.maskshowfileexists.setStyleSheet( - "QLabel { background-color: " - + globalconfig["dialog_savegame_layout"]["onfilenoexistscolor"] - + "; }" - ) - - def __init__(self, pixmap, file) -> None: + def __init__(self, exe, pixmap, file) -> None: super().__init__() self.itemw = globalconfig["dialog_savegame_layout"]["itemw"] self.itemh = globalconfig["dialog_savegame_layout"]["itemh"] @@ -166,6 +149,17 @@ class ItemWidget(QWidget): self._lb.setAlignment(Qt.AlignCenter) layout.addWidget(self._lb) self.setLayout(layout) + self.exe = exe + if os.path.exists(exe): + self.maskshowfileexists.setStyleSheet( + "QLabel { background-color: rgba(255,255,255, 0); }" + ) + else: + self.maskshowfileexists.setStyleSheet( + "QLabel { background-color: " + + globalconfig["dialog_savegame_layout"]["onfilenoexistscolor"] + + "; }" + ) class IMGWidget(QLabel): @@ -199,7 +193,6 @@ class IMGWidget(QLabel): elif globalconfig["imagewrapmode"] == 3: return size - @threader def setimg(self, pixmap): if type(pixmap) != QPixmap: pixmap = pixmap() @@ -1505,10 +1498,10 @@ class dialog_savedgame_new(saveposwindow): self.formLayout.removeWidget(self.flow) self.flow.deleteLater() self.idxsave.clear() - self.flow = ScrollFlow() + self.flow = lazyscrollflow() self.flow.bgclicked.connect(ItemWidget.clearfocus) self.formLayout.insertWidget(self.formLayout.count() - 1, self.flow) - + QApplication.processEvents() for k in savehook_new_list: if newtags != self.currtags: break @@ -1542,7 +1535,9 @@ class dialog_savedgame_new(saveposwindow): if notshow: continue self.newline(k) - self.flow.refreshscroll() + + QApplication.processEvents() + self.flow.resizeandshow() def showmenu(self, p): menu = QMenu(self) @@ -1596,7 +1591,7 @@ class dialog_savedgame_new(saveposwindow): self.currtags = tuple() self.tagswidget.tagschanged.connect(self.tagschanged) formLayout.addWidget(self.tagswidget) - self.flow = ScrollFlow() + self.flow = lazyscrollflow() self.setContextMenuPolicy(Qt.CustomContextMenu) self.customContextMenuRequested.connect(self.showmenu) formLayout.addWidget(self.flow) @@ -1678,11 +1673,9 @@ class dialog_savedgame_new(saveposwindow): return _pix def getagameitem(self, k): - gameitem = ItemWidget( - functools.partial(self._getpixfunction, k), savehook_new_data[k]["title"] + k, functools.partial(self._getpixfunction, k), savehook_new_data[k]["title"] ) - gameitem.connectexepath(k) gameitem.doubleclicked.connect(self.startgame) gameitem.focuschanged.connect(self.itemfocuschanged) return gameitem @@ -1690,16 +1683,18 @@ class dialog_savedgame_new(saveposwindow): def newline(self, k, first=False): checkifnewgame(k) + itemw = globalconfig["dialog_savegame_layout"]["itemw"] + itemh = globalconfig["dialog_savegame_layout"]["itemh"] + if first: - self.flow.insertwidget(0, self.getagameitem(k)) + self.flow.insertwidget( + 0, (functools.partial(self.getagameitem, k), QSize(itemw, itemh)) + ) self.idxsave.insert(0, k) else: - itemw = globalconfig["dialog_savegame_layout"]["itemw"] - itemh = globalconfig["dialog_savegame_layout"]["itemh"] - - self.flow.addwidgetlazy( - functools.partial(self.getagameitem, k), QSize(itemw, itemh) + self.flow.addwidget( + (functools.partial(self.getagameitem, k), QSize(itemw, itemh)) ) # self.flow.addwidget( self.getagameitem(k)) self.idxsave.append(k) diff --git a/LunaTranslator/LunaTranslator/gui/specialwidget.py b/LunaTranslator/LunaTranslator/gui/specialwidget.py index 52f689d2..d2257343 100644 --- a/LunaTranslator/LunaTranslator/gui/specialwidget.py +++ b/LunaTranslator/LunaTranslator/gui/specialwidget.py @@ -1,6 +1,14 @@ -from PyQt5.QtWidgets import QWidget, QSizePolicy, QLabel, QScrollArea,QApplication -from PyQt5.QtGui import QMouseEvent, QPainter, QPen, QFont, QFontMetrics,QRegion -from PyQt5.QtCore import Qt,QEvent +from PyQt5.QtWidgets import QWidget, QSizePolicy, QLabel, QScrollArea, QApplication +from PyQt5.QtGui import ( + QMouseEvent, + QPainter, + QPen, + QFont, + QFontMetrics, + QRegion, + QResizeEvent, +) +from PyQt5.QtCore import Qt, QEvent from PyQt5.QtWidgets import ( QSpacerItem, QWidgetItem, @@ -9,6 +17,8 @@ from PyQt5.QtCore import QPoint, QRect, QSize, Qt, pyqtSignal from PyQt5.QtWidgets import QLayout from traceback import print_exc from myutils.wrapper import trypass +import threading + class chartwidget(QWidget): def __init__(self) -> None: @@ -119,12 +129,14 @@ class chartwidget(QWidget): class ScrollArea(QScrollArea): - scrolled=pyqtSignal(QRect) + scrolled = pyqtSignal(QRect) + def __init__(self, parent=None): super().__init__(parent) self.verticalScrollBar().valueChanged.connect(self.handleScroll) + def handleScroll(self, value): - + viewport_rect = self.viewport().rect() horizontal_scrollbar = self.horizontalScrollBar() vertical_scrollbar = self.verticalScrollBar() @@ -136,17 +148,22 @@ class ScrollArea(QScrollArea): visible_rect = QRect(x, y, width, height) self.scrolled.emit(visible_rect) + + class lazynotify(QWidget): - - def __init__(self,getrealwid) -> None: + + def __init__(self, getrealwid) -> None: super().__init__() - self.done=False - self.getrealwid=getrealwid + self.done = False + self.getrealwid = getrealwid + def do(self): - wid=self.getrealwid() + wid = self.getrealwid() wid.setParent(self) wid.adjustSize() wid.setVisible(True) + + class ScrollFlow(QWidget): bgclicked = pyqtSignal() @@ -163,8 +180,8 @@ class ScrollFlow(QWidget): self.listWidget = qw(self) # self.listWidget.setFixedWidth(600) - self.lazyitems=[] - self.lazydoneidx=[] + self.lazyitems = [] + self.lazydoneidx = [] self.l = FlowLayout() self.listWidget.setLayout(self.l) @@ -173,41 +190,48 @@ class ScrollFlow(QWidget): self.qscrollarea.setWidgetResizable(True) self.qscrollarea.setWidget(self.listWidget) self.qscrollarea.scrolled.connect(self.doshowlazywidget) + @trypass - def doshowlazywidget(self,region:QRect): - for i,widget in enumerate(self.lazyitems): + def doshowlazywidget(self, region: QRect): + for i, widget in enumerate(self.lazyitems): if i in self.lazydoneidx: continue - widget_rect = widget.geometry() #有可能已被delete,必须try - #print(widget_rect) + widget_rect = widget.geometry() # 有可能已被delete,必须try + # print(widget_rect) if region.intersects(widget_rect): - #print(i,widget_rect) + # print(i,widget_rect) self.lazydoneidx.append(i) widget.do() QApplication.processEvents() - + def refreshscroll(self): QApplication.processEvents() self.doshowlazywidget(self.geometry()) + @trypass - def addwidgetlazy(self,wid,size): - wid=lazynotify(wid) + def addwidgetlazy(self, wid, size): + wid = lazynotify(wid) self.lazyitems.append(wid) wid.setFixedSize(size) self.l.addWidget(wid) + @trypass def addwidget(self, wid): self.l.addWidget(wid) + @trypass def insertwidget(self, idx, wid): self.l.insertWidget(idx, 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) @@ -286,7 +310,6 @@ class FlowLayout(QLayout): x = effective_rect.x() y = effective_rect.y() line_height = 0 - for item in self._item_list: wid = item.widget() @@ -316,3 +339,152 @@ class FlowLayout(QLayout): new_height = y + line_height - rect.y() self.heightChanged.emit(new_height) return new_height + + +class lazyscrollflow(QWidget): + bgclicked = pyqtSignal() + + def mousePressEvent(self, _2) -> None: + self.bgclicked.emit() + + def __init__(self): + super().__init__() + self.widgets = [] + self.fakegeos = [] + self._spacing = 6 + self._margin = 9 + self.lock = threading.Lock() + self.internalwid = QWidget(self) + self.qscrollarea = ScrollArea(self) + self.qscrollarea.setWidgetResizable(True) + self.qscrollarea.setWidget(self.internalwid) + self.qscrollarea.scrolled.connect(self.doshowlazywidget) + + def resizeEvent(self, a0: QResizeEvent) -> None: + self.qscrollarea.resize(self.size()) + self.resizeandshow() + return super().resizeEvent(a0) + + @trypass + def doshowlazywidget(self, region: QRect): + needdos = [] + with self.lock: + for i, geo in enumerate(self.fakegeos): + if isinstance(self.widgets[i], QWidget): + continue + + if not region.intersects(geo): + continue + + widfunc, _ = self.widgets[i] + if not widfunc: + continue + self.widgets[i] = (None, _) + needdos.append((i, widfunc)) + for i, widfunc in needdos: + try: + with self.lock: + widfunc = widfunc() + widfunc.setParent(self.internalwid) + widfunc.adjustSize() + widfunc.setVisible(True) + widfunc.setGeometry(self.fakegeos[i]) + self.widgets[i] = widfunc + + QApplication.processEvents() + + except: + pass + + @trypass + def resizeandshow(self): + self.fakeresize() + self.doshowlazywidget(self.internalwid.visibleRegion()) + + def addwidget(self, widfunc): + self.insertwidget(-1, widfunc) + + @trypass + def insertwidget(self, idx, widfunc): + refresh = True + with self.lock: + if idx == -1: + refresh = False + idx = len(self.widgets) + self.widgets.insert(idx, widfunc) + self.fakegeos.insert(idx, QRect()) + + if isinstance(widfunc, QWidget): + widfunc.setParent(self.internalwid) + widfunc.adjustSize() + widfunc.setVisible(True) + if refresh: + self.resizeandshow() + + @trypass + def removeidx(self, idx): + with self.lock: + if idx >= 0 and idx < len(self.widgets): + w = self.widgets[idx] + w.setParent(None) + w.deleteLater() + self.widgets.pop(idx) + self.fakegeos.pop(idx) + self.resizeandshow() + + @trypass + def setfocus(self, idx): + self.widget(idx).setFocus() + + @trypass + def widget(self, idx): + with self.lock: + if idx > 0 or idx < len(self.widgets): + return self.widgets[idx] + else: + return None + + def spacing(self): + return self._spacing + + def fakeresize(self): + if self.qscrollarea.verticalScrollBar().isVisible(): + scrollw = self.qscrollarea.verticalScrollBar().width() + else: + scrollw = 0 + with self.lock: + # m = self.contentsMargins() + rect = QRect() + rect.setSize(self.size()) + effective_rect = rect.adjusted( + self._margin, self._margin, -self._margin, -self._margin + ) # (+m.left(), +m.top(), -m.right(), -m.bottom()) + x = effective_rect.x() + y = effective_rect.y() + line_height = 0 + for i, wid in enumerate(self.widgets): + + space_x = self.spacing() + space_y = self.spacing() + + if isinstance(wid, QWidget): + sz = wid.size() + resize = True + else: + _, sz = wid + resize = False + next_x = x + sz.width() + space_x + if next_x > effective_rect.right() - scrollw and line_height > 0: + x = effective_rect.x() + y = y + line_height + space_y + next_x = x + sz.width() + space_x + line_height = 0 + if resize: + wid.setGeometry(QRect(QPoint(x, y), sz)) + self.fakegeos[i] = QRect(QPoint(x, y), sz) + x = next_x + line_height = max(line_height, sz.height()) + + new_height = y + line_height - rect.y() + self._margin + self.internalwid.setFixedHeight(new_height) + return new_height diff --git a/LunaTranslator/LunaTranslator/myutils/utils.py b/LunaTranslator/LunaTranslator/myutils/utils.py index f7d87e88..aa42850a 100644 --- a/LunaTranslator/LunaTranslator/myutils/utils.py +++ b/LunaTranslator/LunaTranslator/myutils/utils.py @@ -115,7 +115,13 @@ def dispatachtask(gamepath): def everymethodsthread(): while True: - gamepath, searchargs = searchvndbqueue.get() + _ = searchvndbqueue.get() + if isinstance(_, tuple): + gamepath, searchargs = _ + else: + gamepath = _ + dispatachtask(gamepath) + continue if checkneed(gamepath) == False: continue @@ -175,8 +181,7 @@ def checkifnewgame(gamepath, title=None): savehook_new_list.insert(0, gamepath) if gamepath not in savehook_new_data: savehook_new_data[gamepath] = getdefaultsavehook(gamepath, title) - if gamepath != "0": - dispatachtask(gamepath) + searchvndbqueue.put(gamepath) kanjichs2ja = str.maketrans(static_data["kanjichs2ja"]) diff --git a/LunaTranslator/files/defaultconfig/static_data.json b/LunaTranslator/files/defaultconfig/static_data.json index 8a13c81f..ba43f0c5 100644 --- a/LunaTranslator/files/defaultconfig/static_data.json +++ b/LunaTranslator/files/defaultconfig/static_data.json @@ -1,5 +1,5 @@ { - "version":"v2.45.3", + "version":"v2.45.4", "themes":{ "dark":[ {"file":"dark1.qss","name":"PyQtDarkTheme"},