BookImport contains the format-specific logic for extracting metadata and
covers from incoming files. It supports EPUB and PDF sources out of the box and
returns a lightweight ImportResult that the rest of the pipeline uses to build
Book instances.
~/.local/share/bibliotheca/covers).import_book_assets(path, bookIdHex) function that dispatches
to the correct handler based on file extension.BookImport.cpp
├── ensure_covers_dir() // filesystem helper
├── import_epub(...) // libzip + tinyxml2
├── import_pdf(...) // poppler-glib + cairo
└── import_book_assets(...) // public dispatcher
struct ImportResult {
std::string title;
std::string author;
std::string coverPngPath; // empty if no cover extracted
};
If a format fails to provide metadata or a cover, the corresponding fields are
left empty; the caller (usually BibliothecaWindow) merges these with defaults
(e.g., falls back to the filename for the title).
.epub as a ZIP archive via libzip.META-INF/container.xml to locate the OPF package.<dc:title>, <dc:creator>,
and the cover manifest entry (cover-image property or meta name="cover").coverPngPath empty.poppler_document_new_from_file).${coversDir}/${bookId}.png.Errors (e.g., corrupt files) throw std::runtime_error. Callers typically catch
these during batch imports, log the failure, and skip the problematic file.
is_xyz() helpers and import_xyz() methods,
then extend import_book_assets() to dispatch accordingly.BibliothecaWindow computes a SHA-256 id for each selected file, calls
import_book_assets() in a worker thread, and combines the ImportResult with
fallback metadata before enqueuing BookList::upsertMany().
Because cover files live in a shared directory addressed by book id, repeated imports overwrite previous covers, ensuring consistency across sessions.