Files
SaraFem/FolderIcons.py
T

86 lines
3.8 KiB
Python

"""Per-directory custom folder icons (Features: "Add custom icons for
directories... should be able to be changed in properties"). Independent
of the global fullness-variant system in Core.py's FolderIconBands/
AppConfig.FolderFullnessThreshold — a directory listed here always shows
its own fixed icon/image regardless of how full it is; see Browser.py's
_ResolveFolderIcon for how the two combine."""
from dataclasses import dataclass
from pathlib import Path
import toml
from Core import ConfigDir
FolderIconsPath = ConfigDir / "FolderIcons.toml"
# Pre-made choices for the icon picker (Features: "Use the pre-made ones" /
# "add more folder icons (e.g. documents and such)"): Material's own
# folder-shape variants first, then purpose/content icons so a folder can be
# marked by what's in it, not just shape — common special-folder categories
# (Documents, Desktop, Fonts, Games, ...) plus Bookmarks' original set.
FolderIconChoices = [
"FOLDER_OUTLINED", "FOLDER_OPEN", "FOLDER_SPECIAL", "FOLDER_SHARED",
"FOLDER_ZIP", "FOLDER_COPY", "SNIPPET_FOLDER", "RULE_FOLDER",
"STAR_OUTLINE", "FAVORITE_OUTLINE", "WORK_OUTLINE", "HOME_OUTLINED",
"DOWNLOAD_OUTLINED", "IMAGE_OUTLINED", "MUSIC_NOTE_OUTLINED",
"VIDEOCAM_OUTLINED", "CODE_OUTLINED",
"DESCRIPTION_OUTLINED", "DESKTOP_WINDOWS_OUTLINED", "FONT_DOWNLOAD_OUTLINED",
"SPORTS_ESPORTS_OUTLINED", "BACKUP_OUTLINED", "CLOUD_OUTLINED",
"DELETE_OUTLINE", "SETTINGS_OUTLINED", "MENU_BOOK_OUTLINED", "MAIL_OUTLINE",
"CONTACTS_OUTLINED", "SCHOOL_OUTLINED", "BUSINESS_CENTER_OUTLINED",
"SCIENCE_OUTLINED", "PUBLIC_OUTLINED", "LOCK_OUTLINE", "ATTACH_MONEY_OUTLINED",
"RECEIPT_LONG_OUTLINED", "BUILD_OUTLINED", "EXTENSION_OUTLINED",
]
FolderIconLabelOverrides = {
"FOLDER_OUTLINED": "Default", "FOLDER_OPEN": "Open", "FOLDER_SPECIAL": "Special",
"FOLDER_SHARED": "Shared", "FOLDER_ZIP": "Archive", "FOLDER_COPY": "Copy",
"SNIPPET_FOLDER": "Snippet", "RULE_FOLDER": "Rules", "VIDEOCAM_OUTLINED": "Videos",
"DESCRIPTION_OUTLINED": "Documents", "DESKTOP_WINDOWS_OUTLINED": "Desktop",
"FONT_DOWNLOAD_OUTLINED": "Fonts", "SPORTS_ESPORTS_OUTLINED": "Games",
"BACKUP_OUTLINED": "Backup", "CLOUD_OUTLINED": "Cloud",
"DELETE_OUTLINE": "Trash", "SETTINGS_OUTLINED": "Config",
"MENU_BOOK_OUTLINED": "Books", "MAIL_OUTLINE": "Mail",
"CONTACTS_OUTLINED": "Contacts", "SCHOOL_OUTLINED": "School",
"BUSINESS_CENTER_OUTLINED": "Business", "SCIENCE_OUTLINED": "Projects",
"PUBLIC_OUTLINED": "Public", "LOCK_OUTLINE": "Private",
"ATTACH_MONEY_OUTLINED": "Finance", "RECEIPT_LONG_OUTLINED": "Receipts",
"BUILD_OUTLINED": "Tools", "EXTENSION_OUTLINED": "Plugins",
}
@dataclass
class FolderIconOverride:
Icon: str = ""
ImagePath: str = ""
def LoadFolderIconOverrides() -> dict[Path, FolderIconOverride]:
if not FolderIconsPath.exists():
return {}
try:
Data = toml.loads(FolderIconsPath.read_text())
except toml.TomlDecodeError:
return {}
Overrides: dict[Path, FolderIconOverride] = {}
for PathText, Entry in Data.items():
if isinstance(Entry, dict):
Overrides[Path(PathText)] = FolderIconOverride(
Icon=Entry.get("Icon", ""), ImagePath=Entry.get("ImagePath", "")
)
return Overrides
def SetFolderIconOverride(TargetPath: Path, Icon: str, ImagePath: str) -> None:
"""Icon and ImagePath both blank clears the override, back to whatever
the global fullness-variant system would otherwise show."""
Overrides = LoadFolderIconOverrides()
if Icon or ImagePath:
Overrides[TargetPath] = FolderIconOverride(Icon, ImagePath)
else:
Overrides.pop(TargetPath, None)
ConfigDir.mkdir(parents=True, exist_ok=True)
Data = {str(P): {"Icon": O.Icon, "ImagePath": O.ImagePath} for P, O in Overrides.items()}
FolderIconsPath.write_text(toml.dumps(Data))