FeaturePack Capabilities
Usage of Parser, Card, BinaryRuntime, PackPage, PackConfig.
A FeaturePack can provide any combination of the following capabilities.
Parser
URL matching and Task parsing. FeatureService checks each Parser's match() in ascending priority order; the first one returning True takes over.
class FtpParser(TaskParser):
priority = 95
def match(self, options: TaskOptions) -> bool:
return urlparse(options.url).scheme.lower() in {"ftp", "ftps"}
async def parse(self, options: TaskOptions) -> Task:
# Connect to FTP server, get file info, build Task
...matchPassive() is used in passive scenarios like clipboard monitoring; it calls match() by default. It can be overridden to be stricter (for example, matching only specific extensions).
Card
Customize Draft confirmation cards and Task progress cards.
class MyPack(FeaturePack):
packId = "my_pack"
parsers = [MyParser]
taskCards = {MyTask: MyTaskCard}
draftCards = {MyTask: MyDraftCard}taskCardsmaps Task types to TaskCard subclasses (progress cards displayed in the main window)draftCardsmaps Task types to DraftCard subclasses (cards in the confirmation window)- When not registered, default base class cards are used
BinaryRuntime
Manages external executables (ffmpeg, yt-dlp, etc.).
class FfmpegRuntime(BinaryRuntime):
name = "ffmpeg"
canInstall = True
title = "FFmpeg"
description = "Audio/video processing tool"
def path(self) -> str:
return shutil.which("ffmpeg") or ""
async def installTask(self) -> Task:
# Return a download + extract Task
...Declare it in the Pack:
class MyPack(FeaturePack):
def runtimes(self) -> list[BinaryRuntime]:
return [FfmpegRuntime()]The settings page automatically shows an install button for Runtimes with canInstall = True.
PackPage
Adds custom pages to the sidebar (such as a resource store).
class MyPage(PackPage):
icon = FluentIcon.LIBRARY
title = "Resource Downloads"class MyPack(FeaturePack):
def pages(self) -> list[type[PackPage]]:
return [MyPage]PackConfig
Adds persistent configuration items for a Pack, automatically injected into the global settings system.
class FFmpegConfig(PackConfig):
installFolder = ConfigItem("FFmpeg", "InstallFolder", f"{APP_DATA_DIR}/FFmpeg")
def settingGroups(self, parent: QWidget) -> list[CollapsibleSettingCardGroup]:
from app.view.components.setting_card_group import CollapsibleSettingCardGroup
from app.view.components.setting_cards import SelectFolderSettingCard
group = CollapsibleSettingCardGroup(self.tr("FFmpeg"), "ffmpeg", parent)
folderCard = SelectFolderSettingCard(
ffmpegConfig.installFolder, f"{APP_DATA_DIR}/FFmpeg",
self.tr("FFmpeg Install Directory"), group,
)
runtimeCard = self.createRuntimeCard(ffmpegRuntime, group)
folderCard.pathChanged.connect(runtimeCard._onInstallFolderChanged)
group.addSettingCards([folderCard, runtimeCard])
runtimeCard.refreshStatus()
return [group]class FFmpegPack(FeaturePack):
packId = "ffmpeg"
config = FFmpegConfig()Configuration values are read via cfg.pack_FFmpegConfig_installFolder.value. __init_subclass__ automatically prefixes keys with pack_{class name}_, so configuration items with the same name in different Packs do not conflict.