GUI rework to Qt6
This commit is contained in:
3
src/core/_version.py
Normal file
3
src/core/_version.py
Normal file
@@ -0,0 +1,3 @@
|
||||
# Auto-generated version file - do not edit manually
|
||||
# This file is updated from pyproject.toml when available
|
||||
VERSION = "1.1.0"
|
||||
@@ -1,4 +1,106 @@
|
||||
# src/core/constants.py
|
||||
VERSION = "v1.0.4"
|
||||
APP_NAME = "Tagger"
|
||||
APP_VIEWPORT = "1000x700"
|
||||
"""
|
||||
Application constants with dynamic version loading.
|
||||
|
||||
Version is loaded from pyproject.toml if available, otherwise from _version.py.
|
||||
If ENV_DEBUG=true in .env, " DEV" suffix is added to version.
|
||||
"""
|
||||
from pathlib import Path
|
||||
|
||||
# Paths
|
||||
_ROOT_DIR = Path(__file__).parent.parent.parent
|
||||
_PYPROJECT_PATH = _ROOT_DIR / "pyproject.toml"
|
||||
_VERSION_FILE = Path(__file__).parent / "_version.py"
|
||||
_ENV_FILE = _ROOT_DIR / ".env"
|
||||
|
||||
|
||||
def _load_env_debug() -> bool:
|
||||
"""Load ENV_DEBUG from .env file."""
|
||||
if not _ENV_FILE.exists():
|
||||
return False
|
||||
try:
|
||||
with open(_ENV_FILE, "r", encoding="utf-8") as f:
|
||||
for line in f:
|
||||
line = line.strip()
|
||||
if line.startswith("ENV_DEBUG="):
|
||||
value = line.split("=", 1)[1].strip().lower()
|
||||
return value in ("true", "1", "yes")
|
||||
except Exception:
|
||||
pass
|
||||
return False
|
||||
|
||||
|
||||
def _extract_version_from_toml() -> str | None:
|
||||
"""Extract version from pyproject.toml."""
|
||||
if not _PYPROJECT_PATH.exists():
|
||||
return None
|
||||
try:
|
||||
with open(_PYPROJECT_PATH, "r", encoding="utf-8") as f:
|
||||
content = f.read()
|
||||
# Simple parsing - find version = "x.x.x" in [project] section
|
||||
in_project = False
|
||||
for line in content.split("\n"):
|
||||
line = line.strip()
|
||||
if line == "[project]":
|
||||
in_project = True
|
||||
elif line.startswith("[") and in_project:
|
||||
break
|
||||
elif in_project and line.startswith("version"):
|
||||
# version = "1.0.4"
|
||||
if "=" in line:
|
||||
value = line.split("=", 1)[1].strip().strip('"').strip("'")
|
||||
return value
|
||||
except Exception:
|
||||
pass
|
||||
return None
|
||||
|
||||
|
||||
def _load_version_from_file() -> str:
|
||||
"""Load version from _version module."""
|
||||
try:
|
||||
from src.core._version import VERSION as _ver
|
||||
return _ver
|
||||
except ImportError:
|
||||
pass
|
||||
return "0.0.0"
|
||||
|
||||
|
||||
def _save_version_to_file(version: str) -> None:
|
||||
"""Save version to _version.py for fallback."""
|
||||
try:
|
||||
content = f'''# Auto-generated version file - do not edit manually
|
||||
# This file is updated from pyproject.toml when available
|
||||
VERSION = "{version}"
|
||||
'''
|
||||
with open(_VERSION_FILE, "w", encoding="utf-8") as f:
|
||||
f.write(content)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
def _get_version() -> str:
|
||||
"""Get version from pyproject.toml or fallback to _version.py."""
|
||||
# Try to get from pyproject.toml
|
||||
toml_version = _extract_version_from_toml()
|
||||
if toml_version:
|
||||
# Update _version.py for cases when toml is not available
|
||||
_save_version_to_file(toml_version)
|
||||
return toml_version
|
||||
|
||||
# Fallback to _version.py
|
||||
return _load_version_from_file()
|
||||
|
||||
|
||||
# Load configuration
|
||||
DEBUG = _load_env_debug()
|
||||
VERSION = _get_version()
|
||||
|
||||
# Add DEV suffix if debug mode
|
||||
if DEBUG:
|
||||
VERSION = f"{VERSION} DEV"
|
||||
|
||||
# Application name with version
|
||||
APP_NAME = f"Tagger v{VERSION}"
|
||||
|
||||
# Default window size
|
||||
APP_VIEWPORT = "1000x700"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# Module header
|
||||
import sys
|
||||
import subprocess
|
||||
from loguru import logger
|
||||
from .file import File
|
||||
from .tag_manager import TagManager
|
||||
|
||||
@@ -8,21 +9,13 @@ if __name__ == "__main__":
|
||||
sys.exit("This module is not intended to be executed as the main program.")
|
||||
|
||||
|
||||
# Backwards compatibility: load_icon moved to src/ui/utils.py
|
||||
def load_icon(path):
|
||||
"""Deprecated: Use src.ui.utils.load_icon instead."""
|
||||
from src.ui.utils import load_icon as _load_icon
|
||||
return _load_icon(path)
|
||||
|
||||
|
||||
def add_video_resolution_tag(file_obj: File, tagmanager: TagManager):
|
||||
def add_video_resolution_tag(file_obj: File, tagmanager: TagManager) -> None:
|
||||
"""
|
||||
Zjistí vertikální rozlišení videa a přiřadí tag Rozlišení/{výška}p.
|
||||
Vyžaduje ffprobe (FFmpeg).
|
||||
Detect video vertical resolution and assign tag Resolution/{height}p.
|
||||
Requires ffprobe (FFmpeg).
|
||||
"""
|
||||
path = str(file_obj.file_path)
|
||||
try:
|
||||
# ffprobe vrátí width a height ve formátu JSON
|
||||
result = subprocess.run(
|
||||
["ffprobe", "-v", "error", "-select_streams", "v:0",
|
||||
"-show_entries", "stream=width,height", "-of", "csv=p=0:s=x", path],
|
||||
@@ -30,13 +23,13 @@ def add_video_resolution_tag(file_obj: File, tagmanager: TagManager):
|
||||
text=True,
|
||||
check=True
|
||||
)
|
||||
res = result.stdout.strip() # např. "1920x1080"
|
||||
res = result.stdout.strip() # e.g. "1920x1080"
|
||||
if "x" not in res:
|
||||
return
|
||||
width, height = map(int, res.split("x"))
|
||||
tag_name = f"Rozlišení/{height}p"
|
||||
tag_obj = tagmanager.add_tag("Rozlišení", f"{height}p")
|
||||
file_obj.add_tag(tag_obj)
|
||||
print(f"Přiřazen tag {tag_name} k {file_obj.filename}")
|
||||
logger.info("Assigned tag {} to {}", tag_name, file_obj.filename)
|
||||
except Exception as e:
|
||||
print(f"Chyba při získávání rozlišení videa {file_obj.filename}: {e}")
|
||||
logger.error("Failed to get video resolution for {}: {}", file_obj.filename, e)
|
||||
|
||||
1733
src/ui/gui.py
1733
src/ui/gui.py
File diff suppressed because it is too large
Load Diff
@@ -1,19 +1,22 @@
|
||||
"""
|
||||
UI utility functions for Tagger GUI.
|
||||
UI utility functions for Tagger GUI (PySide6).
|
||||
"""
|
||||
from PIL import Image, ImageTk
|
||||
from pathlib import Path
|
||||
from PySide6.QtGui import QIcon, QPixmap
|
||||
|
||||
|
||||
def load_icon(path) -> ImageTk.PhotoImage:
|
||||
def load_icon(path: str | Path, size: int = 16) -> QIcon:
|
||||
"""
|
||||
Load an icon from file and resize to 16x16.
|
||||
Load an icon from file and optionally resize.
|
||||
|
||||
Args:
|
||||
path: Path to the image file
|
||||
size: Icon size in pixels (default 16)
|
||||
|
||||
Returns:
|
||||
ImageTk.PhotoImage resized to 16x16 pixels
|
||||
QIcon object
|
||||
"""
|
||||
img = Image.open(path)
|
||||
img = img.resize((16, 16), Image.Resampling.LANCZOS)
|
||||
return ImageTk.PhotoImage(img)
|
||||
pixmap = QPixmap(str(path))
|
||||
if not pixmap.isNull():
|
||||
pixmap = pixmap.scaled(size, size)
|
||||
return QIcon(pixmap)
|
||||
|
||||
Reference in New Issue
Block a user