Guten Abend,
ich versuche in meinem pdf-Bastelprojekt gerade eine Möglichkeit zu finden das pdf in einem externen pdfviewer der eigenen Wahl anzeigen zu lassen, so wie es mit rechtsklick im Nemo geht. Gibt es dafür eine fertige Methode in einer Bibliothek?
Danke für Eure Antworten vorab
richie
Anzeige eines Kontextmenus mit externen Programmen? Geht das?
nein, das ist ja alles erledigt. Ich frage mit, wo ich die für ein file vorgesehenen Programme herbekomme, um die in ein eigenes Kontextmenu einbauen zu können. Also eine Liste von Editoren für Textfiles oder Bearbeitungsprogramme für Bilddateien, Soundfiles, was auch immer. Irgendwo muss das ja hinterlegt sein, odeR? Gibt es dafür einen System-Abruf vielleicht?
- __blackjack__
- User
- Beiträge: 13969
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@ran: Gibt es auf den meisten Systemen. Also welches System ist es denn nun? Bei Linux könnte man beispielsweise das Programm `xdg-open` verwenden.
“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
Ja, ich arbeite unter Mint. 'xdg-open'' gibt aber soweit ich weiß nur das aktuell eingestellte Bearbeitungsprogramm wieder, ich habe das bei mir auf papers stehen. Aber Metadaten kann klein und schnell Paper Clip, manchmal mache ich was mit Okular, daher dachte ich mir, ich mache mir so ein kleines Kontextmenu, wo ich das jeweils gewünschte auswählen kann. Danke für den Fingerzeig!
- __blackjack__
- User
- Beiträge: 13969
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@ran: Wenn XDG grundsätzlich zur Verfügung steht, dann kann man sich da wohl was mit dem passenden Python-Modul basteln. Mal als Ansatz:
Ergibt bei mir hier gerade:
Man kann von den `DesktopEntry`-Objekten auch noch einen Haufen andere Informationen abfragen, und ich vermute wenn man `locale` setzt, dann kommen da auch die entsprechenden Übersetzungen.
Und ich sehe gerade, dass ein Eintrag doppelt ist, der liegt aber in verschiedenen Verzeichnissen, da habe ich noch das Original in ``/usr/bin`` aber das Programm auch noch mal selbst kompiliert in ``/usr/local/bin/``.
Code: Alles auswählen
#!/usr/bin/env python3
from pathlib import Path
from xdg.BaseDirectory import xdg_data_dirs
from xdg.DesktopEntry import DesktopEntry
from xdg.IniFile import IniFile, ParsingError
from xdg.Mime import get_type2
def main():
mime_type = str(get_type2(Path("test.pdf")))
for data_path in map(Path, xdg_data_dirs):
applications_path = data_path / "applications"
try:
ini = IniFile(applications_path / "mimeinfo.cache")
except ParsingError:
pass # Intentionally ignored.
else:
for filename in ini.get(mime_type, "MIME Cache", list=True):
desktop_entry = DesktopEntry(applications_path / filename)
print(desktop_entry.getName(), "-", desktop_entry.getComment())
if __name__ == "__main__":
main()
Code: Alles auswählen
Foxit Reader - View pdf documents
winebrowser -
calibre - E-book library management: Convert, view, share, catalogue all your e-books
PDF Arranger - PDFs zusammenfügen, umsortieren, trennen, rotieren und zuschneiden
E-book viewer - Viewer for E-books in all the major formats
GNU Image Manipulation Program - Create images and edit photographs
PDF Mod - Seiten in PDF-Dokumenten entfernen, herauslösen und drehen
xpdf - View PDF files
gv - View PS and/or PDF files
calibre - E-book library management: Convert, view, share, catalogue all your e-books
LibreOffice Draw - Create and edit drawings, flow charts and logos using Draw.
Karbon - Create scalable vector drawings
Inkscape - Create and edit Scalable Vector Graphics images
E-book Viewer - Viewer for E-books in all the major formats
Okular - Universal document viewer
Krita -
Document Viewer - View multi-page documents
Und ich sehe gerade, dass ein Eintrag doppelt ist, der liegt aber in verschiedenen Verzeichnissen, da habe ich noch das Original in ``/usr/bin`` aber das Programm auch noch mal selbst kompiliert in ``/usr/local/bin/``.
“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
Krass, vielen Dank, das hilft mir ungemein weiter. Mein Dateibrowser zeigt mir auch für Okular viele Einträge an, ich hatte mich schon gefragt warum. Das scheint mir eine gute Erklärung zu sein. Vielen lieben Dank für die Hilfe
Oder per GObject Introspection (nur GTK):
Code: Alles auswählen
In [1]: from gi.repository import Gio
In [2]: for app in Gio.app_info_get_all_for_type('text/plain'):
...: print(app.get_display_name(),app.get_description(), app.get_executable())
...:
Leafpad Einfacher Texteditor leafpad
Geany Eine kleine und schnelle Entwicklungsumgebung für GTK+ geany
…
AFAIK geht es da aber um die von der Paketverwaltung bereitgestellten Apps. Falls man nur die sehen möchte, die tatsächlich auf dem System installiert sind, müsste man also evtl. noch eine Prüfung via shutil.which() einbauen. Die Funktion ließe sich sogar innerhalb von filter() benutzen, weil sie für nicht vorhandene Kommandos einfach ``None`` liefert. Habe derzeit kein Gtk bzw. kein Linux installiert, sonst hätte ich das mal eben getestet.
in etwa so habe ich es jetzt im Code:
Code: Alles auswählen
# Mögliche PDF-Viewer: Shell-Befehl → Menschlich lesbarer Name
POTENZIELLE_VIEWER = {
"papers": "Papers (GNOME)",
"evince": "Evince (GNOME klassisch)",
"okular": "Okular (KDE)",
"mupdf": "MuPDF",
"zathura": "Zathura",
"xpdf": "XPDF",
"atril": "Atril (MATE)",
"xdg-open": "System-Standard (xdg-open)",
}
# Nur verfügbare Viewer anzeigen
VERFUEGBARE_VIEWER = {
k: v for k, v in POTENZIELLE_VIEWER.items() if shutil.which(k)
}
# Umkehr-Mapping: Menschlicher Name → Shell-Befehl
VIEWER_NAME_TO_CMD = {v: k for k, v in VERFUEGBARE_VIEWER.items()}
@ran:
Das ist allerdings nicht so robust, da du anders als mit den gezeigten Methoden mit einer vorgegeben, hardgecodeten Liste von Executables arbeitest.
@snafu:
Bei mir (Arch Linux, Gnome 3) wird die globale Zuordnung von Mime-Types zu Programmen in der Datei "/usr/share/applications/mimeinfo.cache" gespeichert. Wenn ich ein Paket über den Paketmanager global installiere, wird als einer der Postinstllations-Schritte diese Datei aktualisiert. Die Ausgabe, die ich von dem oben gezeigten API-Aufruft erhalte, entspricht genau den Programmen, die bei mir auch für den Mime-Type installiert und global registriert sind.
Das ist allerdings nicht so robust, da du anders als mit den gezeigten Methoden mit einer vorgegeben, hardgecodeten Liste von Executables arbeitest.
@snafu:
Falls du damit meinst, dass darüber Software angezeigt wird, die über die Paketverwaltung installiert wurde, stimme ich zu. Falls du meinst, dass damit Software angezeigt wird – installiert oder nicht – die über die Paketverwaltung verfügbar ist, dann nicht

