Hallo zusammen!
Für ein von mir geschriebenes Programm, möchte ich nun auch die dazu gehörige Dokumentation schreiben.
Mein Betriebssystem ist Linux Kubuntu 14.04.
Die Dokumentation schreibe ich OpenOffice Writer und erstelle Hyperlinks vom Inhaltsverzeichnis zum Dokument.
Anschließend, erstelle ich über OpenOffice Writer eine PDF-Datei.
Öffne ich die PDF-Datei, funktioniert das mit den Hyperlinkś dort ohne Probleme.
Nun stelle ich mir die Frage, ob und wie es möglich ist, aus meinem Python-Programm, direkt auf bestimmte Hyperlinkś (Textpassagen) in der PDF-Datei zu kommen?
Ich würde mich freuen, wenn Ihr mir dabei helfen könntet und bin über jeden Input von Euch dankbar!
Grüße Nobuddy
Dokumentation im PDF-Format
@Nobuddy: Das ist letztendlich eine Frage der Software die zum Anzeigen des PDF-Dokuments verwendet wird und ob die so ein springen zu einem Ziel irgendwie von aussen steuerbar macht. Und ob man die Ziele irgendwie identifizieren und den Programmfunktionen zuordnen kann. Bei Okular kann man per D-Bus steuern welche Seite angezeigt wird.
Letztendlich würde ich mal sagen dass das keine gute Idee ist. Ein Hinweis darauf ist, dass das meines Wissens kein Programm macht.
Welches GUI-Toolkit verwendest Du denn für das Programm? Viele bieten irgendeinen Mechanismus um Online-Hilfe zu integrieren. Eine Textverarbeitung ist auch nicht unbedingt das übliche Werkzeug. Bei Python würde sich beispielsweise Sphinx anbieten. Da kann man PDFs, HTML, ePub, und noch ein paar andere Formate aus dem selben Quelltext erzeugen.
Letztendlich würde ich mal sagen dass das keine gute Idee ist. Ein Hinweis darauf ist, dass das meines Wissens kein Programm macht.
Welches GUI-Toolkit verwendest Du denn für das Programm? Viele bieten irgendeinen Mechanismus um Online-Hilfe zu integrieren. Eine Textverarbeitung ist auch nicht unbedingt das übliche Werkzeug. Bei Python würde sich beispielsweise Sphinx anbieten. Da kann man PDFs, HTML, ePub, und noch ein paar andere Formate aus dem selben Quelltext erzeugen.
Hallo BlackJack,
das mit der Textverarbeitung und dem umwandeln in ein PDF-Format, war für mich die einfachste Lösung, auch wenn im Nachhinein das nicht zum Ziel führt, wie Du das mir erklärt hast.
Ich verwende als GUI-Toolkit, tkinter.
Das mit Sphinx, werde ich mir anschauen!
Was würdest Du sonst noch, für eine einfache Handhabung vorschlagen?
Grüße Nobuddy
das mit der Textverarbeitung und dem umwandeln in ein PDF-Format, war für mich die einfachste Lösung, auch wenn im Nachhinein das nicht zum Ziel führt, wie Du das mir erklärt hast.
Ich verwende als GUI-Toolkit, tkinter.
Das mit Sphinx, werde ich mir anschauen!
Was würdest Du sonst noch, für eine einfache Handhabung vorschlagen?
Grüße Nobuddy
- noisefloor
- User
- Beiträge: 4187
- Registriert: Mittwoch 17. Oktober 2007, 21:40
- Wohnort: WW
- Kontaktdaten:
Hallo,
im Wiki von ubuntuusers.de gibt's (natürlich) einen Artikel zu Sphinx. Da werden auch so die minimalen Grundlagen erklärt.
Sphinx ist im Python-Umfeld ziemlich populär, d.h. die Chancen stehen auch gut, dass du zumindest ein paar deutsche Blogpost dazu findest.
Sphinx hat nebenbei auch noch den Vorteile, dass man mit Sphinx geschriebene Dokus auch (kostenfrei) online bei readthedocs.org online stellen kann.
Gruß, noisefloor
im Wiki von ubuntuusers.de gibt's (natürlich) einen Artikel zu Sphinx. Da werden auch so die minimalen Grundlagen erklärt.
Sphinx ist im Python-Umfeld ziemlich populär, d.h. die Chancen stehen auch gut, dass du zumindest ein paar deutsche Blogpost dazu findest.
Sphinx hat nebenbei auch noch den Vorteile, dass man mit Sphinx geschriebene Dokus auch (kostenfrei) online bei readthedocs.org online stellen kann.
Gruß, noisefloor
Hallo zusammen,
habe mich jetzt doch zu einer eher 'unorthodoxen' Lösung entschieden.
Wie schon zuvor beschrieben, schreibe ich meine Dokumentation mit OpenOfficeWriter und exportiere dies dann als PDF-Datei.
Bei allen Überschriften, habe ich dahinter einen Tabulator, gefolgt mit dem Feldbefehl Seite, ein Leerzeichen und anschließenden Text '#SEITE' gesetzt.
Beispiel: Das ist eine Überschrift<TAB>3 #Seite
Damit es in dem Dokument nicht komisch aussieht, habe ich die nachfolgende Information nach der Überschrift , unsichtbar gemacht.
Um nun diese Information auswerten zu können, erstelle ich eine Kopie Dokumentation.txt aus der Dokumentation.odt.
Diese Dokumentation.txt durchsuche ich nun nach der Information '#SEITE' und erstelle daraus eine Datei, mit der Seitenangabe und der Überschrift.
In meinem Programm, gibt es Master- und Sub-Buttons, deren Namen identisch mit den Überschriften aus der Dokumentation sind.
Mit einem Dictionary, wird die Position der Buttons ermittelt und die dazu gehörige Dokumentation bereitgestellt, die über die Hilfe oder F1 bei Bedarf abgerufen werden kann.
Grüße Nobuddy
habe mich jetzt doch zu einer eher 'unorthodoxen' Lösung entschieden.
Wie schon zuvor beschrieben, schreibe ich meine Dokumentation mit OpenOfficeWriter und exportiere dies dann als PDF-Datei.
Bei allen Überschriften, habe ich dahinter einen Tabulator, gefolgt mit dem Feldbefehl Seite, ein Leerzeichen und anschließenden Text '#SEITE' gesetzt.
Beispiel: Das ist eine Überschrift<TAB>3 #Seite
Damit es in dem Dokument nicht komisch aussieht, habe ich die nachfolgende Information nach der Überschrift , unsichtbar gemacht.
Um nun diese Information auswerten zu können, erstelle ich eine Kopie Dokumentation.txt aus der Dokumentation.odt.
Diese Dokumentation.txt durchsuche ich nun nach der Information '#SEITE' und erstelle daraus eine Datei, mit der Seitenangabe und der Überschrift.
In meinem Programm, gibt es Master- und Sub-Buttons, deren Namen identisch mit den Überschriften aus der Dokumentation sind.
Mit einem Dictionary, wird die Position der Buttons ermittelt und die dazu gehörige Dokumentation bereitgestellt, die über die Hilfe oder F1 bei Bedarf abgerufen werden kann.
Grüße Nobuddy
- noisefloor
- User
- Beiträge: 4187
- Registriert: Mittwoch 17. Oktober 2007, 21:40
- Wohnort: WW
- Kontaktdaten:
Hallo,
verstehe ich nicht ganz... Wie und wo wird die Doku denn jetzt bereitgestellt, wenn man so einen Sub-Button drückt?
Gruß, noisefloor
verstehe ich nicht ganz... Wie und wo wird die Doku denn jetzt bereitgestellt, wenn man so einen Sub-Button drückt?
Gruß, noisefloor
Hallo noisefloor,
das drücken eines Master- oder Sub-Button, ruft nicht automatisch die Doku auf.
Vielmehr wird der Status der Master- oder Sub-Button in einer Variablen hinterlegt.
Beispiel:
Die aus der 'Dokumentation.txt' erstellten Datei 'HELP_LISTING.txt', mit der Seitenangabe und der Überschrift, dient dazu die richtige Position in der 'Firmware-Dokumentation.pdf' zu finden.
Beispiel 'HELP_LISTING.txt':
Spalte 1 = Überschrift
Gibt es eine zusätzliche Info in der 'HELP_LISTING.txt', wie z.B.:
Erstellen Dictionary aus 'HELP_LISTING.txt':mylist, bezieht sich auf die geladene Liste aus 'HELP_LISTING.txt'.
Das Ausgabeergebnis bei Aufruf Menü Hilfe oder <F1>, ist wie folgt:
'Firmware-Dokumentation.pdf' wird mit xpdf in Position page geöffnet.
Grüße Nobuddy
das drücken eines Master- oder Sub-Button, ruft nicht automatisch die Doku auf.
Vielmehr wird der Status der Master- oder Sub-Button in einer Variablen hinterlegt.
Beispiel:
Code: Alles auswählen
self.help_position = self.masterbutton, self.subbutton
Beispiel 'HELP_LISTING.txt':
- 2 Kunden
3 Lieferanten
4 Kunden - Startseite - Einführung
5 Kunden - Neuanlage
7 Kunden - Kunden - Stammdaten
8 Kunden - Kunden - Kommunikation
Spalte 1 = Überschrift
Gibt es eine zusätzliche Info in der 'HELP_LISTING.txt', wie z.B.:
- 4 Kunden - Kunden - Stammdaten
Code: Alles auswählen
self.help_position = self.masterbutton, self.subbutton, 'Stammdaten'
Code: Alles auswählen
page = 0
content = 1
mydict = dict()
for x in mylist:
line = list()
for y in x[content].split(' - '):
line.append(y)
mydict.update({tuple(line) : x[page]})
Das Ausgabeergebnis bei Aufruf Menü Hilfe oder <F1>, ist wie folgt:
Code: Alles auswählen
page = self.mydict.get(tuple(self.help_position))
if not page:
for key in sorted(self.mydict):
check = ''.join(key)
if check.startswith(''.join(self.content)):
page = self.mydict[key]
break
if page:
# HELP_LISTING.txt, help_listing
filelist = 'help'
output = '{} {}'.format(Path(filelist), page)
subprocess.Popen(['xpdf', Path(filelist), page])
Grüße Nobuddy
Zuletzt geändert von Nobuddy am Freitag 28. November 2014, 10:37, insgesamt 1-mal geändert.
- noisefloor
- User
- Beiträge: 4187
- Registriert: Mittwoch 17. Oktober 2007, 21:40
- Wohnort: WW
- Kontaktdaten:
Hallo,
ok, Danke. Aus dem vorherigen Post ging nämlich nicht hervor, dass die explizit auf xpdf als PDF-Viewer setzt. Auch wenn ich es mir fast gedacht habe
Gruß, noisefloor
ok, Danke. Aus dem vorherigen Post ging nämlich nicht hervor, dass die explizit auf xpdf als PDF-Viewer setzt. Auch wenn ich es mir fast gedacht habe

