From 4b1d45ad42e18a883159419f537f2c4d2309d18c Mon Sep 17 00:00:00 2001 From: dmMaze Date: Wed, 31 Aug 2022 17:45:46 +0800 Subject: [PATCH] v1.3.4 --- CHANGELOG.md | 8 +++++++ CHANGELOG_EN.md | 8 +++++++ ballontranslator/__init__.py | 2 +- ballontranslator/__main__.py | 14 ++++++------ ballontranslator/scripts/build_win.bat | 2 +- ballontranslator/ui/configpanel.py | 19 +++++++++++----- ballontranslator/ui/dlconfig_parse_widgets.py | 7 ------ ballontranslator/ui/drawingpanel.py | 2 +- ballontranslator/ui/mainwindow.py | 2 +- ballontranslator/ui/mainwindowbars.py | 22 ++++++++++--------- ballontranslator/ui/misc.py | 2 +- ballontranslator/ui/scenetext_manager.py | 7 ++++++ ballontranslator/ui/textitem.py | 13 +++++++++-- 13 files changed, 72 insertions(+), 36 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ee58ed5..4694b80a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelogs +### 2022-08-31 +[v1.3.4](https://github.com/dmMaze/BallonsTranslator/releases/tag/v1.3.4)发布 + +1. 添加离线日译英模型Sugoi Translator(仅日译英, 作者[mingshiba](https://www.patreon.com/mingshiba), 已获得集成授权), 感谢[@Snowad14](https://github.com/Snowad14)提供CT2转换模型 +2. 来自[bropines](https://github.com/bropines)的俄语本地化支持 +3. 文本编辑支持字距调节 +4. 调整竖排符号及半角字符位置规则, 详见https://github.com/dmMaze/BallonsTranslator/pull/30 + ### 2022-08-17 [v1.3.0](https://github.com/dmMaze/BallonsTranslator/releases/tag/v1.3.0)发布 diff --git a/CHANGELOG_EN.md b/CHANGELOG_EN.md index 96a37b9f..9f7b8ec3 100644 --- a/CHANGELOG_EN.md +++ b/CHANGELOG_EN.md @@ -1,5 +1,13 @@ # Changelogs +### 2022-08-31 +[v1.3.4](https://github.com/dmMaze/BallonsTranslator/releases/tag/v1.3.4) released + +1. Add Sugoi Translator(Japanese-English only, created & authorized by [mingshiba](https://www.patreon.com/mingshiba)): download the [model](https://drive.google.com/drive/folders/1KnDlfUM9zbnYFTo6iCbnBaBKabXfnVJm) converted by [@Snowad14](https://github.com/Snowad14) and put "sugoi_translator" in the "data" folder. +2. Add support for russian, thanks to [bropines](https://github.com/bropines) +3. Support letter spacing adjustment. +4. Vertical type rework & text rendering bug fixes: https://github.com/dmMaze/BallonsTranslator/pull/30 + ### 2022-08-17 [v1.3.0](https://github.com/dmMaze/BallonsTranslator/releases/tag/v1.3.0) released diff --git a/ballontranslator/__init__.py b/ballontranslator/__init__.py index 18017aa5..591438ba 100644 --- a/ballontranslator/__init__.py +++ b/ballontranslator/__init__.py @@ -4,4 +4,4 @@ # 1. MAJOR version when you make incompatible API changes; # 2. MINOR version when you add functionality in a backwards-compatible manner; # 3. PATCH version when you make backwards-compatible bug fixes. -__version__ = "1.3.0" \ No newline at end of file +__version__ = "1.3.4" \ No newline at end of file diff --git a/ballontranslator/__main__.py b/ballontranslator/__main__.py index 77959ef8..866b07ad 100644 --- a/ballontranslator/__main__.py +++ b/ballontranslator/__main__.py @@ -16,21 +16,21 @@ def main(): else: os.environ['QT_API'] = args.qt_api + if sys.platform == 'win32': + import ctypes + myappid = u'BalloonsTranslator' # arbitrary string + ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(myappid) + import qtpy from qtpy.QtWidgets import QApplication from qtpy.QtCore import QTranslator, QLocale from qtpy.QtGui import QIcon - from ui.mainwindow import MainWindow from ui import constants - - if sys.platform == 'win32': - import ctypes - myappid = u'BalloonsTranslator' # arbitrary string - ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(myappid) - if qtpy.API_NAME[-1] == '6': constants.FLAG_QT6 = True + + from ui.mainwindow import MainWindow os.chdir(constants.PROGRAM_PATH) app = QApplication(sys.argv) diff --git a/ballontranslator/scripts/build_win.bat b/ballontranslator/scripts/build_win.bat index 6007eb6d..3435bdae 100644 --- a/ballontranslator/scripts/build_win.bat +++ b/ballontranslator/scripts/build_win.bat @@ -1,5 +1,5 @@ nuitka --standalone --mingw64 --nofollow-imports --show-memory --show-progress ^ --enable-plugin=pyqt5 --include-qt-plugins=sensible,styles ^ --follow-import-to=dl,utils,ui --include-plugin-directory=ballontranslator/dl,ballontranslator/ui,ballontranslator/utils ^ - --windows-product-version=1.3.0.0 --windows-company-name=DUMMY_WINDOWS_COMPANY_NAME --windows-product-name=BallonTranslator ^ + --windows-product-version=1.3.4.0 --windows-company-name=DUMMY_WINDOWS_COMPANY_NAME --windows-product-name=BallonTranslator ^ --output-dir=release BallonTranslator \ No newline at end of file diff --git a/ballontranslator/ui/configpanel.py b/ballontranslator/ui/configpanel.py index b1ec7c25..94579607 100644 --- a/ballontranslator/ui/configpanel.py +++ b/ballontranslator/ui/configpanel.py @@ -2,9 +2,18 @@ import json from qtpy.QtWidgets import QLayout, QHBoxLayout, QVBoxLayout, QTreeView, QWidget, QLabel, QSizePolicy, QSpacerItem, QCheckBox, QSplitter, QScrollArea, QGroupBox, QLineEdit -from qtpy.QtCore import Qt, QModelIndex, Signal, QSize +from qtpy.QtCore import Qt, QModelIndex, Signal, QSize, QEvent, QItemSelection from qtpy.QtGui import QStandardItem, QStandardItemModel, QMouseEvent, QFont, QColor, QPalette -from qtpy import QtCore + +from . import constants as C + + +# nuitka seems to require import QtCore explicitly +if C.FLAG_QT6: + from PyQt6 import QtCore +else: + from PyQt5 import QtCore + from utils.logger import logger as LOGGER from .stylewidgets import Widget, ConfigComboBox @@ -55,9 +64,9 @@ def setIdx(self, idx0: int, idx1: int) -> None: self.idx0 = idx0 self.idx1 = idx1 - def enterEvent(self, a0: QtCore.QEvent) -> None: + def enterEvent(self, e: QEvent) -> None: self.pressed.emit(self.idx0, self.idx1) - return super().enterEvent(a0) + return super().enterEvent(e) class ConfigBlock(Widget): @@ -224,7 +233,7 @@ def addHeader(self, header: str) -> TableItem: rootNode.appendRow(ti) return ti - def selectionChanged(self, selected: QtCore.QItemSelection, deselected: QtCore.QItemSelection) -> None: + def selectionChanged(self, selected: QItemSelection, deselected: QItemSelection) -> None: dis = deselected.indexes() sel = selected.indexes() model = self.model() diff --git a/ballontranslator/ui/dlconfig_parse_widgets.py b/ballontranslator/ui/dlconfig_parse_widgets.py index b4c15783..21a2dddf 100644 --- a/ballontranslator/ui/dlconfig_parse_widgets.py +++ b/ballontranslator/ui/dlconfig_parse_widgets.py @@ -5,17 +5,10 @@ from utils.logger import logger as LOGGER from .stylewidgets import ConfigComboBox from .constants import CONFIG_FONTSIZE_CONTENT, CONFIG_COMBOBOX_MIDEAN, CONFIG_COMBOBOX_SHORT -from . import constants as c from qtpy.QtWidgets import QHBoxLayout, QVBoxLayout, QWidget, QLabel, QComboBox, QListView, QToolBar, QMenu, QSpacerItem, QPushButton, QCheckBox, QToolButton, QSplitter, QStylePainter, QStyleOption, QStyle, QScrollArea, QLineEdit, QGroupBox, QGraphicsSimpleTextItem from qtpy.QtCore import Qt, Signal from qtpy.QtGui import QFontMetricsF -if c.FLAG_QT6: - from qtpy.QtGui import QAction -else: - from qtpy.QtWidgets import QAction - - class ParamNameLabel(QLabel): diff --git a/ballontranslator/ui/drawingpanel.py b/ballontranslator/ui/drawingpanel.py index a309dfac..239deae2 100644 --- a/ballontranslator/ui/drawingpanel.py +++ b/ballontranslator/ui/drawingpanel.py @@ -575,7 +575,7 @@ def on_inpaint_failed(self): self.clearInpaintItems() def on_canvasctrl_released(self): - if self.currentTool == self.inpaintTool: + if self.isVisible() and self.currentTool == self.inpaintTool: self.runInpaint() def on_begin_scale_tool(self, pos: QPointF): diff --git a/ballontranslator/ui/mainwindow.py b/ballontranslator/ui/mainwindow.py index bd4db961..f6f70ac1 100644 --- a/ballontranslator/ui/mainwindow.py +++ b/ballontranslator/ui/mainwindow.py @@ -4,7 +4,7 @@ from qtpy.QtWidgets import QMainWindow, QHBoxLayout, QVBoxLayout, QApplication, QStackedWidget, QWidget, QSplitter, QListWidget, QShortcut, QListWidgetItem from qtpy.QtCore import Qt, QPoint, QSize -from qtpy.QtGui import QGuiApplication, QIcon, QCloseEvent, QKeySequence, QImage, QPainter, QFont +from qtpy.QtGui import QKeyEvent, QGuiApplication, QIcon, QCloseEvent, QKeySequence, QImage, QPainter, QFont from utils.logger import logger as LOGGER from utils.io_utils import json_dump_nested_obj diff --git a/ballontranslator/ui/mainwindowbars.py b/ballontranslator/ui/mainwindowbars.py index a0b77de3..dd891f1d 100644 --- a/ballontranslator/ui/mainwindowbars.py +++ b/ballontranslator/ui/mainwindowbars.py @@ -4,12 +4,14 @@ from .stylewidgets import Widget, PaintQSlider from .constants import WINDOW_BORDER_WIDTH, BOTTOMBAR_HEIGHT, DRAG_DIR_NONE, DRAG_DIR_VER, DRAG_DIR_BDIAG, DRAG_DIR_FDIAG -from . import constants as c + from qtpy.QtWidgets import QMainWindow, QHBoxLayout, QVBoxLayout, QFileDialog, QLabel, QSizePolicy, QToolBar, QMenu, QSpacerItem, QPushButton, QCheckBox, QToolButton from qtpy.QtCore import Qt, Signal, QPoint from qtpy.QtGui import QMouseEvent, QKeySequence -if c.FLAG_QT6: + +from . import constants as C +if C.FLAG_QT6: from qtpy.QtGui import QAction else: from qtpy.QtWidgets import QAction @@ -297,7 +299,7 @@ def stateCheckerChanged(self, checker_type: str): def mouseMoveEvent(self, e: QMouseEvent) -> None: if not self.mainwindow.isMaximized(): - if c.FLAG_QT6: + if C.FLAG_QT6: g_pos = e.globalPosition().toPoint() else: g_pos = e.globalPos() @@ -317,7 +319,7 @@ def mouseMoveEvent(self, e: QMouseEvent) -> None: return super().mouseMoveEvent(e) def mousePressEvent(self, e: QMouseEvent) -> None: - if c.FLAG_QT6: + if C.FLAG_QT6: g_pos = e.globalPosition().toPoint() else: g_pos = e.globalPos() @@ -346,7 +348,7 @@ def __init__(self, mainwindow: QMainWindow): def mouseMoveEvent(self, e: QMouseEvent) -> None: if not self.mainwindow.isMaximized(): - if c.FLAG_QT6: + if C.FLAG_QT6: g_pos = e.globalPosition().toPoint() else: g_pos = e.globalPos() @@ -366,7 +368,7 @@ def mouseMoveEvent(self, e: QMouseEvent) -> None: return super().mouseMoveEvent(e) def mousePressEvent(self, e: QMouseEvent) -> None: - if c.FLAG_QT6: + if C.FLAG_QT6: g_pos = e.globalPosition().toPoint() else: g_pos = e.globalPos() @@ -436,7 +438,7 @@ def onMinBtnClicked(self): self.mainwindow.showMinimized() def mousePressEvent(self, event: QMouseEvent) -> None: - if c.FLAG_QT6: + if C.FLAG_QT6: g_pos = event.globalPosition().toPoint() else: g_pos = event.globalPos() @@ -466,7 +468,7 @@ def mouseReleaseEvent(self, event: QMouseEvent) -> None: return super().mouseReleaseEvent(event) def mouseMoveEvent(self, event: QMouseEvent) -> None: - if c.FLAG_QT6: + if C.FLAG_QT6: g_pos = event.globalPosition().toPoint() else: g_pos = event.globalPos() @@ -624,7 +626,7 @@ def transCheckerStateChanged(self): def mouseMoveEvent(self, event: QMouseEvent) -> None: if not self.mainwindow.isMaximized(): - if c.FLAG_QT6: + if C.FLAG_QT6: g_pos = event.globalPosition().toPoint() else: g_pos = event.globalPos() @@ -661,7 +663,7 @@ def mouseMoveEvent(self, event: QMouseEvent) -> None: return super().mouseMoveEvent(event) def mousePressEvent(self, e: QMouseEvent) -> None: - if c.FLAG_QT6: + if C.FLAG_QT6: g_pos = e.globalPosition().toPoint() else: g_pos = e.globalPos() diff --git a/ballontranslator/ui/misc.py b/ballontranslator/ui/misc.py index 0616645e..722e3f42 100644 --- a/ballontranslator/ui/misc.py +++ b/ballontranslator/ui/misc.py @@ -139,7 +139,7 @@ class ProjImgTrans: def __init__(self, directory: str = None): self.type = PROJTYPE_IMGTRANS - self.directory: str + self.directory: str = None self.pages: OrderedDict[List[TextBlock]] = OrderedDict() self.not_found_pages: Dict[List[TextBlock]] = {} self.new_pages: List[str] = [] diff --git a/ballontranslator/ui/scenetext_manager.py b/ballontranslator/ui/scenetext_manager.py index e1390551..e1bdff52 100644 --- a/ballontranslator/ui/scenetext_manager.py +++ b/ballontranslator/ui/scenetext_manager.py @@ -327,6 +327,7 @@ def addTextBlkItem(self, textblk_item: TextBlkItem) -> TextBlkItem: textblk_item.rotated.connect(self.onTextBlkItemRotated) textblk_item.content_changed.connect(self.onTextBlkItemContentChanged) textblk_item.doc_size_changed.connect(self.onTextBlkItemSizeChanged) + textblk_item.pasted.connect(self.onBlkitemPaste) return textblk_item def deleteTextblkItem(self, blkitem: TextBlkItem): @@ -371,6 +372,12 @@ def onTextBlkItemSizeChanged(self, idx: int): if self.txtblkShapeControl.blk_item == blk_item: self.txtblkShapeControl.updateBoundingRect() + def onBlkitemPaste(self, idx: int): + blk_item = self.textblk_item_list[idx] + text = self.app.clipboard().text() + cursor = blk_item.textCursor() + cursor.insertText(text) + def onTextBlkItemBeginEdit(self, blk_id: int): blk_item = self.textblk_item_list[blk_id] self.txtblkShapeControl.setBlkItem(blk_item) diff --git a/ballontranslator/ui/textitem.py b/ballontranslator/ui/textitem.py index 388881d9..92ed03e8 100644 --- a/ballontranslator/ui/textitem.py +++ b/ballontranslator/ui/textitem.py @@ -4,7 +4,7 @@ from qtpy.QtWidgets import QGraphicsItem, QWidget, QGraphicsSceneHoverEvent, QGraphicsTextItem, QStyleOptionGraphicsItem, QStyle, QGraphicsSceneMouseEvent from qtpy.QtCore import Qt, QRect, QRectF, QPointF, Signal, QSizeF -from qtpy.QtGui import QFont, QTextCursor, QPixmap, QPainterPath, QTextDocument, QFocusEvent, QPainter, QPen, QColor, QTextCursor, QTextCharFormat, QTextDocument +from qtpy.QtGui import QKeyEvent, QFont, QTextCursor, QPixmap, QPainterPath, QTextDocument, QFocusEvent, QPainter, QPen, QColor, QTextCursor, QTextCharFormat, QTextDocument from dl.textdetector.textblock import TextBlock from utils.imgproc_utils import xywh2xyxypoly, rotate_polygons @@ -27,6 +27,7 @@ class TextBlkItem(QGraphicsTextItem): content_changed = Signal(QGraphicsTextItem) leftbutton_pressed = Signal(int) doc_size_changed = Signal(int) + pasted = Signal(int) def __init__(self, blk: TextBlock = None, idx: int = 0, set_format=True, show_rect=False, *args, **kwargs): super().__init__(*args, **kwargs) self.blk = None @@ -565,4 +566,12 @@ def get_char_fmts(self) -> List[QTextCharFormat]: char_fmts.append(cursor.charFormat()) if cursor.atEnd(): break - return char_fmts \ No newline at end of file + return char_fmts + + def keyPressEvent(self, e: QKeyEvent) -> None: + if e.key() == Qt.Key.Key_V and e.modifiers() == Qt.KeyboardModifier.ControlModifier: + if self.isEditing() is not None: + e.accept() + self.pasted.emit(self.idx) + return + return super().keyPressEvent(e) \ No newline at end of file