Donnerstag, 30. Oktober 2014

Erst Upgrade, dann Neuinstallation - von Ubuntu 12.04 nach 14.04

Letztes Wochenende war es soweit: das Update von Ubuntu 12.04 auf 14.04 stand auf dem Laptop an, den ich beruflich nutze (ein Lenovo T410). Die Prozedur ist ja nicht weiter schwierig und z.B. auch im Wiki von ubuntuusers.de beschrieben.

Dank schnellem Internetzugang ging das ganze auch recht zügig von statten und das Upgrade lief problemlos und fehlerfrei durch.

Nach dem Reboot lief auch alles rund, also alles gut. Dachte ich zumindest. Beim ersten Starten von Empathy unter Trusty war die Darstellung der Chats auf die Standardansicht zurückgesetzt, besser gefällt mir aber eine andere die Darstellung.

Kein Problem, kann man ja umstellen. Nur: im Empathy-Fenster fehlte das komplette Menü "Empathy", welches auch den Menüpunkt "Einstellungen" enthält. Da ich auf meinem privaten Laptop aber schon länger Ubuntu 14.04 installiert habe war ich mir sehr sicher, dass das Menü normalerweise da ist. Hm...

Nun, es gibt schlimmeres, von daher erst Mal weiter gemacht. Aber dieses Phänomen wollte dann später doch untersucht werden. Also mal testweise den Editor "gedit" gestartet. Alle Menüpunkte vorhanden, aber im Menü "Bearbeiten" fehlte auch hier der Punkt "Einstellungen". Das gleiche auch in Rhythmbox - der Menüpunkt zum erreichen der Einstellungen fehlt ebenfalls.

Da mir so gar nicht danach war, diesen Fehler in den Untiefen des Systems zu suchen, habe ich kurzerhand die Installations-DVD heruntergeladen, die wenigen Daten, die noch nicht gesichert waren, gesichert und dann Ubuntu 14.04 neu installiert.

Das lief - wie nicht anders zu erwarten - problemlos und das neue System war jetzt wirklich einsatzbereit. Inklusive der Einstellungs-Menüs, die sind jetzt wieder vorhanden.

Die Neuinstallation ist für mich übrigens nicht weiter tragisch, da ich auf dem beruflich genutzten Laptop quasi ein "Vanilla-Ubuntu" (=keine Anpassungen) nutze. Ich habe zusätzlich nur ein paar Pakete aus den offiziellen Quellen (Apache, MySQL, CouchDB) und ein paar Python-Module installiert, sonst nichts. Und die Dateien im persönlichen Ordner (Musik, Code, Bilder, Dokumente für die Arbeit) werden so wie so regelmäßig gesichert.

Wer das gleiche Problem auch schon hatten und eine Lösung ohne Neuinstallation kennt, der kann dies gerne als Kommentar zu diesem Blogbeitrag posten.

Samstag, 18. Oktober 2014

Python: ListFlowables in ReportLab

ReportLab ist die wohl leistungsfähigste Bibliothek für Python, wenn es um das Erzeugen von PDF-Dateien geht. Von High-Level Zugriffen via Platypus (=Page Layout and Typography Using Scripts) bis zu Low-Level mit direktem Zugriff auf den Canvas bietet ReportLab alles.

Allerdings hat es doch bis zu ReportLab Version 2.6 (erschienen im Oktober 2012) gedauert, bis das direkte Erzeugen von nummerierten und unnummerierten Listen möglich war. Dies war zwar vorher prinzipiell auch möglich, aber nur über Umwege (z.B. bei unnummerierten Listen durch das manuelle hinzufügen eines Bullet Points vor dem Text).

Mit dem seit ReportLab 2.6 vorhandenen Flowable namens "ListFlowable" geht das aber wesentlich einfacher.

Neulich, bei der Überarbeitung eines meiner älteren Python-Skripte, welches auch ReportLab einsetzt, habe ich auch auf diese Flowable umgestellt.