Gruß, noisefloor
Dachte mir, daß dem noch ein bischen mehr Information bedarf.
xpdf ist der einzige PDF-Reader, so wie ich es bis jetzt festgestellt habe, bei dem eine Seiten-Position mit übergeben werden kann.
Mit dem Standard okular bei KDE, wäre es mir zwar lieber gewesen, habe da aber keine Möglichkeit gefunden, dies so umzusetzen.
PS: Habe noch kurz vor Deinem Post, noch in Bezug auf self.help_position, dies etwas erweitert!
Grüße Nobuddy

xpdf ist der einzige PDF-Reader, so wie ich es bis jetzt festgestellt habe, bei dem eine Seiten-Position mit übergeben werden kann.
Mit dem Standard okular bei KDE, wäre es mir zwar lieber gewesen, habe da aber keine Möglichkeit gefunden, dies so umzusetzen.
PS: Habe noch kurz vor Deinem Post, noch in Bezug auf self.help_position, dies etwas erweitert!
Grüße Nobuddy
@Nobuddy: Das ist aber mal wieder teilweise umständlich gruseliger Code.
Was soll denn zum Beispiel das hier bewirken…
…was ``line = x[content].split(' - ')`` nicht schon liefert!?
Und `update()` ist die falsche Methode wenn man da grundsätzlich ein neues Wörterbuchobjekt erzeugt das immer nur *ein* Schlüssel/Wert-Paar enthält. Das ist doch deutlich komplizierter als einfach dem Schlüssel einen Wert zuzuweisen.
Magische Indizes an Namen zu binden ist ja schon mal ganz nett, aber besser wäre es da richtige Namen draus zu machen, also zum Beispiel Attributnamen auf einem `collections.namedtuple`-Typ oder man bindet die einzelnen Elemente direkt in der Schleife an passende Namen.
`x`, `y`, `mylist` und `mydict`? Die Namen sind ja total nichtssagend.
Da würde letztlich so etwas übrig bleiben:
Oder direkt als ein Ausdruck:
Was soll denn zum Beispiel das hier bewirken…
Code: Alles auswählen
line = list()
for y in x[content].split(' - '):
line.append(y)
Und `update()` ist die falsche Methode wenn man da grundsätzlich ein neues Wörterbuchobjekt erzeugt das immer nur *ein* Schlüssel/Wert-Paar enthält. Das ist doch deutlich komplizierter als einfach dem Schlüssel einen Wert zuzuweisen.
Magische Indizes an Namen zu binden ist ja schon mal ganz nett, aber besser wäre es da richtige Namen draus zu machen, also zum Beispiel Attributnamen auf einem `collections.namedtuple`-Typ oder man bindet die einzelnen Elemente direkt in der Schleife an passende Namen.
`x`, `y`, `mylist` und `mydict`? Die Namen sind ja total nichtssagend.
Da würde letztlich so etwas übrig bleiben:
Code: Alles auswählen
path2pagenumber = dict()
for page_number, path in rows:
path2pagenumber[tuple(path.split(' - '))] = page_number
Code: Alles auswählen
path2pagenumber = dict(
(tuple(path.split(' - ')), page_number) for page_number, path in rows
)
Oder als Dictionary Comprehension (ungetestet):BlackJack hat geschrieben:Oder direkt als ein Ausdruck:Code: Alles auswählen
path2pagenumber = dict( (tuple(path.split(' - ')), page_number) for page_number, path in rows )
Code: Alles auswählen
path2pagenumber = {
tuple(path.split('-')): page_number
for page_number, path in rows
}
Zuletzt geändert von snafu am Freitag 28. November 2014, 12:37, insgesamt 1-mal geändert.
- noisefloor
- User
- Beiträge: 4187
- Registriert: Mittwoch 17. Oktober 2007, 21:40
- Wohnort: WW
- Kontaktdaten:
Hallo,
wenn's kein Nachteil ist, dass es "nur" mit xpdf läuft, ist das vorgehen prinzipiell ok. Nur funktioniert der Code halt auf keinem System, wo xpdf nicht installiert ist.
IMHO bietet es sich an, die Doku als HTML Dokument zu liefern. Das öffnest du dann mit dem webbrowser-Modul, was cross-platform läuft.
Und wir wären dann wieder bei Sphinx, weil das gleichermaßen die Doku nach HTML wie auch PDF rendern kann. HTML via Sphinx hat noch den Vorteil, dass du ein schickes Navi-Menü dazu bekommt. Und die Anker auch direkt gesetzt werden.
Gruß, noisefloor
wenn's kein Nachteil ist, dass es "nur" mit xpdf läuft, ist das vorgehen prinzipiell ok. Nur funktioniert der Code halt auf keinem System, wo xpdf nicht installiert ist.
IMHO bietet es sich an, die Doku als HTML Dokument zu liefern. Das öffnest du dann mit dem webbrowser-Modul, was cross-platform läuft.
Und wir wären dann wieder bei Sphinx, weil das gleichermaßen die Doku nach HTML wie auch PDF rendern kann. HTML via Sphinx hat noch den Vorteil, dass du ein schickes Navi-Menü dazu bekommt. Und die Anker auch direkt gesetzt werden.
Gruß, noisefloor
Hallo zusammen und Danke für Euren Input!
@BlackJack, mit gruselig meinst Du wohl etwas umständlich.
Daß 'x[content].split(' - ')' das Gleiche liefert wie:, da war ich mir nicht sicher ... deshalb habe ich den umständlichen Code gepostet.
Mit 'update()', hast Du völlig recht! Habe mich da vielleicht schon zu arg an dies gewöhnt ...
Das mit dem
Zu '`x`, `y`, `mylist` und `mydict`'!
x und y, sind für mich einfach kürzer im Code, als row usw.
mylist und mydict habe ich der Einfachheit verwendet, in meinem Code haben die schon bestimmte Namen, wie self.help_position und self.help_listingdict. Kann mir vorstellen, daß Du mit diesen Namen auch nicht einverstanden bist ...
Anhand Deiner zwei Beispiele in Deinem ersten Post und dem Post von snafu, verstehe ich Deine Rüge, was Du mir zuvor versucht hast mitzuteilen.
Danke für Euren Input, werde mir das aneignen!
Werde auch mal von snafu, dies 'Dictionary Comprehension (ungetestet)' testen!
@noisefloor, das mit xpdf ist momentan meine Lösung, mit Kubuntu 14.04 war dies kein Problem, xpdf nach zu installieren.
Das mit Sphinx ist noch nicht vom Tisch, brauche da aber mehr Zeit dazu, als die von mir aktuell umgesetzte Lösung.
Grüße an Alle
Nobuddy

