Loading launch.py +2 −0 Original line number Diff line number Diff line Loading @@ -220,6 +220,8 @@ def main(): if args.headless: app_args = sys.argv + ['-platform', 'offscreen'] app = QApplication(app_args) app.setApplicationName('BalloonsTranslator') app.setApplicationVersion(VERSION) if not args.headless: ps = QGuiApplication.primaryScreen() Loading ui/text_graphical_effect.py +178 −3 Original line number Diff line number Diff line Loading @@ -2,15 +2,15 @@ from typing import Union, Tuple, Callable import cv2 import numpy as np from qtpy.QtCore import Signal, Qt, QPoint from qtpy.QtGui import QColor, QShowEvent, QPixmap, QImage, QPainter, QFontMetricsF from qtpy.QtCore import Signal, Qt, QPoint, QPointF from qtpy.QtGui import QColor, QShowEvent, QPixmap, QImage, QPainter, QFontMetricsF, QLinearGradient, QPainterPath from qtpy.QtWidgets import QHBoxLayout, QVBoxLayout, QGridLayout, QScrollArea, QGroupBox, QPushButton, QLabel, QDialog from utils import shared as C from .misc import pixmap2ndarray, ndarray2pixmap from utils.fontformat import FontFormat, pt2px from .custom_widget import Widget, ColorPickerLabel, PaintQSlider import math def apply_shadow_effect(img: Union[QPixmap, QImage, np.ndarray], color: QColor, strength=1.0, radius=21) -> Tuple[ QPixmap, np.ndarray, np.ndarray]: Loading Loading @@ -226,3 +226,178 @@ class TextEffectPanelDeprecated(QDialog): self.shadow_color_picker.setPickerColor(self.fontfmt.shadow_color) self.shadow_radius_slider.setValue(int(self.fontfmt.shadow_radius * 100)) self.shadow_strength_slider.setValue(int(self.fontfmt.shadow_strength * 100)) class GradientPreviewPanel(QDialog): apply = Signal() gradient_changed = Signal() def __init__(self, update_text_style_label: Callable, *args, **kwargs) -> None: super().__init__(*args, **kwargs) self.setModal(True) self.update_text_style_label = update_text_style_label self.fontfmt: FontFormat = None self.fontfmt = FontFormat() self.active_fontfmt = FontFormat() # Preview label setup self.preview_label = QLabel(self) self.preview_label.setContentsMargins(0, 0, 0, 0) font = self.preview_label.font() font.setPointSizeF(24) self.preview_label.setFont(font) self.preview_label.setAlignment(Qt.AlignmentFlag.AlignCenter) self.preview_text = self.tr("Gradient") fm = QFontMetricsF(font) br = fm.boundingRect(self.preview_text) br_w, br_h = br.width(), br.height() self.preview_pixmap = QPixmap(int(br_w + br_h * 2), int(br_h * 3)) self.preview_origin = QPointF(int(br_h), int(1.75 * br_h)) self.preview_label.setFixedHeight(int(br_h * 2)) # Enable gradient checkbox self.gradient_enable = QGroupBox(self.tr("Enable Gradient")) self.gradient_enable.setCheckable(True) self.gradient_enable.toggled.connect(self.on_gradient_enabled_changed) # Color pickers start_color_layout = QHBoxLayout() start_color_layout.addWidget(QLabel(self.tr("Start Color:"))) self.gradient_start_picker = ColorPickerLabel(self) self.gradient_start_picker.colorChanged.connect(self.on_gradient_start_color_changed) start_color_layout.addWidget(self.gradient_start_picker) end_color_layout = QHBoxLayout() end_color_layout.addWidget(QLabel(self.tr("End Color:"))) self.gradient_end_picker = ColorPickerLabel(self) self.gradient_end_picker.colorChanged.connect(self.on_gradient_end_color_changed) end_color_layout.addWidget(self.gradient_end_picker) # Angle slider self.angle_slider = PaintQSlider(self.tr("Angle")) self.angle_slider.setRange(0, 359) self.angle_slider.valueChanged.connect(self.on_gradient_angle_changed) # Size slider self.size_slider = PaintQSlider(self.tr("Size")) self.size_slider.setRange(50, 200) self.size_slider.valueChanged.connect(self.on_gradient_size_changed) # Buttons self.apply_btn = QPushButton(self.tr('Apply')) self.apply_btn.clicked.connect(self.on_apply_clicked) self.cancel_btn = QPushButton(self.tr('Cancel')) self.cancel_btn.clicked.connect(self.on_cancel_clicked) # Layout gradient_layout = QVBoxLayout() gradient_layout.addLayout(start_color_layout) gradient_layout.addLayout(end_color_layout) gradient_layout.addWidget(self.angle_slider) gradient_layout.addWidget(self.size_slider) self.gradient_enable.setLayout(gradient_layout) button_layout = QHBoxLayout() button_layout.addWidget(self.apply_btn) button_layout.addWidget(self.cancel_btn) main_layout = QVBoxLayout(self) main_layout.addWidget(self.preview_label) main_layout.addWidget(self.gradient_enable) main_layout.addLayout(button_layout) self.setMaximumHeight(C.TEXTEFFECT_MAXHEIGHT) self.updatePreviewPixmap() def on_gradient_enabled_changed(self, enabled): self.fontfmt.gradient_enabled = enabled self.updatePreviewPixmap() def on_gradient_start_color_changed(self, is_valid): if is_valid: color = self.gradient_start_picker.color self.fontfmt.gradient_start_color = list(color.getRgb()[:3]) # Convert to list and take only RGB self.updatePreviewPixmap() def on_gradient_end_color_changed(self, is_valid): if is_valid: color = self.gradient_end_picker.color self.fontfmt.gradient_end_color = list(color.getRgb()[:3]) # Convert to list and take only RGB self.updatePreviewPixmap() def on_gradient_angle_changed(self, value): self.fontfmt.gradient_angle = float(value) self.updatePreviewPixmap() def on_gradient_size_changed(self, value): self.fontfmt.gradient_size = value / 100 self.updatePreviewPixmap() def updatePreviewPixmap(self): if not self.isVisible(): return self.preview_pixmap.fill(Qt.GlobalColor.transparent) painter = QPainter(self.preview_pixmap) painter.setRenderHint(QPainter.RenderHint.TextAntialiasing) painter.setFont(self.preview_label.font()) if self.fontfmt.gradient_enabled: # Create gradient gradient = QLinearGradient() angle = self.fontfmt.gradient_angle rad = math.radians(angle) dx = math.cos(rad) dy = math.sin(rad) rect = self.preview_pixmap.rect() center = rect.center() radius = max(rect.width(), rect.height()) * self.fontfmt.gradient_size gradient.setStart(center.x() - dx * radius, center.y() - dy * radius) gradient.setFinalStop(center.x() + dx * radius, center.y() + dy * radius) start_color = QColor(*self.fontfmt.gradient_start_color) end_color = QColor(*self.fontfmt.gradient_end_color) gradient.setColorAt(0, start_color) gradient.setColorAt(1, end_color) painter.setBrush(gradient) painter.setPen(Qt.PenStyle.NoPen) # Draw text with gradient path = QPainterPath() path.addText(self.preview_origin, self.preview_label.font(), self.preview_text) painter.drawPath(path) else: painter.drawText(self.preview_origin, self.preview_text) painter.end() self.preview_label.setPixmap(self.preview_pixmap) def on_apply_clicked(self): self.active_fontfmt.gradient_enabled = self.fontfmt.gradient_enabled self.active_fontfmt.gradient_start_color = self.fontfmt.gradient_start_color self.active_fontfmt.gradient_end_color = self.fontfmt.gradient_end_color self.active_fontfmt.gradient_angle = self.fontfmt.gradient_angle self.active_fontfmt.gradient_size = self.fontfmt.gradient_size self.gradient_changed.emit() self.update_text_style_label() self.apply.emit() self.hide() def on_cancel_clicked(self): self.hide() def showEvent(self, e: QShowEvent) -> None: self.updatePreviewPixmap() return super().showEvent(e) def updatePanels(self): self.gradient_enable.setChecked(self.fontfmt.gradient_enabled) self.gradient_start_picker.setPickerColor(self.fontfmt.gradient_start_color) self.gradient_end_picker.setPickerColor(self.fontfmt.gradient_end_color) self.angle_slider.setValue(int(self.fontfmt.gradient_angle)) self.size_slider.setValue(int(self.fontfmt.gradient_size * 100)) ui/text_panel.py +30 −102 Original line number Diff line number Diff line Loading @@ -11,7 +11,7 @@ from utils import config as C from utils.fontformat import FontFormat, px2pt, LineSpacingType from .custom_widget import Widget, ColorPickerLabel, ClickableLabel, CheckableLabel, TextCheckerLabel, AlignmentChecker, QFontChecker, SizeComboBox from .textitem import TextBlkItem from .text_graphical_effect import TextEffectPanelDeprecated from .text_graphical_effect import TextEffectPanelDeprecated, GradientPreviewPanel from .text_advanced_format import TextAdvancedFormatPanel from .text_style_presets import TextStylePresetPanel from . import funcmaps as FM Loading Loading @@ -411,68 +411,21 @@ class FontFormatPanel(Widget): ) self.textadvancedfmt_panel.param_changed.connect(self.on_param_changed) self.effectBtn = ClickableLabel(self.tr("Effect"), self) self.effectBtn.clicked.connect(self.on_effectbtn_clicked) self.effect_panel = TextEffectPanelDeprecated(update_text_style_label=self.update_text_style_label) self.effect_panel.hide() self.shadowBtn = ClickableLabel(self.tr("Shadow"), self) self.shadowBtn.clicked.connect(self.on_shadow_btn_clicked) self.gradientBtn = ClickableLabel(self.tr("Gradient"), self) self.gradientBtn.clicked.connect(self.on_gradient_btn_clicked) self.foldTextBtn = CheckableLabel(self.tr("Unfold"), self.tr("Fold"), False) self.sourceBtn = TextCheckerLabel(self.tr("Source")) self.transBtn = TextCheckerLabel(self.tr("Translation")) # Add gradient controls self.gradientGroup = QGroupBox(self.tr("Gradient"), parent=self) gradientLayout = QVBoxLayout(self.gradientGroup) gradientLayout.setContentsMargins(10, 10, 10, 10) gradientLayout.setSpacing(5) # Enable gradient checkbox self.gradientEnableBox = QCheckBox(self.tr("Enable Gradient"), parent=self.gradientGroup) self.gradientEnableBox.stateChanged.connect(lambda state: self.on_param_changed('gradient_enabled', state == Qt.CheckState.Checked.value)) gradientLayout.addWidget(self.gradientEnableBox) # Start color picker startColorLayout = QHBoxLayout() startColorLayout.addWidget(QLabel(self.tr("Start Color:"), parent=self.gradientGroup)) self.gradientStartColorPicker = ColorPickerLabel(parent=self.gradientGroup) self.gradientStartColorPicker.colorChanged.connect(self.onGradientStartColorChanged) self.gradientStartColorPicker.changingColor.connect(self.changingColor) startColorLayout.addWidget(self.gradientStartColorPicker) gradientLayout.addLayout(startColorLayout) # End color picker endColorLayout = QHBoxLayout() endColorLayout.addWidget(QLabel(self.tr("End Color:"), parent=self.gradientGroup)) self.gradientEndColorPicker = ColorPickerLabel(parent=self.gradientGroup) self.gradientEndColorPicker.colorChanged.connect(self.onGradientEndColorChanged) self.gradientEndColorPicker.changingColor.connect(self.changingColor) endColorLayout.addWidget(self.gradientEndColorPicker) gradientLayout.addLayout(endColorLayout) # Angle slider angleLayout = QHBoxLayout() angleLayout.addWidget(QLabel(self.tr("Angle:"), parent=self.gradientGroup)) self.gradientAngleSlider = QSlider(Qt.Orientation.Horizontal, parent=self.gradientGroup) self.gradientAngleSlider.setRange(0, 359) self.gradientAngleSlider.valueChanged.connect(self.onGradientAngleChanged) angleLayout.addWidget(self.gradientAngleSlider) self.gradientAngleLabel = QLabel("0°", parent=self.gradientGroup) self.gradientAngleLabel.setMinimumWidth(30) angleLayout.addWidget(self.gradientAngleLabel) gradientLayout.addLayout(angleLayout) # Add gradient size control sizeLayout = QHBoxLayout() sizeLayout.addWidget(QLabel(self.tr("Size:"), parent=self.gradientGroup)) self.gradientSizeSlider = QSlider(Qt.Orientation.Horizontal, parent=self.gradientGroup) self.gradientSizeSlider.setRange(50, 200) # 0.5x to 2.0x self.gradientSizeSlider.setValue(100) # Default 1.0x self.gradientSizeSlider.valueChanged.connect(self.onGradientSizeChanged) sizeLayout.addWidget(self.gradientSizeSlider) self.gradientSizeLabel = QLabel("1.0x", parent=self.gradientGroup) self.gradientSizeLabel.setMinimumWidth(40) sizeLayout.addWidget(self.gradientSizeLabel) gradientLayout.addLayout(sizeLayout) self.effect_panel = TextEffectPanelDeprecated(update_text_style_label=self.update_text_style_label) self.effect_panel.hide() self.gradient_panel = GradientPreviewPanel(update_text_style_label=self.update_text_style_label) self.gradient_panel.gradient_changed.connect(self.on_gradient_changed) self.gradient_panel.hide() FONTFORMAT_SPACING = 6 Loading Loading @@ -501,7 +454,8 @@ class FontFormatPanel(Widget): hl3.setAlignment(Qt.AlignmentFlag.AlignCenter) hl3.addLayout(stroke_hlayout) hl3.addLayout(lettersp_hlayout) hl3.addWidget(self.effectBtn) hl3.addWidget(self.shadowBtn) hl3.addWidget(self.gradientBtn) hl3.setContentsMargins(3, 0, 3, 0) hl3.setSpacing(13) hl4 = QHBoxLayout() Loading @@ -520,7 +474,6 @@ class FontFormatPanel(Widget): self.vlayout.addLayout(hl2) self.vlayout.addLayout(hl3) self.vlayout.addLayout(hl4) self.vlayout.addWidget(self.gradientGroup) self.vlayout.setContentsMargins(7, 0, 7, 0) self.vlayout.setSpacing(0) Loading Loading @@ -605,15 +558,6 @@ class FontFormatPanel(Widget): self.formatBtnGroup.italicBtn.setChecked(font_format.italic) self.alignBtnGroup.setAlignment(font_format.alignment) # Initialize gradient controls self.gradientEnableBox.setChecked(font_format.gradient_enabled) self.gradientStartColorPicker.setPickerColor(font_format.gradient_start_color) self.gradientEndColorPicker.setPickerColor(font_format.gradient_end_color) self.gradientAngleSlider.setValue(int(font_format.gradient_angle)) self.gradientAngleLabel.setText(f"{int(font_format.gradient_angle)}°") self.gradientSizeSlider.setValue(int(font_format.gradient_size * 100)) self.gradientSizeLabel.setText(f"{font_format.gradient_size:.1f}x") self.familybox.blockSignals(False) # self.texteffect_panel.set_active_format(font_format) self.textadvancedfmt_panel.set_active_format(font_format) Loading Loading @@ -679,41 +623,25 @@ class FontFormatPanel(Widget): self.set_active_format(blk_fmt, multi_size) self.textstyle_panel.setTitle(f'TextBlock #{textblk_item.idx}') def on_effectbtn_clicked(self): def on_shadow_btn_clicked(self): self.effect_panel.active_fontfmt = C.active_format self.effect_panel.fontfmt = copy.deepcopy(C.active_format) self.effect_panel.updatePanels() self.effect_panel.show() def onGradientAngleChanged(self, value): self.gradientAngleLabel.setText(f"{value}°") self.on_param_changed('gradient_angle', float(value)) def onGradientStartColorChanged(self, is_valid=True): self.focusOnColorDialog = False if is_valid: rgb = self.gradientStartColorPicker.rgb() self.on_param_changed('gradient_start_color', rgb) def onGradientEndColorChanged(self, is_valid=True): self.focusOnColorDialog = False if is_valid: rgb = self.gradientEndColorPicker.rgb() self.on_param_changed('gradient_end_color', rgb) def onGradientSizeChanged(self, value): self.gradientSizeLabel.setText(f"{value/100:.1f}x") self.on_param_changed('gradient_size', value/100) def updateGradientControls(self, fontfmt: FontFormat): self.gradientEnableBox.setChecked(fontfmt.gradient_enabled) self.gradientStartColorPicker.setRGB(*fontfmt.gradient_start_color) self.gradientEndColorPicker.setRGB(*fontfmt.gradient_end_color) self.gradientAngleSlider.setValue(int(fontfmt.gradient_angle)) self.gradientAngleLabel.setText(f"{int(fontfmt.gradient_angle)}°") self.gradientSizeSlider.setValue(int(fontfmt.gradient_size * 100)) self.gradientSizeLabel.setText(f"{fontfmt.gradient_size:.1f}x") def updateFontFormatPanel(self, fontfmt: FontFormat): self.updateGradientControls(fontfmt) self.update_text_style_label() def on_gradient_btn_clicked(self): self.gradient_panel.active_fontfmt = C.active_format self.gradient_panel.fontfmt = copy.deepcopy(C.active_format) self.gradient_panel.updatePanels() self.gradient_panel.show() def on_gradient_changed(self): """Handle gradient changes from the preview panel""" start_color = self.gradient_panel.gradient_start_picker.color.getRgb()[:3] end_color = self.gradient_panel.gradient_end_picker.color.getRgb()[:3] self.on_param_changed('gradient_enabled', self.gradient_panel.fontfmt.gradient_enabled) self.on_param_changed('gradient_start_color', start_color) self.on_param_changed('gradient_end_color', end_color) self.on_param_changed('gradient_angle', self.gradient_panel.fontfmt.gradient_angle) self.on_param_changed('gradient_size', self.gradient_panel.fontfmt.gradient_size) utils/shared.py +1 −1 Original line number Diff line number Diff line Loading @@ -4,7 +4,7 @@ import os.path as osp import json import sys ICON_PATH = 'icons/[ICONNAME]' ICON_PATH = 'icons/icon.icns' PROGRAM_PATH = osp.abspath(osp.dirname(osp.dirname(__file__))) LOGGING_PATH = osp.join(PROGRAM_PATH, 'logs') Loading Loading
launch.py +2 −0 Original line number Diff line number Diff line Loading @@ -220,6 +220,8 @@ def main(): if args.headless: app_args = sys.argv + ['-platform', 'offscreen'] app = QApplication(app_args) app.setApplicationName('BalloonsTranslator') app.setApplicationVersion(VERSION) if not args.headless: ps = QGuiApplication.primaryScreen() Loading
ui/text_graphical_effect.py +178 −3 Original line number Diff line number Diff line Loading @@ -2,15 +2,15 @@ from typing import Union, Tuple, Callable import cv2 import numpy as np from qtpy.QtCore import Signal, Qt, QPoint from qtpy.QtGui import QColor, QShowEvent, QPixmap, QImage, QPainter, QFontMetricsF from qtpy.QtCore import Signal, Qt, QPoint, QPointF from qtpy.QtGui import QColor, QShowEvent, QPixmap, QImage, QPainter, QFontMetricsF, QLinearGradient, QPainterPath from qtpy.QtWidgets import QHBoxLayout, QVBoxLayout, QGridLayout, QScrollArea, QGroupBox, QPushButton, QLabel, QDialog from utils import shared as C from .misc import pixmap2ndarray, ndarray2pixmap from utils.fontformat import FontFormat, pt2px from .custom_widget import Widget, ColorPickerLabel, PaintQSlider import math def apply_shadow_effect(img: Union[QPixmap, QImage, np.ndarray], color: QColor, strength=1.0, radius=21) -> Tuple[ QPixmap, np.ndarray, np.ndarray]: Loading Loading @@ -226,3 +226,178 @@ class TextEffectPanelDeprecated(QDialog): self.shadow_color_picker.setPickerColor(self.fontfmt.shadow_color) self.shadow_radius_slider.setValue(int(self.fontfmt.shadow_radius * 100)) self.shadow_strength_slider.setValue(int(self.fontfmt.shadow_strength * 100)) class GradientPreviewPanel(QDialog): apply = Signal() gradient_changed = Signal() def __init__(self, update_text_style_label: Callable, *args, **kwargs) -> None: super().__init__(*args, **kwargs) self.setModal(True) self.update_text_style_label = update_text_style_label self.fontfmt: FontFormat = None self.fontfmt = FontFormat() self.active_fontfmt = FontFormat() # Preview label setup self.preview_label = QLabel(self) self.preview_label.setContentsMargins(0, 0, 0, 0) font = self.preview_label.font() font.setPointSizeF(24) self.preview_label.setFont(font) self.preview_label.setAlignment(Qt.AlignmentFlag.AlignCenter) self.preview_text = self.tr("Gradient") fm = QFontMetricsF(font) br = fm.boundingRect(self.preview_text) br_w, br_h = br.width(), br.height() self.preview_pixmap = QPixmap(int(br_w + br_h * 2), int(br_h * 3)) self.preview_origin = QPointF(int(br_h), int(1.75 * br_h)) self.preview_label.setFixedHeight(int(br_h * 2)) # Enable gradient checkbox self.gradient_enable = QGroupBox(self.tr("Enable Gradient")) self.gradient_enable.setCheckable(True) self.gradient_enable.toggled.connect(self.on_gradient_enabled_changed) # Color pickers start_color_layout = QHBoxLayout() start_color_layout.addWidget(QLabel(self.tr("Start Color:"))) self.gradient_start_picker = ColorPickerLabel(self) self.gradient_start_picker.colorChanged.connect(self.on_gradient_start_color_changed) start_color_layout.addWidget(self.gradient_start_picker) end_color_layout = QHBoxLayout() end_color_layout.addWidget(QLabel(self.tr("End Color:"))) self.gradient_end_picker = ColorPickerLabel(self) self.gradient_end_picker.colorChanged.connect(self.on_gradient_end_color_changed) end_color_layout.addWidget(self.gradient_end_picker) # Angle slider self.angle_slider = PaintQSlider(self.tr("Angle")) self.angle_slider.setRange(0, 359) self.angle_slider.valueChanged.connect(self.on_gradient_angle_changed) # Size slider self.size_slider = PaintQSlider(self.tr("Size")) self.size_slider.setRange(50, 200) self.size_slider.valueChanged.connect(self.on_gradient_size_changed) # Buttons self.apply_btn = QPushButton(self.tr('Apply')) self.apply_btn.clicked.connect(self.on_apply_clicked) self.cancel_btn = QPushButton(self.tr('Cancel')) self.cancel_btn.clicked.connect(self.on_cancel_clicked) # Layout gradient_layout = QVBoxLayout() gradient_layout.addLayout(start_color_layout) gradient_layout.addLayout(end_color_layout) gradient_layout.addWidget(self.angle_slider) gradient_layout.addWidget(self.size_slider) self.gradient_enable.setLayout(gradient_layout) button_layout = QHBoxLayout() button_layout.addWidget(self.apply_btn) button_layout.addWidget(self.cancel_btn) main_layout = QVBoxLayout(self) main_layout.addWidget(self.preview_label) main_layout.addWidget(self.gradient_enable) main_layout.addLayout(button_layout) self.setMaximumHeight(C.TEXTEFFECT_MAXHEIGHT) self.updatePreviewPixmap() def on_gradient_enabled_changed(self, enabled): self.fontfmt.gradient_enabled = enabled self.updatePreviewPixmap() def on_gradient_start_color_changed(self, is_valid): if is_valid: color = self.gradient_start_picker.color self.fontfmt.gradient_start_color = list(color.getRgb()[:3]) # Convert to list and take only RGB self.updatePreviewPixmap() def on_gradient_end_color_changed(self, is_valid): if is_valid: color = self.gradient_end_picker.color self.fontfmt.gradient_end_color = list(color.getRgb()[:3]) # Convert to list and take only RGB self.updatePreviewPixmap() def on_gradient_angle_changed(self, value): self.fontfmt.gradient_angle = float(value) self.updatePreviewPixmap() def on_gradient_size_changed(self, value): self.fontfmt.gradient_size = value / 100 self.updatePreviewPixmap() def updatePreviewPixmap(self): if not self.isVisible(): return self.preview_pixmap.fill(Qt.GlobalColor.transparent) painter = QPainter(self.preview_pixmap) painter.setRenderHint(QPainter.RenderHint.TextAntialiasing) painter.setFont(self.preview_label.font()) if self.fontfmt.gradient_enabled: # Create gradient gradient = QLinearGradient() angle = self.fontfmt.gradient_angle rad = math.radians(angle) dx = math.cos(rad) dy = math.sin(rad) rect = self.preview_pixmap.rect() center = rect.center() radius = max(rect.width(), rect.height()) * self.fontfmt.gradient_size gradient.setStart(center.x() - dx * radius, center.y() - dy * radius) gradient.setFinalStop(center.x() + dx * radius, center.y() + dy * radius) start_color = QColor(*self.fontfmt.gradient_start_color) end_color = QColor(*self.fontfmt.gradient_end_color) gradient.setColorAt(0, start_color) gradient.setColorAt(1, end_color) painter.setBrush(gradient) painter.setPen(Qt.PenStyle.NoPen) # Draw text with gradient path = QPainterPath() path.addText(self.preview_origin, self.preview_label.font(), self.preview_text) painter.drawPath(path) else: painter.drawText(self.preview_origin, self.preview_text) painter.end() self.preview_label.setPixmap(self.preview_pixmap) def on_apply_clicked(self): self.active_fontfmt.gradient_enabled = self.fontfmt.gradient_enabled self.active_fontfmt.gradient_start_color = self.fontfmt.gradient_start_color self.active_fontfmt.gradient_end_color = self.fontfmt.gradient_end_color self.active_fontfmt.gradient_angle = self.fontfmt.gradient_angle self.active_fontfmt.gradient_size = self.fontfmt.gradient_size self.gradient_changed.emit() self.update_text_style_label() self.apply.emit() self.hide() def on_cancel_clicked(self): self.hide() def showEvent(self, e: QShowEvent) -> None: self.updatePreviewPixmap() return super().showEvent(e) def updatePanels(self): self.gradient_enable.setChecked(self.fontfmt.gradient_enabled) self.gradient_start_picker.setPickerColor(self.fontfmt.gradient_start_color) self.gradient_end_picker.setPickerColor(self.fontfmt.gradient_end_color) self.angle_slider.setValue(int(self.fontfmt.gradient_angle)) self.size_slider.setValue(int(self.fontfmt.gradient_size * 100))
ui/text_panel.py +30 −102 Original line number Diff line number Diff line Loading @@ -11,7 +11,7 @@ from utils import config as C from utils.fontformat import FontFormat, px2pt, LineSpacingType from .custom_widget import Widget, ColorPickerLabel, ClickableLabel, CheckableLabel, TextCheckerLabel, AlignmentChecker, QFontChecker, SizeComboBox from .textitem import TextBlkItem from .text_graphical_effect import TextEffectPanelDeprecated from .text_graphical_effect import TextEffectPanelDeprecated, GradientPreviewPanel from .text_advanced_format import TextAdvancedFormatPanel from .text_style_presets import TextStylePresetPanel from . import funcmaps as FM Loading Loading @@ -411,68 +411,21 @@ class FontFormatPanel(Widget): ) self.textadvancedfmt_panel.param_changed.connect(self.on_param_changed) self.effectBtn = ClickableLabel(self.tr("Effect"), self) self.effectBtn.clicked.connect(self.on_effectbtn_clicked) self.effect_panel = TextEffectPanelDeprecated(update_text_style_label=self.update_text_style_label) self.effect_panel.hide() self.shadowBtn = ClickableLabel(self.tr("Shadow"), self) self.shadowBtn.clicked.connect(self.on_shadow_btn_clicked) self.gradientBtn = ClickableLabel(self.tr("Gradient"), self) self.gradientBtn.clicked.connect(self.on_gradient_btn_clicked) self.foldTextBtn = CheckableLabel(self.tr("Unfold"), self.tr("Fold"), False) self.sourceBtn = TextCheckerLabel(self.tr("Source")) self.transBtn = TextCheckerLabel(self.tr("Translation")) # Add gradient controls self.gradientGroup = QGroupBox(self.tr("Gradient"), parent=self) gradientLayout = QVBoxLayout(self.gradientGroup) gradientLayout.setContentsMargins(10, 10, 10, 10) gradientLayout.setSpacing(5) # Enable gradient checkbox self.gradientEnableBox = QCheckBox(self.tr("Enable Gradient"), parent=self.gradientGroup) self.gradientEnableBox.stateChanged.connect(lambda state: self.on_param_changed('gradient_enabled', state == Qt.CheckState.Checked.value)) gradientLayout.addWidget(self.gradientEnableBox) # Start color picker startColorLayout = QHBoxLayout() startColorLayout.addWidget(QLabel(self.tr("Start Color:"), parent=self.gradientGroup)) self.gradientStartColorPicker = ColorPickerLabel(parent=self.gradientGroup) self.gradientStartColorPicker.colorChanged.connect(self.onGradientStartColorChanged) self.gradientStartColorPicker.changingColor.connect(self.changingColor) startColorLayout.addWidget(self.gradientStartColorPicker) gradientLayout.addLayout(startColorLayout) # End color picker endColorLayout = QHBoxLayout() endColorLayout.addWidget(QLabel(self.tr("End Color:"), parent=self.gradientGroup)) self.gradientEndColorPicker = ColorPickerLabel(parent=self.gradientGroup) self.gradientEndColorPicker.colorChanged.connect(self.onGradientEndColorChanged) self.gradientEndColorPicker.changingColor.connect(self.changingColor) endColorLayout.addWidget(self.gradientEndColorPicker) gradientLayout.addLayout(endColorLayout) # Angle slider angleLayout = QHBoxLayout() angleLayout.addWidget(QLabel(self.tr("Angle:"), parent=self.gradientGroup)) self.gradientAngleSlider = QSlider(Qt.Orientation.Horizontal, parent=self.gradientGroup) self.gradientAngleSlider.setRange(0, 359) self.gradientAngleSlider.valueChanged.connect(self.onGradientAngleChanged) angleLayout.addWidget(self.gradientAngleSlider) self.gradientAngleLabel = QLabel("0°", parent=self.gradientGroup) self.gradientAngleLabel.setMinimumWidth(30) angleLayout.addWidget(self.gradientAngleLabel) gradientLayout.addLayout(angleLayout) # Add gradient size control sizeLayout = QHBoxLayout() sizeLayout.addWidget(QLabel(self.tr("Size:"), parent=self.gradientGroup)) self.gradientSizeSlider = QSlider(Qt.Orientation.Horizontal, parent=self.gradientGroup) self.gradientSizeSlider.setRange(50, 200) # 0.5x to 2.0x self.gradientSizeSlider.setValue(100) # Default 1.0x self.gradientSizeSlider.valueChanged.connect(self.onGradientSizeChanged) sizeLayout.addWidget(self.gradientSizeSlider) self.gradientSizeLabel = QLabel("1.0x", parent=self.gradientGroup) self.gradientSizeLabel.setMinimumWidth(40) sizeLayout.addWidget(self.gradientSizeLabel) gradientLayout.addLayout(sizeLayout) self.effect_panel = TextEffectPanelDeprecated(update_text_style_label=self.update_text_style_label) self.effect_panel.hide() self.gradient_panel = GradientPreviewPanel(update_text_style_label=self.update_text_style_label) self.gradient_panel.gradient_changed.connect(self.on_gradient_changed) self.gradient_panel.hide() FONTFORMAT_SPACING = 6 Loading Loading @@ -501,7 +454,8 @@ class FontFormatPanel(Widget): hl3.setAlignment(Qt.AlignmentFlag.AlignCenter) hl3.addLayout(stroke_hlayout) hl3.addLayout(lettersp_hlayout) hl3.addWidget(self.effectBtn) hl3.addWidget(self.shadowBtn) hl3.addWidget(self.gradientBtn) hl3.setContentsMargins(3, 0, 3, 0) hl3.setSpacing(13) hl4 = QHBoxLayout() Loading @@ -520,7 +474,6 @@ class FontFormatPanel(Widget): self.vlayout.addLayout(hl2) self.vlayout.addLayout(hl3) self.vlayout.addLayout(hl4) self.vlayout.addWidget(self.gradientGroup) self.vlayout.setContentsMargins(7, 0, 7, 0) self.vlayout.setSpacing(0) Loading Loading @@ -605,15 +558,6 @@ class FontFormatPanel(Widget): self.formatBtnGroup.italicBtn.setChecked(font_format.italic) self.alignBtnGroup.setAlignment(font_format.alignment) # Initialize gradient controls self.gradientEnableBox.setChecked(font_format.gradient_enabled) self.gradientStartColorPicker.setPickerColor(font_format.gradient_start_color) self.gradientEndColorPicker.setPickerColor(font_format.gradient_end_color) self.gradientAngleSlider.setValue(int(font_format.gradient_angle)) self.gradientAngleLabel.setText(f"{int(font_format.gradient_angle)}°") self.gradientSizeSlider.setValue(int(font_format.gradient_size * 100)) self.gradientSizeLabel.setText(f"{font_format.gradient_size:.1f}x") self.familybox.blockSignals(False) # self.texteffect_panel.set_active_format(font_format) self.textadvancedfmt_panel.set_active_format(font_format) Loading Loading @@ -679,41 +623,25 @@ class FontFormatPanel(Widget): self.set_active_format(blk_fmt, multi_size) self.textstyle_panel.setTitle(f'TextBlock #{textblk_item.idx}') def on_effectbtn_clicked(self): def on_shadow_btn_clicked(self): self.effect_panel.active_fontfmt = C.active_format self.effect_panel.fontfmt = copy.deepcopy(C.active_format) self.effect_panel.updatePanels() self.effect_panel.show() def onGradientAngleChanged(self, value): self.gradientAngleLabel.setText(f"{value}°") self.on_param_changed('gradient_angle', float(value)) def onGradientStartColorChanged(self, is_valid=True): self.focusOnColorDialog = False if is_valid: rgb = self.gradientStartColorPicker.rgb() self.on_param_changed('gradient_start_color', rgb) def onGradientEndColorChanged(self, is_valid=True): self.focusOnColorDialog = False if is_valid: rgb = self.gradientEndColorPicker.rgb() self.on_param_changed('gradient_end_color', rgb) def onGradientSizeChanged(self, value): self.gradientSizeLabel.setText(f"{value/100:.1f}x") self.on_param_changed('gradient_size', value/100) def updateGradientControls(self, fontfmt: FontFormat): self.gradientEnableBox.setChecked(fontfmt.gradient_enabled) self.gradientStartColorPicker.setRGB(*fontfmt.gradient_start_color) self.gradientEndColorPicker.setRGB(*fontfmt.gradient_end_color) self.gradientAngleSlider.setValue(int(fontfmt.gradient_angle)) self.gradientAngleLabel.setText(f"{int(fontfmt.gradient_angle)}°") self.gradientSizeSlider.setValue(int(fontfmt.gradient_size * 100)) self.gradientSizeLabel.setText(f"{fontfmt.gradient_size:.1f}x") def updateFontFormatPanel(self, fontfmt: FontFormat): self.updateGradientControls(fontfmt) self.update_text_style_label() def on_gradient_btn_clicked(self): self.gradient_panel.active_fontfmt = C.active_format self.gradient_panel.fontfmt = copy.deepcopy(C.active_format) self.gradient_panel.updatePanels() self.gradient_panel.show() def on_gradient_changed(self): """Handle gradient changes from the preview panel""" start_color = self.gradient_panel.gradient_start_picker.color.getRgb()[:3] end_color = self.gradient_panel.gradient_end_picker.color.getRgb()[:3] self.on_param_changed('gradient_enabled', self.gradient_panel.fontfmt.gradient_enabled) self.on_param_changed('gradient_start_color', start_color) self.on_param_changed('gradient_end_color', end_color) self.on_param_changed('gradient_angle', self.gradient_panel.fontfmt.gradient_angle) self.on_param_changed('gradient_size', self.gradient_panel.fontfmt.gradient_size)
utils/shared.py +1 −1 Original line number Diff line number Diff line Loading @@ -4,7 +4,7 @@ import os.path as osp import json import sys ICON_PATH = 'icons/[ICONNAME]' ICON_PATH = 'icons/icon.icns' PROGRAM_PATH = osp.abspath(osp.dirname(osp.dirname(__file__))) LOGGING_PATH = osp.join(PROGRAM_PATH, 'logs') Loading