776 lines
20 KiB
Markdown
776 lines
20 KiB
Markdown
|
|
# 📝 Tagger - Centrální Poznámky Projektu
|
||
|
|
|
||
|
|
> **DŮLEŽITÉ:** Tento soubor obsahuje VŠE co potřebuji vědět o projektu.
|
||
|
|
> Pokud pracuji na Tagger, VŽDY nejdříve přečtu tento soubor!
|
||
|
|
|
||
|
|
**Poslední aktualizace:** 2025-12-23
|
||
|
|
**Verze:** 1.0.2
|
||
|
|
**Status:** ✅ Stable, v aktivním vývoji
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🎯 O projektu
|
||
|
|
|
||
|
|
**Tagger** je desktopová aplikace pro správu a organizaci souborů pomocí hierarchických tagů (štítků).
|
||
|
|
|
||
|
|
**Hlavní funkce:**
|
||
|
|
- Rekurzivní procházení složek
|
||
|
|
- Hierarchické tagy (kategorie/název)
|
||
|
|
- Filtrování podle tagů
|
||
|
|
- Metadata uložená v JSON souborech
|
||
|
|
- Automatická detekce rozlišení videí (ffprobe)
|
||
|
|
- Dvě verze GUI: klasické a moderní (qBittorrent-style)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 📁 Struktura projektu
|
||
|
|
|
||
|
|
```
|
||
|
|
Tagger/
|
||
|
|
├── Tagger.py # Entry point - klasické GUI
|
||
|
|
├── Tagger_modern.py # Entry point - moderní GUI
|
||
|
|
├── PROJECT_NOTES.md # ← TENTO SOUBOR - HLAVNÍ ZDROJ PRAVDY
|
||
|
|
├── pyproject.toml # Poetry konfigurace
|
||
|
|
├── poetry.lock # Zamčené verze závislostí
|
||
|
|
├── pytest.ini # Pytest konfigurace
|
||
|
|
├── .editorconfig # Editor konfigurace
|
||
|
|
├── .gitignore # Git ignore pravidla
|
||
|
|
│
|
||
|
|
├── src/
|
||
|
|
│ ├── core/ # Jádro aplikace (ŽÁDNÉ UI!)
|
||
|
|
│ │ ├── tag.py # Tag value object (immutable)
|
||
|
|
│ │ ├── tag_manager.py # Správa tagů a kategorií
|
||
|
|
│ │ ├── file.py # File s metadaty
|
||
|
|
│ │ ├── file_manager.py # Správa souborů, filtrování
|
||
|
|
│ │ ├── config.py # Konfigurace (JSON)
|
||
|
|
│ │ ├── utils.py # list_files() - rekurzivní procházení
|
||
|
|
│ │ ├── media_utils.py # load_icon(), ffprobe
|
||
|
|
│ │ ├── constants.py # APP_NAME, VERSION, APP_VIEWPORT
|
||
|
|
│ │ └── list_manager.py # Třídění (málo používaný)
|
||
|
|
│ │
|
||
|
|
│ └── ui/
|
||
|
|
│ ├── gui.py # Původní Tkinter GUI
|
||
|
|
│ ├── gui_modern.py # Moderní qBittorrent-style GUI ✨ NOVÉ
|
||
|
|
│ └── gui_old.py # Backup původního GUI
|
||
|
|
│
|
||
|
|
├── tests/ # 116 testů, 100% core coverage
|
||
|
|
│ ├── __init__.py
|
||
|
|
│ ├── conftest.py # Pytest fixtures
|
||
|
|
│ ├── test_tag.py # 13 testů
|
||
|
|
│ ├── test_tag_manager.py # 19 testů
|
||
|
|
│ ├── test_file.py # 22 testů
|
||
|
|
│ ├── test_file_manager.py # 22 testů
|
||
|
|
│ ├── test_utils.py # 17 testů
|
||
|
|
│ ├── test_config.py # 18 testů
|
||
|
|
│ ├── test_media_utils.py # 3 testy
|
||
|
|
│ └── README.md # Dokumentace testů
|
||
|
|
│
|
||
|
|
├── src/resources/
|
||
|
|
│ └── images/32/ # Ikony (16x16 PNG)
|
||
|
|
│ ├── 32_unchecked.png
|
||
|
|
│ ├── 32_checked.png
|
||
|
|
│ └── 32_tag.png
|
||
|
|
│
|
||
|
|
└── docs/ # Dokumentace (ZASTARALÁ - použij tento soubor!)
|
||
|
|
├── ARCHITECTURE.md # ⚠️ DEPRECATED - info je zde
|
||
|
|
├── CONTRIBUTING.md # ⚠️ DEPRECATED - info je zde
|
||
|
|
└── GUI_MODERN_README.md # ⚠️ DEPRECATED - info je zde
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🎨 Architektura
|
||
|
|
|
||
|
|
### Vrstvová struktura
|
||
|
|
|
||
|
|
```
|
||
|
|
┌─────────────────────────────────┐
|
||
|
|
│ Presentation (UI) │ ← gui.py, gui_modern.py
|
||
|
|
│ - Tkinter GUI │ - NESMÍ obsahovat business logiku
|
||
|
|
│ - Jen zobrazení + interakce │ - NESMÍ importovat přímo z core
|
||
|
|
├─────────────────────────────────┤
|
||
|
|
│ Business Logic │ ← FileManager, TagManager
|
||
|
|
│ - Správa souborů/tagů │ - Callable z UI
|
||
|
|
│ - Filtrování, validace │ - Callback pattern pro notifikace
|
||
|
|
├─────────────────────────────────┤
|
||
|
|
│ Data Layer │ ← File, Tag (models)
|
||
|
|
│ - File, Tag třídy │ - Immutable kde je možné
|
||
|
|
│ - Validation logic │ - __eq__ a __hash__ správně
|
||
|
|
├─────────────────────────────────┤
|
||
|
|
│ Persistence │ ← config.py, .!tag soubory
|
||
|
|
│ - JSON soubory │ - UTF-8 encoding VŽDY
|
||
|
|
│ - Config management │ - ensure_ascii=False
|
||
|
|
└─────────────────────────────────┘
|
||
|
|
```
|
||
|
|
|
||
|
|
### Klíčová pravidla
|
||
|
|
|
||
|
|
#### ✅ CO DĚLAT:
|
||
|
|
|
||
|
|
1. **UI NESMÍ obsahovat business logiku**
|
||
|
|
```python
|
||
|
|
# ❌ ŠPATNĚ
|
||
|
|
class GUI:
|
||
|
|
def save_file(self):
|
||
|
|
with open(file, 'w') as f:
|
||
|
|
json.dump(data, f)
|
||
|
|
|
||
|
|
# ✅ SPRÁVNĚ
|
||
|
|
class GUI:
|
||
|
|
def save_file(self):
|
||
|
|
self.filemanager.save_file(file)
|
||
|
|
```
|
||
|
|
|
||
|
|
2. **Core moduly NESMÍ importovat UI**
|
||
|
|
```python
|
||
|
|
# V src/core/*.py NIKDY:
|
||
|
|
import tkinter
|
||
|
|
from src.ui import anything
|
||
|
|
```
|
||
|
|
|
||
|
|
3. **Dependency Injection - předávat dependencies přes konstruktor**
|
||
|
|
```python
|
||
|
|
class FileManager:
|
||
|
|
def __init__(self, tagmanager: TagManager):
|
||
|
|
self.tagmanager = tagmanager
|
||
|
|
```
|
||
|
|
|
||
|
|
4. **UTF-8 encoding VŠUDE**
|
||
|
|
```python
|
||
|
|
with open(file, 'w', encoding='utf-8') as f:
|
||
|
|
json.dump(data, f, ensure_ascii=False, indent=2)
|
||
|
|
```
|
||
|
|
|
||
|
|
5. **Type hints VŽDY**
|
||
|
|
```python
|
||
|
|
def filter_files(files: List[File], tags: List[Tag]) -> List[File]:
|
||
|
|
pass
|
||
|
|
```
|
||
|
|
|
||
|
|
#### ❌ CO NEDĚLAT:
|
||
|
|
|
||
|
|
1. **Globální stav**
|
||
|
|
```python
|
||
|
|
# ❌ NIKDY
|
||
|
|
current_file = None # global
|
||
|
|
```
|
||
|
|
|
||
|
|
2. **Magic numbers**
|
||
|
|
```python
|
||
|
|
# ❌ ŠPATNĚ
|
||
|
|
if len(files) > 100:
|
||
|
|
|
||
|
|
# ✅ SPRÁVNĚ
|
||
|
|
MAX_FILES = 100
|
||
|
|
if len(files) > MAX_FILES:
|
||
|
|
```
|
||
|
|
|
||
|
|
3. **Ignorovat exceptions**
|
||
|
|
```python
|
||
|
|
# ❌ NIKDY
|
||
|
|
try:
|
||
|
|
operation()
|
||
|
|
except:
|
||
|
|
pass
|
||
|
|
```
|
||
|
|
|
||
|
|
4. **Hardcoded paths**
|
||
|
|
```python
|
||
|
|
# ❌ ŠPATNĚ
|
||
|
|
icon = "/home/user/icon.png"
|
||
|
|
|
||
|
|
# ✅ SPRÁVNĚ
|
||
|
|
ICON_DIR = Path(__file__).parent / "resources"
|
||
|
|
icon = ICON_DIR / "icon.png"
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🔑 Klíčové komponenty
|
||
|
|
|
||
|
|
### 1. Tag (immutable value object)
|
||
|
|
|
||
|
|
```python
|
||
|
|
class Tag:
|
||
|
|
def __init__(self, category: str, name: str):
|
||
|
|
self.category = category # Nemění se po vytvoření!
|
||
|
|
self.name = name
|
||
|
|
|
||
|
|
@property
|
||
|
|
def full_path(self) -> str:
|
||
|
|
return f"{self.category}/{self.name}"
|
||
|
|
|
||
|
|
def __eq__(self, other):
|
||
|
|
return (self.category, self.name) == (other.category, other.name)
|
||
|
|
|
||
|
|
def __hash__(self):
|
||
|
|
return hash((self.category, self.name))
|
||
|
|
```
|
||
|
|
|
||
|
|
**Proč immutable?**
|
||
|
|
- Lze použít jako klíč v dict/set
|
||
|
|
- Thread-safe
|
||
|
|
- Jasná sémantika rovnosti
|
||
|
|
|
||
|
|
### 2. File (reprezentace souboru s metadaty)
|
||
|
|
|
||
|
|
```python
|
||
|
|
class File:
|
||
|
|
def __init__(self, file_path: Path, tagmanager=None):
|
||
|
|
self.file_path = file_path
|
||
|
|
self.filename = file_path.name
|
||
|
|
self.metadata_filename = parent / f".{filename}.!tag"
|
||
|
|
self.tags: list[Tag] = []
|
||
|
|
self.date: str | None = None
|
||
|
|
self.get_metadata() # Auto-load při vytvoření
|
||
|
|
```
|
||
|
|
|
||
|
|
**Metadata format (.filename.!tag):**
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"new": false,
|
||
|
|
"ignored": false,
|
||
|
|
"tags": ["Stav/Nové", "Video/HD"],
|
||
|
|
"date": "2025-12-23"
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**DŮLEŽITÉ:**
|
||
|
|
- Každá změna (add_tag, set_date) automaticky volá `save_metadata()`
|
||
|
|
- UTF-8 encoding!
|
||
|
|
- ensure_ascii=False pro češtinu
|
||
|
|
|
||
|
|
### 3. TagManager (správa tagů)
|
||
|
|
|
||
|
|
```python
|
||
|
|
class TagManager:
|
||
|
|
def __init__(self):
|
||
|
|
self.tags_by_category = {} # {category: set(Tag)}
|
||
|
|
|
||
|
|
def add_tag(self, category: str, name: str) -> Tag:
|
||
|
|
# Vytvoří kategorii pokud neexistuje
|
||
|
|
# Používá set - duplicity automaticky ignorovány
|
||
|
|
# Vrací Tag objekt
|
||
|
|
```
|
||
|
|
|
||
|
|
**Speciální chování:**
|
||
|
|
- Když odstraníš poslední tag z kategorie → kategorie se smaže
|
||
|
|
- Set zajišťuje uniqueness
|
||
|
|
- Vždy vrací Tag objekt (ne string)
|
||
|
|
|
||
|
|
### 4. FileManager (správa souborů)
|
||
|
|
|
||
|
|
```python
|
||
|
|
class FileManager:
|
||
|
|
def __init__(self, tagmanager: TagManager):
|
||
|
|
self.filelist: list[File] = []
|
||
|
|
self.tagmanager = tagmanager
|
||
|
|
self.on_files_changed = None # CALLBACK pro UI!
|
||
|
|
self.config = load_config()
|
||
|
|
|
||
|
|
def append(self, folder: Path):
|
||
|
|
# Rekurzivně načte soubory
|
||
|
|
# Ignoruje podle patterns
|
||
|
|
# Vytvoří File objekty
|
||
|
|
# Zavolá on_files_changed callback
|
||
|
|
```
|
||
|
|
|
||
|
|
**Callback pattern:**
|
||
|
|
```python
|
||
|
|
# V GUI:
|
||
|
|
filemanager.on_files_changed = self.update_ui
|
||
|
|
|
||
|
|
# V FileManager:
|
||
|
|
if self.on_files_changed:
|
||
|
|
self.on_files_changed(self.filelist)
|
||
|
|
```
|
||
|
|
|
||
|
|
**Proč callback?**
|
||
|
|
- Core nezávisí na UI
|
||
|
|
- Jednoduché na testování
|
||
|
|
- Flexibilní (můžeš změnit UI bez změny core)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🎨 GUI Verze
|
||
|
|
|
||
|
|
### Klasické GUI (gui.py)
|
||
|
|
|
||
|
|
```
|
||
|
|
┌─────────────────────────────────────────┐
|
||
|
|
│ Soubor │ Pohled │ Funkce Menu
|
||
|
|
├──────────┬──────────────────────────────┤
|
||
|
|
│ │ [Filter____] [Name][Name][ASC]
|
||
|
|
│ Tree │ ┌──────────────────────────┐ │
|
||
|
|
│ (tagy) │ │ Listbox (soubory) │ │
|
||
|
|
│ 📂 Štítky│ │ - file1.txt — 2025-01-01│ │
|
||
|
|
│ ☑ Nové │ │ - file2.mp4 │ │
|
||
|
|
│ ☐ HD │ │ - file3.jpg │ │
|
||
|
|
│ │ └──────────────────────────┘ │
|
||
|
|
├──────────┴──────────────────────────────┤
|
||
|
|
│ Status: Připraven │
|
||
|
|
└─────────────────────────────────────────┘
|
||
|
|
```
|
||
|
|
|
||
|
|
**Použít:** `poetry run python Tagger.py`
|
||
|
|
|
||
|
|
### Moderní GUI (gui_modern.py) ✨ NOVÉ
|
||
|
|
|
||
|
|
```
|
||
|
|
┌─────────────────────────────────────────────────────┐
|
||
|
|
│ 📁 Otevřít │ 🔄 │ 🏷️ │ 📅 🔍 [____] Toolbar
|
||
|
|
├────────────┬────────────────────────────────────────┤
|
||
|
|
│ 📂 Štítky │ ☐ Plná │ Třídění: [Název] [▲] │
|
||
|
|
│ ├─📁 Stav │ ┌──────────────────────────────────┐ │
|
||
|
|
│ │ ☑ Nové │ │ Název│Datum│Štítky│Velikost │ │
|
||
|
|
│ │ ☐ OK │ │file1 │2025 │HD │1.2 MB │ │
|
||
|
|
│ ├─📁 Video│ │file2 │ │4K │15 MB │ │
|
||
|
|
│ │ ☐ HD │ └──────────────────────────────────┘ │
|
||
|
|
│ │ ☐ 4K │ │
|
||
|
|
├────────────┴───────────────────────────────────────┤
|
||
|
|
│ Připraven 3 vybráno │ 125 souborů │
|
||
|
|
└─────────────────────────────────────────────────────┘
|
||
|
|
```
|
||
|
|
|
||
|
|
**Použít:** `poetry run python Tagger_modern.py`
|
||
|
|
|
||
|
|
**Nové funkce:**
|
||
|
|
- 📋 Tabulka s 4 sloupci (Název, Datum, Štítky, Velikost)
|
||
|
|
- 🔧 Toolbar s tlačítky
|
||
|
|
- ⌨️ Keyboard shortcuts (Ctrl+O, Ctrl+T, F5, Del...)
|
||
|
|
- 📊 Status bar se 3 sekcemi
|
||
|
|
- 🎨 qBittorrent-inspired design
|
||
|
|
|
||
|
|
**Keyboard shortcuts:**
|
||
|
|
- `Ctrl+O` - Otevřít složku
|
||
|
|
- `Ctrl+Q` - Ukončit
|
||
|
|
- `Ctrl+T` - Přiřadit tagy
|
||
|
|
- `Ctrl+D` - Nastavit datum
|
||
|
|
- `Ctrl+F` - Focus search
|
||
|
|
- `F5` - Refresh
|
||
|
|
- `Del` - Smazat z indexu
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🔧 Vývoj
|
||
|
|
|
||
|
|
### Setup prostředí
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Poetry environment (VŽDY použij poetry!)
|
||
|
|
poetry install
|
||
|
|
poetry shell
|
||
|
|
|
||
|
|
# Nebo přímo:
|
||
|
|
poetry run python Tagger_modern.py
|
||
|
|
```
|
||
|
|
|
||
|
|
**Poetry environment path:**
|
||
|
|
```
|
||
|
|
/home/honza/.cache/pypoetry/virtualenvs/tagger-qKyHMOtL-py3.12
|
||
|
|
```
|
||
|
|
|
||
|
|
### Spuštění aplikace
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Moderní GUI (doporučeno)
|
||
|
|
poetry run python Tagger_modern.py
|
||
|
|
|
||
|
|
# Klasické GUI
|
||
|
|
poetry run python Tagger.py
|
||
|
|
```
|
||
|
|
|
||
|
|
### Testy
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Všechny testy (116 testů)
|
||
|
|
poetry run pytest tests/ -v
|
||
|
|
|
||
|
|
# S coverage
|
||
|
|
poetry run pytest tests/ --cov=src/core --cov-report=html
|
||
|
|
|
||
|
|
# Konkrétní modul
|
||
|
|
poetry run pytest tests/test_file.py -v
|
||
|
|
|
||
|
|
# Quick check
|
||
|
|
poetry run pytest tests/ -q
|
||
|
|
```
|
||
|
|
|
||
|
|
**Test coverage:** 100% core modulů ✅
|
||
|
|
|
||
|
|
### Linting & Formatting
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# TODO: Přidat black, flake8 do pyproject.toml
|
||
|
|
# Zatím manuální kontrola podle PEP 8
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 📝 Coding Standards
|
||
|
|
|
||
|
|
### Python Style
|
||
|
|
|
||
|
|
- **PEP 8** s výjimkami:
|
||
|
|
- Max line length: **120** (ne 79)
|
||
|
|
- Indentation: **4 mezery** (ne taby)
|
||
|
|
- **UTF-8** encoding všude
|
||
|
|
- **Type hints** povinné
|
||
|
|
- **Docstrings** pro public API
|
||
|
|
|
||
|
|
### Naming Conventions
|
||
|
|
|
||
|
|
```python
|
||
|
|
# Classes
|
||
|
|
class FileManager:
|
||
|
|
pass
|
||
|
|
|
||
|
|
# Functions/methods
|
||
|
|
def load_config():
|
||
|
|
pass
|
||
|
|
|
||
|
|
# Constants
|
||
|
|
APP_NAME = "Tagger"
|
||
|
|
MAX_FILES = 1000
|
||
|
|
|
||
|
|
# Private
|
||
|
|
def _internal_method():
|
||
|
|
pass
|
||
|
|
```
|
||
|
|
|
||
|
|
### Imports Order
|
||
|
|
|
||
|
|
```python
|
||
|
|
# 1. Standard library
|
||
|
|
import os
|
||
|
|
import sys
|
||
|
|
from pathlib import Path
|
||
|
|
|
||
|
|
# 2. Third-party
|
||
|
|
import tkinter as tk
|
||
|
|
from PIL import Image
|
||
|
|
|
||
|
|
# 3. Local
|
||
|
|
from src.core.file import File
|
||
|
|
from src.core.tag import Tag
|
||
|
|
```
|
||
|
|
|
||
|
|
### String Formatting
|
||
|
|
|
||
|
|
```python
|
||
|
|
# ✅ F-strings
|
||
|
|
name = "John"
|
||
|
|
msg = f"Hello, {name}!"
|
||
|
|
|
||
|
|
# ❌ NE
|
||
|
|
msg = "Hello, " + name
|
||
|
|
msg = "Hello, {}".format(name)
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🔀 Git Workflow
|
||
|
|
|
||
|
|
### Branches
|
||
|
|
|
||
|
|
```
|
||
|
|
main/master ← Production (NE commity přímo!)
|
||
|
|
↑
|
||
|
|
release ← Release candidate
|
||
|
|
↑
|
||
|
|
devel ← Development integration
|
||
|
|
↑
|
||
|
|
feature/* ← Feature branches ← VYVÍJÍME TADY
|
||
|
|
```
|
||
|
|
|
||
|
|
### Commit Messages
|
||
|
|
|
||
|
|
```
|
||
|
|
<type>: <subject>
|
||
|
|
|
||
|
|
[optional body]
|
||
|
|
|
||
|
|
🤖 Generated with Claude Code
|
||
|
|
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
|
||
|
|
```
|
||
|
|
|
||
|
|
**Types:**
|
||
|
|
- `feat:` - Nová funkce
|
||
|
|
- `fix:` - Bug fix
|
||
|
|
- `refactor:` - Refactoring
|
||
|
|
- `test:` - Testy
|
||
|
|
- `docs:` - Dokumentace
|
||
|
|
- `style:` - Formátování
|
||
|
|
- `chore:` - Build, dependencies
|
||
|
|
|
||
|
|
**Příklad:**
|
||
|
|
```bash
|
||
|
|
git commit -m "feat: Add modern qBittorrent-style GUI
|
||
|
|
|
||
|
|
Implemented new GUI with toolbar, table view,
|
||
|
|
and keyboard shortcuts.
|
||
|
|
|
||
|
|
🤖 Generated with Claude Code
|
||
|
|
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>"
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🎯 Design Decisions (ADR)
|
||
|
|
|
||
|
|
### ADR-001: JSON soubory místo databáze
|
||
|
|
|
||
|
|
**Rozhodnutí:** Metadata v `.filename.!tag` JSON souborech
|
||
|
|
|
||
|
|
**Proč:**
|
||
|
|
- ✅ Jednoduchý backup (copy složky)
|
||
|
|
- ✅ Git-friendly
|
||
|
|
- ✅ Portable
|
||
|
|
- ✅ Metadata zůstanou při přesunu souboru
|
||
|
|
|
||
|
|
**Kdy přehodnotit:**
|
||
|
|
- Pokud >10k souborů (zvážit SQLite)
|
||
|
|
|
||
|
|
### ADR-002: Callback pattern pro UI updates
|
||
|
|
|
||
|
|
**Rozhodnutí:** `on_files_changed` callback
|
||
|
|
|
||
|
|
**Proč:**
|
||
|
|
- ✅ Core nezávisí na UI
|
||
|
|
- ✅ Jednoduché testování
|
||
|
|
- ✅ Flexibilní
|
||
|
|
|
||
|
|
**Alternativy zamítnuté:**
|
||
|
|
- Observer pattern (overkill)
|
||
|
|
- Event system (složitější)
|
||
|
|
|
||
|
|
### ADR-003: Tkinter pro GUI
|
||
|
|
|
||
|
|
**Rozhodnutí:** Tkinter (standard library)
|
||
|
|
|
||
|
|
**Proč:**
|
||
|
|
- ✅ Žádné extra dependencies
|
||
|
|
- ✅ Cross-platform
|
||
|
|
- ✅ Dobře dokumentované
|
||
|
|
|
||
|
|
**Alternativy:**
|
||
|
|
- Qt - lepší UI, ale větší závislost
|
||
|
|
- Web - overkill pro desktop app
|
||
|
|
|
||
|
|
### ADR-004: Poetry pro dependencies
|
||
|
|
|
||
|
|
**Rozhodnutí:** Poetry místo pip
|
||
|
|
|
||
|
|
**Proč:**
|
||
|
|
- ✅ Deterministické buildy (poetry.lock)
|
||
|
|
- ✅ Dev dependencies oddělené
|
||
|
|
- ✅ Moderní tool
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🐛 Známé problémy & TODO
|
||
|
|
|
||
|
|
### Aktuální problémy
|
||
|
|
|
||
|
|
1. **Git merge konflikty**
|
||
|
|
- `poetry.lock` a `pyproject.toml` - konflikty při merge devel→feature
|
||
|
|
- `tests/test_image.py` - deleted in devel, modified in feature
|
||
|
|
- **Stav:** Nezresolváno ⚠️
|
||
|
|
|
||
|
|
2. **ListManager málo použitý**
|
||
|
|
- Třídící logika duplicitní v GUI
|
||
|
|
- **TODO:** Refactor nebo odstranit
|
||
|
|
|
||
|
|
3. **Dlouhé operace blokují UI**
|
||
|
|
- ffprobe detection běží v main threadu
|
||
|
|
- **TODO:** Threading pro dlouhé operace
|
||
|
|
|
||
|
|
### Plánované features
|
||
|
|
|
||
|
|
- [ ] Progress bar pro dlouhé operace
|
||
|
|
- [ ] Undo/Redo mechanismus
|
||
|
|
- [ ] Export do CSV/Excel
|
||
|
|
- [ ] Dark mode theme
|
||
|
|
- [ ] Drag & drop souborů
|
||
|
|
- [ ] Image preview v sidebar
|
||
|
|
- [ ] SQLite fallback pro >10k souborů
|
||
|
|
- [ ] Full-text search
|
||
|
|
|
||
|
|
### Nice to have
|
||
|
|
|
||
|
|
- [ ] Plugin systém
|
||
|
|
- [ ] Web interface (Flask)
|
||
|
|
- [ ] Cloud sync (Dropbox, GDrive)
|
||
|
|
- [ ] Batch rename podle tagů
|
||
|
|
- [ ] Smart folder suggestions
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 📊 Metriky projektu
|
||
|
|
|
||
|
|
**Řádky kódu:** ~1060 Python LOC
|
||
|
|
**Testy:** 116 (všechny ✅)
|
||
|
|
**Test coverage:** 100% core modulů
|
||
|
|
**Python verze:** 3.12
|
||
|
|
**Dependencies:** Pillow (PIL)
|
||
|
|
**Vývojové prostředí:** Poetry
|
||
|
|
|
||
|
|
**Performance:**
|
||
|
|
- ✅ Dobré: <1000 souborů
|
||
|
|
- ⚠️ Přijatelné: 1000-5000 souborů
|
||
|
|
- ❌ Pomalé: >5000 souborů
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🔍 Debugování
|
||
|
|
|
||
|
|
### Časté problémy
|
||
|
|
|
||
|
|
**1. "Cannot import ImageTk"**
|
||
|
|
```bash
|
||
|
|
# Řešení: Použij poetry environment
|
||
|
|
poetry run python Tagger_modern.py
|
||
|
|
```
|
||
|
|
|
||
|
|
**2. "Config file not found"**
|
||
|
|
```bash
|
||
|
|
# Normální při prvním spuštění
|
||
|
|
# Vytvoří se automaticky config.json
|
||
|
|
```
|
||
|
|
|
||
|
|
**3. "Metadata corrupted"**
|
||
|
|
```python
|
||
|
|
# V config.py je graceful degradation
|
||
|
|
# Vrátí default config při chybě
|
||
|
|
```
|
||
|
|
|
||
|
|
### Logování
|
||
|
|
|
||
|
|
```python
|
||
|
|
# Zatím jen print() statements
|
||
|
|
# TODO: Přidat logging module
|
||
|
|
|
||
|
|
import logging
|
||
|
|
logging.basicConfig(level=logging.DEBUG)
|
||
|
|
logger = logging.getLogger(__name__)
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 📚 Dokumentace
|
||
|
|
|
||
|
|
**✅ AKTUÁLNÍ:**
|
||
|
|
- **PROJECT_NOTES.md** - TENTO SOUBOR (single source of truth) ⭐
|
||
|
|
- Docstrings v kódu
|
||
|
|
|
||
|
|
**📝 Poznámka:**
|
||
|
|
- Všechny ostatní .md soubory byly smazány a skonsolidovány SEM
|
||
|
|
- .gitignore ignoruje všechny .md kromě PROJECT_NOTES.md
|
||
|
|
- Pokud vytvoříš nový .md, MUSÍŠ ho přidat do .gitignore whitelist
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 💡 Pro AI asistenty (jako Claude)
|
||
|
|
|
||
|
|
### Když začínám práci na projektu:
|
||
|
|
|
||
|
|
1. ✅ **PŘEČTI TENTO SOUBOR CELÝ!**
|
||
|
|
2. ✅ Zkontroluj `git status`
|
||
|
|
3. ✅ Aktivuj poetry environment
|
||
|
|
4. ✅ Spusť testy (`poetry run pytest tests/`)
|
||
|
|
5. ✅ Dodržuj pravidla výše
|
||
|
|
|
||
|
|
### Při commitování:
|
||
|
|
|
||
|
|
1. ✅ Testy prošly (`pytest tests/`)
|
||
|
|
2. ✅ Type hints přidány
|
||
|
|
3. ✅ UTF-8 encoding
|
||
|
|
4. ✅ Žádné TODO/FIXME
|
||
|
|
5. ✅ Commit message formát správný
|
||
|
|
|
||
|
|
### Při přidání nové funkce:
|
||
|
|
|
||
|
|
1. ✅ Testy napsány PŘED implementací (TDD)
|
||
|
|
2. ✅ Dokumentace aktualizována (TENTO SOUBOR!)
|
||
|
|
3. ✅ Architecture decision zdokumentováno (pokud významné)
|
||
|
|
4. ✅ Type hints všude
|
||
|
|
5. ✅ Error handling přidán
|
||
|
|
|
||
|
|
### Při refactoringu:
|
||
|
|
|
||
|
|
1. ✅ Testy před (měly by projít)
|
||
|
|
2. ✅ Refactor
|
||
|
|
3. ✅ Testy po (měly by stále projít)
|
||
|
|
4. ✅ Update dokumentace
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 📞 Kontakt & Help
|
||
|
|
|
||
|
|
**Autor:** honza
|
||
|
|
**Repository:** /home/honza/Dokumenty/Tagger
|
||
|
|
**Python:** 3.12
|
||
|
|
**OS:** Linux 6.14.0-37-generic
|
||
|
|
|
||
|
|
**Pro pomoc:**
|
||
|
|
- Přečti TENTO soubor
|
||
|
|
- Podívej se do testů (`tests/`)
|
||
|
|
- Zkontroluj docstrings v kódu
|
||
|
|
- V nouzi spusť: `poetry run python -i` a explorej objekty
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 📅 Changelog
|
||
|
|
|
||
|
|
### [Unreleased]
|
||
|
|
- Merge konflikty s devel branch (poetry.lock, test_image.py)
|
||
|
|
|
||
|
|
### [1.0.2] - 2025-12-23
|
||
|
|
- ✨ Přidáno moderní GUI (gui_modern.py)
|
||
|
|
- ✨ Keyboard shortcuts
|
||
|
|
- ✨ Tabulkové zobrazení s 4 sloupci
|
||
|
|
- ✨ Toolbar s tlačítky
|
||
|
|
- ✨ 116 testů (100% core coverage)
|
||
|
|
- 📝 Vytvoření PROJECT_NOTES.md (tento soubor)
|
||
|
|
- 🔧 Poetry setup
|
||
|
|
|
||
|
|
### [1.0.1] - 2025-10-05
|
||
|
|
- 🐛 Bug fixy
|
||
|
|
- ✨ Video resolution detection
|
||
|
|
|
||
|
|
### [1.0.0] - 2025-10-05
|
||
|
|
- 🎉 Initial release
|
||
|
|
- ✨ Základní funkcionalita
|
||
|
|
- ✨ Tkinter GUI
|
||
|
|
- ✨ JSON metadata
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🎉 Poznámky na závěr
|
||
|
|
|
||
|
|
**Tento soubor je SINGLE SOURCE OF TRUTH pro projekt Tagger.**
|
||
|
|
|
||
|
|
Když přidávám funkci, fixuju bug, nebo dělám změnu:
|
||
|
|
1. Nejdřív PŘEČTU tento soubor
|
||
|
|
2. Pak UPRAVÍM kód
|
||
|
|
3. Pak AKTUALIZUJU tento soubor
|
||
|
|
|
||
|
|
**Living document** - průběžně aktualizován!
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
**Last updated:** 2025-12-23 18:30
|
||
|
|
**Next review:** Při každé větší změně
|
||
|
|
**Maintainer:** Claude Sonnet 4.5 + honza
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 📋 Changelog dokumentace
|
||
|
|
|
||
|
|
### 2025-12-23 11:24 - Konsolidace dokumentace
|
||
|
|
- ✅ Smazány: CONTRIBUTING.md, GUI_MODERN_README.md, docs/ARCHITECTURE.md
|
||
|
|
- ✅ Vše skonsolidováno do PROJECT_NOTES.md
|
||
|
|
- ✅ Vytvořen README.md pro GitHub (základní intro)
|
||
|
|
- ✅ Aktualizován .gitignore (ignoruje všechny .md kromě PROJECT_NOTES.md a README.md)
|
||
|
|
- ⭐ **PROJECT_NOTES.md je nyní jediný zdroj pravdy pro dokumentaci!**
|