@BlackJack, mit gruselig meinst Du wohl etwas umständlich.
Daß 'x[content].split(' - ')' das Gleiche liefert wie:
Code: Alles auswählen
line = list()
for y in x[content].split(' - '):
line.append(y)
Mit 'update()', hast Du völlig recht! Habe mich da vielleicht schon zu arg an dies gewöhnt ...

Das mit dem
Vielleicht könntest Du mir zu 'Attributnamen' und `collections.namedtuple` kurz etwas posten, daß mir das klar wird?...... aber besser wäre es da richtige Namen draus zu machen, also zum Beispiel Attributnamen auf einem `collections.namedtuple`-Typ oder man bindet die einzelnen Elemente direkt in der Schleife an passende Namen.
Zu '`x`, `y`, `mylist` und `mydict`'!
x und y, sind für mich einfach kürzer im Code, als row usw.
mylist und mydict habe ich der Einfachheit verwendet, in meinem Code haben die schon bestimmte Namen, wie self.help_position und self.help_listingdict. Kann mir vorstellen, daß Du mit diesen Namen auch nicht einverstanden bist ...

Anhand Deiner zwei Beispiele in Deinem ersten Post und dem Post von snafu, verstehe ich Deine Rüge, was Du mir zuvor versucht hast mitzuteilen.
Danke für Euren Input, werde mir das aneignen!

