API Reference
Package
Entry point
argparse_qt
argparse helpers for passing Qt command-line options.
- pbpicat.argparse_qt.add_qt_arguments(parser)[source]
Add Qt command-line options to parser, collected in
args.qt_args.Each
--option [value]is stored as["-option"]or["-option", "value"]and appended toargs.qt_args, ready to be passed directly toQApplication.Qt options are hidden from the
usage:line to reduce noise; they still appear in the “Qt options” section of the full--helpoutput.- Parameters:
parser (ArgumentParser)
- Return type:
None
Internationalisation
Internationalisation bootstrap for PBPicat.
Call setup(app) once before creating any window.
- pbpicat.i18n.available_languages()[source]
Return [(lang_code, lang_name_in_that_language), …] sorted by code.
config
- pbpicat.config.set_base_dir(path)[source]
Override the base config directory. Must be called before init_catalogs().
- Parameters:
path (Path)
- Return type:
None
- pbpicat.config.load_current_catalog_name()[source]
Read catalog.conf; validate that the named directory exists; fall back to first available.
- Return type:
- pbpicat.config.set_current_catalog(name)[source]
Switch the in-memory current catalog. Hidden catalogs are not persisted to catalog.conf, so the next startup falls back to the last non-hidden catalog.
- Parameters:
name (str)
- Return type:
None
- pbpicat.config.list_catalogs(*, include_hidden=False)[source]
List catalog names. Names starting with “.” or “-” are hidden by default.
- pbpicat.config.duplicate_catalog(source_name, dest_name)[source]
Copy all files from source_name catalog into a new dest_name catalog.
- pbpicat.config.init_catalogs()[source]
Ensure at least one catalog exists, migrate legacy files if needed, load active catalog.
- Return type:
None
- pbpicat.config.qsettings()[source]
Return a QSettings instance pointing to the active catalog’s ui.conf.
- Return type:
PySide6.QtCore.QSettings
- pbpicat.config.app_qsettings()[source]
Return a QSettings instance for application-level state (window geometry, etc.).
Stored in <config_dir>/app.conf, independent of the active catalog.
- Return type:
PySide6.QtCore.QSettings
renamer
- pbpicat.renamer.validate_schema(fields)[source]
Returns (dirs, parts, numeric_spec) or raises ValueError.
dirs — consecutive non-empty non-numeric fields from start (directory path) parts — all non-empty non-numeric fields (joined with ‘_’ for filename) numeric_spec — the ‘#…’ field if present, else None
- pbpicat.renamer.find_max_number(dest_dir, basename, extensions=None)[source]
Return the maximum numeric suffix used in dest_dir for filenames containing basename_NNN.
If extensions is given, only files whose suffix (lowercased) is in that set are considered.
- pbpicat.renamer.build_rename_plan(dest_root, schema_fields, source_paths, sidecar_extensions, image_extensions, video_extensions=None, video_marker='', video_marker_pos=0)[source]
Build (src, dst) pairs for source_paths and their sidecars. Raises ValueError for schema errors, FileExistsError if a destination already exists.
For video files, video_marker is inserted at video_marker_pos within the schema parts.
- pbpicat.renamer.build_renumber_plan(schema_fields, source_paths, sidecar_extensions, image_extensions, video_extensions=None, video_marker='', video_marker_pos=0)[source]
Build (src, dst) pairs for in-place renumbering starting from 1. Images and videos have separate counters. Only includes pairs where src != dst. Raises ValueError if the schema has no numeric field.
- pbpicat.renamer.execute_renumber(pairs)[source]
Execute in-place renaming via a two-phase temp rename to avoid conflicts. Rolls back on error.
- pbpicat.renamer.undo_renumber(pairs)[source]
Reverse a renumber plan: new_dst → original_src via two-phase rename.
image_io
Image loading helpers with Pillow fallback for formats Qt cannot handle.
image_ops
Lossless image rotation. jpegtran (libjpeg-turbo) required for JPEG files.
- pbpicat.image_ops.repair_jpeg_sos(data)[source]
Fix a malformed SOS header found in some camera firmware (e.g. certain Samsung front-camera modules): baseline (non-progressive) JPEGs must have Se=63 in the SOS segment, but these encoders write Se=0. Strict decoders (jpegtran/libjpeg-turbo) reject this with “Invalid SOS parameters for sequential JPEG”; lenient decoders (Qt, Pillow) just warn and decode anyway. Patching the header byte is lossless: no entropy-coded data is touched. Returns the input unchanged if no such defect is found.
- pbpicat.image_ops.get_exif_orientation(path)[source]
Return EXIF Orientation value 2–8 if present and non-trivial, else None.
- pbpicat.image_ops.rotate_lossless(path, op)[source]
Apply a lossless rotation/flip to path in-place.
- op: 90, -90, 180 (degrees CW)
“auto” (apply + clear EXIF orientation tag) “hflip” / “vflip” / “transpose” / “transverse” (for undo of flip-type EXIF)
Returns the inverse op for undo.
Raises RuntimeError (user-friendly) if jpegtran is unavailable for a JPEG file. Raises ValueError if op == “auto” and no EXIF orientation found.
platform
Platform-specific helpers. Loaded once at import time.
ui
icons
dir_tree
file_list_widget
- class pbpicat.ui.file_list_widget.FileListWidget(*args, **kwargs)[source]
Table displaying image and video files with thumbnail, name and sidecar indicator.
Columns: THUMB | NAME | SIDECAR
- Signals:
rename_requested(list[Path])
- Parameters:
config (dict)
- set_rotation_actions(rotate_ccw, rotate_cw, rotate_180, rotate_auto, reset_exif)[source]
- Return type:
None
- set_rotate_callback(callback)[source]
callback(paths: list[Path], op) — called when the image viewer requests rotation.
- Return type:
None
- reconfigure(config)[source]
Apply new config (thumbnail size, extensions) and refresh.
- Parameters:
config (dict)
- Return type:
None
- next_row_after_files(paths)[source]
Return the row to select after paths are removed from the list.
Counts non-removed files up to and including the last removed file’s position — that is the index of the file that follows in the new list.
- refresh_and_select(row)[source]
Refresh the table then select the given row (clamped to valid range).
- Parameters:
row (int)
- Return type:
None
- refresh_and_select_paths(paths)[source]
Refresh the table then select all rows whose path is in paths.
- refresh_thumbnails_for_paths(paths)[source]
Reload thumbnails only for the given paths without rebuilding the table.