mirror of
https://github.com/TagStudioDev/TagStudio.git
synced 2026-02-01 07:39:10 +00:00
feat(ui): preview support for source engine files
* Fix text and RAW image handling - Fix RAW images not being loaded correctly in the preview panel - Fix trying to read size data from null images - Refactor `os.stat` to `<Path object>.stat()` - Remove unnecessary upper/lower conversions - Improve encoding compatibility beyond UTF-8 when reading text files - Code cleanup * Use chardet for character encoding detection * Add support for waveform + album cover thumbnails * Rename "cover" variables for MyPy * Rename "audio_tags" variables for MyPy + typing * Add # type: ignore to fromstring method * Add GIF preview support * Add rough check for invalid video codecs * Add ".plist" to PLAINTEXT_TYPES * Add readable video tester * Add ".psd" to IMAGE_TYPES; Handle ID3NoHeaderError * Improve and style waveform previews * Add final return statement to _album_artwork() * Add final return statement to _audio_waveform() * Tweak waveform color and size * Fix ItemThumb label text color in light mode * Fix most theme UI legibility issues * Match additional UI to color scheme * ruff format * feat(ui): add UI color palette dict * feat(ui) center and color small font previews * fix(ui): large font previews follow app theme * fix(ui): blender previews follow app theme * feat(ui): add resizable thumbnail options * fix: mkv files with "[0][0][0][0]" codec load properly * fix: missing audio files properly handled * feat(ui): use system accent color for thumb selections * fix(ui): hide gif preview in multi-selections * feat(ui): add dynamic file thumb icons * fix(ui): hide previous thumbnail before resizing * (fix): catch ffmpeg errors in file tester * Squashed commit of the following: commit9a3c19d398Author: Travis Abendshien <lvnvtravis@gmail.com> Date: Wed Jul 24 22:57:32 2024 -0700 fix: add missing comma + sort extensions commit53b2db9b5fAuthor: Travis Abendshien <lvnvtravis@gmail.com> Date: Wed Jul 24 14:46:16 2024 -0700 refactor: move type constants to new media classes * feat(ui): add media types and icon resources * feat(ui): add more default media types and icons Add additional default icons for: - Blender - Presentation - Program - Spreadsheet Add/expand additional media types: - PDF - Packages * fix: remove leading dot in preview panel ext * refactor: remove edge from `four_corner_gradient()` * fix: handle missing files in `resource_manager` * fix(ui): thumb edges fading on refresh * feat(ui): add default icons for audio+vector thumbs * feat(ui): apply edge to default icon thumbs * chore: remove unused code * refactor(ui): move loading icon to `ResourceManager` * added support for Source 1 + 2 file thumbnails All plaintext variants and VTF file conversions. * Added render code for VTF files Added support for VTF files by using the vtf2img library for PIL * Add files via upload * fixed Ruff errors * fixed Ruff errors * chore: organize imports, lists; ruff formatting * Change references of Source to Source Engine * Added error handler + changed source to source engine * add struct to import and docstring for source_engine * complying to the demigod ruff * chore: format with ruff --------- Co-authored-by: Travis Abendshien <46939827+CyanVoxel@users.noreply.github.com>
This commit is contained in:
@@ -14,3 +14,4 @@ pydub==0.25.1
|
||||
mutagen==1.47.0
|
||||
numpy==1.26.4
|
||||
ffmpeg-python==0.2.0
|
||||
vtf2img==0.1.0
|
||||
|
||||
@@ -35,6 +35,7 @@ class MediaType(str, Enum):
|
||||
PRESENTATION: str = "presentation"
|
||||
PROGRAM: str = "program"
|
||||
SHORTCUT: str = "shortcut"
|
||||
SOURCE_ENGINE: str = "source_engine"
|
||||
SPREADSHEET: str = "spreadsheet"
|
||||
TEXT: str = "text"
|
||||
VIDEO: str = "video"
|
||||
@@ -236,6 +237,20 @@ class MediaCategories:
|
||||
".ts",
|
||||
".txt",
|
||||
".xml",
|
||||
".vmt",
|
||||
".fgd",
|
||||
".nut",
|
||||
".cfg",
|
||||
".conf",
|
||||
".vdf",
|
||||
".vcfg",
|
||||
".gi",
|
||||
".inf",
|
||||
".vqlayout",
|
||||
".qss",
|
||||
".vsc",
|
||||
".kv3",
|
||||
".vsnd_template",
|
||||
}
|
||||
_PRESENTATION_SET: set[str] = {
|
||||
".key",
|
||||
@@ -244,6 +259,9 @@ class MediaCategories:
|
||||
".pptx",
|
||||
}
|
||||
_PROGRAM_SET: set[str] = {".app", ".exe"}
|
||||
_SOURCE_ENGINE_SET: set[str] = {
|
||||
".vtf",
|
||||
}
|
||||
_SHORTCUT_SET: set[str] = {".desktop", ".lnk", ".url"}
|
||||
_SPREADSHEET_SET: set[str] = {
|
||||
".csv",
|
||||
@@ -377,6 +395,11 @@ class MediaCategories:
|
||||
extensions=_SHORTCUT_SET,
|
||||
is_iana=False,
|
||||
)
|
||||
SOURCE_ENGINE_TYPES: MediaCategory = MediaCategory(
|
||||
media_type=MediaType.SOURCE_ENGINE,
|
||||
extensions=_SOURCE_ENGINE_SET,
|
||||
is_iana=False,
|
||||
)
|
||||
SPREADSHEET_TYPES: MediaCategory = MediaCategory(
|
||||
media_type=MediaType.SPREADSHEET,
|
||||
extensions=_SPREADSHEET_SET,
|
||||
@@ -416,6 +439,7 @@ class MediaCategories:
|
||||
PRESENTATION_TYPES,
|
||||
PROGRAM_TYPES,
|
||||
SHORTCUT_TYPES,
|
||||
SOURCE_ENGINE_TYPES,
|
||||
SPREADSHEET_TYPES,
|
||||
TEXT_TYPES,
|
||||
VIDEO_TYPES,
|
||||
|
||||
@@ -284,6 +284,12 @@ _UI_COLORS: dict = {
|
||||
ColorType.LIGHT_ACCENT: "#FFFFFF",
|
||||
ColorType.DARK_ACCENT: "#1e1e1e",
|
||||
},
|
||||
"red": {
|
||||
ColorType.PRIMARY: "#e22c3c",
|
||||
ColorType.BORDER: "#e54252",
|
||||
ColorType.LIGHT_ACCENT: "#f39caa",
|
||||
ColorType.DARK_ACCENT: "#440d12",
|
||||
},
|
||||
"green": {
|
||||
ColorType.PRIMARY: "#28bb48",
|
||||
ColorType.BORDER: "#43c568",
|
||||
@@ -296,12 +302,6 @@ _UI_COLORS: dict = {
|
||||
ColorType.LIGHT_ACCENT: "#EFD4FB",
|
||||
ColorType.DARK_ACCENT: "#3E1555",
|
||||
},
|
||||
"red": {
|
||||
ColorType.PRIMARY: "#e22c3c",
|
||||
ColorType.BORDER: "#e54252",
|
||||
ColorType.LIGHT_ACCENT: "#f39caa",
|
||||
ColorType.DARK_ACCENT: "#440d12",
|
||||
},
|
||||
"theme_dark": {
|
||||
ColorType.PRIMARY: "#333333",
|
||||
ColorType.BORDER: "#555555",
|
||||
|
||||
@@ -47,6 +47,10 @@ class FieldContainer(QWidget):
|
||||
self.edit_icon_128 = theme_fg_overlay(FieldContainer.edit_icon_128)
|
||||
self.trash_icon_128 = theme_fg_overlay(FieldContainer.trash_icon_128)
|
||||
|
||||
self.clipboard_icon_128 = theme_fg_overlay(FieldContainer.clipboard_icon_128)
|
||||
self.edit_icon_128 = theme_fg_overlay(FieldContainer.edit_icon_128)
|
||||
self.trash_icon_128 = theme_fg_overlay(FieldContainer.trash_icon_128)
|
||||
|
||||
self.root_layout = QVBoxLayout(self)
|
||||
self.root_layout.setObjectName("baseLayout")
|
||||
self.root_layout.setContentsMargins(0, 0, 0, 0)
|
||||
|
||||
@@ -8,6 +8,7 @@ import math
|
||||
from copy import deepcopy
|
||||
from io import BytesIO
|
||||
from pathlib import Path
|
||||
import struct
|
||||
|
||||
import cv2
|
||||
import numpy as np
|
||||
@@ -39,6 +40,7 @@ from src.qt.helpers.file_tester import is_readable_video
|
||||
from src.qt.helpers.gradient import four_corner_gradient
|
||||
from src.qt.helpers.text_wrapper import wrap_full_text
|
||||
from src.qt.resource_manager import ResourceManager
|
||||
from vtf2img import Parser
|
||||
|
||||
ImageFile.LOAD_TRUNCATED_IMAGES = True
|
||||
|
||||
@@ -600,6 +602,33 @@ class ThumbRenderer(QObject):
|
||||
)
|
||||
return im
|
||||
|
||||
def _source_engine(self, filepath: Path) -> Image.Image:
|
||||
"""
|
||||
This is a function to convert the VTF (Valve Texture Format) files to thumbnails, it works using the VTF2IMG library for PILLOW.
|
||||
"""
|
||||
parser = Parser(filepath)
|
||||
im: Image.Image = None
|
||||
try:
|
||||
im = parser.get_image()
|
||||
|
||||
except (
|
||||
AttributeError,
|
||||
UnidentifiedImageError,
|
||||
FileNotFoundError,
|
||||
TypeError,
|
||||
struct.error,
|
||||
) as e:
|
||||
if str(e) == "expected string or buffer":
|
||||
logging.info(
|
||||
f"[ThumbRenderer][VTF][INFO] {filepath.name} Doesn't have an embedded thumbnail. ({type(e).__name__})"
|
||||
)
|
||||
|
||||
else:
|
||||
logging.error(
|
||||
f"[ThumbRenderer][VTF][ERROR]: Couldn't render thumbnail for {filepath.name} ({type(e).__name__})"
|
||||
)
|
||||
return im
|
||||
|
||||
def _font_short_thumb(self, filepath: Path, size: int) -> Image.Image:
|
||||
"""Render a small font preview ("Aa") thumbnail from a font file.
|
||||
|
||||
@@ -961,6 +990,10 @@ class ThumbRenderer(QObject):
|
||||
elif MediaType.BLENDER in MediaCategories.get_types(ext):
|
||||
image = self._blender(_filepath)
|
||||
|
||||
# VTF ==========================================================
|
||||
elif MediaType.SOURCE_ENGINE in MediaCategories.get_types(ext):
|
||||
image = self._source_engine(_filepath)
|
||||
|
||||
# No Rendered Thumbnail ========================================
|
||||
if not image:
|
||||
raise UnidentifiedImageError
|
||||
|
||||
Reference in New Issue
Block a user