Werde auch mal von snafu, dies 'Dictionary Comprehension (ungetestet)' testen!
@noisefloor, das mit xpdf ist momentan meine Lösung, mit Kubuntu 14.04 war dies kein Problem, xpdf nach zu installieren.
Das mit Sphinx ist noch nicht vom Tisch, brauche da aber mehr Zeit dazu, als die von mir aktuell umgesetzte Lösung.

Grüße an Alle
Nobuddy
@Nobuddy: Man sollte bei Namen nicht daran denken das die möglichst kurz sind und damit schneller geschrieben werden können, sondern ob die beim Lesen etwas taugen. Denn Quelltext wird deutlich öfter gelesen als geschrieben und *dann* ist es wichtig den möglichst leicht verstehen zu können und nicht möglichst wenige Zeichen zu haben. Und das ist einfacher wenn die Namen die Bedeutung widergeben die man direkt lesen kann und nicht kryptische Buchstabenkürzel die man immer im Kopf erst ”übersetzen” muss.
Hallo BlackJack,
habe die Bedeutung, von leicht verständlichem Code verstanden.
Werde dies bei meinen zukünftigen Posts beachten!
Habe mich ein wenig in Bezug auf < Attributnamen auf einem `collections.namedtuple` > umgeschaut.
Ist eine prima Sache, wenn man es richtig verstanden hat, aber dafür brauche ich noch ein wenig ...
Ich habe einfach etwas herumprobiert, um zu verstehen.
Habe dies mal probiert, ohne Class ... usw.
Printausgabe 0: <class '__main__.lieferant'>
Wenn ich das richtige verstehe, habe ich hier Attributnamen für 'Lieferant' erstellt.
Ist das so richtig?
Hier weise ich 'Lieferant' Inhalte zu und binde die Inhalte zu 'L04711'.
Printausgabe 1: lieferant(lieferant='04711', namen='Test GmbH')
Printausgabe 2: Test GmbH
Ist das ein kleiner Anfang ind die richtige Richtung?
Grüße Nobuddy
habe die Bedeutung, von leicht verständlichem Code verstanden.
Werde dies bei meinen zukünftigen Posts beachten!
Habe mich ein wenig in Bezug auf < Attributnamen auf einem `collections.namedtuple` > umgeschaut.
Ist eine prima Sache, wenn man es richtig verstanden hat, aber dafür brauche ich noch ein wenig ...

