Initial commit

This commit is contained in:
2026-09-04 19:49:43 +02:00
parent 7ce9248e95
commit 30faf00ba2
47 changed files with 3946 additions and 0 deletions

View File

@@ -0,0 +1,148 @@
"""
paperless_formats.py - Dateiformate und ihre Bearbeitbarkeit in LibreOffice.
Zentral gehalten, weil drei Stellen dieselbe Information brauchen: die
Versionsauswahl beim Öffnen, die Wahl des Speicherfilters beim Zurueck-
schreiben und der Hinweis, wenn eine Fassung nicht sinnvoll bearbeitbar ist.
"""
# Endung -> (Anzeigename, LibreOffice-Filter oder None, bearbeitbar)
#
# "bearbeitbar" meint: LibreOffice kann die Datei öffnen UND im selben
# Format wieder speichern, sodass ein sinnvoller Rückweg ins Archiv
# entsteht. PDF lässt sich zwar in Draw öffnen, ein Zurückschreiben
# ergaebe aber ein anderes Dokument - deshalb hier "nur Ansicht".
FORMATS = {
".odt": ("ODF Text", "writer8", True),
".ods": ("ODF Tabelle", "calc8", True),
".odp": ("ODF Präsentation", "impress8", True),
".odg": ("ODF Zeichnung", "draw8", True),
".doc": ("Word 97", "MS Word 97", True),
".docx": ("Word", "MS Word 2007 XML", True),
".dot": ("Word-Vorlage", "MS Word 97 Vorlage", True),
".rtf": ("Rich Text", "Rich Text Format", True),
".xls": ("Excel 97", "MS Excel 97", True),
".xlsx": ("Excel", "Calc MS Excel 2007 XML", True),
".ppt": ("PowerPoint 97", "MS PowerPoint 97", True),
".pptx": ("PowerPoint", "Impress MS PowerPoint 2007 XML", True),
".txt": ("Text", "Text", True),
".csv": ("CSV", "Text - txt - csv (StarCalc)", True),
".pdf": ("PDF", None, False),
".eml": ("E-Mail", None, False),
".msg": ("E-Mail", None, False),
".xml": ("XML", None, False),
".html": ("HTML", None, False),
".zip": ("Archiv", None, False),
".png": ("Bild", None, False),
".jpg": ("Bild", None, False),
".jpeg": ("Bild", None, False),
".tif": ("Bild", None, False),
".tiff": ("Bild", None, False),
}
MIME_TO_EXT = {
"application/vnd.oasis.opendocument.text": ".odt",
"application/vnd.oasis.opendocument.spreadsheet": ".ods",
"application/vnd.oasis.opendocument.presentation": ".odp",
"application/vnd.oasis.opendocument.graphics": ".odg",
"application/msword": ".doc",
"application/vnd.openxmlformats-officedocument.wordprocessingml.document": ".docx",
"application/vnd.ms-excel": ".xls",
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": ".xlsx",
"application/vnd.ms-powerpoint": ".ppt",
"application/vnd.openxmlformats-officedocument.presentationml.presentation": ".pptx",
"application/rtf": ".rtf",
"text/rtf": ".rtf",
"text/plain": ".txt",
"text/csv": ".csv",
"application/pdf": ".pdf",
"message/rfc822": ".eml",
"text/html": ".html",
"application/xml": ".xml",
"text/xml": ".xml",
"application/zip": ".zip",
}
def extension(filename=None, mime_type=None):
"""Endung aus Dateiname oder MIME-Typ, immer kleingeschrieben."""
if filename and "." in filename:
return "." + filename.rsplit(".", 1)[-1].lower()
if mime_type:
return MIME_TO_EXT.get(mime_type.split(";")[0].strip().lower(), "")
return ""
def describe(filename=None, mime_type=None):
"""(Anzeigename, Filter, bearbeitbar) für eine Datei."""
ext = extension(filename, mime_type)
if ext in FORMATS:
return FORMATS[ext]
return (ext.lstrip(".").upper() or "unbekannt", None, False)
def is_editable(filename=None, mime_type=None):
return describe(filename, mime_type)[2]
def is_known(filename=None, mime_type=None):
"""
Ist das Format in der Tabelle verzeichnet?
Wichtig für die Unterscheidung zweier Fälle: Ein PDF ist BEKANNT und
nicht bearbeitbar — da hilft kein Zureden. Ein unbekanntes Format
dagegen ist womöglich sehr wohl bearbeitbar, es steht nur nicht in der
Tabelle. Dann soll der Anwender entscheiden dürfen, statt vom Programm
ausgebremst zu werden.
"""
return extension(filename, mime_type) in FORMATS
def detail(filename=None, mime_type=None):
"""
Ausführliche Angabe für Hinweistexte: Anzeigename plus die Rohdaten,
aus denen er abgeleitet wurde. Damit lässt sich erkennen, welche
Formate in FORMATS ergänzt werden sollten.
"""
name = describe(filename, mime_type)[0]
teile = [t for t in (filename, mime_type) if t]
return "%s%s" % (name, ", ".join(teile)) if teile else name
# Dokumentart -> Vorgabeformat für Dateien, die noch nie gespeichert wurden.
# Ermittelt über supportsService() am geöffneten Dokument.
SERVICE_DEFAULTS = (
("com.sun.star.text.TextDocument", ".odt", "writer8"),
("com.sun.star.sheet.SpreadsheetDocument", ".ods", "calc8"),
("com.sun.star.presentation.PresentationDocument", ".odp", "impress8"),
("com.sun.star.drawing.DrawingDocument", ".odg", "draw8"),
("com.sun.star.formula.FormulaProperties", ".odf", "math8"),
)
def default_for_document(doc):
"""
(Endung, Filter) für ein Dokument ohne Speicherort.
Ein neu angelegtes, noch nie gespeichertes Dokument hat keinen URL.
Damit es trotzdem abgelegt werden kann, wird es in ein temporäres
Verzeichnis geschrieben - im zur Anwendung passenden ODF-Format.
"""
for service, ext, filt in SERVICE_DEFAULTS:
try:
if doc.supportsService(service):
return ext, filt
except Exception:
continue
return ".odt", "writer8"
def store_filter(filename=None, mime_type=None):
"""LibreOffice-Filtername zum Speichern im Originalformat."""
return describe(filename, mime_type)[1]
def label(filename=None, mime_type=None):
"""Kurzbeschreibung für die Anzeige, z. B. 'ODF Text'."""
return describe(filename, mime_type)[0]