Skip to content

Repository files navigation

PDF Manager

A desktop toolkit for everyday PDF work — merging, splitting, reordering, converting — that runs entirely on your machine. No uploads, no accounts, no network access at any point.

Built with Python and Tkinter, so it launches from a standard Python installation without a packaging step or a browser.

Features

Tab What it does
Merge PDFs Merge any number of files. Optionally interleave them, taking page 1 from each file, then page 2 from each — the way to reassemble a double-sided scan made as two single-sided passes.
Extract Pages Pull a page selection such as 1-5, 7, 9-12 into a new file.
Split PDF Split one document into many, using ranges you define or ranges imported from the PDF's own bookmarks.
Reorder Pages Reorder pages by hand, reverse them, or de-interleave odd and even positions.
Convert PDF Export pages as JPG or PNG at 72–600 DPI, or the whole document as DOCX or HTML.
Text to PDF Typeset plain-text files, one PDF each or all combined, with a choice of font family, size, and page size.
Insert Pages Insert another PDF's pages, or blank pages, at any position.

Encrypted PDFs are supported throughout: the application asks for the password once, when you pick the file, and remembers it for the rest of the session.

Requirements

  • Python 3.11 or newer, built with Tk support (python -m tkinter should open a window)
  • The four runtime dependencies listed in requirements.txt

Dependencies are never installed automatically. If one is missing, the application says exactly which, and which command fixes it.

Installation

git clone https://github.com/eulerchavesneto/pdf_manager.git
cd pdf_manager

python3 -m venv .venv
source .venv/bin/activate          # Windows: .venv\Scripts\activate

pip install -e .

pip install -e . installs the four runtime dependencies and puts the package on the path. requirements.txt alone is not enough: the code lives under src/, so Python would not find it.

Usage

source .venv/bin/activate          # Windows: .venv\Scripts\activate
python -m pdf_manager

Installing also registers a pdf-manager command, which runs the same thing:

pdf-manager

Or without activating the environment at all:

./.venv/bin/python -m pdf_manager

Window size and the folders you last used are remembered between sessions.

How your files are protected

Three rules hold across every operation, and each is covered by tests:

Writes are atomic. Output goes to a temporary file beside the destination and is moved into place only once it is complete. An error, a full disk, or a crash halfway through can never leave a truncated PDF where a good one used to be.

A source is never used as a destination. PDF pages are read lazily, so writing over a file that is still being read is how an original gets destroyed. The application detects this — including when the same file is reached by two different paths — and asks for a different destination instead.

Filenames cannot collide silently. Bookmark titles become filenames when you import an outline, and two chapters may well share a title. Names are sanitised for every platform (illegal characters, Windows device names such as CON, overlong titles, trailing dots) and disambiguated as name (2).pdf rather than overwriting one another.

Behaviour worth knowing

  • Page selections keep the order you type. 3,1 produces a document with page 3 first. Descending ranges work too: 9-5 means those five pages, backwards.
  • Text conversion is Unicode-safe. The application resolves a real TrueType font from your system rather than using reportlab's Latin-1-only built-ins, so accented text, typographic quotes, and non-Latin scripts survive. A character the chosen font genuinely cannot draw is replaced with , never dropped in silence.
  • Long operations run in the background. The window stays responsive, the progress bar reflects real work, and a Cancel button stops the job at the next checkpoint. Action buttons are disabled while a job is running, so the same operation cannot be started twice.
  • Unexpected errors are logged with their traceback, not printed to a console that may not exist. Anticipated problems — a bad page range, a locked file — are reported as plain messages instead.

Settings and logs live in the standard per-user location:

Platform Location
macOS ~/Library/Application Support/pdf-manager/
Linux ~/.config/pdf-manager/
Windows %APPDATA%\pdf-manager\

Architecture

The project is split into two halves that never reach into each other:

src/pdf_manager/
├── core/                 pure PDF logic — imports no GUI toolkit
│   ├── documents.py      safe opening, atomic writing, path guards
│   ├── pageranges.py     parsing "1-5, 7" and formatting it back
│   ├── naming.py         filename sanitising and collision avoidance
│   ├── merge.py          concatenating and interleaving
│   ├── pages.py          extract, split, reorder, insert
│   ├── outline.py        reading bookmarks into split definitions
│   ├── convert.py        images, DOCX, HTML
│   ├── text_to_pdf.py    typesetting plain text
│   ├── fonts.py          resolving Unicode-capable fonts
│   ├── progress.py       progress reporting and cancellation
│   └── errors.py         typed, user-facing failures
└── gui/                  Tkinter shell
    ├── app.py            main window, status bar, progress
    ├── worker.py         background thread ↔ Tk queue bridge
    ├── context.py        services handed to each tab
    ├── widgets.py        reusable path picker and reorderable list
    └── tabs/             one module per tab

core takes plain paths and values, reports progress through an optional callback, and raises typed errors. That is what lets the same functions run under the GUI's worker thread and directly inside the test suite. gui collects inputs and renders outcomes; it contains no PDF logic.

Development

pip install -e ".[dev]"

pytest                # 224 tests
ruff check src tests  # linting

The test suite generates every PDF it needs at run time — each page stamped with its own marker — so an assertion can state exactly which original page ended up where. It covers the core end to end and builds the real Tkinter window to catch a tab that fails to construct. GUI tests skip themselves where no display is available.

Built with

pypdf for page-level manipulation, PyMuPDF for rendering and text extraction, reportlab for typesetting, and python-docx for Word output.

License

MIT.

About

Offline desktop toolkit for merging, splitting, reordering and converting PDFs — Python + Tkinter, no uploads, no accounts

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages