diff --git a/gui.py b/gui.py index 9af0f89..37e96e9 100644 --- a/gui.py +++ b/gui.py @@ -11,6 +11,7 @@ import threading import re import json from pdf_to_ics import extract_dienstplan_data, create_ics_from_dienstplan +from update_checker import check_for_updates, get_current_version # Versuche tkinterdnd2 zu importieren (optional für besseres Drag & Drop) try: @@ -56,6 +57,10 @@ class PDFtoICSGUI: # Drag & Drop einrichten self.setup_drag_and_drop() + # Update-Prüfung im Hintergrund starten + update_thread = threading.Thread(target=self.check_for_updates_background, daemon=True) + update_thread.start() + # Speichere Konfiguration beim Schließen self.root.protocol("WM_DELETE_WINDOW", self.on_closing) @@ -445,6 +450,34 @@ class PDFtoICSGUI: f"Es wurden {success_count} ICS-Datei(en) erfolgreich erstellt!\n\n" f"Speicherort: {output_dir}" )) + + def check_for_updates_background(self): + """Prüfe auf Updates im Hintergrund""" + try: + update_available, new_version, download_url = check_for_updates() + + if update_available: + # Zeige Update-Dialog auf dem Main-Thread + self.root.after(0, self.show_update_dialog, new_version, download_url) + except Exception as e: + # Stille Fehler ignorieren, damit GUI nicht beeinflusst wird + pass + + def show_update_dialog(self, new_version, download_url): + """Zeige Update-Dialog""" + current_version = get_current_version() + + response = messagebox.showinfo( + "Update verfügbar", + f"Eine neue Version ist verfügbar!\n\n" + f"Aktuelle Version: v{current_version}\n" + f"Neue Version: v{new_version}\n\n" + f"Möchten Sie die neue Version herunterladen?" + ) + + if response == 'ok': # Dialog mit OK-Button + import webbrowser + webbrowser.open(download_url) def main(): diff --git a/install.sh b/install.sh index 197590f..414a5c9 100755 --- a/install.sh +++ b/install.sh @@ -138,7 +138,7 @@ mkdir -p "$(dirname "$DESKTOP_FILE")" # Kopiere Dateien print_step "Kopiere Anwendungsdateien..." -cp -r *.py *.md *.sh *.cmd .gitignore "$INSTALL_DIR/" 2>/dev/null || true +cp -r *.py *.md *.sh *.cmd version.txt .gitignore "$INSTALL_DIR/" 2>/dev/null || true print_success "Dateien kopiert nach $INSTALL_DIR" # Erstelle Python Virtual Environment @@ -150,7 +150,7 @@ print_success "Virtual Environment erstellt" # Installiere Python-Abhängigkeiten print_step "Installiere Python-Abhängigkeiten..." .venv/bin/pip install -q --upgrade pip -.venv/bin/pip install -q pdfplumber icalendar pypdf2 pytz +.venv/bin/pip install -q pdfplumber icalendar pypdf2 pytz packaging .venv/bin/pip install -q tkinterdnd2 2>/dev/null || print_warning "tkinterdnd2 optional nicht installiert (kein Problem)" print_success "Abhängigkeiten installiert" diff --git a/update_checker.py b/update_checker.py new file mode 100644 index 0000000..df4f468 --- /dev/null +++ b/update_checker.py @@ -0,0 +1,109 @@ +#!/usr/bin/env python3 +""" +Update-Checker für PDF zu ICS Konverter +Prüft auf Updates über Gitea API +""" + +import urllib.request +import json +from pathlib import Path +from packaging import version as pkg_version + +# Gitea-Konfiguration +GITEA_URL = "https://git.file-archive.de" +REPO_OWNER = "webfarben" +REPO_NAME = "pdf_to_ics" + + +def get_current_version(): + """Lese aktuelle lokal gespeicherte Version""" + try: + version_file = Path(__file__).parent / 'version.txt' + if version_file.exists(): + with open(version_file, 'r') as f: + return f.read().strip() + except Exception as e: + print(f"Warnung: Version konnte nicht gelesen werden: {e}") + return "0.0.0" + + +def get_latest_version(): + """ + Prüfe Latest Release auf Gitea + + Returns: + Tupel (version_string, download_url) oder (None, None) bei Fehler + """ + try: + # Gitea API Endpoint für neueste Release + url = f"{GITEA_URL}/api/v1/repos/{REPO_OWNER}/{REPO_NAME}/releases/latest" + + with urllib.request.urlopen(url, timeout=5) as response: + data = json.loads(response.read().decode()) + + # Extrahiere Version aus Tag (z.B. "v1.0.0" -> "1.0.0") + tag = data.get('tag_name', '').lstrip('v') + if not tag: + return None, None + + # HTML-URL für Download (Download-Seite auf Gitea) + download_url = f"{GITEA_URL}/{REPO_OWNER}/{REPO_NAME}/releases/tag/{data.get('tag_name', '')}" + + return tag, download_url + + except urllib.error.URLError as e: + print(f"Warnung: Konnte Gitea nicht erreichen ({GITEA_URL}): {e}") + return None, None + except json.JSONDecodeError: + print("Warnung: Gitea Response konnte nicht geparst werden") + return None, None + except Exception as e: + print(f"Warnung: Update-Check fehlgeschlagen: {e}") + return None, None + + +def check_for_updates(): + """ + Prüfe ob ein Update verfügbar ist + + Returns: + Tupel (update_available, new_version, download_url) + - update_available: Bool + - new_version: Version String oder None + - download_url: URL zur Download-Seite oder None + """ + current = get_current_version() + latest, url = get_latest_version() + + if latest is None: + # Bei Fehler kein Update-Dialog + return False, None, None + + try: + # Vergleiche Versionen + if pkg_version.parse(latest) > pkg_version.parse(current): + return True, latest, url + except Exception as e: + print(f"Warnung: Versionenvergleich fehlgeschlagen: {e}") + + return False, None, None + + +if __name__ == "__main__": + # Test + current = get_current_version() + print(f"Aktuelle Version: {current}") + print(f"Gitea-Server: {GITEA_URL}/{REPO_OWNER}/{REPO_NAME}\n") + + latest, url = get_latest_version() + if latest: + print(f"Neueste Version auf Gitea: {latest}") + print(f"Download-URL: {url}") + + update_available, new_version, download_url = check_for_updates() + if update_available: + print(f"✓ Update verfügbar: v{new_version}") + else: + print("✓ Sie verwenden bereits die neueste Version") + else: + print(f"⚠ Konnte Gitea nicht erreichen ({GITEA_URL})") diff --git a/version.txt b/version.txt new file mode 100644 index 0000000..3eefcb9 --- /dev/null +++ b/version.txt @@ -0,0 +1 @@ +1.0.0