Ich habe einfach etwas herumprobiert, um zu verstehen.
Habe dies mal probiert, ohne Class ... usw.
Code: Alles auswählen
from collections import namedtuple
Lieferant = namedtuple('lieferant','lieferant namen')
print(Lieferant)
Wenn ich das richtige verstehe, habe ich hier Attributnamen für 'Lieferant' erstellt.
Ist das so richtig?
Code: Alles auswählen
L04711 = Lieferant('04711', 'Test GmbH')
print(L04711)
print(L04711.namen)
Printausgabe 1: lieferant(lieferant='04711', namen='Test GmbH')
Printausgabe 2: Test GmbH
Ist das ein kleiner Anfang ind die richtige Richtung?
Grüße Nobuddy
Die Funktionsweise von Namedtuples hast du richtig erfasst. Das sind im Grunde eine Art Datenspeicher mit sprechenden Namen. Hilfreich sind sie, wenn man eine reine Datenstruktur benötigt, die ohne eigene Funktionalität auskommt. Wenn man dann aus einer solchen Struktur etwas abruft a la ``print(info.name)``, dann ist das halt lesbarer als ein ``print(info[2])`` oder als das umständlichere ``id, date, name = info; print(name)`` (jetzt nur als Beispiel gemeint).
Hallo zusammen,
wünsche Euch ein gutes neues Jahr!
Gleichzeitig möchte ich mich im Nachhinein, für Euren Input bedanken und habe mir diesen angeeignet.
Zur Lesbarkeit von Code, auf Bezug meiner Kürzel x .. y und Co, habe ich Abstand genommen und weise jetzt statt dessen Namen zu, die aussagekräftig sind.
Ich habe dies bemerkt, als ich älteren Code von mir wieder angefasst habe und es schwierig war, sich einzufinden.
Dies war auch ein weiterer Grund, die Empfehlung von BlackJack umzusetzen.
Das mit den namestuple, funktioniert inzwischen echt super und vereinfacht das Leben ungemein.
Was mir hier zugute kam, war daß ich schon lang zuvor, die Steuerung von Listen, Listennamen und Spaltennamen zentralisiert hatte und die Spaltennamen in den Listen vereinheitlicht hatte.
Grüße Nobuddy
wünsche Euch ein gutes neues Jahr!

Gleichzeitig möchte ich mich im Nachhinein, für Euren Input bedanken und habe mir diesen angeeignet.
Zur Lesbarkeit von Code, auf Bezug meiner Kürzel x .. y und Co, habe ich Abstand genommen und weise jetzt statt dessen Namen zu, die aussagekräftig sind.
Ich habe dies bemerkt, als ich älteren Code von mir wieder angefasst habe und es schwierig war, sich einzufinden.
Dies war auch ein weiterer Grund, die Empfehlung von BlackJack umzusetzen.
Das mit den namestuple, funktioniert inzwischen echt super und vereinfacht das Leben ungemein.
Was mir hier zugute kam, war daß ich schon lang zuvor, die Steuerung von Listen, Listennamen und Spaltennamen zentralisiert hatte und die Spaltennamen in den Listen vereinheitlicht hatte.
Grüße Nobuddy