Da die Doku von ReportLab zu diesem Thema - leider - etwas dünn ist, habe ich hier in diesem Blogebeitrag mal ein paar Sachen dazu aufgeschrieben.

Grundsätzlich ist die Sache recht simpel. Nach dem Import der benötigten Module erstellt man ein ListFlowable, welches die Punkte der Liste als ListItems enthält. Der Quelltext für eine Liste mit drei Punkten sieht so aus:

from reportlab.lib.styles import getSampleStyleSheet
from reportlab.lib.pagesizes import A4
from reportlab.platypus import Paragraph, SimpleDocTemplate, ListFlowable, \
                               ListItem

styles = getSampleStyleSheet()
style = styles['Normal']
story = []

t1 = ListFlowable([ListItem(Paragraph('foo', style)),
                   ListItem(Paragraph('bar', style)),
                   ListItem(Paragraph('spamegg', style))])
story.append(t1)
doc = SimpleDocTemplate('testdoc.pdf', size=A4)
doc.build(story)

So wird eine nummerierte Liste erzeugt, der Standard des ListFlowables, wenn keine weiteren Vorgaben gemacht werden.

Möchte man eine unnummerierte Liste erzeugen, muss dem ListFlowable das Argument bulletType und start mitgegeben werden:

t1 = ListFlowable([ListItem(Paragraph('foo', style)),
                   ListItem(Paragraph('bar', style)),
                   ListItem(Paragraph('spamegg', style))],
                   bulletType='bullet',
                   start='circle')

Möchte man statt Kreisen als Bullet Points z.B. Quadrate haben, dann ersetzt man einfach start='circle' durch start='square'.

Wer aus den obigen Beispielen ein PDF generiert wird feststellen, dass sowohl die Zahl als auch die Bullet Points ziemlich groß sind, größer als der Text, formatiert mit dem Beispiel-Stylesheet aus ReportLab. Fügt man noch das Argument bulletFontSize hinzu, gefolgt von der gewünschten Schriftgröße (also z.B. bulletFontSize=8), dann werden Schrift bzw. Bullet Points in der angegebenen Schriftgröße dargestellt.
Alternativ kann man für unnummerierten Listen auch folgendes angeben: start='bulletchar'. Dann wird als Zeichen standardmäßig ein kleiner Punkt (HTML: ·) verwendet.

Bei nummerierten Listen kann aber ReportLab aber nicht nur mit "normalen" Zahlen zählen, sondern auch:
bulletType='i' # römische Zahlen
bulletType='a' # Zählung: a, b , c, ...
bulletType='A' # Zählung: A, B, C, ...

Mit dem Argument start kann  man den Beginn der Zählung bei nummerierten Listen den Beginn der Zahlung festlegen. bulletType='A', start='10' würde z..B. die Zählung der Liste bei J starten lassen.

Weiterhin werden standardmäßig alle Listen linksbündig ausgerichtet. Möchte man die Listen gegenüber dem Text etwas einrücken, dann muss man die für die Aufzählungszeichen und den zugehörigen Text separat machen, wie z.B.:

p1 = Paragraph('etwas Text', style)
t1 = ListFlowable([ListItem(Paragraph('foo', style), leftIndent=25),
                   ListItem(Paragraph('bar', style), leftIndent=25),
                   ListItem(Paragraph('spamegg', style),leftIndent=25)],
                   bulletType='bullet',
                   start='bulletchar',
                   leftIdent=10)
story.append(p1)
story.append(t1)
story.append(p1)

Und das ListFlowable kann natürlich auch verschachtelt werden, für verschachtelte Liste. Eine Liste mit zwei Ebenen sieht z.B. so aus:

t1 = ListFlowable([ListItem(Paragraph('foo', style)),
                   ListItem(Paragraph('bar', style)),
                   ListFlowable([ListItem(Paragraph('spam', style)),
                                 ListItem(Paragraph('egg', style))],
                                 bulletType='a'),
                   ListItem(Paragraph('more', style))])

Ein paar weiter Tipps zum ListFlowable und dessen Formatierungsmöglichkeiten gibt es auch in einem Thread bei stackoverflow.