Anzeige eines Kontextmenus mit externen Programmen? Geht das?

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
ran
User
Beiträge: 22
Registriert: Mittwoch 23. April 2025, 14:48

ist halt eine ziemliche Verrenkung, aus .desktop nur passende viewer raus zu filtern.

Code: Alles auswählen

import os

def finde_programme_mit_strengem_pdf_mimetype_und_namen():
    suchpfade = [
        "/usr/share/applications",
        os.path.expanduser("~/.local/share/applications"),
        "/var/lib/flatpak/exports/share/applications",
        os.path.expanduser("~/.local/share/flatpak/exports/share/applications")
    ]

    erlaubte_mimetypes = {"application/pdf", "application/x-pdf"}
    verbotene_namen = {"calibre", "image", "window"}

    ergebnisse = []

    for verzeichnis in suchpfade:
        if not os.path.exists(verzeichnis):
            continue

        for datei in os.listdir(verzeichnis):
            if not datei.endswith(".desktop"):
                continue

            pfad = os.path.join(verzeichnis, datei)
            try:
                with open(pfad, "r", encoding="utf-8", errors="ignore") as f:
                    lines = f.readlines()

                name = None
                mimetype = ""

                for zeile in lines:
                    if zeile.startswith("Name="):
                        name = zeile.strip().split("=", 1)[-1]
                    elif zeile.startswith("MimeType="):
                        full_mime = zeile.strip().split("=", 1)[-1]
                        pdf_types = [
                            m for m in full_mime.split(";")
                            if m.strip().lower() in erlaubte_mimetypes
                        ]
                        mimetype = ";".join(pdf_types)

                if not mimetype or not name:
                    continue

                # Namen filtern
                name_lower = name.lower()
                if any(verboten in name_lower for verboten in verbotene_namen):
                    continue

                ergebnisse.append((name, mimetype))

            except Exception:
                continue

    return ergebnisse

# Ausgabe
if __name__ == "__main__":
    ergebnisse = finde_programme_mit_strengem_pdf_mimetype_und_namen()
    print("📄 Final gefilterte PDF-Programme:\n")
    for name, mimetype in ergebnisse:
        print(f"{name:<30} → {mimetype}")
ergibt (ich habe extra ein paar mehr installiert)
📄 Final gefilterte PDF-Programme:

E-book viewer → application/pdf
Slim PDF Reader 2.0 → application/pdf
Okular → application/pdf
Document Viewer → application/pdf
MuPDF → application/pdf
Atril Document Viewer → application/pdf
New Drawing → application/pdf
Zathura → application/pdf
Paperwork → application/pdf
[Finished in 44ms]
Benutzeravatar
__blackjack__
User
Beiträge: 13969
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@ran: Da sind ja auch wieder hart kodierte Pfade. Du fragtest nach einem Standard, programmierst dann aber selbst etwas das schlechter ist als sich tatsächlich an dem Standard zu orientieren, und was man nicht selbst machen muss, weil es ja das `xdg`-Modul gibt. XDG/Freedesktop ist halt der Standard, und da bekommen Gnome und KDE auch ihre „Öffnen mit…“-Listen her. Danach fragtest Du ja.
“The best book on programming for the layman is »Alice in Wonderland«; but that's because it's the best book on anything for the layman.” — Alan J. Perlis
ran
User
Beiträge: 22
Registriert: Mittwoch 23. April 2025, 14:48

Danke für die schnelle Antwort, ich muss jetzt mal ein wenig darüber meditieren
ran
User
Beiträge: 22
Registriert: Mittwoch 23. April 2025, 14:48

@blackjack Ja, stimmt, du hattest es ja schon ganz am Anfang des Threads angesprochen, aber ich habe rumgedooft statt das direkt umzusetzen. Jetzt wird alles sauber gefunden, hätte ich damit auch gleich haben können. Entschuldige bitte.

Code: Alles auswählen


def finde_verfügbare_pdf_viewer():
    erlaubte_mimetypes = {"application/pdf", "application/x-pdf"}
    verbotene_namen = {"calibre", "image", "window"}

    viewer_dict = {}

    # Durchlaufe alle .desktop-Dateien in XDG-konformen Pfaden
    for verzeichnis in BaseDirectory.load_data_paths("applications"):
        if not os.path.exists(verzeichnis):
            continue
        for root, _, files in os.walk(verzeichnis):
            for datei in files:
                if not datei.endswith(".desktop"):
                    continue
                pfad = os.path.join(root, datei)
                try:
                    eintrag = DesktopEntry.DesktopEntry(pfad)

                    name = eintrag.getName()
                    exec_line = eintrag.getExec()
                    mimetypes = eintrag.getMimeTypes()

                    if not name or not exec_line or not mimetypes:
                        continue

                    if any(wort in name.lower() for wort in verbotene_namen):
                        continue

                    if not any(mt in erlaubte_mimetypes for mt in mimetypes):
                        continue

                    befehl = shlex.split(exec_line)
                    befehl = [arg for arg in befehl if not arg.startswith("%")]

                    if befehl and name not in viewer_dict:
                        viewer_dict[name] = befehl

                except Exception:
                    continue

    viewer_dict["System-Standard (xdg-open)"] = ["xdg-open"]
    return dict(sorted(viewer_dict.items()))


Antworten