Add splash screen and PyInstaller build script
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -17,3 +17,4 @@ _office_convertiti_pdf/
|
|||||||
build/
|
build/
|
||||||
dist/
|
dist/
|
||||||
*.spec
|
*.spec
|
||||||
|
*.exe
|
||||||
|
|||||||
25
README.md
25
README.md
@@ -141,9 +141,30 @@ Per Office COM serve anche `pywin32`, installato nell'ambiente in cui viene eseg
|
|||||||
|
|
||||||
Il progetto e pensato per essere trasformato in un eseguibile Windows con PyInstaller.
|
Il progetto e pensato per essere trasformato in un eseguibile Windows con PyInstaller.
|
||||||
|
|
||||||
Da valutare:
|
Script disponibile:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
.\build_exe.ps1 -Clean
|
||||||
|
```
|
||||||
|
|
||||||
|
Lo script:
|
||||||
|
|
||||||
|
- installa le dipendenze Python;
|
||||||
|
- installa/aggiorna PyInstaller;
|
||||||
|
- include lo splash screen `assets/splash.png`;
|
||||||
|
- crea un eseguibile Windows `dist\ZipBundler.exe`;
|
||||||
|
- prova a includere Ghostscript se trova `gswin64c`, `gswin32c` o `gs` nel PATH.
|
||||||
|
|
||||||
|
Lo splash screen riporta `ZipBundler`, `versione 1.0` e `ai.teamstudio.it`.
|
||||||
|
|
||||||
|
Componenti inclusi o gestiti:
|
||||||
|
|
||||||
|
- CustomTkinter, Pillow e PyMuPDF vengono inclusi da PyInstaller come dipendenze Python;
|
||||||
|
- Ghostscript viene incluso se rilevato in fase di build;
|
||||||
|
- Microsoft Office non viene incluso: la conversione Office -> PDF usa Office COM e richiede Office installato sul PC di destinazione.
|
||||||
|
|
||||||
|
Da valutare in futuro:
|
||||||
|
|
||||||
- inclusione o rilevamento esterno di Ghostscript;
|
|
||||||
- gestione piu esplicita di `pywin32`;
|
- gestione piu esplicita di `pywin32`;
|
||||||
- eventuale icona applicativa;
|
- eventuale icona applicativa;
|
||||||
- firma dell'eseguibile, se necessaria in ambiente aziendale.
|
- firma dell'eseguibile, se necessaria in ambiente aziendale.
|
||||||
|
|||||||
BIN
assets/splash.png
Normal file
BIN
assets/splash.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.6 MiB |
77
build_exe.ps1
Normal file
77
build_exe.ps1
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
param(
|
||||||
|
[switch]$Clean,
|
||||||
|
[switch]$SkipGhostscriptBundle
|
||||||
|
)
|
||||||
|
|
||||||
|
$ErrorActionPreference = "Stop"
|
||||||
|
|
||||||
|
$ProjectRoot = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||||
|
Set-Location $ProjectRoot
|
||||||
|
|
||||||
|
$AppName = "ZipBundler"
|
||||||
|
$EntryPoint = Join-Path $ProjectRoot "zipbundler.py"
|
||||||
|
$SplashImage = Join-Path $ProjectRoot "assets\splash.png"
|
||||||
|
|
||||||
|
if (-not (Test-Path -LiteralPath $EntryPoint)) {
|
||||||
|
throw "File principale non trovato: $EntryPoint"
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not (Test-Path -LiteralPath $SplashImage)) {
|
||||||
|
throw "Immagine splash non trovata: $SplashImage"
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($Clean) {
|
||||||
|
Remove-Item -LiteralPath (Join-Path $ProjectRoot "build") -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
|
Remove-Item -LiteralPath (Join-Path $ProjectRoot "dist") -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
|
Remove-Item -LiteralPath (Join-Path $ProjectRoot "$AppName.spec") -Force -ErrorAction SilentlyContinue
|
||||||
|
}
|
||||||
|
|
||||||
|
python -m pip install --upgrade pip
|
||||||
|
python -m pip install -r requirements.txt
|
||||||
|
python -m pip install --upgrade pyinstaller
|
||||||
|
|
||||||
|
$argsList = @(
|
||||||
|
"--noconfirm",
|
||||||
|
"--clean",
|
||||||
|
"--windowed",
|
||||||
|
"--onefile",
|
||||||
|
"--name", $AppName,
|
||||||
|
"--splash", $SplashImage,
|
||||||
|
"--add-data", "$SplashImage;assets",
|
||||||
|
"--hidden-import", "customtkinter",
|
||||||
|
"--hidden-import", "PIL._tkinter_finder",
|
||||||
|
"--hidden-import", "fitz",
|
||||||
|
"--hidden-import", "win32com",
|
||||||
|
"--hidden-import", "win32com.client",
|
||||||
|
"--hidden-import", "pythoncom"
|
||||||
|
)
|
||||||
|
|
||||||
|
if (-not $SkipGhostscriptBundle) {
|
||||||
|
$ghostscriptCommand = Get-Command gswin64c.exe, gswin32c.exe, gs.exe -ErrorAction SilentlyContinue | Select-Object -First 1
|
||||||
|
if ($ghostscriptCommand) {
|
||||||
|
$ghostscriptBin = Split-Path -Parent $ghostscriptCommand.Source
|
||||||
|
$ghostscriptRoot = Split-Path -Parent $ghostscriptBin
|
||||||
|
Write-Host "Includo Ghostscript da: $ghostscriptRoot"
|
||||||
|
$argsList += @("--add-data", "$ghostscriptRoot;ghostscript")
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Write-Warning "Ghostscript non trovato nel PATH. Il programma usera Ghostscript solo se installato sul PC di destinazione."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Write-Warning "Bundle Ghostscript saltato per richiesta esplicita."
|
||||||
|
}
|
||||||
|
|
||||||
|
$argsList += $EntryPoint
|
||||||
|
|
||||||
|
python -m PyInstaller @argsList
|
||||||
|
|
||||||
|
$exePath = Join-Path $ProjectRoot "dist\$AppName.exe"
|
||||||
|
if (Test-Path -LiteralPath $exePath) {
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "Build completata:"
|
||||||
|
Write-Host $exePath
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw "Build completata senza trovare l'eseguibile atteso: $exePath"
|
||||||
|
}
|
||||||
@@ -141,6 +141,14 @@ def shortened_stem(stem, max_length=80):
|
|||||||
|
|
||||||
|
|
||||||
def find_ghostscript():
|
def find_ghostscript():
|
||||||
|
bundled_root = getattr(sys, "_MEIPASS", None)
|
||||||
|
if bundled_root:
|
||||||
|
bundled_ghostscript = Path(bundled_root) / "ghostscript"
|
||||||
|
for executable in ("gswin64c.exe", "gswin32c.exe", "gs.exe"):
|
||||||
|
matches = list(bundled_ghostscript.rglob(executable))
|
||||||
|
if matches:
|
||||||
|
return str(matches[0])
|
||||||
|
|
||||||
for executable in ("gswin64c", "gswin32c", "gs"):
|
for executable in ("gswin64c", "gswin32c", "gs"):
|
||||||
path = shutil.which(executable)
|
path = shutil.which(executable)
|
||||||
if path:
|
if path:
|
||||||
@@ -1432,6 +1440,13 @@ class ZipBundlerApp(ctk.CTk):
|
|||||||
|
|
||||||
def run_gui():
|
def run_gui():
|
||||||
app = ZipBundlerApp()
|
app = ZipBundlerApp()
|
||||||
|
try:
|
||||||
|
import pyi_splash
|
||||||
|
|
||||||
|
pyi_splash.close()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
app.mainloop()
|
app.mainloop()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user