All notable changes to TextTools will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- Default tab is now Clean (was Find/Replace)
- Keyboard shortcuts: Ctrl+F (find), Ctrl+H (replace), F3 (find next)
- Encoding conversion button (F-001): re-saves file as UTF-8
- Cursor position and character count in status bar
- Save As (was stubbed)
- Window geometry and splitter positions persist across sessions (QSettings)
- Encoding label now shows "utf-8" for ASCII files (ASCII is a subset of UTF-8)
TextDocumentdataclass — core domain model for loaded files (filepath,content,encoding,modified)CleaningOptionsdataclass — configuration for text cleaning passesTextProcessingService— stateless text cleaning:trim_whitespace,clean_whitespace,remove_tabs,apply_optionsFileService— atomic file save (tempfile.mkstemp+os.replace), encoding detection viachardetwith 0.7 confidence thresholdMainViewModel— full signal/slot implementation:document_loaded,encoding_detected,file_saved,error_occurred,status_changed; slots forload_file,save_file,apply_cleaning,replace_allMainWindow— wires QFileSystemModel file tree, all checkbox/button signals, find/replace with wrap-around cursor, ViewModel signal handlerschardet>=5.0.0runtime dependency for encoding detectionmypy,black,isortdev dependencies inrequirements.txt- 60 unit and integration tests (100% coverage on models and TextProcessingService; 98% on ViewModel)
AGENTS.mdrewritten with TextTools-specific architecture reference and widget objectName table
- Renamed project from Template-Desktop-Application to TextTools
main.pycomposition root now wiresFileService+TextProcessingService→MainViewModel→MainWindow; logging to stdout onlyMainWindowchanged fromQMainWindowsubclass to a plain Python controller —self.uiis the loaded.uiQMainWindow, preventing nested-QMainWindow sizing bugs- All template/scaffold files removed (
ExampleModel,ExampleService,example_model.pytests) - CI workflow updated:
develop→testingbranch, action versions pinned to v4/v5,pip→uv .uiwindow title changed from"MainWindow"to"TextTools"pyproject.tomlmypy config: addedexplicit_package_bases = true
QFileSystemModelimport moved fromPySide6.QtGuitoPySide6.QtWidgets(correct for PySide6 6.10.x)- Black/isort formatting applied to all source files
- MVVM architecture scaffold:
ExampleModel,MainViewModel,ExampleService,MainWindow - Qt Designer
.uifile loading viaQUiLoaderwithfindChild()widget access pattern - Dependency injection wired in
main.py:create_application() - Test suite: 9 unit tests for Model (100% coverage), 10 unit tests for ViewModel (96% coverage), 3 integration tests
ServiceProtocolpattern usingtyping.Protocolfor mockable service interfaces- Branch protection system: pre-commit hook blocks commits to
main,.agents/branch_protection.pyfor AI agent checks - Coverage auto-configured in
pyproject.toml(addopts); no extra flags needed when runningpytest - Logging to both file (
app.log) and console
- PySide6 >= 6.8.0
- pytest >= 8.3.0, pytest-qt >= 4.4.0, pytest-mock >= 3.14.0, pytest-cov >= 5.0.0
- Python 3.14, Linux only