Bei mir (Arch Linux, Gnome 3) wird die globale Zuordnung von Mime-Types zu Programmen in der Datei "/usr/share/applications/mimeinfo.cache" gespeichert. Wenn ich ein Paket über den Paketmanager global installiere, wird als einer der Postinstllations-Schritte diese Datei aktualisiert. Die Ausgabe, die ich von dem oben gezeigten API-Aufruft erhalte, entspricht genau den Programmen, die bei mir auch für den Mime-Type installiert und global registriert sind.
- __blackjack__
- User
- Beiträge: 13969
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
Insgesamt ist das von der Linux-Paketverwaltung unabhängig. Ich habe da mehrere Programme drin, die ich an der Paketverwaltung vorbei installiert habe. Die müssen sich halt bei der Installation über die entsprechenden xdg-Programme mit einer *.Desktop-Datei bei der Datenbank bekannt machen, damit sie im Startmenü auftauchen, und in der *.Desktop-Datei kann ein Programm auch angeben für welche MIME-Typen es verantwortlich gemacht werden kann. Hier mal die vom Foxit-Reader:
Code: Alles auswählen
[Desktop Entry]
Name=Foxit Reader
Comment=View pdf documents
Keywords=pdf;ppdf;
StartupNotify=true
Terminal=false
Type=Application
Categories=Application;Office;Viewer;X-Red-Hat-Base;
MimeType=application/pdf;application/ppdf;
Icon=FoxitReader
Exec=/home/bj/opt/foxitsoftware/foxitreader/FoxitReader.sh %F
“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
ich hatte vorher ein script über /usr/share/applications laufen lassen und mir alles mit viewer ausgeben lassen, danach eins geschrieben, das mir die 8 Batzillionen Wiederholungen von Okular rausfischte und es blieb nicht viel brauchbares übrig, das allerdings auch kryptisch, da dachte ich mir, ich schreib ein paar zusammen, die bestimmt überall irgendwie auftauchen, bevor da ebook viewer und libreoffice draw auftauchen. Wäre ja nett, wenn sich die Programmierer mal iwann auf nen Standard einigen könnten.
Code: Alles auswählen
import os
desktop_dir = "/usr/share/applications"
found = {}
for root, _, files in os.walk(desktop_dir):
for file in files:
if not file.endswith(".desktop"):
continue
path = os.path.join(root, file)
try:
with open(path, "r", encoding="utf-8", errors="ignore") as f:
lines = f.readlines()
name = None
exec_line = None
has_pdf = False
for line in lines:
lower = line.lower()
if "application/pdf" in lower:
has_pdf = True
if line.startswith("Name="):
name = line.strip().split("=", 1)[-1]
if line.startswith("Exec="):
exec_line = line.strip().split("=", 1)[-1]
if has_pdf and name and exec_line:
key = (name.lower(), exec_line.lower()) # für Duplikat-Filterung
if key not in found:
found[key] = (name, exec_line)
except Exception as e:
print(f"Fehler bei Datei {path}: {e}")
# Ausgabe
for name, exec_line in sorted(found.values()):
print(f"{name:<30} → {exec_line}")
Sorry, Ausgabe vergessen
Atril Document Viewer → atril %U
Document Viewer → xreader %U
E-book viewer → ebook-viewer --detach %f
MuPDF → mupdf %f
New Drawing → libreoffice --draw
New Private Window → /usr/bin/vivaldi-stable --incognito
New Window with a Temporary Profile → chromium --temp-profile
Okular → okular %U
Slim PDF Reader 2.0 → /opt/investintech/spr/bin/SlimPDFReader
Zathura → zathura %U
calibre → calibre --detach %U
gImageReader → gimagereader-gtk %U
[Finished in 48ms]
- noisefloor
- User
- Beiträge: 4167
- Registriert: Mittwoch 17. Oktober 2007, 21:40
- Wohnort: WW
- Kontaktdaten:
Hallo,
Gruß, noisefloor
Gibt es doch (schon lange): die genannten MIME-Types. Weiterführende Erklärung siehe z.B. https://wiki.ubuntuusers.de/MIME-Typ/.Wäre ja nett, wenn sich die Programmierer mal iwann auf nen Standard einigen könnten.
Gruß, noisefloor
@ran: Wie denn auch? Das gibt dir das passende Programm, mit dem der Benutzer PDFs öffnen will. Der Code von __blackjack__ zeigt dir, wie du alle entsprechenden Programme erhälst. Und stattdessen verwendest du eine hard zusammengefrickelte Liste, die nur auf deinem System funktioniert? Das kann man so machen, ist aber nun wirklich Dimensionen von dem Ursprungsthema des Threads entfernt. Und es ist in meinen Augen auchnicht wirklich sinnvoll.
- __blackjack__
- User
- Beiträge: 13969
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
Nur ``/usr/share/applications/`` ist übrigens auch ein bisschen wenig. Mindestens mal Snaps und Flatpacks können Verzeichnisse haben, wo passende Programme liegen können. Hier mal die Liste der Verzeichnisse die bei mir bei meinem gezeigten Code abgearbeitet werden:
Code: Alles auswählen
['/home/bj/.local/share',
'/usr/share/plasma',
'/home/bj/.local/share/flatpak/exports/share',
'/var/lib/flatpak/exports/share',
'/usr/local/share',
'/usr/share',
'/var/lib/snapd/desktop']
“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