A PySide6 desktop application for text processing on Linux. Provides encoding conversion (to UTF-8), text formatting/cleaning, find/replace, and file management through a split-panel interface.
Status: v0.3.0 — core features implemented and tested. Encoding conversion, find/replace, text cleaning, and file I/O are fully functional. See DESIGN.md for the full specification.
- Language: Python 3.14
- UI Framework: PySide6 6.8.0+ (Qt for Python)
- Architecture: MVVM with dependency injection
- Testing: pytest + pytest-qt + pytest-mock
- Package Manager: UV
- Platform: Linux only
Prerequisites: Python 3.14, Linux.
# Install UV (if not already installed)
curl -LsSf https://astral.sh/uv/install.sh | sh
# Create virtual environment and install dependencies
uv venv
source .venv/bin/activate
uv pip install -r requirements.txtpython src/main.pyCoverage runs automatically with every pytest invocation (configured in pyproject.toml):
# All tests (includes coverage report)
pytest tests/
# Single test file
pytest tests/unit/test_text_document.py
# Filtered by name
pytest -k "test_viewmodel" tests/# Type checking
mypy src/
# Formatting
black src/ tests/
isort src/ tests/All layouts are defined in Qt Designer .ui files under src/views/ui/. Never hardcode layouts in Python — load them with QUiLoader and access widgets via findChild().
designer src/views/ui/main_window.uisrc/
├── models/ # Pure Python dataclasses, validation, business logic (no Qt)
├── viewmodels/ # QObject subclasses, signals/slots, calls services
├── views/ # Loads .ui files, connects signals — no business logic
│ └── ui/ # Qt Designer .ui files
├── services/ # File I/O, external integrations — injected into ViewModels
├── utils/ # Constants, helpers
└── main.py # Composition root — wires services → viewmodels → views
main.py:create_application() is the sole place where dependencies are composed. Layers only know about the layer directly below them.
- All development happens on the
testingbranch mainis protected by pre-commit hooks — only human-authorized merges- Run
python .agents/branch_protection.pybefore modifications if uncertain
Runtime:
PySide6>=6.8.0
chardet>=5.0.0 # optional: encoding detection (falls back to utf-8 without it)
Development / testing:
pytest>=8.3.0, pytest-qt>=4.4.0, pytest-mock>=3.14.0, pytest-cov>=5.0.0
mypy>=1.0.0, black>=24.0.0, isort>=5.13.0