Initial Commit
This commit is contained in:
29
LICENSE
29
LICENSE
@@ -1,18 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2026 marco.morath
|
||||
Copyright (c) 2026 Marco Morath
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
||||
associated documentation files (the "Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
|
||||
following conditions:
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial
|
||||
portions of the Software.
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
||||
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
|
||||
EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
466
README.md
466
README.md
@@ -1,3 +1,465 @@
|
||||
# libreoffice-paperless-connector
|
||||
# Paperless-Connector für LibreOffice
|
||||
|
||||
Addon für Libreoffice um Paperless-NGX anzubinden.
|
||||
Erweiterung, die Dokumente direkt aus einem Paperless-ngx-Archiv öffnet,
|
||||
Bearbeitungen als **neue Version desselben Dokuments** ablegt, die
|
||||
Klassifizierung bearbeitet und zeitlich begrenzte Freigabelinks erzeugt.
|
||||
|
||||
Voraussetzung ist Paperless-ngx **3.0 oder neuer** — erst dort gibt es die
|
||||
Dokumentversionierung.
|
||||
|
||||
---
|
||||
|
||||
## Funktionen
|
||||
|
||||
| Befehl | Wirkung |
|
||||
|---|---|
|
||||
| **Aus Paperless öffnen** | Suche, Trefferliste, Versionsliste — lädt das **Original** |
|
||||
| **Als neue Version ablegen** | hängt die Fassung als Version an das bestehende Dokument |
|
||||
| **In Paperless ablegen** | neues Dokument **oder** neue Version eines beliebigen anderen Dokuments |
|
||||
| **Klassifizierung bearbeiten** | Titel, Datum, Korrespondent, Dokumenttyp, Tags |
|
||||
| **Freigabelink erzeugen** | zeitlich begrenzter, unauthentifizierter Link, optional mit Kennzeichnung |
|
||||
| **Status anzeigen** | Kennung, Titel, Versionsanzahl des aktuellen Dokuments |
|
||||
| **Verbindung einrichten** | Basisadresse und API-Token |
|
||||
|
||||
Erreichbar über das Menü **Extras → Paperless** und über eine eigene
|
||||
Symbolleiste.
|
||||
|
||||
---
|
||||
|
||||
## Sprachen
|
||||
|
||||
Die Oberfläche liegt in **Deutsch, Englisch und Französisch** vor. Die
|
||||
Sprache richtet sich nach der Einstellung von LibreOffice, nicht nach der
|
||||
des Betriebssystems — maßgeblich ist die Sprache, in der die Erweiterung
|
||||
erscheint.
|
||||
|
||||
Übersetzt wird in `pythonpath/paperless_i18n.py`. Als Schlüssel dient der
|
||||
deutsche Text selbst; fehlt eine Übersetzung, erscheint das deutsche
|
||||
Original. Eine weitere Sprache ergänzt man, indem man ein Wörterbuch nach
|
||||
dem Muster von `EN` anlegt und in `KATALOG` einträgt.
|
||||
|
||||
Die Menü- und Symbolleistentexte liegen getrennt davon in `Addons.xcu`;
|
||||
dort sind sie je Sprache als `xml:lang`-Werte hinterlegt.
|
||||
|
||||
## Sicherheit
|
||||
|
||||
Ausführlich in [SICHERHEIT.md](SICHERHEIT.md). Die wichtigsten Punkte:
|
||||
|
||||
- **Makros werden nie ausgeführt.** Heruntergeladene Dateien werden mit
|
||||
`MacroExecutionMode = NEVER_EXECUTE` geladen — auch eine Rückfrage gibt
|
||||
es nicht. Ein Dokument aus dem Archiv ist fremder Inhalt, selbst aus dem
|
||||
eigenen Bestand.
|
||||
- **Keine externen Inhalte beim Öffnen.** `UpdateDocMode = NO_UPDATE`.
|
||||
- **Dateinamen aus der Antwort werden vollständig bereinigt**, beide
|
||||
Pfadtrennzeichen, Windows-Gerätenamen, Punkte am Ende.
|
||||
- **Arbeitsverzeichnis im Benutzerprofil**, nicht in `/tmp` — dort wäre ein
|
||||
Symlink-Angriff möglich.
|
||||
- **Nur http und https** als Basisadresse und bei Weiterleitungen.
|
||||
- **Größenbegrenzung** auf Antworten.
|
||||
|
||||
## Bewusste Entwurfsentscheidungen
|
||||
|
||||
### Eigene Schaltflächen statt Speichern-Knopf
|
||||
|
||||
Paperless als echtes Speicherziel in die Datei-Dialoge einzuhängen würde
|
||||
einen **UCB Content Provider** erfordern — C++-UNO-Arbeit in einer sehr
|
||||
dünn dokumentierten Ecke, für ein Einzelprojekt nicht tragfähig.
|
||||
|
||||
Eigene Schaltflächen sind ohnehin die ehrlichere Lösung: Es bleibt
|
||||
sichtbar, wann eine neue Version im Archiv entsteht, und ein versehentliches
|
||||
Strg+S erzeugt keine Archivversion.
|
||||
|
||||
### Prüfungen vor der Freigabe
|
||||
|
||||
Ein Link auf einen Stand, der nur lokal existiert, wäre irreführend — der
|
||||
Empfänger bekäme etwas anderes zu sehen als der Absender vor sich hat.
|
||||
Deshalb wird vorher geprüft:
|
||||
|
||||
| Zustand | Reaktion |
|
||||
|---|---|
|
||||
| Dokument nicht in Paperless | Angebot, es zuerst abzulegen |
|
||||
| lokale Änderungen nicht abgelegt | Auswahl: abbrechen, trotzdem teilen, oder erst neue Version ablegen |
|
||||
|
||||
Zusätzlich lässt sich das Dokument beim Teilen mit einem **Tag**
|
||||
kennzeichnen, voreingestellt `Sharelink`. Das macht geteilte Dokumente
|
||||
später gezielt auffindbar — Paperless zeigt zwar die eigenen Freigaben an,
|
||||
aber ein Tag lässt sich in gespeicherten Ansichten und Regeln verwenden.
|
||||
|
||||
Der zuletzt verwendete Tagname wird gemerkt. Ist er noch nicht vorhanden,
|
||||
wird er nach Rückfrage angelegt. Vorhandene Tags des Dokuments bleiben
|
||||
erhalten.
|
||||
|
||||
### Drei Wege ins Archiv
|
||||
|
||||
| Befehl | Ergebnis |
|
||||
|---|---|
|
||||
| **Als neue Version ablegen** | eine weitere Fassung **desselben** Dokuments |
|
||||
| **In Paperless ablegen** → Neues Dokument | eigenständiges Dokument mit eigener Versionskette und Seriennummer |
|
||||
| **In Paperless ablegen** → An bestehendes anhängen | neue Version eines **beliebigen anderen** Dokuments |
|
||||
|
||||
Der dritte Weg deckt eine Lücke, die Dokumentenverwaltungen gern
|
||||
offenlassen:
|
||||
|
||||
> Die Rechnung kommt als PDF ins Archiv. Später entsteht die bearbeitbare
|
||||
> Fassung. Beides gehört zusammen — aber das PDF war zuerst da.
|
||||
|
||||
„Als neue Version ablegen" zielt immer auf das eigene Wurzeldokument und
|
||||
hilft hier nicht. Über die Zielauswahl lässt sich dagegen jedes vorhandene
|
||||
Dokument suchen und die geöffnete Datei daran anhängen.
|
||||
|
||||
Beim neuen Dokument lässt sich die Klassifizierung des Ursprungs
|
||||
übernehmen — Dokumenttyp, Korrespondent, Tags, Zusatzfelder und
|
||||
Eigentümer. Zusatzfelder mit **Herkunftsbezug** werden bewusst nicht
|
||||
kopiert — wer aus einem anderen System migriert hat, führt dort oft ein Feld
|
||||
mit der Fremdkennung, und eine Kopie mit derselben Kennung wäre falsch.
|
||||
Welche Feldnamen das betrifft, steht in den Einstellungen unter
|
||||
`herkunftsfelder`.
|
||||
|
||||
In beiden Fällen kann das geöffnete Fenster danach dem Ziel zugeordnet
|
||||
werden. Weitere Versionen landen dann dort.
|
||||
|
||||
Der Befehl funktioniert auch mit Dateien, die **nicht** aus Paperless
|
||||
stammen — dann ist er der Weg, sie überhaupt erst einzuliefern.
|
||||
|
||||
Und er funktioniert mit Dokumenten, die **noch nie gespeichert** wurden.
|
||||
Ein frisch angelegtes „Unbenannt 1" hat keinen Speicherort; es wird dann in
|
||||
dasselbe temporäre Verzeichnis geschrieben, das auch beim Öffnen benutzt
|
||||
wird, im zur Anwendung passenden ODF-Format. Der eingegebene Titel bestimmt
|
||||
dabei den Dateinamen, unter dem Paperless das Original ablegt.
|
||||
|
||||
### Ein Dialog von oben nach unten
|
||||
|
||||
```
|
||||
┌─ Suche ──────────────────────────────────────── [Suchen] ─┐
|
||||
│ │
|
||||
│ Dokumente ASN Datum Titel │
|
||||
│ ┌──────────────────────────────────────────────────────┐ │
|
||||
│ │ 11263 2024-02-11 Mietvertrag │ │
|
||||
│ │ 11264 2024-03-02 Nebenkostenabrechnung │ │
|
||||
│ └──────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ Versionen Nr. Datum Format Bezeichnung │
|
||||
│ ┌──────────────────────────────────────────────────────┐ │
|
||||
│ │ • 3 2026-09-01 PDF LibreOffice 2026-09-01 │ │
|
||||
│ │ 2 2025-06-04 ODF Text │ │
|
||||
│ │ 1 2024-02-11 ODF Text │ │
|
||||
│ └──────────────────────────────────────────────────────┘ │
|
||||
│ Bearbeitbar. Änderungen können als neue Version … │
|
||||
│ ☐ Schreibgeschützt öffnen [Öffnen] [Abbrechen] │
|
||||
└────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
Die Spaltenüberschrift steht jeweils **unter** der Bezeichnung des
|
||||
Abschnitts und über der Liste, nicht daneben.
|
||||
|
||||
Beide Listen verwenden eine dicht laufende Schrift mit festen
|
||||
Spaltenbreiten und senkrechten Strichen als Trenner. Die Schriftgröße wird
|
||||
bewusst nicht festgelegt, sondern vom Dialog geerbt — also die Vorgabe des
|
||||
Systems. Mit der sonst
|
||||
üblichen Proportionalschrift wären mit Leerzeichen aufgefüllte Spalten
|
||||
**nicht** ausgerichtet — die Überschrift stünde woanders als der Inhalt.
|
||||
|
||||
Die Trefferliste zeigt je Dokument **einen** Eintrag, nämlich das
|
||||
Wurzeldokument. Bei Auswahl füllt sich darunter die Versionsliste mit
|
||||
Nummer, Datum, **Dateiformat** und Bezeichnung.
|
||||
|
||||
Vorausgewählt ist die aktuellste Version. Ein **Punkt** markiert Fassungen,
|
||||
die LibreOffice nach der Formattabelle nicht bearbeiten kann — etwa ein
|
||||
PDF, während eine ältere Version noch das ODT ist.
|
||||
|
||||
### Öffnungsart
|
||||
|
||||
Unten im Dialog wird die Öffnungsart gewählt. Die Vorbelegung ist ein
|
||||
**Vorschlag, keine Vorschrift** — die Formaterkennung kann danebenliegen,
|
||||
und dann soll der Anwender trotzdem bearbeitbar öffnen können.
|
||||
|
||||
| Fall | Vorbelegung | Hinweis |
|
||||
|---|---|---|
|
||||
| bekannt und bearbeitbar | Bearbeitbar | — |
|
||||
| **nicht erkannt** | Bearbeitbar | zeigt Dateiname und MIME-Typ, damit das Format gemeldet und ergänzt werden kann |
|
||||
| bekannt, nicht bearbeitbar (PDF, E-Mail) | Schreibgeschützt | bearbeitbar bleibt wählbar |
|
||||
|
||||
Beim Zurückschreiben eines unbekannten Formats kommt eine Rückfrage: Es
|
||||
gibt dann keinen passenden Speicherfilter, LibreOffice speichert im
|
||||
eigenen Format, und die Dateiendung passt danach möglicherweise nicht mehr
|
||||
zum Inhalt.
|
||||
|
||||
Welche Formate als bearbeitbar gelten, steht in
|
||||
`pythonpath/paperless_formats.py`. Die Tabelle lässt sich dort ergänzen —
|
||||
wenn im Hinweistext regelmäßig derselbe MIME-Typ auftaucht, gehört er
|
||||
hinein.
|
||||
|
||||
Die Formatangabe steht nicht in der eingebetteten `versions`-Liste, deshalb
|
||||
ruft die Erweiterung je Version einen Datensatz ab. Die Ergebnisse werden
|
||||
zwischengespeichert, damit das Blättern in der Trefferliste nicht bei jedem
|
||||
Tastendruck erneut abfragt.
|
||||
|
||||
### Immer das Original laden
|
||||
|
||||
Der Download erfolgt mit `?original=true`. Bei ZUGFeRD bleibt damit die
|
||||
eingebettete XML erhalten, bei E-Mails die Anhänge. Die von Paperless
|
||||
erzeugte Archivfassung wäre eine Ableitung.
|
||||
|
||||
### Kennung in den Dokumenteigenschaften
|
||||
|
||||
Die Paperless-ID wird in den **benutzerdefinierten Dokumenteigenschaften**
|
||||
abgelegt (`PaperlessDocumentId`). Diese überleben einen ODF-Speichervorgang
|
||||
und wandern sogar mit, wenn die Datei kopiert wird.
|
||||
|
||||
Als Rückfallebene dient eine lokale Zuordnungsdatei über den Datei-URL —
|
||||
für Formate, die keine solchen Eigenschaften kennen.
|
||||
|
||||
### Betriebssystemneutral
|
||||
|
||||
Die Erweiterung läuft unter Linux, Windows und macOS. Was dafür nötig war:
|
||||
|
||||
| Punkt | Umsetzung |
|
||||
|---|---|
|
||||
| Konfigurationsort | `%APPDATA%` unter Windows, sonst `XDG_CONFIG_HOME` bzw. `~/.config` |
|
||||
| Pfade | durchgehend `os.path.join`, nie feste Trennzeichen |
|
||||
| Datei-URLs | `unohelper.systemPathToFileUrl` statt eigener Zusammensetzung |
|
||||
| Dateinamen | Windows-Verbotszeichen und Gerätenamen werden auch unter Linux entfernt |
|
||||
|
||||
Eine Einschränkung: `chmod` ist unter Windows weitgehend wirkungslos. Die
|
||||
Einstellungsdatei mit dem Token liegt dort im Benutzerprofil, auf das
|
||||
andere Benutzer standardmäßig keinen Zugriff haben — der Schutz kommt also
|
||||
vom Betriebssystem statt von den Dateirechten.
|
||||
|
||||
`build.sh` ist ein Shell-Skript und läuft nur unter Linux und macOS. Es
|
||||
wird ausschließlich zur Entwicklung gebraucht; die fertige `.oxt` lässt
|
||||
sich überall installieren.
|
||||
|
||||
### Ohne `requests`
|
||||
|
||||
Die in LibreOffice mitgelieferte Python-Laufzeit bringt nur die
|
||||
Standardbibliothek mit. Alles läuft über `urllib`, inklusive
|
||||
selbstgebautem Multipart-Upload.
|
||||
|
||||
---
|
||||
|
||||
## Bauen und installieren
|
||||
|
||||
```bash
|
||||
./build.sh
|
||||
unopkg add --force paperless-libreoffice-1.1.0.oxt
|
||||
```
|
||||
|
||||
> **Zur Versionsabhängigkeit:** `OpenOffice.org-minimal-version` in
|
||||
> `description.xml` bezieht sich auf die OpenOffice-**Referenzversion**, und
|
||||
> die ist bei LibreOffice dauerhaft auf **4.1** eingefroren — unabhängig
|
||||
> davon, ob die installierte Version 7, 24 oder 25 heißt. Ein Wert wie `7.0`
|
||||
> schließt dort jede Installation aus und führt zu „Die Erweiterung benötigt
|
||||
> mindestens OpenOffice.org Referenzversion 7.0".
|
||||
>
|
||||
> Für echte LibreOffice-Versionen gibt es `lo:LibreOffice-minimal-version`
|
||||
> im Namensraum `http://libreoffice.org/extensions/description/2011`.
|
||||
|
||||
LibreOffice danach **vollständig beenden**, auch den Schnellstarter:
|
||||
|
||||
```bash
|
||||
pkill soffice
|
||||
```
|
||||
|
||||
Entfernen:
|
||||
|
||||
```bash
|
||||
unopkg remove org.example.paperless.libreoffice
|
||||
```
|
||||
|
||||
Alternativ über Extras → Extension Manager.
|
||||
|
||||
---
|
||||
|
||||
## Einrichten
|
||||
|
||||
1. **Extras → Paperless → Verbindung einrichten**
|
||||
2. Basisadresse eintragen, etwa `https://dms.example.org` — ohne
|
||||
abschließenden Schrägstrich
|
||||
3. API-Token eintragen. Erzeugt wird er im **Benutzerprofil** von
|
||||
Paperless, nicht in der allgemeinen Verwaltung
|
||||
4. Speichern — die Verbindung wird sofort geprüft
|
||||
|
||||
Die Einstellungen liegen unter
|
||||
`~/.config/paperless-libreoffice/settings.json` mit Modus 600.
|
||||
|
||||
> **Zum Token:** Er liegt im Klartext in dieser Datei. Das entspricht dem,
|
||||
> was andere Desktop-Anwendungen tun, ist aber kein Geheimnisspeicher. Wer
|
||||
> es strenger will, müsste die Erweiterung an den Systemschlüsselbund
|
||||
> anbinden — über `com.sun.star.task.PasswordContainer` oder libsecret.
|
||||
|
||||
---
|
||||
|
||||
## Ablauf im Alltag
|
||||
|
||||
```
|
||||
Extras → Paperless → Aus Paperless öffnen…
|
||||
Suchbegriff oder Archiv-Seriennummer eingeben
|
||||
Dokument auswählen → öffnet sich in LibreOffice
|
||||
|
||||
… bearbeiten, zwischendurch normal mit Strg+S speichern
|
||||
(bleibt lokal, das Archiv bleibt unberührt)
|
||||
|
||||
Extras → Paperless → Als neue Version ablegen
|
||||
Rückfrage bestätigen → Upload → Bestätigung mit Versions-ID
|
||||
```
|
||||
|
||||
Die bisherige Fassung bleibt als Version erhalten. In Paperless entsteht
|
||||
kein neuer Eintrag, sondern eine Version am bestehenden Dokument.
|
||||
|
||||
---
|
||||
|
||||
## Fehlersuche
|
||||
|
||||
Die Erweiterung erscheint nicht im Menü:
|
||||
|
||||
```bash
|
||||
unopkg list | grep -i paperless
|
||||
```
|
||||
|
||||
Fehlt sie, wurde LibreOffice nicht vollständig beendet. Python-Fehler beim
|
||||
Laden erscheinen auf der Konsole:
|
||||
|
||||
```bash
|
||||
soffice --writer
|
||||
```
|
||||
|
||||
Ausführlichere Meldungen mit:
|
||||
|
||||
```bash
|
||||
SAL_LOG="+WARN+INFO.extensions" soffice --writer
|
||||
```
|
||||
|
||||
### Bekannte Stolpersteine
|
||||
|
||||
**Dokument ohne Speicherort.** Ein noch nie gespeichertes Dokument wird
|
||||
für die Ablage automatisch temporär geschrieben. In LibreOffice bleibt es
|
||||
danach weiterhin ungespeichert — das ist Absicht, damit nicht ungefragt
|
||||
eine Datei im Dateisystem entsteht, von der niemand weiß.
|
||||
|
||||
**„Dieses Dokument stammt nicht aus Paperless."** Die Kennung wurde nicht
|
||||
gefunden. Das passiert, wenn die Datei über den normalen Öffnen-Dialog
|
||||
geladen wurde oder das Format keine benutzerdefinierten
|
||||
Dokumenteigenschaften kennt.
|
||||
|
||||
**Speichern in Fremdformaten.** Beim Zurückspeichern eines DOCX oder XLSX
|
||||
wird der passende Filter gewählt (siehe `FORMATS` in
|
||||
`pythonpath/paperless_formats.py`). Fehlt ein Format dort, speichert
|
||||
LibreOffice als ODF — dann stimmt die Endung nicht mehr zum Inhalt.
|
||||
|
||||
**Freigabelinks.** Der Endpunkt heißt je nach Paperless-Version
|
||||
`share_links/` oder `sharelinks/`. Beide werden probiert.
|
||||
|
||||
**HTTP 403 nur über die Domain, nicht über die IP.** Klassisches Zeichen
|
||||
dafür, dass ein Schutzsystem vor der Anwendung den User-Agent abweist.
|
||||
`urllib` sendet ohne Zutun `Python-urllib/3.x`, und diese Kennung steht in
|
||||
den Sperrlisten von CrowdSec, fail2ban und gängigen WAF-Regelwerken.
|
||||
|
||||
Die Erweiterung setzt deshalb eine eigene Kennung. Wird auch die
|
||||
abgewiesen, lässt sie sich in `paperless_client.py` über die Konstante
|
||||
`USER_AGENT` ändern.
|
||||
|
||||
Zum Nachstellen:
|
||||
|
||||
```bash
|
||||
curl -s -o /dev/null -w '%{http_code}\n' -A "Python-urllib/3.10" \
|
||||
-H "Authorization: Token $PT" https://dms.example.org/api/documents/
|
||||
```
|
||||
|
||||
403 gegenüber 200 mit der curl-Vorgabe bestätigt die Ursache. Die
|
||||
Fehlermeldung kann dabei von einem völlig anderen Dienst stammen als dem,
|
||||
den man ansprechen wollte.
|
||||
|
||||
---
|
||||
|
||||
## Symbole
|
||||
|
||||
Alle Symbole teilen dieselbe Grundform — ein Blatt mit umgeknickter Ecke in
|
||||
Paperless-Grün — damit die Leiste als zusammengehörige Gruppe erkennbar
|
||||
bleibt. Unterschieden wird über eine farbige Scheibe unten rechts:
|
||||
|
||||
| Befehl | Beizeichen |
|
||||
|---|---|
|
||||
| **Markensymbol** | gefüllte grüne Fläche mit weißem Blatt, ganz links in der Leiste |
|
||||
| Öffnen | blauer Pfeil nach unten |
|
||||
| Neue Version | oranger Pfeil nach oben mit Plus |
|
||||
| In Paperless ablegen | oranger Pfeil nach oben mit Sternchen, zweites Blatt dahinter |
|
||||
| Klassifizierung | violettes Etikett |
|
||||
| Teilen | türkise verbundene Punkte |
|
||||
| Einstellungen | graues Zahnrad |
|
||||
|
||||
Das Markensymbol steht am Anfang der Leiste, durch einen Trenner von den
|
||||
Befehlen abgesetzt. Es ist mit **Status anzeigen** belegt, also nicht nur
|
||||
Zierde. Durch die gefüllte Fläche unterscheidet es sich deutlich von den
|
||||
Bordmitteln von LibreOffice — man sieht auf einen Blick, wo die
|
||||
Paperless-Leiste beginnt und endet.
|
||||
|
||||
### Format
|
||||
|
||||
Registriert sind **SVG**. LibreOffice skaliert sie auf die eingestellte
|
||||
Symbolgröße (Extras → Optionen → Ansicht → Symbolgröße: Klein, Groß, Sehr
|
||||
groß). Mit PNG wären nur zwei feste Größen möglich, und bei „Sehr groß"
|
||||
würde hochgerechnet.
|
||||
|
||||
Erzeugt werden die Symbole mit `make_icons.py` aus einer **gemeinsamen
|
||||
Geometriebeschreibung** — SVG und PNG können deshalb nicht auseinanderlaufen.
|
||||
Das Skript braucht Pillow für die PNG-Ausgabe und wird nur zur Entwicklung
|
||||
gebraucht; die fertigen Dateien liegen unter `icons/` und sind im Paket.
|
||||
|
||||
Zusätzlich zu den SVG enthält das Paket PNG in 16, 26 und 32 Pixeln als
|
||||
Rückfallebene. Sollte die SVG-Unterstützung in einer LibreOffice-Version
|
||||
nicht greifen und gar kein Symbol erscheinen, in `Addons.xcu` umstellen:
|
||||
|
||||
```
|
||||
ImageSmallURL → %origin%/icons/paperless-NAME_16.png
|
||||
ImageBigURL → %origin%/icons/paperless-NAME_26.png
|
||||
```
|
||||
|
||||
### Reihenfolge in der Leiste
|
||||
|
||||
```
|
||||
[Paperless] │ [Öffnen] [Neue Version] [Ablegen unter] [Klassifizierung] [Teilen] │ [Verbindung]
|
||||
```
|
||||
|
||||
## Aufbau
|
||||
|
||||
```
|
||||
paperless_addon.py Protokoll-Handler, Befehlslogik
|
||||
make_icons.py erzeugt die Symbole (nur zur Entwicklung)
|
||||
pythonpath/
|
||||
paperless_client.py REST-Client, nur Standardbibliothek
|
||||
paperless_config.py Einstellungen, Dokumentzuordnung
|
||||
paperless_dialogs.py UNO-Dialoge, programmatisch aufgebaut
|
||||
paperless_formats.py Formate, Filter, Bearbeitbarkeit
|
||||
Addons.xcu Menü, Symbolleiste, Symbole
|
||||
icons/ 16x16 und 26x26 PNG je Befehl
|
||||
ProtocolHandler.xcu Registrierung von paperless.Command:*
|
||||
```
|
||||
|
||||
Der Protokoll-Handler ist der Kern: Menüeinträge lösen URLs wie
|
||||
`paperless.Command:Open` aus, die LibreOffice an die registrierte Klasse
|
||||
weiterreicht.
|
||||
|
||||
---
|
||||
|
||||
## Stand und Grenzen
|
||||
|
||||
Version 1.1.0. Das Gerüst ist vollständig und die Client-Logik getestet,
|
||||
aber die Erweiterung ist an einer echten Instanz noch nicht über längere
|
||||
Zeit erprobt.
|
||||
|
||||
Nicht enthalten:
|
||||
|
||||
- **Zusatzfelder** im Klassifizierungsdialog — nur die Grundfelder
|
||||
- **Fortschrittsanzeige** beim Upload — bei großen Dateien wirkt
|
||||
LibreOffice währenddessen eingefroren
|
||||
- **Übersetzungen** über die Oberflächentexte hinaus
|
||||
- **Konfliktbehandlung**, wenn dasselbe Dokument parallel anderswo
|
||||
geändert wurde
|
||||
|
||||
Der letzte Punkt ist der relevanteste für den Mehrbenutzerbetrieb.
|
||||
Paperless kennt keine Sperren; wer zeitgleich arbeitet, erzeugt zwei
|
||||
Versionen statt eines Konflikts. Bei einem kleinen Kreis ist das
|
||||
verschmerzbar.
|
||||
|
||||
Die Software wird ohne jegliche Gewähr oder Haftungsübernahme bereitgestellt.
|
||||
Die Nutzung erfolgt auf eigene Gefahr.
|
||||
|
||||
Reference in New Issue
Block a user