39a086b41b
Build Windows CPU / build (push) Has been cancelled
Build Windows CUDA 10.2 / build (push) Has been cancelled
Build Windows CUDA 11.8 / build (push) Has been cancelled
Build Windows CUDA 12.6 / build (push) Has been cancelled
Build Windows DirectML / build (push) Has been cancelled
327 lines
14 KiB
Python
327 lines
14 KiB
Python
"""
|
|
@desc: 高级设置页面
|
|
"""
|
|
import sys
|
|
|
|
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, ComboBoxSettingCard, 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
|
|
from backend.tools.constant import VideoSubFinderDecoder
|
|
|
|
class AdvancedSettingInterface(ScrollArea):
|
|
"""高级设置页面"""
|
|
|
|
def __init__(self, parent=None):
|
|
super().__init__(parent)
|
|
self.parent = parent
|
|
self.version_manager = VersionService()
|
|
self.__initWidget()
|
|
|
|
def __initWidget(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.advanced_group.addSettingCard(self.rec_batch_number)
|
|
self.advanced_group.addSettingCard(self.max_batch_size)
|
|
self.advanced_group.addSettingCard(self.subtitle_area)
|
|
self.advanced_group.addSettingCard(self.extract_frequency)
|
|
self.advanced_group.addSettingCard(self.tolerant_pixel_y)
|
|
self.advanced_group.addSettingCard(self.tolerant_pixel_x)
|
|
self.advanced_group.addSettingCard(self.subtitle_area_deviation_pixel)
|
|
self.advanced_group.addSettingCard(self.waterark_area_num)
|
|
self.advanced_group.addSettingCard(self.threshold_text_similarity)
|
|
self.advanced_group.addSettingCard(self.drop_score)
|
|
self.advanced_group.addSettingCard(self.subtitle_area_deviation_rate)
|
|
self.advanced_group.addSettingCard(self.save_directory)
|
|
self.advanced_group.addSettingCard(self.check_update_on_startup)
|
|
self.expandLayout.addWidget(self.advanced_group)
|
|
|
|
self.video_sub_finder_group.addSettingCard(self.video_sub_finder_cpu_cores)
|
|
self.video_sub_finder_group.addSettingCard(self.video_sub_finder_decoder)
|
|
self.expandLayout.addWidget(self.video_sub_finder_group)
|
|
|
|
self.dev_group.addSettingCard(self.debug_ocr_loss)
|
|
self.dev_group.addSettingCard(self.debug_no_delete_cache)
|
|
self.dev_group.addSettingCard(self.delete_empty_time_stamp)
|
|
self.expandLayout.addWidget(self.dev_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.advanced_group = SettingCardGroup(tr["Setting"]["AdvancedSetting"], self.scrollWidget)
|
|
# VideoSubFinder设置组
|
|
self.video_sub_finder_group = SettingCardGroup(tr["Setting"]["VideoSubFinderSetting"], self.scrollWidget)
|
|
# 开发设置组
|
|
self.dev_group = SettingCardGroup(tr["Setting"]["DevSetting"], self.scrollWidget)
|
|
# 关于设置组
|
|
self.about_group = SettingCardGroup(tr["Setting"]["AboutSetting"], self.scrollWidget)
|
|
|
|
# 每张图中同时识别的文本框数量
|
|
self.rec_batch_number = RangeSettingCard(
|
|
configItem=config.recBatchNumber,
|
|
icon=FluentIcon.SEARCH,
|
|
title=tr["Setting"]["RecBatchNumber"],
|
|
content=tr["Setting"]["RecBatchNumberDesc"],
|
|
parent=self.advanced_group
|
|
)
|
|
# DB算法每个batch识别多少张
|
|
self.max_batch_size = RangeSettingCard(
|
|
configItem=config.maxBatchSize,
|
|
icon=FluentIcon.SEARCH_MIRROR,
|
|
title=tr["Setting"]["MaxBatchSize"],
|
|
content=tr["Setting"]["MaxBatchSizeDesc"],
|
|
parent=self.advanced_group
|
|
)
|
|
# 字幕出现区域
|
|
self.subtitle_area = ComboBoxSettingCard(
|
|
configItem=config.subtitleArea,
|
|
icon=FluentIcon.VIEW,
|
|
title=tr["Setting"]["SubtitleArea"],
|
|
content=tr["Setting"]["SubtitleAreaDesc"],
|
|
parent=self.advanced_group,
|
|
texts=tr['SubtitleArea'].values(),
|
|
)
|
|
# 每一秒抓取多少帧进行OCR识别
|
|
self.extract_frequency = RangeSettingCard(
|
|
configItem=config.extractFrequency,
|
|
icon=FluentIcon.SPEED_HIGH,
|
|
title=tr["Setting"]["ExtractFrequency"],
|
|
content=tr["Setting"]["ExtractFrequencyDesc"],
|
|
parent=self.advanced_group
|
|
)
|
|
# 容忍的像素点偏差
|
|
self.tolerant_pixel_y = RangeSettingCard(
|
|
configItem=config.tolerantPixelY,
|
|
icon=FluentIcon.ARROW_DOWN,
|
|
title=tr["Setting"]["TolerantPixelY"],
|
|
content=tr["Setting"]["TolerantPixelYDesc"],
|
|
parent=self.advanced_group
|
|
)
|
|
self.tolerant_pixel_x = RangeSettingCard(
|
|
configItem=config.tolerantPixelX,
|
|
icon=FluentIcon.RIGHT_ARROW,
|
|
title=tr["Setting"]["TolerantPixelX"],
|
|
content=tr["Setting"]["TolerantPixelXDesc"],
|
|
parent=self.advanced_group
|
|
)
|
|
# 字幕区域偏移量
|
|
self.subtitle_area_deviation_pixel = RangeSettingCard(
|
|
configItem=config.subtitleAreaDeviationPixel,
|
|
icon=FluentIcon.MOVE,
|
|
title=tr["Setting"]["SubtitleAreaDeviationPixel"],
|
|
content=tr["Setting"]["SubtitleAreaDeviationPixelDesc"],
|
|
parent=self.advanced_group
|
|
)
|
|
# 最有可能出现的水印区域
|
|
self.waterark_area_num = RangeSettingCard(
|
|
configItem=config.waterarkAreaNum,
|
|
icon=FluentIcon.PHOTO,
|
|
title=tr["Setting"]["WaterarkAreaNum"],
|
|
content=tr["Setting"]["WaterarkAreaNumDesc"],
|
|
parent=self.advanced_group
|
|
)
|
|
# 文本相似度阈值
|
|
self.threshold_text_similarity = RangeSettingCard(
|
|
configItem=config.thresholdTextSimilarity,
|
|
icon=FluentIcon.DICTIONARY,
|
|
title=tr["Setting"]["ThresholdTextSimilarity"],
|
|
content=tr["Setting"]["ThresholdTextSimilarityDesc"],
|
|
parent=self.advanced_group
|
|
)
|
|
# 字幕提取中置信度低于0.75的不要
|
|
self.drop_score = RangeSettingCard(
|
|
configItem=config.dropScore,
|
|
icon=FluentIcon.ACCEPT_MEDIUM,
|
|
title=tr["Setting"]["DropScore"],
|
|
content=tr["Setting"]["DropScoreDesc"],
|
|
parent=self.advanced_group
|
|
)
|
|
# 字幕区域允许偏差
|
|
self.subtitle_area_deviation_rate = RangeSettingCard(
|
|
configItem=config.subtitleAreaDeviationRate,
|
|
icon=FluentIcon.PIE_SINGLE,
|
|
title=tr["Setting"]["SubtitleAreaDeviationRate"],
|
|
content=tr["Setting"]["SubtitleAreaDeviationRateDesc"],
|
|
parent=self.advanced_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
|
|
)
|
|
# VideoSubFinder CPU核心数
|
|
self.video_sub_finder_cpu_cores = RangeSettingCard(
|
|
configItem=config.videoSubFinderCpuCores,
|
|
icon=FluentIcon.SPEED_MEDIUM,
|
|
title=tr["Setting"]["VideoSubFinderCpuCores"],
|
|
content=tr["Setting"]["VideoSubFinderCpuCoresDesc"],
|
|
parent=self.video_sub_finder_group
|
|
)
|
|
# VideoSubFinder 视频解码组件
|
|
self.video_sub_finder_decoder = ComboBoxSettingCard(
|
|
configItem=config.videoSubFinderDecoder,
|
|
icon=FluentIcon.VIDEO,
|
|
title=tr["Setting"]["VideoSubFinderDecoder"],
|
|
content=tr["Setting"]["VideoSubFinderDecoderDesc"],
|
|
texts=[item.value for item in VideoSubFinderDecoder],
|
|
parent=self.video_sub_finder_group
|
|
)
|
|
# 输出丢失的字幕帧
|
|
self.debug_ocr_loss = SwitchSettingCard(
|
|
configItem=config.debugOcrLoss,
|
|
icon=FluentIcon.QUESTION,
|
|
title=tr["Setting"]["DebugOcrLoss"],
|
|
content=tr["Setting"]["DebugOcrLossDesc"],
|
|
parent=self.dev_group
|
|
)
|
|
# 是否不删除缓存数据
|
|
self.debug_no_delete_cache = SwitchSettingCard(
|
|
configItem=config.debugNoDeleteCache,
|
|
icon=FluentIcon.FOLDER,
|
|
title=tr["Setting"]["DebugNoDeleteCache"],
|
|
content=tr["Setting"]["DebugNoDeleteCacheDesc"],
|
|
parent=self.dev_group
|
|
)
|
|
# 是否删除空时间轴
|
|
self.delete_empty_time_stamp = SwitchSettingCard(
|
|
configItem=config.deleteEmptyTimeStamp,
|
|
icon=FluentIcon.DELETE,
|
|
title=tr["Setting"]["DeleteEmptyTimeStamp"],
|
|
content=tr["Setting"]["DeleteEmptyTimeStampDesc"],
|
|
parent=self.dev_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)
|
|
|
|
def macos_scrollarea_issue_workaround(self):
|
|
if sys.platform != "darwin":
|
|
return
|
|
self.verticalScrollBar().setValue(0)
|
|
self.scrollWidget.adjustSize()
|
|
self.expandLayout.update()
|
|
self.expandLayout.activate()
|
|
|
|
def resizeEvent(self, event):
|
|
# macos_scrollarea_issue_workaround
|
|
if sys.platform == "darwin":
|
|
self.verticalScrollBar().setValue(0)
|
|
super().resizeEvent(event) |