Releases: ppoilbarbe/PBRenamer
Releases · ppoilbarbe/PBRenamer
Release list
v1.4.3
Fixed
- Linux bundle — font selection:
_load_bundled_fonts()now explicitly sets
Ubuntu as the application font after registering the bundled.ttffiles.
Thelibfontconfig.sobundled by PyInstaller has its default config path
hardcoded to the build machine's conda prefix; on any other machine that path
is absent and fontconfig fails silently, leaving Qt with no valid system font
and an unpredictable default. Forcing Ubuntu bypasses fontconfig for font
selection while the runtime hook (pyi_rth_fonts.py) still provides a
portablefonts.confso rendering settings (anti-aliasing, hinting…) are
inherited from the system/etc/fonts/fonts.conf.
v1.4.2
Fixed
- Linux bundle: fonts and font size are now identical between local and CI
builds. Thefonts.confembedded by PyInstaller contained absolute paths to
the build machine's conda environment; on any other machine those paths are
missing and Qt fell back to system fonts only, at a different size. Fix: conda
fonts (fonts-conda-ecosystem: Ubuntu, DejaVu, Inconsolata, SourceCodePro)
are included in the bundle viapbrenamer.specfor glyph coverage; a runtime
hook (hooks/pyi_rth_fonts.py) generates a portablefonts.confat startup
that includes the system/etc/fonts/fonts.confand calls
FcFini()/FcInit()to force fontconfig re-initialisation with the correct
config — the system font is then resolved normally by Qt, with the same size
as in the local run.
(Closes #2) - ReadTheDocs build: removed the
pre_buildstep that attempted to run
pyside6-uicon*.uifiles — no such files exist (*_ui.pyare committed
hand-written sources); the stale step caused the RTD build to fail on every
tag since1.4.1
v1.4.1
Fixed
audio_meta.read_fieldnow returnsNonefor video container files (MP4,
MKV, MOV, …); previouslyread_fieldcalled mutagen directly without going
throughcan_read, so mutagen — which can read MP4 tags — returned audio
field values (title, duration, …) for video files;{au:…}tokens in a
replacement template could therefore resolve on video files as if they were
pure-audio files
v1.4.0 [YANKED]
Added
settings.configure(config_dir)— new public function that overrides the
configuration directory used by all settings and i18n functions; a single call
redirectssettings,i18n, andPatternPresetsconfig I/O simultaneously;
passNoneto restore the platform default; intended for testing--config-dir DIRCLI option (both GUI and headless modes): overrides the
configuration directory at startup before any settings access; intended for
testing (noted in--help)- Window geometry persistence for all windows and dialogs (except About):
MainWindow,FileInfoWindow,HistoryDialog,SettingsDialog,
ShortcutsDialog, andPatternHelpDialogsave/restore size and position
across sessions viaWindowState.save_geometry/load_geometry - LRU management for search, replace, and named-saves dropdowns: the most
recently used entry is promoted to position 0 on each use; history is
capped at 20 entries - Mixed file-type replacement templates: when
{im:…},{vi:…}, or
{au:…}tokens from more than one namespace appear in the same template,
substitute()probes each namespace withcan_read()at runtime — the
applicable namespace follows strict behaviour (absent field without default
→FieldResolutionError), non-applicable namespaces silently contribute
""without requiring a default {vi:…}field resolution now rejects files that have no video track even
when MediaInfo returns a General track (e.g. JPEG files parsed by
pymediainfo)- UI layouts converted from Qt Designer
.uifiles to hand-written Python
source (*_ui.py):main_window_ui.py,history_dialog_ui.py,
settings_dialog_ui.py,about_dialog_ui.py— eliminates the Qt Designer
file-parsing step at build time
Changed
- Test configuration isolation:
conftest.pyprovides aconfig_dirautouse
fixture that redirects all settings I/O to a per-test temporary directory via
settings.configure(); the real~/.config/pbrenameris never touched
during test runs; tests that need direct file access can request the
config_dirfixture to obtain the path - Named saves storage format migrated from a flat JSON dict (no ordering
guarantee) to an ordered JSON list[{"name": …, …config…}, …]; legacy
dict files are read transparently and upgraded on next write patternHelp.PatternHelpDialog: geometry now restored inshowEvent
(first paint) rather than in the constructor, matching the behaviour of all
other secondary windows
Fixed
audio_meta.can_readnow returnsFalsefor video container files (MP4,
MKV, MOV, …) that carry no audio-only track; previously aGeneraltrack
from pymediainfo could satisfy the read check, causing{au:…}fields to
attempt — and silently fail — audio tag extraction on video files- Main window geometry was not restored at startup:
restoreGeometry()was
called in__init__beforeshow(), so the window manager ignored it;
moved toshowEvent(fires once via_geometry_restoredflag) - Named saves combo list order reverted to sorted order on a subsequent save:
Qt'sQCompleter(auto-attached to the editableQComboBox) received
textChangedevents from the embeddedQLineEditeven while
combo.blockSignals(True)was active, and could queue a deferred
activatedcallback that calleduse_savewith a wrong index; fixed by
blocking theQLineEditsignals separately and usingsetCurrentIndex
instead ofsetCurrentTextduring_populate_named_saves - Preview pane appeared and immediately disappeared on the first click in the
directory tree:_on_directory_selectedwas called twice for the initial
path, the second call with the same path clearing the just-populated
preview; fixed with an early-return guard when the path has not changed
Removed
- Qt Designer
.uifiles (about_dialog.ui,history_dialog.ui,
main_window.ui,settings_dialog.ui) — replaced by*_ui.pyPython
sources tools/extract_ui_strings.py— no longer needed; translatable strings are
extracted directly from Python source via pybabel
v1.3.0
Added
- Undo button displays the number of available undo levels — text changes to
"Undo (N)" and the tooltip explains how many rename batches can be reverted - Case-transform modifier in replacement field tokens:
=(unchanged),-
(lower),+(upper),!(capitalise first char),*(Title Case) - Centre-align (
^) in replacement field tokens - Toolbar-state and preview-delay persistence in Settings
tools/po_check.py: PO file inspection tool using the babel library
(statistics, untranslated entries, regex search, language diff) — replaces
ad-hocgrep/msgfmtusage that breaks on multi-line entriessrc/pbrenamer/argparse_qt.py:add_qt_arguments()declares Qt CLI flags
(--style,--platform, …) as a proper argparse argument group; collected in
args.qt_argsas single-dash tokens ready forQApplication; Qt options are
hidden from theusage:line to reduce noise while remaining fully visible in
the--helpoutputtools/fix_po_files.py: utility to normalise PO file formatting in bulk- Comprehensive test suite covering all source modules at 100%; includes the
full main window (_on_preview,_refresh_conflicts, context menus, undo,
conflict detection, drag-and-drop, keyboard shortcuts, settings dialog,
file-info window, pattern-help dialog, presets, bookmarks, i18n bootstrap,
and all core modules) - Headless Qt test execution via
QT_QPA_PLATFORM=offscreeninconftest.py;
QMenu.execpatched at module level so no blocking dialog appears during CI
or localmake testruns
Changed
main()now usesparse_args()instead ofparse_known_args(); unknown
flags are rejected natively by argparse —_validate_qt_argvremoved
Fixed
{L}search-pattern token now matches Unicode letters; accented Latin
(é,ê,ü, …), Cyrillic, Greek and all other Unicode letter categories
are captured correctly — was limited to ASCII[a-zA-Z], now uses
[^\W\d_]which covers all\wcharacters that are neither digits nor
underscores- Qt built-in translations are now loaded alongside the application catalogue
so dialog buttons (OK,Cancel,Yes,No, …) are correctly translated
when a non-English language is selected - Pattern help dialog: HTML-escaped
{1:<12}so the browser no longer
interprets<12>as an HTML tag - Fifteen
# pragma: no coverguards on reachable logic replaced by targeted
tests: case-insensitive no-match inrename_using_plain_text, zero-width
regex guard,{newnum}CLI branch (start value, invalid start, no-match,
field error, collision k+=1), rename failure exit path,main()headless
dispatch,_parse_exif_datetimeon malformed input,_read_iptcunknown
key,_apply_caseunknown modifier
v1.2.0
Added
- Shortcuts menu (
Go → Shortcuts): navigate instantly to system directories
(Home, Desktop, Documents, Downloads, Pictures, Music, Videos on all platforms;
GTK bookmarks on Linux) and user-defined shortcuts - Right-click on any directory in the tree to Add as shortcut; shortcuts are
persisted toshortcuts.jsonin the user config directory - Edit Shortcuts dialog (
Go → Edit Shortcuts): reorder (Move up / Move down)
and remove user-defined shortcuts - File information window (
View → File information): non-modal window that
shows the actual values of all replacement fields ({date},{mdatetime},
{dir},{im:…},{au:…},{vi:…}, …) for the currently selected file;
updates live as the selection changes - Restore last opened directory setting in the new Behaviour group of the
Settings dialog; when enabled, the app reopens the last accessed directory at
startup (CLI-provided directory always takes priority; default: disabled) make runnow accepts anARGSvariable to forward arguments and options to
the program (e.g.make run ARGS="--debug /some/dir")
Fixed
email.utilswas incorrectly listed in PyInstallerexcludes, causing
importlib.metadatacalls in the About dialog to fail in packaged builds- CI
testjob now compiles.mocatalogues before running the test suite,
fixing fourtest_i18n.pyfailures (available_languages()globs.mofiles
which are gitignored and were absent on the runner)
Changed
- Executable names are now lowercase in the PyInstaller spec and CI artifact globs
(e.g.pbrenamer-1.2.0-linux-x86_64instead ofPBRenamer-…) pybabel extractnow uses--no-locationto omit source-file/line-number
comments from.pofiles;make translateis idempotent on an unchanged
source tree, fixingmake distalways producing adevbuild instead of
using the git tag version
v1.1.0
Added
srcdistMakefile target: produces a source archive
dist/pbrenamer-<ver>-src.tar.gzviagit archivetools/git_version.sh: derives the version string from the exact Git tag
when HEAD is tagged and the working tree is clean, falls back todev;
used by bothdistandsrcdisttargets
Changed
- i18n toolchain replaced:
xgettext/msgmerge/msgfmt/msginitremoved in
favour ofpybabel extract/update/compile/init;babel.cfgmapping
file added;gettextdependency replaced bybabelinenvironment.yml
Removed
.mocompiled catalogues removed from the repository (now gitignored); the
CI regenerates them viapybabel compilebefore each PyInstaller build
v1.0.0
Added
- Translations for six new languages: German (
de), Spanish (es), Italian
(it), Russian (ru), Vietnamese (vi), and Simplified Chinese (zh_CN) - All 272 translatable strings covered in each new locale;
.mofiles compiled
and committed alongside the.posources
v0.3.2
v0.3.1
Fixed
- README: remove insert/delete at position and manual rename from feature
list (functions exist infiletools.pybut are not wired to the GUI)