feat: Autostart + Minimiert starten Funktionalität
- Autostart: Desktop-Entry wird in ~/.config/autostart/ erstellt - Minimiert starten: App startet direkt im System-Tray - Einstellungen lesen Config direkt, kein CLI-Flag nötig - README.md aktualisiert Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
71e5b92b50
commit
b0fd6889a3
4 changed files with 98 additions and 1 deletions
10
README.md
10
README.md
|
|
@ -16,6 +16,8 @@ Basiert auf **PJSUA2** (SIP-Stack) und **PySide6** (Qt-GUI). Verbindet sich übe
|
||||||
- **Responsives Layout**: Kompakt (nur Wählfeld) oder Breit (Wählfeld + Tabs)
|
- **Responsives Layout**: Kompakt (nur Wählfeld) oder Breit (Wählfeld + Tabs)
|
||||||
- **Click-to-Call**: `tel:` und `sip:` URI-Handler via D-Bus Single-Instance
|
- **Click-to-Call**: `tel:` und `sip:` URI-Handler via D-Bus Single-Instance
|
||||||
- **KDE-Integration**: System-Tray, D-Bus-Benachrichtigungen mit Annehmen/Ablehnen
|
- **KDE-Integration**: System-Tray, D-Bus-Benachrichtigungen mit Annehmen/Ablehnen
|
||||||
|
- **Autostart**: Automatisch beim Systemstart starten (XDG-konform)
|
||||||
|
- **Minimiert starten**: Optional direkt in den System-Tray starten
|
||||||
- **PipeWire-Audio**: Natives PipeWire/PulseAudio-Routing, separates Klingelton-Gerät
|
- **PipeWire-Audio**: Natives PipeWire/PulseAudio-Routing, separates Klingelton-Gerät
|
||||||
- **AppImage**: Komplett unabhängiges Paket (kein Python/Qt auf dem Zielsystem nötig)
|
- **AppImage**: Komplett unabhängiges Paket (kein Python/Qt auf dem Zielsystem nötig)
|
||||||
|
|
||||||
|
|
@ -207,6 +209,14 @@ Gespeichert unter `~/.config/sipwebapp/config.json`:
|
||||||
- CardDAV-Accounts (Multi-Account)
|
- CardDAV-Accounts (Multi-Account)
|
||||||
- BLF-Extensions
|
- BLF-Extensions
|
||||||
- Favoriten (manuell gepinnt)
|
- Favoriten (manuell gepinnt)
|
||||||
|
- Allgemein: Autostart, Minimiert starten, Tray-Verhalten
|
||||||
|
|
||||||
|
### Autostart
|
||||||
|
|
||||||
|
Wenn in den Einstellungen aktiviert, wird ein Desktop-Entry erstellt:
|
||||||
|
`~/.config/autostart/sipwebapp.desktop`
|
||||||
|
|
||||||
|
Die Option "Minimiert starten" lässt die App direkt im System-Tray starten, ohne das Hauptfenster anzuzeigen.
|
||||||
|
|
||||||
## AppImage bauen
|
## AppImage bauen
|
||||||
|
|
||||||
|
|
|
||||||
22
main.py
22
main.py
|
|
@ -58,6 +58,17 @@ def _uri_aus_args():
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
|
||||||
|
def _minimiert_starten(config=None):
|
||||||
|
"""Prüft ob minimiert gestartet werden soll (Config oder Kommandozeile)."""
|
||||||
|
# Kommandozeile hat Vorrang (für manuelles Testen)
|
||||||
|
if "--minimiert" in sys.argv or "-m" in sys.argv:
|
||||||
|
return True
|
||||||
|
# Sonst aus Config lesen
|
||||||
|
if config:
|
||||||
|
return config.allgemein.get("minimiert_starten", False)
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
class _DBusService(dbus.service.Object):
|
class _DBusService(dbus.service.Object):
|
||||||
"""D-Bus Service für Single-Instance und URI-Weiterleitung."""
|
"""D-Bus Service für Single-Instance und URI-Weiterleitung."""
|
||||||
|
|
||||||
|
|
@ -111,6 +122,11 @@ def main():
|
||||||
)
|
)
|
||||||
|
|
||||||
from ui.hauptfenster import HauptFenster
|
from ui.hauptfenster import HauptFenster
|
||||||
|
from utils.config_manager import ConfigManager
|
||||||
|
|
||||||
|
# Config laden für minimiert_starten Einstellung
|
||||||
|
config = ConfigManager()
|
||||||
|
|
||||||
fenster = HauptFenster()
|
fenster = HauptFenster()
|
||||||
|
|
||||||
# D-Bus Service registrieren (für Click-to-Call von Browser)
|
# D-Bus Service registrieren (für Click-to-Call von Browser)
|
||||||
|
|
@ -123,6 +139,12 @@ def main():
|
||||||
except dbus.DBusException:
|
except dbus.DBusException:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
# Minimiert starten? (aus Config oder --minimiert Flag)
|
||||||
|
minimiert = _minimiert_starten(config)
|
||||||
|
if minimiert:
|
||||||
|
# Direkt in Tray starten, Fenster nicht anzeigen
|
||||||
|
fenster.hide()
|
||||||
|
else:
|
||||||
fenster.show()
|
fenster.show()
|
||||||
fenster.starten()
|
fenster.starten()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -178,6 +178,10 @@ class EinstellungenDialog(QDialog):
|
||||||
"Beim Systemstart automatisch starten")
|
"Beim Systemstart automatisch starten")
|
||||||
form.addRow(self.autostart_check)
|
form.addRow(self.autostart_check)
|
||||||
|
|
||||||
|
self.minimiert_starten_check = QCheckBox(
|
||||||
|
"Minimiert starten (direkt in System-Tray)")
|
||||||
|
form.addRow(self.minimiert_starten_check)
|
||||||
|
|
||||||
# Klingelton-Datei
|
# Klingelton-Datei
|
||||||
klingelton_layout = QHBoxLayout()
|
klingelton_layout = QHBoxLayout()
|
||||||
self.klingelton_eingabe = QLineEdit()
|
self.klingelton_eingabe = QLineEdit()
|
||||||
|
|
@ -289,6 +293,8 @@ class EinstellungenDialog(QDialog):
|
||||||
allg = self._config.allgemein
|
allg = self._config.allgemein
|
||||||
self.tray_check.setChecked(allg.get("minimieren_in_tray", True))
|
self.tray_check.setChecked(allg.get("minimieren_in_tray", True))
|
||||||
self.autostart_check.setChecked(allg.get("autostart", False))
|
self.autostart_check.setChecked(allg.get("autostart", False))
|
||||||
|
self.minimiert_starten_check.setChecked(
|
||||||
|
allg.get("minimiert_starten", False))
|
||||||
self.klingelton_eingabe.setText(allg.get("klingelton", ""))
|
self.klingelton_eingabe.setText(allg.get("klingelton", ""))
|
||||||
|
|
||||||
# CardDAV-Accounts laden
|
# CardDAV-Accounts laden
|
||||||
|
|
@ -462,6 +468,8 @@ class EinstellungenDialog(QDialog):
|
||||||
self.tray_check.isChecked())
|
self.tray_check.isChecked())
|
||||||
self._config.set("allgemein", "autostart",
|
self._config.set("allgemein", "autostart",
|
||||||
self.autostart_check.isChecked())
|
self.autostart_check.isChecked())
|
||||||
|
self._config.set("allgemein", "minimiert_starten",
|
||||||
|
self.minimiert_starten_check.isChecked())
|
||||||
self._config.set("allgemein", "klingelton",
|
self._config.set("allgemein", "klingelton",
|
||||||
self.klingelton_eingabe.text())
|
self.klingelton_eingabe.text())
|
||||||
|
|
||||||
|
|
@ -478,5 +486,7 @@ class EinstellungenDialog(QDialog):
|
||||||
self._config.set("blf", "extensions", extensions)
|
self._config.set("blf", "extensions", extensions)
|
||||||
|
|
||||||
self._config.speichern()
|
self._config.speichern()
|
||||||
|
# Autostart Desktop-Entry erstellen/entfernen
|
||||||
|
self._config.autostart_aktualisieren()
|
||||||
self.einstellungen_geaendert.emit()
|
self.einstellungen_geaendert.emit()
|
||||||
self.accept()
|
self.accept()
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
import shutil
|
||||||
|
import sys
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -10,6 +12,13 @@ KONFIG_VERZEICHNIS = Path(
|
||||||
os.environ.get("XDG_CONFIG_HOME", Path.home() / ".config")
|
os.environ.get("XDG_CONFIG_HOME", Path.home() / ".config")
|
||||||
) / "sipwebapp"
|
) / "sipwebapp"
|
||||||
|
|
||||||
|
# Autostart-Verzeichnis (XDG-Standard)
|
||||||
|
AUTOSTART_VERZEICHNIS = Path(
|
||||||
|
os.environ.get("XDG_CONFIG_HOME", Path.home() / ".config")
|
||||||
|
) / "autostart"
|
||||||
|
|
||||||
|
AUTOSTART_DATEI = AUTOSTART_VERZEICHNIS / "sipwebapp.desktop"
|
||||||
|
|
||||||
KONFIG_DATEI = KONFIG_VERZEICHNIS / "config.json"
|
KONFIG_DATEI = KONFIG_VERZEICHNIS / "config.json"
|
||||||
ANRUFLISTE_DATEI = KONFIG_VERZEICHNIS / "anrufliste.json"
|
ANRUFLISTE_DATEI = KONFIG_VERZEICHNIS / "anrufliste.json"
|
||||||
KONTAKTE_DATEI = KONFIG_VERZEICHNIS / "kontakte.json"
|
KONTAKTE_DATEI = KONFIG_VERZEICHNIS / "kontakte.json"
|
||||||
|
|
@ -33,6 +42,7 @@ STANDARD_KONFIG = {
|
||||||
"allgemein": {
|
"allgemein": {
|
||||||
"minimieren_in_tray": True,
|
"minimieren_in_tray": True,
|
||||||
"autostart": False,
|
"autostart": False,
|
||||||
|
"minimiert_starten": False, # Beim Autostart minimiert in Tray starten
|
||||||
"klingelton": "", # Pfad zu WAV-Datei
|
"klingelton": "", # Pfad zu WAV-Datei
|
||||||
},
|
},
|
||||||
"carddav": {
|
"carddav": {
|
||||||
|
|
@ -202,3 +212,48 @@ class ConfigManager:
|
||||||
KONFIG_VERZEICHNIS.mkdir(parents=True, exist_ok=True)
|
KONFIG_VERZEICHNIS.mkdir(parents=True, exist_ok=True)
|
||||||
with open(KONTAKTE_DATEI, "w", encoding="utf-8") as f:
|
with open(KONTAKTE_DATEI, "w", encoding="utf-8") as f:
|
||||||
json.dump(kontakte, f, indent=2, ensure_ascii=False)
|
json.dump(kontakte, f, indent=2, ensure_ascii=False)
|
||||||
|
|
||||||
|
# --- Autostart ---
|
||||||
|
|
||||||
|
def autostart_aktivieren(self):
|
||||||
|
"""Desktop-Entry für Autostart erstellen."""
|
||||||
|
AUTOSTART_VERZEICHNIS.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
# Executable ermitteln
|
||||||
|
if getattr(sys, 'frozen', False):
|
||||||
|
# PyInstaller/AppImage: sys.executable ist das Binary
|
||||||
|
exec_path = sys.executable
|
||||||
|
else:
|
||||||
|
# Entwicklung: Python + main.py
|
||||||
|
main_py = Path(__file__).parent.parent / "main.py"
|
||||||
|
exec_path = f"{sys.executable} {main_py}"
|
||||||
|
|
||||||
|
# Kein --minimiert Flag nötig - App liest selbst aus Config
|
||||||
|
|
||||||
|
desktop_entry = f"""[Desktop Entry]
|
||||||
|
Type=Application
|
||||||
|
Version=1.0
|
||||||
|
Name=SIP Softphone
|
||||||
|
Comment=SIP-Softphone für FreePBX/Asterisk
|
||||||
|
GenericName=Internet-Telefonie
|
||||||
|
Exec={exec_path}
|
||||||
|
Icon=sipwebapp
|
||||||
|
Categories=Network;Telephony;
|
||||||
|
StartupNotify=false
|
||||||
|
Terminal=false
|
||||||
|
X-GNOME-Autostart-enabled=true
|
||||||
|
"""
|
||||||
|
with open(AUTOSTART_DATEI, "w", encoding="utf-8") as f:
|
||||||
|
f.write(desktop_entry)
|
||||||
|
|
||||||
|
def autostart_deaktivieren(self):
|
||||||
|
"""Desktop-Entry für Autostart entfernen."""
|
||||||
|
if AUTOSTART_DATEI.exists():
|
||||||
|
AUTOSTART_DATEI.unlink()
|
||||||
|
|
||||||
|
def autostart_aktualisieren(self):
|
||||||
|
"""Autostart-Eintrag basierend auf Konfiguration erstellen oder entfernen."""
|
||||||
|
if self.allgemein.get("autostart", False):
|
||||||
|
self.autostart_aktivieren()
|
||||||
|
else:
|
||||||
|
self.autostart_deaktivieren()
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue