mirror of
https://git.srhtnin.garden/sarah/SaraSort.git
synced 2026-10-14 18:48:11 +02:00
SaraSort: Flet GUI for configuring SaraSortd
Flowchart of inputs/outputs with editable arrows, service page (status, controls, autostart, version, logs), config editor (form + raw), templates, tools (warnings, filename tester, failed files) and settings with SaraFem-compatible export/import. AppImage build and a SaraSuite manifest in Packaging/. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
commit
f7ed23edf9
22 files changed
+3399
No files matched your search
+130
@@ -0,0 +1,130 @@
|
||||
"""Ready-made connections ("Pictures sorting" and so on): a list of patterns
|
||||
plus a few settings, installed between an input and an output you pick.
|
||||
|
||||
Built-ins live here. Your own are TOML files in
|
||||
~/.config/SaraSuite/SaraSort/Templates/, same keys as SortTemplate:
|
||||
|
||||
Name = "3D prints"
|
||||
Description = "Models and slicer files."
|
||||
Icon = "VIEW_IN_AR"
|
||||
Patterns = ["*.stl", "*.3mf"]
|
||||
NewFileName = "~^" # optional; OutputDirConf.toml's default otherwise
|
||||
SuggestedOutput = "~/Prints" # optional
|
||||
[OutputSettings] # optional, top-level keys of the output's config
|
||||
DeleteOrg = 1
|
||||
[InputSettings] # optional, top-level keys of the input's config
|
||||
SortDirs = 0
|
||||
"""
|
||||
|
||||
import re
|
||||
from dataclasses import asdict, dataclass, field
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
import tomlkit
|
||||
|
||||
from Core import UserTemplatesDir
|
||||
|
||||
|
||||
@dataclass
|
||||
class SortTemplate:
|
||||
Name: str
|
||||
Description: str = ""
|
||||
Icon: str = "FOLDER_COPY_OUTLINED"
|
||||
Patterns: list[str] = field(default_factory=list)
|
||||
NewFileName: str = "" # empty: OutputDirConf.toml's default
|
||||
SuggestedOutput: str = ""
|
||||
OutputSettings: dict = field(default_factory=dict)
|
||||
InputSettings: dict = field(default_factory=dict)
|
||||
FilePath: Optional[Path] = None # set for your own templates
|
||||
|
||||
@property
|
||||
def BuiltIn(self) -> bool:
|
||||
return self.FilePath is None
|
||||
|
||||
|
||||
BuiltInTemplates = [
|
||||
SortTemplate(
|
||||
"Pictures", "Photos, screenshots and other images.", "IMAGE_OUTLINED",
|
||||
["*.jp*g", "*.png", "*.gif", "*.webp", "*.bmp", "*.svg", "*.heic", "*.tif*", "*.avif"],
|
||||
SuggestedOutput="~/Pictures",
|
||||
),
|
||||
SortTemplate(
|
||||
"Videos", "Video files.", "MOVIE_OUTLINED",
|
||||
["*.mp4", "*.mkv", "*.webm", "*.mov", "*.avi", "*.m4v"],
|
||||
SuggestedOutput="~/Videos",
|
||||
),
|
||||
SortTemplate(
|
||||
"Music", "Audio files.", "MUSIC_NOTE_OUTLINED",
|
||||
["*.mp3", "*.flac", "*.ogg", "*.opus", "*.wav", "*.m4a", "*.aac"],
|
||||
SuggestedOutput="~/Music",
|
||||
),
|
||||
SortTemplate(
|
||||
"Documents", "PDFs, office files and text.", "DESCRIPTION_OUTLINED",
|
||||
["*.pdf", "*.doc*", "*.odt", "*.rtf", "*.txt", "*.md", "*.xls*", "*.ods", "*.csv", "*.ppt*", "*.odp", "*.epub"],
|
||||
SuggestedOutput="~/Documents",
|
||||
),
|
||||
SortTemplate(
|
||||
"Archives (unpacked)", "Archives, unpacked in the output and the archive removed.", "FOLDER_ZIP_OUTLINED",
|
||||
["*.zip", "*.tar", "*.tar.gz", "*.tgz", "*.tar.xz", "*.tar.bz2"],
|
||||
OutputSettings={"Unzip": ["zip", "tar", "tar.gz", "tgz", "tar.xz", "tar.bz2"]},
|
||||
),
|
||||
SortTemplate(
|
||||
"Git repositories", "Folders (e.g. cloned repos) are zipped by the input, moved and unzipped in the output.",
|
||||
"ACCOUNT_TREE_OUTLINED", ["*.zip"],
|
||||
SuggestedOutput="~/Applications",
|
||||
OutputSettings={"Unzip": ["zip"]},
|
||||
InputSettings={"SortDirs": 1},
|
||||
),
|
||||
SortTemplate(
|
||||
"Logs", "Log files, renamed with today's date in front.", "RECEIPT_LONG_OUTLINED",
|
||||
["*.log", "*.log.*"], NewFileName="[y].[m].[d]_~^",
|
||||
),
|
||||
SortTemplate(
|
||||
"3D printing", "Models, OpenSCAD files and slicer output.", "VIEW_IN_AR_OUTLINED",
|
||||
["*.stl", "*.3mf", "*.scad", "*.step", "*.stp", "*.obj", "*.gcode", "*.bgcode"],
|
||||
),
|
||||
SortTemplate(
|
||||
"Installers", "AppImages, packages and Flatpak refs.", "INSTALL_DESKTOP_OUTLINED",
|
||||
["*.AppImage", "*.rpm", "*.deb", "*.flatpak", "*.flatpakref"],
|
||||
),
|
||||
SortTemplate(
|
||||
"Backup copy", "Copies everything instead of moving it (DeleteOrg = 0).", "CONTENT_COPY_OUTLINED",
|
||||
["*"], OutputSettings={"DeleteOrg": 0},
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
def UserTemplates() -> list[SortTemplate]:
|
||||
if not UserTemplatesDir.is_dir():
|
||||
return []
|
||||
Found = []
|
||||
Known = set(SortTemplate.__dataclass_fields__) - {"FilePath"}
|
||||
for FilePath in sorted(UserTemplatesDir.glob("*.toml")):
|
||||
try:
|
||||
Data = tomlkit.parse(FilePath.read_text()).unwrap()
|
||||
except (OSError, tomlkit.exceptions.TOMLKitError):
|
||||
continue
|
||||
Values = {Key: Value for Key, Value in Data.items() if Key in Known}
|
||||
Values.setdefault("Name", FilePath.stem)
|
||||
Found.append(SortTemplate(**Values, FilePath=FilePath))
|
||||
return Found
|
||||
|
||||
|
||||
def AllTemplates() -> list[SortTemplate]:
|
||||
return BuiltInTemplates + UserTemplates()
|
||||
|
||||
|
||||
def SaveUserTemplate(Template: SortTemplate) -> Path:
|
||||
UserTemplatesDir.mkdir(parents=True, exist_ok=True)
|
||||
FileName = re.sub(r"[^A-Za-z0-9]+", "", Template.Name.title()) or "Template"
|
||||
FilePath = UserTemplatesDir / f"{FileName}.toml"
|
||||
Data = {Key: Value for Key, Value in asdict(Template).items() if Key != "FilePath" and Value not in ("", {}, [])}
|
||||
Data["Patterns"] = Template.Patterns
|
||||
FilePath.write_text(tomlkit.dumps(Data))
|
||||
return FilePath
|
||||
|
||||
|
||||
def DeleteUserTemplate(Template: SortTemplate) -> None:
|
||||
if Template.FilePath:
|
||||
Template.FilePath.unlink(missing_ok=True)
|
||||
Reference in new issue
Block a user