Files
video-subtitle-remover/ui/advanced_setting_interface.py
2025-05-22 19:50:24 +08:00

270 lines
12 KiB
Python

"""
@desc: 高级设置页面
"""
from PySide6 import QtWidgets, QtCore, QtGui
from PySide6.QtWidgets import QFileDialog
from qfluentwidgets import (ScrollArea, ExpandLayout, CardWidget, SubtitleLabel,
FluentIcon, NavigationWidget, NavigationItemPosition,
SettingCardGroup, RangeSettingCard, SwitchSettingCard,
HyperlinkCard, PrimaryPushSettingCard, PushSettingCard,
MessageBox)
from backend.config import config, tr, VERSION, PROJECT_HOME_URL, PROJECT_ISSUES_URL, PROJECT_RELEASES_URL
from backend.tools.version_service import VersionService
from backend.tools.concurrent import TaskExecutor
class AdvancedSettingInterface(ScrollArea):
"""高级设置页面"""
def __init__(self, parent=None):
super().__init__(parent)
self.parent = parent
self.version_manager = VersionService()
self.__init_widgets()
def __init_widgets(self):
# 创建滚动内容的容器
self.scrollWidget = QtWidgets.QWidget(self)
self.expandLayout = ExpandLayout(self.scrollWidget)
# 设置滚动区域属性
self.setWidget(self.scrollWidget)
self.enableTransparentBackground()
self.setWidgetResizable(True)
self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
# 设置滚动区域样式以适应主题
self.setAttribute(QtCore.Qt.WA_StyledBackground)
# 设置UI
self.setup_ui()
self.setup_layout()
def setup_layout(self):
self.subtitle_detection_group.addSettingCard(self.subtitle_yx_axis_difference_pixel)
self.subtitle_detection_group.addSettingCard(self.subtitle_area_deviation_pixel)
self.subtitle_detection_group.addSettingCard(self.subtitle_area_y_axis_difference_pixel)
self.subtitle_detection_group.addSettingCard(self.subtitle_area_pixel_tolerance_y_pixel)
self.subtitle_detection_group.addSettingCard(self.subtitle_area_pixel_tolerance_x_pixel)
self.subtitle_detection_group.addSettingCard(self.subtitle_timeline_backward_frame_count)
self.subtitle_detection_group.addSettingCard(self.subtitle_timeline_forward_frame_count)
self.expandLayout.addWidget(self.subtitle_detection_group)
self.sttn_group.addSettingCard(self.sttn_neighbor_stride)
self.sttn_group.addSettingCard(self.sttn_reference_length)
self.sttn_group.addSettingCard(self.sttn_max_load_num)
self.expandLayout.addWidget(self.sttn_group)
self.propainter_group.addSettingCard(self.propainter_max_load_num)
self.expandLayout.addWidget(self.propainter_group)
self.advanced_group.addSettingCard(self.save_directory)
self.advanced_group.addSettingCard(self.check_update_on_startup)
self.expandLayout.addWidget(self.advanced_group)
self.about_group.addSettingCard(self.feedback)
self.about_group.addSettingCard(self.copyright)
self.about_group.addSettingCard(self.project_link)
self.expandLayout.addWidget(self.about_group)
self.expandLayout.setSpacing(16)
self.expandLayout.setContentsMargins(16, 16, 16, 48)
def setup_ui(self):
"""设置UI"""
# 字幕检测设置组
self.subtitle_detection_group = SettingCardGroup(tr["Setting"]["SubtitleDetectionSetting"], self.scrollWidget)
# STTN设置组
self.sttn_group = SettingCardGroup(tr["Setting"]["SttnSetting"], self.scrollWidget)
# Propainter设置组
self.propainter_group = SettingCardGroup(tr["Setting"]["ProPainterSetting"], self.scrollWidget)
# 高级设置组
self.advanced_group = SettingCardGroup(tr["Setting"]["AdvancedSetting"], self.scrollWidget)
# 关于设置组
self.about_group = SettingCardGroup(tr["Setting"]["AboutSetting"], self.scrollWidget)
self.subtitle_yx_axis_difference_pixel = RangeSettingCard(
configItem=config.subtitleYXAxisDifferencePixel,
icon=FluentIcon.ZOOM,
title=tr["Setting"]["SubtitleYXAxisDifferencePixel"],
content=tr["Setting"]["SubtitleYXAxisDifferencePixelDesc"],
parent=self.subtitle_detection_group
)
self.subtitle_area_deviation_pixel = RangeSettingCard(
configItem=config.subtitleAreaDeviationPixel,
icon=FluentIcon.ZOOM_IN,
title=tr["Setting"]["SubtitleAreaDeviationPixel"],
content=tr["Setting"]["SubtitleAreaDeviationPixelDesc"],
parent=self.subtitle_detection_group
)
self.subtitle_area_y_axis_difference_pixel = RangeSettingCard(
configItem=config.subtitleAreaYAxisDifferencePixel,
icon=FluentIcon.ALIGNMENT,
title=tr["Setting"]["SubtitleAreaYAxisDifferencePixel"],
content=tr["Setting"]["SubtitleAreaYAxisDifferencePixelDesc"],
parent=self.subtitle_detection_group
)
self.subtitle_area_pixel_tolerance_y_pixel = RangeSettingCard(
configItem=config.subtitleAreaPixelToleranceYPixel,
icon=FluentIcon.UP,
title=tr["Setting"]["SubtitleAreaPixelToleranceYPixel"],
content=tr["Setting"]["SubtitleAreaPixelToleranceYPixelDesc"],
parent=self.subtitle_detection_group
)
self.subtitle_area_pixel_tolerance_x_pixel = RangeSettingCard(
configItem=config.subtitleAreaPixelToleranceXPixel,
icon=FluentIcon.RIGHT_ARROW,
title=tr["Setting"]["SubtitleAreaPixelToleranceXPixel"],
content=tr["Setting"]["SubtitleAreaPixelToleranceXPixelDesc"],
parent=self.subtitle_detection_group
)
self.subtitle_timeline_backward_frame_count = RangeSettingCard(
configItem=config.subtitleTimelineBackwardFrameCount,
icon=FluentIcon.PAGE_LEFT,
title=tr["Setting"]["SubtitleTimelineBackwardFrameCount"],
content=tr["Setting"]["SubtitleTimelineBackwardFrameCountDesc"],
parent=self.subtitle_detection_group
)
self.subtitle_timeline_forward_frame_count = RangeSettingCard(
configItem=config.subtitleTimelineForwardFrameCount,
icon=FluentIcon.PAGE_RIGHT,
title=tr["Setting"]["subtitleTimelineForwardFrameCount"],
content=tr["Setting"]["subtitleTimelineForwardFrameCountDesc"],
parent=self.subtitle_detection_group
)
self.sttn_neighbor_stride = RangeSettingCard(
configItem=config.sttnNeighborStride,
icon=FluentIcon.UNIT,
title=tr["Setting"]["SttnNeighborStride"],
content=tr["Setting"]["SttnNeighborStrideDesc"],
parent=self.sttn_group
)
self.sttn_reference_length = RangeSettingCard(
configItem=config.sttnReferenceLength,
icon=FluentIcon.MORE,
title=tr["Setting"]["SttnReferenceLength"],
content=tr["Setting"]["SttnReferenceLengthDesc"],
parent=self.sttn_group
)
self.sttn_max_load_num = RangeSettingCard(
configItem=config.sttnMaxLoadNum,
icon=FluentIcon.DICTIONARY,
title=tr["Setting"]["SttnMaxLoadNum"],
content=tr["Setting"]["SttnMaxLoadNumDesc"],
parent=self.sttn_group
)
self.propainter_max_load_num = RangeSettingCard(
configItem=config.propainterMaxLoadNum,
icon=FluentIcon.DICTIONARY,
title=tr["Setting"]["PropainterMaxLoadNum"],
content=tr["Setting"]["PropainterMaxLoadNumDesc"],
parent=self.propainter_group
)
# 视频保存路径
self.save_directory = PushSettingCard(
text=tr["Setting"]["ChooseDirectory"],
icon=FluentIcon.DOWNLOAD,
title=tr["Setting"]["SaveDirectory"],
content=tr["Setting"]["SaveDirectoryDefault"] if not config.saveDirectory.value else config.saveDirectory.value,
parent=self.advanced_group
)
self.save_directory.clicked.connect(self.choose_save_directory)
self.check_update_on_startup = SwitchSettingCard(
configItem=config.checkUpdateOnStartup,
icon=FluentIcon.UPDATE,
title=tr["Setting"]["CheckUpdateOnStartup"],
content=tr["Setting"]["CheckUpdateOnStartupDesc"],
parent=self.advanced_group
)
# 添加反馈链接
self.feedback = PrimaryPushSettingCard(
text=tr["Setting"]["FeedbackButton"],
icon=FluentIcon.MAIL,
title=tr["Setting"]["FeedbackTitle"],
content=tr["Setting"]["FeedbackDesc"],
parent=self.about_group
)
self.feedback.clicked.connect(lambda: QtGui.QDesktopServices.openUrl(
QtCore.QUrl(PROJECT_ISSUES_URL)
))
# 添加版权信息
self.copyright = PrimaryPushSettingCard(
text=tr["Setting"]["CopyrightButton"],
icon=FluentIcon.MAIL,
title=tr["Setting"]["CopyrightTitle"],
content=tr["Setting"]["CopyrightDesc"].format(VERSION),
parent=self.about_group
)
self.copyright.clicked.connect(lambda: self.check_update())
# 添加项目链接
self.project_link = HyperlinkCard(
url=PROJECT_HOME_URL,
text=PROJECT_HOME_URL,
icon=FluentIcon.GITHUB,
title=tr["Setting"]["ProjectLinkTitle"],
content=tr["Setting"]["ProjectLinkDesc"],
parent=self.about_group
)
def show_message_box(self, title: str, content: str, showYesButton=False, yesSlot=None):
""" show message box """
w = MessageBox(title, content, self)
if not showYesButton:
w.cancelButton.setText(self.tr('Close'))
w.yesButton.hide()
w.buttonLayout.insertStretch(0, 1)
if w.exec() and yesSlot is not None:
yesSlot()
def check_update(self, ignore=False):
""" check software update
Parameters
----------
ignore: bool
ignore message box when no updates are available
"""
TaskExecutor.runTask(self.version_manager.has_new_version).then(
lambda success: self.on_version_info_fetched(success, ignore))
def on_version_info_fetched(self, success, ignore=False):
if success:
self.show_message_box(
tr["Setting"]["UpdatesAvailableTitle"],
tr["Setting"]["UpdatesAvailableDesc"].format(self.version_manager.lastest_version),
True,
lambda: QtGui.QDesktopServices.openUrl(
QtCore.QUrl(PROJECT_RELEASES_URL)
)
)
elif not ignore:
self.show_message_box(
tr["Setting"]["NoUpdatesAvailableTitle"],
tr["Setting"]["NoUpdatesAvailableDesc"],
)
def choose_save_directory(self):
"""选择保存目录"""
last_save_directory = "./" if not config.saveDirectory.value else config.saveDirectory.value
folder = QFileDialog.getExistingDirectory(
self, tr['Setting']['ChooseDirectory'], last_save_directory)
if not folder:
folder = ""
config.set(config.saveDirectory, folder)
self.save_directory.setContent(tr["Setting"]["SaveDirectoryDefault"] if not config.saveDirectory.value else config.saveDirectory.value)