diff --git a/LunaTranslator/LunaTranslator/LunaTranslator.py b/LunaTranslator/LunaTranslator/LunaTranslator.py index 9a539d21..32cd51d8 100644 --- a/LunaTranslator/LunaTranslator/LunaTranslator.py +++ b/LunaTranslator/LunaTranslator/LunaTranslator.py @@ -908,8 +908,29 @@ class MAINUI: self.__currentexe = None except: print_exc() + @threader + def clickwordcallback(self,word, append): + if globalconfig["usewordorigin"] == False: + word = word["orig"] + else: + word = word.get("origorig", word["orig"]) + if globalconfig["usecopyword"]: + if append: + winsharedutils.clipboard_set( + winsharedutils.clipboard_get() + word + ) + else: + winsharedutils.clipboard_set(word) + if globalconfig["usesearchword"]: + self.searchwordW.getnewsentencesignal.emit( + word, append + ) def setshowintab_checked(self, widget): + try: + self.translation_ui + except: + return if widget == self.translation_ui: winsharedutils.showintab(int(widget.winId()), globalconfig["showintab"]) return diff --git a/LunaTranslator/LunaTranslator/gui/inputdialog.py b/LunaTranslator/LunaTranslator/gui/inputdialog.py index 26005e5c..95cabd4f 100644 --- a/LunaTranslator/LunaTranslator/gui/inputdialog.py +++ b/LunaTranslator/LunaTranslator/gui/inputdialog.py @@ -249,9 +249,7 @@ class autoinitdialog(QDialog): ) lineW.rejected.connect(self.close) lineW.accepted.connect( - functools.partial( - save, None if "callback" not in line else line["callback"] - ) + functools.partial(save, line.get("callback", None)) ) lineW.button(QDialogButtonBox.StandardButton.Ok).setText(_TR("确定")) @@ -281,17 +279,17 @@ class autoinitdialog(QDialog): regist.append([dd, key, lineW.isChecked]) elif line["type"] == "spin": lineW = FocusDoubleSpin() - lineW.setMinimum(0 if "min" not in line else line["min"]) - lineW.setMaximum(100 if "max" not in line else line["max"]) - lineW.setSingleStep(0.1 if "step" not in line else line["step"]) + lineW.setMinimum(line.get("min", 0)) + lineW.setMaximum(line.get("max", 100)) + lineW.setSingleStep(line.get("step", 0.1)) lineW.setValue(dd[key]) lineW.valueChanged.connect(functools.partial(dd.__setitem__, key)) elif line["type"] == "intspin": lineW = FocusSpin() - lineW.setMinimum(0 if "min" not in line else line["min"]) - lineW.setMaximum(100 if "max" not in line else line["max"]) - lineW.setSingleStep(1 if "step" not in line else line["step"]) + lineW.setMinimum(line.get("min", 0)) + lineW.setMaximum(line.get("max", 100)) + lineW.setSingleStep(line.get("step", 1)) lineW.setValue(dd[key]) lineW.valueChanged.connect(functools.partial(dd.__setitem__, key)) if "name" in line: diff --git a/LunaTranslator/LunaTranslator/gui/setting_display_text.py b/LunaTranslator/LunaTranslator/gui/setting_display_text.py index 61981efa..eb97455d 100644 --- a/LunaTranslator/LunaTranslator/gui/setting_display_text.py +++ b/LunaTranslator/LunaTranslator/gui/setting_display_text.py @@ -1,17 +1,22 @@ from qtsymbols import * import functools -import gobject -from myutils.config import globalconfig, _TRL +import gobject, os +from myutils.config import globalconfig, _TRL, _TR from gui.inputdialog import multicolorset from gui.usefulwidget import ( D_getsimplecombobox, + getsimplecombobox, getsimpleswitch, D_getspinbox, getspinbox, D_getcolorbutton, + getcolorbutton, D_getsimpleswitch, selectcolor, - FocusFontCombo + FocusFontCombo, + FocusCombo, + FocusDoubleSpin, + FocusSpin, ) @@ -67,6 +72,115 @@ def createfenciwitch(self): return self.show_fenciswitch +def createinternalfontsettings(self, group, _type): + globalconfig["rendertext_using_internal"][group] = _type + __internal = globalconfig["rendertext"][group][_type] + dd = __internal.get("args", {}) + lay: QFormLayout = self.goodfontsettingsWidget.layout() + while lay.count() > 2: + item = lay.takeAt(2) + if not item: + break + w = item.widget() + lay.removeWidget(w) + w.deleteLater() + for key in dd: + line = __internal["argstype"][key] + name = line["name"] + _type = line["type"] + if _type == "colorselect": + lineW = getcolorbutton( + dd, + key, + transparent=False, + callback=functools.partial( + lambda dd, key, _: selectcolor( + self, dd, key, self.miaobian_color_button + ), + dd, + key, + ), + name="miaobian_color_button", + parent=self, + ) + elif _type == "spin": + lineW = FocusDoubleSpin() + lineW.setMinimum(line.get("min", 0)) + lineW.setMaximum(line.get("max", 100)) + lineW.setSingleStep(line.get("step", 0.1)) + lineW.setValue(dd[key]) + lineW.valueChanged.connect(functools.partial(dd.__setitem__, key)) + + elif _type == "intspin": + lineW = FocusSpin() + lineW.setMinimum(line.get("min", 0)) + lineW.setMaximum(line.get("max", 100)) + lineW.setSingleStep(line.get("step", 1)) + lineW.setValue(dd[key]) + lineW.valueChanged.connect(functools.partial(dd.__setitem__, key)) + lay.addRow( + name, + lineW, + ) + + +def resetgroudswitchcallback(self, group): + + try: + self.goodfontgroupswitch.currentIndexChanged.disconnect() + except: + pass + _ = [] + for k in globalconfig["rendertext"][group]: + if not os.path.exists(f"LunaTranslator/rendertext/internal/{group}/{k}.py"): + _.append(k) + for k in _: + globalconfig["rendertext"][group].pop(k) + + if ( + globalconfig["rendertext_using_internal"][group] + not in globalconfig["rendertext"][group] + ): + globalconfig["rendertext_using_internal"][group] = list( + globalconfig["rendertext"][group].keys() + )[0] + self.goodfontgroupswitch.clear() + self.goodfontgroupswitch.addItems( + _TRL( + [ + globalconfig["rendertext"][group][x]["name"] + for x in globalconfig["rendertext"][group] + ] + ) + ) + self.goodfontgroupswitch.setCurrentIndex(-1) + self.goodfontgroupswitch.currentIndexChanged.connect( + lambda idx: createinternalfontsettings( + self, group, list(globalconfig["rendertext"][group].keys())[idx] + ) + ) + self.goodfontgroupswitch.setCurrentIndex( + list(globalconfig["rendertext"][group].keys()).index( + globalconfig["rendertext_using_internal"][group] + ) + ) + + +def firsttime(self): + + self.goodfontgroupswitch = FocusCombo() + self.goodfontsettingsformlayout.addRow(_TR("字体样式"), self.goodfontgroupswitch) + resetgroudswitchcallback(self, globalconfig["rendertext_using"]) + + +def creategoodfontwid(self): + + self.goodfontsettingsWidget = QGroupBox() + self.goodfontsettingsformlayout = QFormLayout() + self.goodfontsettingsWidget.setLayout(self.goodfontsettingsformlayout) + return self.goodfontsettingsWidget, functools.partial(firsttime, self) + + def xianshigrid(self): textgrid = [ @@ -93,71 +207,21 @@ def xianshigrid(self): ("加粗字体", 5), D_getsimpleswitch(globalconfig, "showbold"), ], + [], [ - "", - ], - [ - ("字体样式", 3), + ("显示引擎", 3), ( D_getsimplecombobox( - _TRL( - [ - "普通字体", - "空心字体", - "描边字体", - "描边字体_2", - "描边字体_2_投影", - "发光字体", - ] - ), + _TRL(list(globalconfig["rendertext"].keys())), globalconfig, - "zitiyangshi2", + "rendertext_using", + internallist=list(globalconfig["rendertext"].keys()), + callback=functools.partial(resetgroudswitchcallback, self), ), 6, ), ], - [ - ("特殊字体样式填充颜色", 5), - D_getcolorbutton( - globalconfig, - "miaobiancolor", - transparent=False, - callback=lambda: selectcolor( - self, globalconfig, "miaobiancolor", self.miaobian_color_button - ), - name="miaobian_color_button", - parent=self, - ), - ], - [ - ("空心线宽", 3), - ( - D_getspinbox( - 0.1, 100, globalconfig, "miaobianwidth", double=True, step=0.1 - ), - 3, - ), - "", - ("描边宽度", 3), - ( - D_getspinbox( - 0.1, 100, globalconfig, "miaobianwidth2", double=True, step=0.1 - ), - 3, - ), - ], - [ - ("发光亮度", 3), - (D_getspinbox(1, 100, globalconfig, "shadowforce"), 3), - "", - ("投影距离", 3), - ( - D_getspinbox( - 0.1, 100, globalconfig, "traceoffset", double=True, step=0.1 - ), - 3, - ), - ], + [(functools.partial(creategoodfontwid, self), 0)], [], [ ("显示原文", 5), diff --git a/LunaTranslator/LunaTranslator/gui/textbrowser.py b/LunaTranslator/LunaTranslator/gui/textbrowser.py index bd7852d7..b50fde19 100644 --- a/LunaTranslator/LunaTranslator/gui/textbrowser.py +++ b/LunaTranslator/LunaTranslator/gui/textbrowser.py @@ -1,780 +1,74 @@ from qtsymbols import * -import functools -from traceback import print_exc from myutils.config import globalconfig - - -class Qlabel_c(QLabel): - - def mousePressEvent(self, ev): - self.pr = True - return super().mousePressEvent(ev) - - def mouseMoveEvent(self, ev): - pass - # return super().mouseMoveEvent(ev) - - def mouseReleaseEvent(self, event: QMouseEvent): - try: - if self.geometry().contains(self.parent().mapFromGlobal(QCursor.pos())): - try: - if self.pr: - if event.button() == Qt.MouseButton.RightButton: - self.callback(True) - else: - self.callback(False) - except: - print_exc() - self.pr = False - except: - print_exc() - return super().mouseReleaseEvent(event) - - def enterEvent(self, a0) -> None: - if self.company: - self.company.setStyleSheet("background-color: rgba(0,0,0,0.5);") - self.setStyleSheet("background-color: rgba(0,0,0,0.5);") - return super().enterEvent(a0) - - def leaveEvent(self, a0) -> None: - if self.company: - self.company.setStyleSheet("background-color: rgba(0,0,0,0.01);") - self.setStyleSheet("background-color: rgba(0,0,0,0.01);") - return super().leaveEvent(a0) - - -class QGraphicsDropShadowEffect_multi(QGraphicsDropShadowEffect): - def __init__(self, x) -> None: - self.x = x - super().__init__() - - def draw(self, painter) -> None: - for i in range(self.x): - super().draw(painter) - - -class BorderedLabel(QLabel): - def move(self, point: QPoint): - self.movedx = 0 - self.movedy = 0 - text = self.text() - isarabic = any((ord(char) >= 0x0600 and ord(char) <= 0x06E0) for char in text) - if isarabic: - self.movedx -= self.width() - self.movedx -= self.m_fontOutLineWidth - self.movedy -= self.m_fontOutLineWidth - point.setX(int(point.x() + self.movedx)) - point.setY(int(point.y() + self.movedy)) - super().move(point) - - def pos(self) -> QPoint: - p = super().pos() - p.setX(int(p.x() - self.movedx)) - p.setY(int(p.y() - self.movedy)) - return p - - def clearShadow(self): - self.setGraphicsEffect(None) - - def setShadow(self, colorshadow, width=1, deepth=1, trace=False): - - shadow2 = QGraphicsDropShadowEffect_multi(deepth) - if trace: - shadow2.setBlurRadius(width) - shadow2.setOffset(QPointF(width, width)) - else: - shadow2.setBlurRadius(width) - shadow2.setOffset(0) - shadow2.setColor(QColor(colorshadow)) - self.setGraphicsEffect(shadow2) - - def __init__(self, parent=None): - super().__init__(parent) - self.movedy = 0 - self.movedx = 0 - self.m_outLineColor = QColor() - self.m_fontOutLineWidth = 1 - self.m_contentColor = QColor() - self._type = 0 - self._pix = None - self._m_text = "" - - def text(self): - return self._m_text - - def setText(self, text): - self._m_text = text - - def setColorWidth(self, outLineColor, contentColor, width, _type=0): - - self.m_outLineColor = QColor(outLineColor) - self.m_contentColor = QColor(contentColor) - self.m_fontOutLineWidth = width - self._type = _type - - def adjustSize(self): - self._pix = None - font = self.font() - text = self.text() - font_m = QFontMetrics(font) - self.resize( - int(font_m.size(0, text).width() + 2 * self.m_fontOutLineWidth), - int(font_m.height() + 2 * self.m_fontOutLineWidth), - ) - - def labelresetcolor(self, color, rate=1): - c1 = color - c2 = globalconfig["miaobiancolor"] - if c1 is None: - c1 = "" - if c2 is None: - c2 = "" - if globalconfig["zitiyangshi2"] == 2: - self.setColorWidth(c1, c2, rate * globalconfig["miaobianwidth2"]) - self.clearShadow() - elif globalconfig["zitiyangshi2"] == 3: - self.setColorWidth(c2, c1, rate * globalconfig["miaobianwidth2"]) - self.clearShadow() - elif globalconfig["zitiyangshi2"] == 1: - self.setColorWidth(c1, c2, rate * globalconfig["miaobianwidth"], 1) - self.clearShadow() - elif globalconfig["zitiyangshi2"] == 4: - self.setColorWidth(c2, c1, rate * globalconfig["miaobianwidth2"]) - self.setShadow(c2, rate * globalconfig["traceoffset"], 1, True) - elif globalconfig["zitiyangshi2"] == 0: - self.setColorWidth("", c1, 0, 2) - self.clearShadow() - elif globalconfig["zitiyangshi2"] == 5: - self.setColorWidth("", c2, 0, 2) - self.setShadow( - c1, rate * globalconfig["fontsize"], globalconfig["shadowforce"] - ) - - def paintEvent(self, event): - if not self._pix: - rate = self.devicePixelRatioF() - self._pix = QPixmap(self.size() * rate) - self._pix.setDevicePixelRatio(rate) - self._pix.fill(Qt.GlobalColor.transparent) - text = self.text() - font = self.font() - font_m = QFontMetrics(font) - painter = QPainter(self._pix) - - painter.setRenderHint(QPainter.RenderHint.Antialiasing) - path = QPainterPath() - if self._type == 2: - - path.addText( - 0, - font_m.ascent(), - font, - text, - ) - painter.fillPath(path, QBrush(self.m_contentColor)) - else: - path.addText( - self.m_fontOutLineWidth, - self.m_fontOutLineWidth + font_m.ascent(), - font, - text, - ) - - pen = QPen( - self.m_outLineColor, - self.m_fontOutLineWidth, - Qt.PenStyle.SolidLine, - Qt.PenCapStyle.RoundCap, - Qt.PenJoinStyle.RoundJoin, - ) - - if self._type == 0: - painter.strokePath(path, pen) - painter.fillPath(path, QBrush(self.m_contentColor)) - elif self._type == 1: - painter.fillPath(path, QBrush(self.m_contentColor)) - painter.strokePath(path, pen) - painter = QPainter(self) - painter.drawPixmap(0, 0, self._pix) +import importlib class Textbrowser(QLabel): - contentsChanged = pyqtSignal(int, int) + contentsChanged = pyqtSignal(QSize) + + _padding = 10 def __makeborder(self, size: QSize): - _padding_resize = 5 - _padding_move = 5 - _padding = _padding_resize + _padding_move + _padding = self._padding self.masklabel_right.move(self.width() - _padding, 0) self.masklabel_bottom.move(0, 0 + size.height() - _padding) self.masklabel_left.resize(_padding, size.height()) self.masklabel_right.resize(_padding, size.height()) self.masklabel_bottom.resize(size.width(), _padding) - def move(self, x, y): - super().move(x, y) - self.textbrowser.move(x, y) - self.atback2.move(x, y) - self.toplabel2.move(x, y) - - self.__makeborder(self.size()) - def resizeEvent(self, event: QResizeEvent): - self.atback2.resize(event.size()) - self.toplabel2.resize(event.size()) - self.masklabel.resize(event.size()) - + _padding = self._padding + self.textbrowser.setGeometry( + _padding, + 0, + event.size().width() - 2 * _padding, + event.size().height() - _padding, + ) self.__makeborder(event.size()) - def contentchangedfunction(self): - sz = self.textbrowser.document().size().toSize() - self.textbrowser.resize(self.width(), sz.height()) - self.contentsChanged.emit(sz.width(), sz.height()) + def _contentsChanged(self, size: QSize): + self.contentsChanged.emit(QSize(size.width(), size.height())) + + def loadinternal(self): + tb = importlib.import_module( + f'rendertext.{globalconfig["rendertext_using"]}' + ).TextBrowser + + self.textbrowser = tb(self) + self.textbrowser.setMouseTracking(True) + self.textbrowser.contentsChanged.connect(self._contentsChanged) def __init__(self, parent): super().__init__(parent) self.setMouseTracking(True) - - self.atback2 = QLabel(parent) - - self.toplabel2 = QLabel(parent) - self.atback2.setMouseTracking(True) - self.textbrowser = QTextBrowser(parent) - self.textbrowser.document().contentsChanged.connect(self.contentchangedfunction) - self.tranparentcolor = QColor() - self.tranparentcolor.setAlpha(0) - self.textbrowser.setTextColor(self.tranparentcolor) - self.cleared = False - self.font = QFont() - - self.toplabel2.setMouseTracking(True) - - self.textbrowser.setStyleSheet( - "border-width: 0;\ - border-style: outset;\ - background-color: rgba(0, 0, 0, 0)" - ) - - self.textcursor = self.textbrowser.textCursor() - self.textbrowser.setVerticalScrollBarPolicy( - Qt.ScrollBarPolicy.ScrollBarAlwaysOff - ) - self.textbrowser.setHorizontalScrollBarPolicy( - Qt.ScrollBarPolicy.ScrollBarAlwaysOff - ) - self.masklabel = QLabel(self.textbrowser) - self.masklabel.setMouseTracking(True) - self.masklabel_left = QLabel(self.textbrowser) + self.cleared = True + self.loadinternal() + self.masklabel_left = QLabel(self) self.masklabel_left.setMouseTracking(True) - self.masklabel_right = QLabel(self.textbrowser) + # self.masklabel_left.setStyleSheet('background-color:red') + self.masklabel_right = QLabel(self) + # self.masklabel_right.setStyleSheet('background-color:red') self.masklabel_right.setMouseTracking(True) - self.masklabel_bottom = QLabel(self.textbrowser) + self.masklabel_bottom = QLabel(self) self.masklabel_bottom.setMouseTracking(True) - - self.savetaglabels = [] - self.searchmasklabels_clicked = [] - self.searchmasklabels = [] - self.backcolorlabels = [] - - self.yinyinglabels = [] - self.yinyinglabels_idx = 0 - - self.yinyingpos = 0 - self.yinyingposline = 0 - self.lastcolor = None + # self.masklabel_bottom.setStyleSheet('background-color:red') self.setselectable() - self.blockcount = 0 - self.iteryinyinglabelsave = {} def setselectable(self): - self.masklabel.setHidden(globalconfig["selectable"]) + self.textbrowser.setselectable(globalconfig["selectable"]) - def setnextfont(self, origin): - if origin: - self.font.setFamily(globalconfig["fonttype"]) - else: - self.font.setFamily(globalconfig["fonttype2"]) - self.font.setPointSizeF(globalconfig["fontsize"]) - self.font.setBold(globalconfig["showbold"]) - - self.textbrowser.moveCursor(QTextCursor.MoveOperation.End) - f = QTextCharFormat() - f.setFont(self.font) - f.setForeground(self.tranparentcolor) - c = self.textbrowser.textCursor() - c.setCharFormat(f) - self.textbrowser.setTextCursor(c) - - def setAlignment(self, x): - self.textbrowser.setAlignment(x) - - def append(self, x, tag, color): - if self.cleared: - _space = "" - self.blockcount = 0 - b1 = 0 - else: - _space = "\n" - b1 = self.textbrowser.document().blockCount() + def iter_append(self, iter_context_class, origin, atcenter, text, color): + cleared = self.cleared self.cleared = False - self.textbrowser.insertPlainText(_space + x) + self.textbrowser.iter_append( + iter_context_class, origin, atcenter, text, color, cleared + ) - b2 = self.textbrowser.document().blockCount() - - fh = globalconfig["extra_space"] - for i in range(self.blockcount, self.textbrowser.document().blockCount()): - b = self.textbrowser.document().findBlockByNumber(i) - tf = b.blockFormat() - if isqt5: - lht = QTextBlockFormat.LineHeightTypes.LineDistanceHeight - else: - lht = 4 - tf.setLineHeight(fh, lht) - self.textcursor.setPosition(b.position()) - self.textcursor.setBlockFormat(tf) - self.textbrowser.setTextCursor(self.textcursor) - self.blockcount = self.textbrowser.document().blockCount() - - if len(tag) > 0: - self.addtag(tag) - self.showyinyingtext(b1, b2, color) - - def getcurrpointer(self): - return self.textcursor.position() - - def insertatpointer(self, pointer, text): - self.textcursor.setPosition(pointer) - self.textbrowser.setTextCursor(self.textcursor) - self.textbrowser.insertPlainText(text) - - def deletebetween(self, p1, p2): - self.textcursor.setPosition(p1, QTextCursor.MoveMode.MoveAnchor) - self.textcursor.setPosition(p2, QTextCursor.MoveMode.KeepAnchor) - self.textcursor.removeSelectedText() - - def showyinyingtext2(self, color, iter_context_class, pos, text): - if iter_context_class not in self.iteryinyinglabelsave: - self.iteryinyinglabelsave[iter_context_class] = [[], 0] - maxh = 0 - maxh2 = 9999999 - for label in self.iteryinyinglabelsave[iter_context_class][0]: - maxh2 = min(label.pos().y(), maxh2) - if label.isVisible() == False: - continue - label.hide() - maxh = max(label.pos().y(), maxh) - - subtext = [] - subpos = [] - lastpos = None - posx = pos - for i in range(len(text)): - self.textcursor.setPosition(posx) - posx += 1 - tl1 = self.textbrowser.cursorRect(self.textcursor).topLeft() - if lastpos is None or tl1.y() != lastpos.y() or text[i] == "\n": - lastpos = tl1 - subpos.append(lastpos) - subtext.append("") - subtext[-1] += text[i] - - maxnewh = 0 - for i in range(len(subtext)): - if self.iteryinyinglabelsave[iter_context_class][1] >= len( - self.iteryinyinglabelsave[iter_context_class][0] - ): - self.iteryinyinglabelsave[iter_context_class][0].append( - BorderedLabel(self.toplabel2) - ) - maxnewh = max(maxnewh, subpos[i].y()) - _ = self.iteryinyinglabelsave[iter_context_class][0][ - self.iteryinyinglabelsave[iter_context_class][1] - ] - _.labelresetcolor(color) - _.setText(subtext[i]) - _.setFont(self.font) - _.adjustSize() - _.move(subpos[i]) - _.show() - self.iteryinyinglabelsave[iter_context_class][1] += 1 - - if maxh: - if maxnewh == 0: - maxnewh = maxh2 - for label in self.yinyinglabels: - if label.isVisible() == False: - continue - if label.pos().y() > maxh: - label.move( - QPoint(label.pos().x(), label.pos().y() + maxnewh - maxh) - ) - for klass in self.iteryinyinglabelsave: - if klass == iter_context_class: - continue - for label in self.iteryinyinglabelsave[klass][0]: - if label.isVisible() == False: - continue - if label.pos().y() > maxh: - label.move( - QPoint(label.pos().x(), label.pos().y() + maxnewh - maxh) - ) - - def showyinyingtext(self, b1, b2, color): - linei = self.yinyingposline - - doc = self.textbrowser.document() - block = doc.findBlockByNumber(0) - - for blocki in range(b1, b2): - block = doc.findBlockByNumber(blocki) - layout = block.layout() - blockstart = block.position() - lc = layout.lineCount() - for lineii in range(lc): - line = layout.lineAt(lineii) - - s = line.textStart() - l = line.textLength() - self.textcursor.setPosition(blockstart + s) - self.textbrowser.setTextCursor(self.textcursor) - tl1 = self.textbrowser.cursorRect(self.textcursor).topLeft() - - if self.yinyinglabels_idx >= len(self.yinyinglabels): - self.yinyinglabels.append(BorderedLabel(self.toplabel2)) - _ = self.yinyinglabels[self.yinyinglabels_idx] - self.yinyinglabels_idx += 1 - _.labelresetcolor(color) - _.setText(block.text()[s : s + l]) - _.setFont(self.font) - _.adjustSize() - _.move(tl1) - _.show() - linei += 1 - self.yinyingposline = linei - - def addsearchwordmask(self, x, raw, callback=None): - if len(x) == 0: - return - # print(x) - pos = 0 - labeli = 0 - self.textcursor.setPosition(0) - self.textbrowser.setTextCursor(self.textcursor) - - idx = 0 - heigth, __, _ = self.getfh(False) - for word in x: - idx += 1 - l = len(word["orig"]) - tl1 = self.textbrowser.cursorRect(self.textcursor).topLeft() - - tl4 = self.textbrowser.cursorRect(self.textcursor).bottomRight() - - if True: - self.textcursor.setPosition(pos + l) - self.textbrowser.setTextCursor(self.textcursor) - - tl2 = self.textbrowser.cursorRect(self.textcursor).bottomRight() - tl3 = self.textbrowser.cursorRect(self.textcursor).topLeft() - color = self.randomcolor(word) - if color: - if word["orig"] not in ["\n", " ", ""]: - if labeli >= len(self.searchmasklabels) - 1: - ql = QLabel(self.atback2) - ql.setMouseTracking(True) - self.searchmasklabels.append(ql) - - ql = Qlabel_c(self.textbrowser) - ql.setMouseTracking(True) - ql.setStyleSheet("background-color: rgba(0,0,0,0.01);") - self.searchmasklabels_clicked.append(ql) - - ql = QLabel(self.atback2) - ql.setMouseTracking(True) - self.searchmasklabels.append(ql) - - ql = Qlabel_c(self.textbrowser) - ql.setMouseTracking(True) - ql.setStyleSheet("background-color: rgba(0,0,0,0.01);") - self.searchmasklabels_clicked.append(ql) - if tl1.y() != tl3.y(): - for __i in range(len(word["orig"])): - self.textcursor.setPosition(pos + __i) - self.textbrowser.setTextCursor(self.textcursor) - _tl = self.textbrowser.cursorRect( - self.textcursor - ).topLeft() - if _tl.y() != tl1.y(): - break - self.textcursor.setPosition(pos + l) - self.textbrowser.setTextCursor(self.textcursor) - __fm = self.getfh(False, getfm=True) - w1 = int(__fm.size(0, word["orig"][:__i]).width()) - w2 = int(__fm.size(0, word["orig"][__i:]).width()) - - pos1 = ( - tl1.x() + 1, - tl1.y(), - w1 - 2, - int(heigth), - ) - pos2 = tl3.x() + 1 - w2, tl3.y(), w2 - 2, int(heigth) - - if ( - globalconfig["usesearchword"] - or globalconfig["usecopyword"] - ): - self.searchmasklabels_clicked[labeli].setGeometry(*pos1) - self.searchmasklabels_clicked[labeli].show() - self.searchmasklabels_clicked[labeli].company = ( - self.searchmasklabels_clicked[labeli + 1] - ) - if callback: - self.searchmasklabels_clicked[labeli].callback = ( - functools.partial(callback, (word)) - ) - - self.searchmasklabels_clicked[labeli + 1].setGeometry( - *pos2 - ) - self.searchmasklabels_clicked[labeli + 1].show() - self.searchmasklabels_clicked[labeli + 1].company = ( - self.searchmasklabels_clicked[labeli] - ) - if callback: - self.searchmasklabels_clicked[ - labeli + 1 - ].callback = functools.partial(callback, (word)) - - if globalconfig["show_fenci"]: - self.searchmasklabels[labeli].setGeometry(*pos1) - self.searchmasklabels[labeli].setStyleSheet( - "background-color: rgba{};".format(color) - ) - self.searchmasklabels[labeli].show() - - self.searchmasklabels[labeli + 1].setGeometry(*pos2) - self.searchmasklabels[labeli + 1].setStyleSheet( - "background-color: rgba{};".format(color) - ) - self.searchmasklabels[labeli + 1].show() - labeli += 2 - else: - - pos1 = ( - tl1.x() + 1, - tl1.y(), - tl2.x() - tl1.x() - 2, - int(heigth), - ) - if ( - globalconfig["usesearchword"] - or globalconfig["usecopyword"] - ): - self.searchmasklabels_clicked[labeli].setGeometry(*pos1) - self.searchmasklabels_clicked[labeli].company = None - self.searchmasklabels_clicked[labeli].show() - if callback: - self.searchmasklabels_clicked[labeli].callback = ( - functools.partial(callback, word) - ) - if globalconfig["show_fenci"]: - self.searchmasklabels[labeli].setGeometry(*pos1) - self.searchmasklabels[labeli].setStyleSheet( - "background-color: rgba{};".format(color) - ) - self.searchmasklabels[labeli].show() - labeli += 1 - - tl1 = tl3 - tl4 = tl2 - - pos += l - - def randomcolor(self, word): - if word.get("isdeli", False): - return None - c = QColor("white") - if "cixing" in word: - try: - if globalconfig["cixingcolorshow"][word["cixing"]] == False: - return None - c = QColor(globalconfig["cixingcolor"][word["cixing"]]) - except: - pass - return (c.red(), c.green(), c.blue(), globalconfig["showcixing_touming"] / 100) - - def getfh(self, half, origin=True, getfm=False): - - font = QFont() - font.setBold(globalconfig["showbold"]) - if origin: - font.setFamily(globalconfig["fonttype"]) - else: - font.setFamily(globalconfig["fonttype2"]) - - # font.setPixelSize(int(globalconfig['fontsize']) ) - if half: - font.setPointSizeF((globalconfig["fontsize"]) * globalconfig["kanarate"]) - else: - font.setPointSizeF((globalconfig["fontsize"])) - fm = QFontMetricsF(font) - if getfm: - return fm - return fm.height(), fm.ascent(), font - - def addtag(self, x): - pos = 0 - - fasall, _, fontorig = self.getfh(False) - fha, fascent, fonthira = self.getfh(True) - for i in range(0, self.textbrowser.document().blockCount()): - b = self.textbrowser.document().findBlockByNumber(i) - - tf = b.blockFormat() - if isqt5: - lht = QTextBlockFormat.LineHeightTypes.FixedHeight - else: - lht = 2 - tf.setLineHeight(fasall + fha, lht) - self.textcursor.setPosition(b.position()) - self.textcursor.setBlockFormat(tf) - self.textbrowser.setTextCursor(self.textcursor) - x = self.nearmerge(x, pos, fonthira, fontorig) - self.settextposcursor(pos) - savetaglabels_idx = 0 - for word in x: - l = len(word["orig"]) - - tl1 = self.textbrowser.cursorRect(self.textcursor).topLeft() - - self.settextposcursor(pos + l) - pos += l - - tl2 = self.textbrowser.cursorRect(self.textcursor).topLeft() - if word["hira"] == word["orig"]: - continue - # print(tl1,tl2,word['hira'],self.textbrowser.textCursor().position()) - if word["orig"] == " ": - continue - if savetaglabels_idx >= len(self.savetaglabels): - self.savetaglabels.append(BorderedLabel(self.atback2)) - self.solvejiaminglabel( - self.savetaglabels[savetaglabels_idx], word, fonthira, tl1, tl2, fascent - ) - savetaglabels_idx += 1 - - def settextposcursor(self, pos): - self.textcursor.setPosition(pos) - self.textbrowser.setTextCursor(self.textcursor) - - def nearmerge(self, x, startpos, fonthira, fontorig): - pos = startpos - linex = [] - newline = [] - self.settextposcursor(pos) - _metrichira = QFontMetricsF(fonthira) - _metricorig = QFontMetricsF(fontorig) - for i, word in enumerate(x): - word["orig_w"] = _metricorig.size(0, word["orig"]).width() - word["hira_w"] = _metrichira.size(0, word["hira"]).width() - # print(word['hira'],word['hira_w']) - newline.append(word) - - l = len(word["orig"]) - tl1 = self.textbrowser.cursorRect(self.textcursor).topLeft() - self.settextposcursor(pos + l) - pos += l - - tl2 = self.textbrowser.cursorRect(self.textcursor).topLeft() - - # print(tl1,tl2,word['hira'],self.textbrowser.textCursor().position()) - - if tl1.y() != tl2.y() or i == len(x) - 1: - linex.append(newline) - newline = [] - res = [] - for line in linex: - - while True: - allnotbig = True - newline = [] - canmerge = False - for word in line: - if ( - word["hira"] == word["orig"] - or word["hira"] == "" - or word["orig"] == "" - ): - newline.append(word.copy()) - canmerge = False - else: - if ( - len(newline) > 0 - and canmerge - and ( - word["hira_w"] + newline[-1]["hira_w"] - > word["orig_w"] + newline[-1]["orig_w"] - ) - ): - # print(word['hira'],word['hira_w'],newline[-1]['hira_w'],word['orig_w'],newline[-1]['orig_w']) - newline[-1]["hira"] += word["hira"] - newline[-1]["orig"] += word["orig"] - newline[-1]["hira_w"] += word["hira_w"] - newline[-1]["orig_w"] += word["orig_w"] - allnotbig = False - else: - newline.append(word.copy()) - canmerge = True - line = newline - if allnotbig: - break - res += newline - newline = [] - self.settextposcursor(startpos) - return res - - def solvejiaminglabel(self, _: BorderedLabel, word, font, tl1, tl2, fh): - _.labelresetcolor(globalconfig["jiamingcolor"], rate=globalconfig["kanarate"]) - _.setText(word["hira"]) - _.setFont(font) - _.adjustSize() - w = _.width() - - if tl1.y() != tl2.y(): - # print(label,word) - x = tl1.x() - if x + w / 2 < self.textbrowser.width(): - x = tl1.x() - y = tl1.y() - fh - else: - x = tl2.x() - w - y = tl2.y() - fh - else: - x = tl1.x() / 2 + tl2.x() / 2 - w / 2 - y = tl2.y() - fh - - _.move(QPoint(int(x), int(y))) - - _.show() - return _ + def append(self, origin, atcenter, text, tag, flags, color): + cleared = self.cleared + self.cleared = False + self.textbrowser.append(origin, atcenter, text, tag, flags, color, cleared) def clear(self): - for label in self.searchmasklabels: - label.hide() - for label in self.searchmasklabels_clicked: - label.hide() - for label in self.savetaglabels: - label.hide() - - self.yinyinglabels_idx = 0 - for label in self.yinyinglabels: - label.hide() - for klass, labels in self.iteryinyinglabelsave.items(): - for label in labels[0]: - label.hide() - labels[1] = 0 - self.yinyingpos = 0 - self.yinyingposline = 0 self.cleared = True self.textbrowser.clear() diff --git a/LunaTranslator/LunaTranslator/gui/translatorUI.py b/LunaTranslator/LunaTranslator/gui/translatorUI.py index fb5a841a..7fcc9b0a 100644 --- a/LunaTranslator/LunaTranslator/gui/translatorUI.py +++ b/LunaTranslator/LunaTranslator/gui/translatorUI.py @@ -17,7 +17,7 @@ from gui.dialog_savedgame import browserdialog, dialog_savedgame_integrated class QUnFrameWindow(resizableframeless): - displayglobaltooltip= pyqtSignal(str) + displayglobaltooltip = pyqtSignal(str) displayres = pyqtSignal(dict) displayraw1 = pyqtSignal(dict) displaystatus = pyqtSignal(str, str, bool, bool) @@ -99,7 +99,7 @@ class QUnFrameWindow(resizableframeless): except: print_exc() - def showraw(self, kwargs): # hira,res,color,onlytrans): + def showraw(self, kwargs): # res,color,onlytrans): text = kwargs.get("text") color = kwargs.get("color") onlytrans = kwargs.get("onlytrans") @@ -113,13 +113,7 @@ class QUnFrameWindow(resizableframeless): else: _res = text if globalconfig["isshowrawtext"]: - hira = ( - globalconfig["isshowhira"] - or globalconfig["usesearchword"] - or globalconfig["usecopyword"] - or globalconfig["show_fenci"] - ) - self.showline(clear=clear, text=_res, hira=hira, color=color) + self.showline(clear=clear, text=_res, isshowrawtext=True, color=color) else: self.showline(clear=clear) @@ -157,98 +151,45 @@ class QUnFrameWindow(resizableframeless): clear = kwargs.get("clear", True) origin = kwargs.get("origin", True) text = kwargs.get("text", None) - color = kwargs.get("color", None) - hira = kwargs.get("hira", False) + color = kwargs.get("color", 'black') + isshowrawtext = kwargs.get("isshowrawtext", False) iter_context = kwargs.get("iter_context", None) if clear: self.translate_text.clear() - self.saveiterclasspointer.clear() if text is None: return text = self.cleartext(text) - if hira: - hira = self.parsehira(text) - else: - hira = [] - self.translate_text.setnextfont(origin) - if globalconfig["showatcenter"]: - self.translate_text.setAlignment(Qt.AlignmentFlag.AlignCenter) - else: - self.translate_text.setAlignment(Qt.AlignmentFlag.AlignLeft) + atcenter = globalconfig["showatcenter"] if iter_context: _, iter_context_class = iter_context - - if iter_context_class not in self.saveiterclasspointer: - self.translate_text.append(" ", hira, origin) - self.saveiterclasspointer[iter_context_class] = { - "currtext": "", - "curr": self.translate_text.getcurrpointer(), - "start": self.translate_text.getcurrpointer(), - } - - currbefore = self.saveiterclasspointer[iter_context_class]["curr"] - currlen = len(self.saveiterclasspointer[iter_context_class]["currtext"]) - if len(text) < currlen: - self.translate_text.deletebetween( - self.saveiterclasspointer[iter_context_class]["start"] + len(text), - self.saveiterclasspointer[iter_context_class]["curr"], - ) - else: - newtext = text[currlen:] - self.translate_text.insertatpointer( - self.saveiterclasspointer[iter_context_class]["start"] + currlen, - newtext, - ) - - self.saveiterclasspointer[iter_context_class]["currtext"] = text - currcurrent = self.translate_text.getcurrpointer() - self.saveiterclasspointer[iter_context_class]["curr"] = currcurrent - currchange = currcurrent - currbefore - for klass in self.saveiterclasspointer: - if klass == iter_context_class: - continue - if self.saveiterclasspointer[klass]["curr"] > currbefore: - self.saveiterclasspointer[klass]["curr"] += currchange - self.saveiterclasspointer[klass]["start"] += currchange - - self.translate_text.showyinyingtext2( - color, - iter_context_class, - self.saveiterclasspointer[iter_context_class]["start"], - text, + self.translate_text.iter_append( + iter_context_class, origin, atcenter, text, color ) - else: + hira = [] + isshowhira = isshow_fenci = isfenciclick = False + if isshowrawtext: + isshowhira = globalconfig["isshowhira"] + isshow_fenci = globalconfig["show_fenci"] + isfenciclick = ( + globalconfig["usesearchword"] or globalconfig["usecopyword"] + ) + needhira = isshow_fenci or isshowhira or isfenciclick + if needhira: + hira = self.parsehira(text) + self.translate_text.append( - text, hira if globalconfig["isshowhira"] else [], color + origin, + atcenter, + text, + hira, + (isshowhira, isshow_fenci, isfenciclick), + color, ) - if hira: - - @threader - def callback(word, append): - if globalconfig["usewordorigin"] == False: - word = word["orig"] - else: - word = word.get("origorig", word["orig"]) - - if globalconfig["usecopyword"]: - if append: - winsharedutils.clipboard_set( - winsharedutils.clipboard_get() + word - ) - else: - winsharedutils.clipboard_set(word) - if globalconfig["usesearchword"]: - gobject.baseobject.searchwordW.getnewsentencesignal.emit( - word, append - ) - - self.translate_text.addsearchwordmask(hira, text, callback) - if globalconfig["autodisappear"]: flag = (globalconfig["showintab"] and self.isMinimized()) or ( not globalconfig["showintab"] and self.isHidden() @@ -591,13 +532,14 @@ class QUnFrameWindow(resizableframeless): self.buttons = {} self.showbuttons = [] self.stylebuttons = {} - self.saveiterclasspointer = {} - def displayglobaltooltip_f(self,string): + + def displayglobaltooltip_f(self, string): QToolTip.showText( - QCursor.pos(), - string, - gobject.baseobject.translation_ui, - ) + QCursor.pos(), + string, + gobject.baseobject.translation_ui, + ) + def initsignals(self): self.hidesignal.connect(self.hide_) self.displayglobaltooltip.connect(self.displayglobaltooltip_f) @@ -644,7 +586,6 @@ class QUnFrameWindow(resizableframeless): self._TitleLabel = QLabel(self) self.addbuttons() self.translate_text = Textbrowser(self) - self.translate_text.contentsChanged.connect(self.textAreaChanged) def createborderradiusstring(self, r, merge, top=False): @@ -695,7 +636,7 @@ class QUnFrameWindow(resizableframeless): ) self.translate_text.setStyleSheet( - "border-width: 0;%s;background-color: %s" + "Textbrowser{border-width: 0;%s;background-color: %s}" % ( topr, str2rgba( @@ -879,21 +820,17 @@ class QUnFrameWindow(resizableframeless): globalconfig["locktools"] = not globalconfig["locktools"] self.refreshtoolicon() - def textAreaChanged(self, w, h): + def textAreaChanged(self, size: QSize): if globalconfig["fixedheight"]: return if self.translate_text.cleared: return - newHeight = h + newHeight = size.height() + self.translate_text._padding width = self.width() self.resize( width, - int( - max(0, -globalconfig["extra_space"]) - + newHeight - + globalconfig["buttonsize"] * 1.5 - ), + int(newHeight + globalconfig["buttonsize"] * 1.5), ) def clickRange(self, auto): diff --git a/LunaTranslator/LunaTranslator/gui/usefulwidget.py b/LunaTranslator/LunaTranslator/gui/usefulwidget.py index fecfb145..8d62e454 100644 --- a/LunaTranslator/LunaTranslator/gui/usefulwidget.py +++ b/LunaTranslator/LunaTranslator/gui/usefulwidget.py @@ -30,6 +30,7 @@ class FocusCombo(QComboBox): class FocusFontCombo(QFontComboBox, FocusCombo): pass + class FocusSpin(QSpinBox): def __init__(self, parent: QWidget = None) -> None: super().__init__(parent) @@ -423,7 +424,8 @@ def callbackwrap(d, k, call, _): def comboboxcallbackwrap(internallist, d, k, call, _): - d[k] = internallist[_] + _ = internallist[_] + d[k] = _ if call: try: call(_) @@ -670,7 +672,53 @@ class abstractwebview(QWidget): on_ZoomFactorChanged = pyqtSignal(float) html_limit = 2 * 1024 * 1024 - def parsehtml(self, html): + # 必须的接口 + def _setHtml(self, html): + pass + + def navigate(self, url): + pass + + # + def _parsehtml(self, html): + return self._parsehtml_dark_auto(html) + + def set_zoom(self, zoom): + pass + + def set_transparent_background(self): + pass + + def clear(self): + self.navigate("about:blank") + + def setHtml(self, html): + html = self._parsehtml(html) + if len(html) < self.html_limit: + self._setHtml(html) + else: + os.makedirs("cache/temp", exist_ok=True) + lastcachehtml = os.path.abspath("cache/temp/" + str(time.time()) + ".html") + with open(lastcachehtml, "w", encoding="utf8") as ff: + ff.write(html) + self.navigate(lastcachehtml) + + def _parsehtml_dark(self, html): + if nowisdark(): + html = ( + html + + """ + """ + ) + return html + + def _parsehtml_dark_auto(self, html): return ( html + """ @@ -690,9 +738,6 @@ class abstractwebview(QWidget): """ ) - def set_zoom(self, zoom): - pass - class WebivewWidget(abstractwebview): @@ -766,9 +811,56 @@ class WebivewWidget(abstractwebview): size = getscaledrect(a0.size()) windows.MoveWindow(hwnd, 0, 0, size[0], size[1], True) - def setHtml(self, html): + def _setHtml(self, html): self.webview.set_html(html) + def set_transparent_background(self): + winsharedutils.set_transparent_background(self.get_controller()) + + +class QWebWrap(abstractwebview): + + def __init__(self) -> None: + super().__init__() + from PyQt5.QtWebEngineWidgets import QWebEngineView + + self.internal = QWebEngineView(self) + self.internal.page().urlChanged.connect( + lambda qurl: self.on_load.emit(qurl.url()) + ) + self.internal_zoom = 1 + t = QTimer(self) + t.setInterval(100) + t.timeout.connect(self.__getzoomfactor) + t.timeout.emit() + t.start() + + def set_zoom(self, zoom): + self.internal_zoom = zoom + self.internal.setZoomFactor(zoom) + + def __getzoomfactor(self): + z = self.internal.zoomFactor() + if z != self.internal_zoom: + self.internal_zoom = z + self.on_ZoomFactorChanged.emit(z) + + def navigate(self, url: str): + from PyQt5.QtCore import QUrl + + if not url.lower().startswith("http"): + url = url.replace("\\", "/") + self.internal.load(QUrl(url)) + + def _setHtml(self, html): + self.internal.setHtml(html) + + def resizeEvent(self, a0: QResizeEvent) -> None: + self.internal.resize(a0.size()) + + def _parsehtml(self, html): + return self._parsehtml_dark(html) + class mshtmlWidget(abstractwebview): @@ -797,22 +889,11 @@ class mshtmlWidget(abstractwebview): size = getscaledrect(a0.size()) self.browser.resize(0, 0, size[0], size[1]) - def setHtml(self, html): + def _setHtml(self, html): self.browser.set_html(html) - def parsehtml(self, html): - if nowisdark(): - html = ( - html - + """ - """ - ) + def _parsehtml(self, html): + html = self._parsehtml_dark(html) html = """
{}""".format( QFontDatabase.systemFont(QFontDatabase.GeneralFont).family(), html ) @@ -850,68 +931,12 @@ def D_getsimplekeyseq(dic, key, callback=None): return lambda: getsimplekeyseq(dic, key, callback) -class QWebWrap(abstractwebview): - - def __init__(self) -> None: - super().__init__() - from PyQt5.QtWebEngineWidgets import QWebEngineView - - self.internal = QWebEngineView(self) - self.internal.page().urlChanged.connect( - lambda qurl: self.on_load.emit(qurl.url()) - ) - self.internal_zoom = 1 - t = QTimer(self) - t.setInterval(100) - t.timeout.connect(self.__getzoomfactor) - t.timeout.emit() - t.start() - - def parsehtml(self, html): - if nowisdark(): - html = ( - html - + """ - """ - ) - return html - - def set_zoom(self, zoom): - self.internal_zoom = zoom - self.internal.setZoomFactor(zoom) - - def __getzoomfactor(self): - z = self.internal.zoomFactor() - if z != self.internal_zoom: - self.internal_zoom = z - self.on_ZoomFactorChanged.emit(z) - - def navigate(self, url: str): - from PyQt5.QtCore import QUrl - - if not url.lower().startswith("http"): - url = url.replace("\\", "/") - self.internal.load(QUrl(url)) - - def setHtml(self, html): - self.internal.setHtml(html) - - def resizeEvent(self, a0: QResizeEvent) -> None: - self.internal.resize(a0.size()) - - class auto_select_webview(QWidget): on_load = pyqtSignal(str) on_ZoomFactorChanged = pyqtSignal(float) def clear(self): - self.navigate("about:blank") + self.internal.clear() def navigate(self, url): self._maybecreate() @@ -921,15 +946,7 @@ class auto_select_webview(QWidget): def setHtml(self, html): self._maybecreate() self.internal.set_zoom(self.internalsavedzoom) - html = self.internal.parsehtml(html) - if len(html) < self.internal.html_limit: - self.internal.setHtml(html) - else: - os.makedirs("cache/temp", exist_ok=True) - lastcachehtml = os.path.abspath("cache/temp/" + str(time.time()) + ".html") - with open(lastcachehtml, "w", encoding="utf8") as ff: - ff.write(html) - self.internal.navigate(lastcachehtml) + self.internal.setHtml(html) def set_zoom(self, zoom): self.internalsavedzoom = zoom @@ -1078,9 +1095,14 @@ def automakegrid(grid: QGridLayout, lis, save=False, savelist=None): col = maxl - nowc else: col = -maxl // cols + do = None if callable(wid): wid = wid() + if isinstance(wid, tuple): + wid, do = wid grid.addWidget(wid, nowr, nowc, 1, col) + if do: + do() if save: ll.append(wid) nowc += cols @@ -1280,8 +1302,8 @@ class listediter(QDialog): "", multi=False, edit=None, - isdir=self.ispathsedit.get("isdir",False), - filter1=self.ispathsedit.get("filter1",'*.*'), + isdir=self.ispathsedit.get("isdir", False), + filter1=self.ispathsedit.get("filter1", "*.*"), callback=self.__cb, ) else: diff --git a/LunaTranslator/LunaTranslator/qtsymbols.py b/LunaTranslator/LunaTranslator/qtsymbols.py index eb1213f8..866a8896 100644 --- a/LunaTranslator/LunaTranslator/qtsymbols.py +++ b/LunaTranslator/LunaTranslator/qtsymbols.py @@ -1,6 +1,6 @@ try: from PyQt5 import QtSvg - from PyQt5.QtWidgets import QFrame,QListView,QCheckBox,QAbstractItemView,QTextEdit,QTableView,QHeaderView,QColorDialog,QSpinBox,QDoubleSpinBox,QComboBox,QDialogButtonBox,QMainWindow,QMessageBox,QDialog,QGridLayout,QTextBrowser,QGraphicsDropShadowEffect,QWidget,QSizePolicy,QScrollArea,QApplication,QPushButton,QSystemTrayIcon,QPlainTextEdit,QAction,QMenu,QFileDialog,QKeySequenceEdit,QLabel,QSpacerItem,QWidgetItem,QLayout,QTextBrowser,QLineEdit,QFormLayout,QSizePolicy,QTabWidget,QTabBar,QSplitter,QListWidget,QListWidgetItem,QHBoxLayout,QVBoxLayout,QSizeGrip,QFontComboBox,QProgressBar,QRadioButton,QButtonGroup,QSlider,QToolTip + 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 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 from PyQt5.QtCore import QObject,pyqtSignal,Qt,QSize,QByteArray,QBuffer,QPointF,QPoint,QRect,QEvent,QModelIndex,QTimer isqt5 = True @@ -8,7 +8,7 @@ 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 + 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 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 from PyQt6.QtCore import QObject,pyqtSignal,Qt,QSize,QByteArray,QBuffer,QPointF,QPoint,QRect,QEvent,QModelIndex,QTimer isqt5 = False \ No newline at end of file diff --git a/LunaTranslator/LunaTranslator/rendertext/internal/textbrowser/base.py b/LunaTranslator/LunaTranslator/rendertext/internal/textbrowser/base.py new file mode 100644 index 00000000..836f423d --- /dev/null +++ b/LunaTranslator/LunaTranslator/rendertext/internal/textbrowser/base.py @@ -0,0 +1,121 @@ +from qtsymbols import * +from myutils.config import globalconfig + + +class QGraphicsDropShadowEffect_multi(QGraphicsDropShadowEffect): + def __init__(self, x) -> None: + self.x = x + super().__init__() + + def draw(self, painter) -> None: + for i in range(self.x): + super().draw(painter) + + +class base(QLabel): + def paintText(self, painter: QPainter): + raise Exception + + def setShadow(self): + pass + + def moveoffset(self): + return self.config.get("width", 0), self.config.get("width", 0) + + def extraWH(self): + return 2 * self.config.get("width", 0), 2 * self.config.get("width", 0) + + def init(self): + pass + + @property + def config(self): + return globalconfig["rendertext"]["textbrowser"][self.typename].get("args", {}) + + @property + def basecolor(self): + return self._basecolor + + + def setColor(self, color: str): + if color is None: + self._basecolor = QColor() + else: + self._basecolor = QColor(color) + + + def __init__(self, typename, parent): + super().__init__(parent) + self._basecolor = QColor() + self.typename = typename + self.movedy = 0 + self.movedx = 0 + self._pix = None + self._m_text = "" + + self.init() + + def adjustSize(self): + self._pix = None + font = self.font() + text = self.text() + font_m = QFontMetrics(font) + w, h = self.extraWH() + self.resize( + int(font_m.size(0, text).width() + w), + int(font_m.height() + h), + ) + self.setShadow() + + def move(self, point: QPoint): + self.movedx = 0 + self.movedy = 0 + text = self.text() + isarabic = any((ord(char) >= 0x0600 and ord(char) <= 0x06E0) for char in text) + if isarabic: + self.movedx -= self.width() + x, y = self.moveoffset() + self.movedx -= x + self.movedy -= y + point.setX(int(point.x() + self.movedx)) + point.setY(int(point.y() + self.movedy)) + super().move(point) + + def pos(self) -> QPoint: + p = super().pos() + p.setX(int(p.x() - self.movedx)) + p.setY(int(p.y() - self.movedy)) + return p + + def clearShadow(self): + self.setGraphicsEffect(None) + + def setShadow_internal(self, colorshadow, width=1, deepth=1, trace=False): + + shadow2 = QGraphicsDropShadowEffect_multi(deepth) + if trace: + shadow2.setBlurRadius(width) + shadow2.setOffset(QPointF(width, width)) + else: + shadow2.setBlurRadius(width) + shadow2.setOffset(0) + shadow2.setColor(QColor(colorshadow)) + self.setGraphicsEffect(shadow2) + + def text(self): + return self._m_text + + def setText(self, text): + self._m_text = text + + def paintEvent(self, event): + if not self._pix: + rate = self.devicePixelRatioF() + self._pix = QPixmap(self.size() * rate) + self._pix.setDevicePixelRatio(rate) + self._pix.fill(Qt.GlobalColor.transparent) + painter = QPainter(self._pix) + painter.setRenderHint(QPainter.RenderHint.Antialiasing) + self.paintText(painter) + painter = QPainter(self) + painter.drawPixmap(0, 0, self._pix) diff --git a/LunaTranslator/LunaTranslator/rendertext/internal/textbrowser/faguang.py b/LunaTranslator/LunaTranslator/rendertext/internal/textbrowser/faguang.py new file mode 100644 index 00000000..19045051 --- /dev/null +++ b/LunaTranslator/LunaTranslator/rendertext/internal/textbrowser/faguang.py @@ -0,0 +1,13 @@ +from qtsymbols import * +from rendertext.internal.textbrowser.normal import TextLine as TextLabel_0 + + +class TextLine(TextLabel_0): + def usingcolor(self): + return QColor(self.config["fillcolor"]) + + def setShadow(self): + font = self.font() + self.setShadow_internal( + self.basecolor, font.pointSizeF(), self.config["shadowforce"] + ) diff --git a/LunaTranslator/LunaTranslator/rendertext/internal/textbrowser/miaobian0.py b/LunaTranslator/LunaTranslator/rendertext/internal/textbrowser/miaobian0.py new file mode 100644 index 00000000..a16e305d --- /dev/null +++ b/LunaTranslator/LunaTranslator/rendertext/internal/textbrowser/miaobian0.py @@ -0,0 +1,34 @@ +from qtsymbols import * +from rendertext.internal.textbrowser.base import base + + +class TextLine(base): + + def colorpair(self): + return QColor(self.config["fillcolor"]), QColor(self.basecolor) + + def paintText(self, painter: QPainter): + self.m_outLineColor, self.m_contentColor = self.colorpair() + self.m_fontOutLineWidth = self.config["width"] + + text = self.text() + font = self.font() + font_m = QFontMetrics(font) + path = QPainterPath() + path.addText( + self.m_fontOutLineWidth, + self.m_fontOutLineWidth + font_m.ascent(), + font, + text, + ) + + pen = QPen( + self.m_outLineColor, + self.m_fontOutLineWidth, + Qt.PenStyle.SolidLine, + Qt.PenCapStyle.RoundCap, + Qt.PenJoinStyle.RoundJoin, + ) + + painter.fillPath(path, QBrush(self.m_contentColor)) + painter.strokePath(path, pen) diff --git a/LunaTranslator/LunaTranslator/rendertext/internal/textbrowser/miaobian1.py b/LunaTranslator/LunaTranslator/rendertext/internal/textbrowser/miaobian1.py new file mode 100644 index 00000000..94532b07 --- /dev/null +++ b/LunaTranslator/LunaTranslator/rendertext/internal/textbrowser/miaobian1.py @@ -0,0 +1,34 @@ +from qtsymbols import * +from rendertext.internal.textbrowser.base import base + + +class TextLine(base): + + def colorpair(self): + return QColor(self.config["fillcolor"]), QColor(self.basecolor) + + def paintText(self, painter: QPainter): + self.m_outLineColor, self.m_contentColor = self.colorpair() + self.m_fontOutLineWidth = self.config["width"] + + text = self.text() + font = self.font() + font_m = QFontMetrics(font) + path = QPainterPath() + path.addText( + self.m_fontOutLineWidth, + self.m_fontOutLineWidth + font_m.ascent(), + font, + text, + ) + + pen = QPen( + self.m_outLineColor, + self.m_fontOutLineWidth, + Qt.PenStyle.SolidLine, + Qt.PenCapStyle.RoundCap, + Qt.PenJoinStyle.RoundJoin, + ) + + painter.strokePath(path, pen) + painter.fillPath(path, QBrush(self.m_contentColor)) diff --git a/LunaTranslator/LunaTranslator/rendertext/internal/textbrowser/miaobian2.py b/LunaTranslator/LunaTranslator/rendertext/internal/textbrowser/miaobian2.py new file mode 100644 index 00000000..09f87261 --- /dev/null +++ b/LunaTranslator/LunaTranslator/rendertext/internal/textbrowser/miaobian2.py @@ -0,0 +1,7 @@ +from qtsymbols import * +from rendertext.internal.textbrowser.miaobian import TextLine as TB1 + + +class TextLine(TB1): + def colorpair(self): + return QColor(self.basecolor), QColor(self.config["fillcolor"]) diff --git a/LunaTranslator/LunaTranslator/rendertext/internal/textbrowser/normal.py b/LunaTranslator/LunaTranslator/rendertext/internal/textbrowser/normal.py new file mode 100644 index 00000000..6ff900aa --- /dev/null +++ b/LunaTranslator/LunaTranslator/rendertext/internal/textbrowser/normal.py @@ -0,0 +1,21 @@ +from qtsymbols import * +from rendertext.internal.textbrowser.base import base + + +class TextLine(base): + def usingcolor(self): + return self.basecolor + + def paintText(self, painter: QPainter): + path = QPainterPath() + + text = self.text() + font = self.font() + font_m = QFontMetrics(font) + path.addText( + 0, + font_m.ascent(), + font, + text, + ) + painter.fillPath(path, QBrush(self.usingcolor())) diff --git a/LunaTranslator/LunaTranslator/rendertext/internal/webview/faguang.py b/LunaTranslator/LunaTranslator/rendertext/internal/webview/faguang.py new file mode 100644 index 00000000..c357deff --- /dev/null +++ b/LunaTranslator/LunaTranslator/rendertext/internal/webview/faguang.py @@ -0,0 +1,25 @@ +from qtsymbols import * +import uuid + + +def gen_html(configs, text, fm, fs, bold, atcenter, color): + align = "text-align: center;" if atcenter else "" + bold = "font-weight: bold;" if bold else "" + _id = f"luna_{uuid.uuid4()}" + ntimes = "" + for i in range(configs["shadowforce"]): + ntimes += f"0px 0px {fs*0.4}px {color}" + if i == configs["shadowforce"] - 1: + ntimes += ";" + else: + ntimes += "," + style = f"""""" + + return style + f'