A desktop project management application with a Microsoft Project Pro look and feel, built with Python, PyQt5, and MPXJ.
Runs entirely offline — no cloud, no subscription, no additional software required.
- Open and save
.mpp,.xml,.mpt,.mpxproject files via the MPXJ library - Gantt Chart — two-row calendar header (month / day), task bars with progress overlay, baseline strip, critical-path highlighting (completed tasks excluded from CPM), predecessor dependency arrows, milestone diamonds; overallocation shown as orange task-bar border; zoom in/out via toolbar overlay (bottom-right corner) or
Ctrl++/Ctrl+- - Task Sheet — full-width hierarchical entry table (default view on startup); 9 columns including coloured progress bars (light-blue → blue → green → red >100%) and enriched predecessor display (
ID – Task Name); collapse/expand summary tasks; double-click opens the full Task Information dialog - Task editing — inline cell editing (Name, Duration, % Done); double-click opens a full Task Information dialog (General / Predecessors / Notes tabs)
- Resource Sheet — view, add, and delete resources; coloured progress bar for Max Units with MPXJ fraction/percentage scale normalisation; 36 px row height matching the Gantt/Task views; double-click opens Resource Information dialog
- Resource Usage Graph — collapsible resource/task hierarchy on the left with a timeline grid on the right; shows how many hours each resource and assignment consumes per working day; four zoom modes: monthly (one column per month), weekly (one column per ISO week), daily (one column per day), hourly (one column per work hour with a dedicated two-row hour header — working hours read from the project calendar, defaulting to 08:00–17:00; break hours shown in grey; optional Show Off-Hours toggle in the Format menu extends the hourly view to a full 24-hour clock); day/header columns are always pixel-aligned regardless of scroll position; collapse/expand resource rows; ◄ Today scroll button; zoom and Show Sundays settings apply globally
- Dependencies — view, add, and delete task links; predecessor arrows are drawn in the Gantt view
- Baseline Tracking — compare baseline vs actual dates and duration, with variance highlighting
- Row status icons in the task grid (drawn pixmap icons, with hover tooltips):
- Purple diamond = milestone
- Blue page = has notes (shown before other alerts)
- Amber triangle = % complete > 100
- Orange circle = overdue (past finish date and not 100% complete)
- Red circle = critical path task (only for tasks with < 100% completion)
- Context-sensitive Edit menu — Insert / Delete labels update based on the active tab
- Consistent styling — Office blue toolbar and menu bar, light-blue table headers, alternating rows, Segoe UI fonts
- Keyboard shortcuts —
Ctrl+N/O/S,Insert/Delete,Ctrl++/Ctrl+-zoom, double-click for detail dialogs - Confluence Calendar Sync — import public holidays and team vacations from a Confluence Team Calendar directly into the project and resource calendars via Playwright SSO (
Project → Sync Confluence Calendar). Stale entries that were cancelled in Confluence are automatically removed on every sync, and exceptions older than 30 days are pruned from all calendars. The entire operation is undoable with a single Ctrl+Z.
| Package | Version |
|---|---|
| Python | ≥ 3.12 |
| PyQt5 | ≥ 5.15 |
| JPype1 | ≥ 1.4 |
| mpxj | ≥ 16.0 |
| OpenJDK | 17 (bundled automatically by cli.bat) |
| requests | ≥ 2.28 (Confluence calendar sync) |
| playwright | ≥ 1.40 (Confluence SSO auth) |
cli.batcli.bat will:
- Detect or download OpenJDK 17 into
tools\java\ - Create a Python virtual environment (
venv\) - Install all Python dependencies from
requirements.txt - Activate the environment and launch the application
To open a file directly from the command line, use:
python src\main.py --open "path\to\project.mpp"Project Offline/
├── SConstruct SCons build script (standalone installer)
├── cli.bat One-click launcher (setup + run)
├── cli.lnk Desktop shortcut
├── requirements.txt Python dependencies
├── src/
│ ├── _version.py Build version constant (auto-generated by scons)
│ ├── app_debug.py Debug flag and project-state dump helper
│ ├── app_tabs.py Named TAB_* / RIBBON_* constants for QTabWidget indices
│ ├── baseline_manager.py Baseline tracking business logic
│ ├── dialogs.py Detail dialogs (Task / Resource / Dependency / Baseline / Project Info)
│ ├── export_gantt.py Export Gantt chart to SVG and PlantUML formats
│ ├── file_handler.py MPXJ file open/save via JPype
│ ├── history_manager.py Per-view undo / redo history
│ ├── holidays.py Public holiday computation for new-project calendar setup
│ ├── icons.py QIcon generation for ribbon buttons
│ ├── import_plantuml.py Import PlantUML @startgantt files into an MPXJ ProjectFile
│ ├── logic.py In-memory project model
│ ├── main.py Entry point; auto-discovers OpenJDK at startup
│ ├── menu.py Menu bar (File / Edit / View)
│ ├── progress_worker.py Reusable modal progress dialog + background worker base
│ ├── ribbon.py MS Project-style ribbon toolbar
│ ├── settings_dialogs.py Configuration dialogs (KeePass / Jira)
│ ├── settings_manager.py Persistent settings for KeePass and Jira integrations
│ ├── stylesheet.py QSS theme
│ ├── toolbar.py Toolbar (New/Open/Save | Add/Delete | Zoom)
│ ├── ui.py Main window (QMainWindow)
│ ├── integrations/
│ │ ├── ad_integration.py Active Directory integration
│ │ ├── confluence_calendar_integration.py Confluence Team Calendar sync (holidays + vacations)
│ │ ├── email_integration.py Email report sending
│ │ ├── jira_integration.py Jira issue sync
│ │ ├── jira_sync.py Jira sync helpers
│ │ ├── keepass_integration.py KeePass credential lookup
│ │ ├── secondary_calendar_integration.py Secondary calendar import
│ │ └── version_control_integration.py SVN / Git integration
│ └── views/
│ ├── hour_mode.py Shared hourly-zoom infrastructure (constants, calendar reader,
│ │ coordinate helpers, HourModeHeader widget)
│ ├── baseline_view.py Baseline tracking
│ ├── cpm_results_view.py Read-only CPM results panel
│ ├── dependency_view.py Dependency list
│ ├── gantt_view.py Gantt chart (calendar, zoom, arrows)
│ ├── resource_usage_graph_view.py Resource Usage Graph (daily hour grid)
│ ├── resource_usage_histogram_view.py Resource Usage Histogram strip
│ ├── resource_view.py Resource sheet
│ ├── task_sheet_view.py Task Sheet (hierarchical entry table)
│ ├── task_view.py Editable task grid with status icons
│ ├── team_planner_view.py Team Planner (resource rows, drag-and-drop)
│ └── timeline_view.py Timeline view
├── tools/
│ ├── java/ OpenJDK 17 (downloaded on first run)
│ └── pyi_rthook_jdk.py PyInstaller runtime hook (sets JAVA_HOME + Playwright paths)
├── dist/ Build output (created by scons)
│ ├── ProjectOffline/ Self-contained application bundle
│ └── ProjectOffline_vX.X_installer.exe Console SFX installer
├── build/ Intermediate build artefacts (created by scons)
└── venv/ Python virtual environment (created on first run)
| Key | Action |
|---|---|
Ctrl+N |
New project |
Ctrl+O |
Open project file |
Ctrl+S |
Save project file |
Insert |
Add task / resource |
Delete |
Delete selected rows |
Ctrl++ |
Zoom in (Gantt) |
Ctrl+- |
Zoom out (Gantt) |
Double-click |
Open detail dialog |
A self-contained installer (no Python required on the target machine) can be produced with SCons and PyInstaller.
:: 1. Download OpenJDK 17 into tools\java\
python tools\download_openjdk.py
:: 2. Install the build tool
pip install pyinstaller scons
:: 3. Download 7-Zip Extra from https://www.7-zip.org/download.html
:: and place 7zCon.sfx (console SFX, no UAC) in one of:
:: C:\Program Files\7-Zip\7zCon.sfx (recommended)
:: tools\7zCon.sfx (repo-local fallback)sconsThis runs four steps in sequence:
| Step | Action | Output |
|---|---|---|
| 1 | PyInstaller one-dir bundle | dist\ProjectOffline\ |
| 2 | Copy OpenJDK 17 | dist\ProjectOffline\jdk\ |
| 3 | Copy Playwright Chromium | dist\ProjectOffline\ms-playwright\ |
| 4 | Create SFX installer | dist\ProjectOffline_vYYYY.MM.DD-HH.MM_installer.exe |
The SFX is a plain command-line 7-Zip self-extractor — no GUI, no UAC elevation.
:: Extract next to the installer (creates ProjectOffline\ in the same folder)
ProjectOffline_v2026.05.02-19.35_installer.exe
:: Extract to a specific directory
ProjectOffline_v2026.05.02-19.35_installer.exe -o"C:\Apps"The build signs both the application .exe and the SFX installer using
signtool.exe from the Windows SDK. Pass your certificate's SHA-1 thumbprint:
scons SIGN_THUMBPRINT=<40-hex-chars>
:: Or by certificate subject name (CN substring)
scons SIGN_SUBJECT="Your Company Name"If no signing credentials are supplied, scons prints a list of code-signing
certificates available in the Windows Personal store — useful for finding the
thumbprint of a SafeNet eToken certificate:
# Equivalent PowerShell command
Get-ChildItem Cert:\CurrentUser\My |
Where-Object { $_.EnhancedKeyUsageList -match 'Code Signing' } |
Format-Table Thumbprint, Subject, NotAfterWith a SafeNet eToken: insert the token and ensure SafeNet Authentication
Client is running before invoking scons. The token PIN is prompted by the
SafeNet middleware — no password is stored in the build script.
scons -c :: removes dist\ and build\The project includes a comprehensive test suite covering all major modules and views. Tests run fully offline without requiring a JVM, Confluence server, or browser.
# Install test dependencies
pip install pytest
# Run the full test suite
pytest tests/ -v
# Run specific test modules
pytest tests/test_confluence_calendar_integration.py -v
pytest tests/views/test_gantt_view.py -v
# Run tests matching a keyword
pytest tests/ -v -k "calendar"Key coverage areas:
- Confluence Calendar — SSO auth flow, HTTPS validation, holiday/vacation import, resource auto-creation, stale-entry removal, expired-entry pruning, platform-specific file permissions
- File Operations — JVM lifecycle, MPXJ file open/save, error handling
- Undo/Redo — Per-view snapshot stacks, re-entrant protection, history depth limits
- Views — Task grid, Gantt chart, resource sheet, dependencies, baseline tracking, team planner
- Dialogs — Task/Resource/Dependency information editors
All Java classes and network operations are mocked via unittest.mock so tests run in milliseconds without external dependencies. See tests/README.md for detailed coverage information.
- MPXJ cannot write native
.mppfiles (proprietary binary format). Save is in MSPDI XML (.xml), which can be reopened by compatible project management tools. - The first run downloads OpenJDK (~180 MB) into
tools\java\. Subsequent runs use the local copy. - Designed for Windows environments. Python must be installed and available in
PATH.
MIT — see LICENSE.