Springe zum Hauptinhalt

NoN: Fortschritte und Release

Knights of Ni - little release on the prairie

Der GTK+-Desktop-Client für den statischen Webseitengenerators Nikola hat seit der letzten Erwähnung hier weitere Fortschritte machen können.

Da Nikola v8 im Juni zu erwarten ist und ich noch nicht weiß, was an Nacharbeiten auf mich zukommt, habe ich den aktuellen Status als Release gespeichert.

Neuigkeiten

Headerbar

Das Untermenü ist auf die rechte Seite gewandert, links befindet sich der GUI-/Terminal-StackSwitcher, neu ist der Button zum Öffnen des Nikola-Handbuchs.

Erweiterte Deployment-Optionen
  • GitLab: "Deploy to GitHub"-Button nutzen, Hilfe zur Konfiguration gibt es hier

  • Andere: existiert in der conf.py die Variable. DEPLOY_COMMANDS, wird mit dem "Deploy"-Button das 'default'-Preset ausgeführt.

GtkApplication

NoN läuft nun als echte GtkApplication.

Desktop-Eintrag

Enteenteenteente...

Post/Page im Browser öffnen

Per Rechtsklick lässt sich aus der Übersicht der Beitrag im Browser öffnen.

Diverser Kleinkram

Bugfixes, verbessertes Logging, Python-Code ist nun PEP8-konform (sagt pycodestyle).

/images/non/non3.thumbnail.png

Überarbeitete Oberfläche in Glade 3.22

Im Zuge der Veröffentlichung von GNOME 3.28 wurde auch Glade eine ordentliche Portion Zuwendung zuteil.

Headerbar

Das in GNOME 3.10 (Veröffentlichung 2013) eingeführte Headerbar-Widget ließ sich selbst bereits in Glade verwenden, die Anwendung selbst nutzte sie bisher nicht. Sie vereint Titelleiste, Menü, Toolbar und die Projekt-Tableiste. Durch diese Komprimierung wird viel leerer Raum eingespart (siehe Screenshots).

Arbeitsfläche

Die Dreiteilung der Oberfläche ist erhalten geblieben, es gibt aber zwei wesentliche Änderungen:

  1. Die Widgetauswahl erfolgt nicht mehr aus der linken Spalte, sondern sie ist oben auf der mittleren Arbeitsfläche als Buttonleiste mit Dropdown-Menü erreichbar.

  2. In der nun freien Spalte werden die Widgetstruktur des aktuellen Projekts angezeigt. Diese war zuvor in der oberen Hälfte der rechten Spalte zu finden.

Die Verlagerung der Widgetauswahl ermöglicht eine komplette Nutzung des vertikalen Platzes für die Anzeige der Struktur auf der linken sowie deren Eigenschaften auf der rechten Seite.

Tour

Beim ersten Aufruf der neuen Version startet ein Assistent, der etwas aufdringlich die Neuerungen anpreist. Dieser kann jederzeit über die Einstellungen in der Headerbar unter "Einführung in interaktive Benutzeroberflächen" erneut aufgerufen werden.

/images/glade322_tour.png

Tour-Wizard

Screenshots

/images/glade322.thumbnail.png

Glade 3.22

/images/01_glade.thumbnail.png

Glade 3.20

Nikola: everything zen

[UPDATE] Artikel wurde aktualisiert, keine manuelle Installation mehr notwendig

Aktualisiertes zen-Thema für Nikola

Ein Nachteil von Nikola ist meiner Meinung nach die stiefmütterliche Behandlung der Themes. Das von mir genutzte zen-Thema hatte ich bereits vor einiger Zeit auf Font Awesome 4-Icons geupdated und hier als Archiv zum Download bereitgestellt.

Inzwischen gibt es nicht nur Version 5 von Font Awesome, sondern auch einen Fork des Projektes namens Fork Awesome mit ein paar neuen Icons.

Dank eines Kommentars einer der Nikola-Devs (thx Roberto) hier habe ich mich nun durchgerungen, meine Änderungen offiziell per Pull Request einzureichen. Die zen-Familie ist nun auch im offiziellen Repository auf Font Awesome v4.7.0 geupdatet. Außerdem gibt es eine neue Variante, die die Fork Awesome-Icons nutzt. Eine manuelle Installation erübrigt sich also, sie kann direkt im Nikola-Projektordner erfolgen:

$ nikola theme -i zen-forkawesome

Anschließend muss das Thema nur noch in der conf.py aktiviert werden:

THEME = "zen-forkawesome"

Desweiteren werden die Icons nun mit "fa fa-iconname" angesprochen statt zuvor mit "icon-iconname". Dies ist auch in conf.py.sample vermerkt und wird bei der Installation des Themas angezeigt.

Die Änderungen werden natürlich erst nach dem nächsten nikola build wirksam. Da zen-forkawesome auf zen basiert, wird dieses Thema automatisch mit installiert.

Kivy: Starter-Paket

Kivy ist ein plattformunabhängiges GUI-Toolkit, mit dem man Python-Programme erstellen kann, die auf Linux, Windows, Mac und mobilen Plattformen (iOS, Android) laufen - die reptiloide eierlegende Wollmilchsau sozusagen.

Für mein nächstes kleines Vorhaben werde ich darauf zurückgreifen, deshalb gibt es hier das kleine Link-Starterpaket:

Videos

Empfehlenswert sind auch die folgenden Videoreihen:

Neu: der Kettlebattle-Generator

Der Kettlebattle-Generator - eine kleine Flask-App für die großen Muskelpartien

/images/kbgen.thumbnail.png

Kettle...was?

Genau. Okay, du weißt nicht, was Kettlebattle ist, kein Problem. Die Menschen, die diesem Unsinn nachgehen, dürften sich zahlenmäßig aktuell im einstelligen Bereich bewegen (Stand: Januar 2018).

Kettlebattle ist ein kollaboratives Kettlebell-Home-Workout ab zwei Mitspielern.

Die Frontlinie der "Battle" verläuft dabei nicht zwischen den Mitspielern, sondern zwischen Motivation, Schweinehund, Sofa und Hanteln. Team up!

Spielregeln

  1. Die Kontaktaufnahme

    Der potentielle Mitspieler wird mit "Kettlebattle?" kontaktiert.

  2. Der Workout-Vorschlag

    Hat der Mitspieler die Kontaktaufnahme positiv beantwortet, schlägt der Initiator ein Workout vor, das der Mitspieler akzeptieren muss. Fairness geht vor. Wer nach einem langen Tag mitten in der Nacht seinem Mitspieler ein hartes Workout vorschlägt, hat schnell keine Mitspieler mehr.

  3. Do you even lift?

    Do it.

  4. Das Finisher-Selfie

    Der krönende Abschluss jeder Kettlebattle ist das Finisher-Foto, das man dem Mitspieler nach dem Workout als Beweis seiner Sportlichkeit zuschickt. Hierbei ist absolute Ernsthaftigkeit zu wahren, es geht hier schließlich um Kettlebattle!

Der Generator

Der Kettlebattle-Generator ist eine Einseiten-Web-App, mit der sich aus einem zuvor definierten Übungspool ein Workout generieren lässt.

Habenwill!

  • für die Ausführung wird Flask benötigt

  • Download und Entpacken des Quellcodes von GitHub

  • kbgen.py ausführen, dies startet den internen Flask-Server

  • 127.0.0.1:5000 aufrufen

  • Workout generieren

  • Werte können per Spinner geändert werden

Konfiguration

In der kbgen.py gibt es 3 Variablen für individuelle Einstellungen:

  1. `REPS_PRESET`: Tupel mit 2 Werten (int) für die Preset-Buttons, Gesamtwiederholungen

  2. `KB_EX`: Liste von Übungen, die bei der Kettlebattle zur Auswahl stehen sollen, ein Listeneintrag ist ein Tupel nach dem Muster (Name, Minimum bei Preset 1, Minimum bei Preset 2)

  3. `MAX_EX`: Maximale Anzahl (int) von Übungen, die aus der Liste durchgeführt werden sollen, Minimumwerte werden immer gezählt

Verweise

Pläne für später?

  • Export in Textbildchen (leben wir nicht in tollen Zeiten?)

  • Favoritenliste/Liste der letzten Kettlebattles

  • Lokalisation

Zugegeben, darauf hat die Welt nicht gerade gewartet. Aber nun ist es irgendwie trotzdem da. Willkommen!


Kommentieren auf

Texteditor mit GtkSourceView

Text-Widget mit GtkSourceView

GTK+ bietet mit Gtk.TextView ein Widget zum Anzeigen und Bearbeiten von Text/-dateien an. Wie beim TreeView-Widget werden die Daten (model) und die Anzeige (view) getrennt voneinander gehandhabt. Das datentragende Modell zu TextView ist TextBuffer.

GtkSourceView ist eine Erweiterung und Unterklasse von TextView, die Syntaxhighlighting, Farbschemata, Laden/Speichern, Vervollständigung und andere Funktionen unterstützt.

Im Beispiel wird ein Editor ergestellt, der bestimmte Dateien laden und speichern kann, sowie eine rudimentäre Suchfunktion und ein Widget zum Farbschemawechseln bereitstellt.

/images/22_editor_gtksv.thumbnail.png

Glade

GtkSourceView

Die SourceView-Widgets befinden sich unterhalb einer eigenen gleichnamigen Hauptkategorie in der Seitenleiste.

  • GtkSourceView: das eigentliche Editorwidget, das in einem ScrolledWindow platziert wird

  • GtkSourceMap: Miniaturansicht und Unterklasse von SourceView

  • GtkSourceStyleSchemeChooserWidget: Widget zur Auswahl eines StyleSchemes

In Glade lassen sich bereits viele Eigenschaften des Editorbereichs festlegen wie die Anzeige der Zeilennummern, Einrückung, Umbruchverhalten usw., die sich natürlich auch über set_property festlegen oder ändern lassen.

Beim StyleChooser-Widget wird das Signal button-release-event belegt, um das ausgewählte StyleScheme auf die SourceView-Widgets anzuwenden.

SourceMap

Das Widget muss mit der anzuzeigenden Quelle, einem SourceView-Widget, verknüpft werden (über "Allgemein > View"). Es wird dann der Inhalt des SourceView-Widgets verkleinert (standardmäßig mit Schriftgröße in 1pt) angezeigt. Durch scrollen in SourceMap verändert man gleichzeitig die Anzeige in SourceView.

Headerbar

Die Headerbar enthält verschiedene Buttons zum Laden, Suchen und Speichern:

  • "Python file" und "Glade file" laden die entsprechenden Dateien dieses Beispieles in den Editor (Signal clicked)

  • Die Sucheingabe ist ein Gtk.SearchEntry-Widget (Signale search-changed und activate)

  • "Save .bak" und "Save" speichern die Dateien (Signal clicked)

Python

SourceView

Initialisierung

Widgets, die nicht zum Gtk-Modul gehören, müssen zunächst als initialisiert werden (siehe auch Vte-Terminal):

GObject.type_register(GtkSource.View)

Das SourceView-Widget besitzt bereits einen integrierten Textbuffer, welcher mit get_buffer abgefragt werden kann:

self.buffer = self.view.get_buffer()

Desweiteren werden noch Objekte zum Laden und Speichern von Dateien sowie fürs Syntaxhighlighting benötigt:

self.sourcefile = GtkSource.File()
self.lang_manager = GtkSource.LanguageManager()

Datei laden

Die zu öffnende Datei muss dem GtkSource.File-Objekt im Gio.File-Format und anschließend an GtkSource.FileLoader übergeben werden. Die Information zum Syntaxhighlighting erhält der Buffer:

sourcefile.set_location(Gio.File.new_for_path("file"))
buffer.set_language(self.lang_manager.get_language("language"))
loader = GtkSource.FileLoader.new(buffer, sourcefile)
loader.load_async(0, None, None, None, None, None)

Datei speichern

Analog zum Laden erfolgt das Speichern mit GtkSource.FileSaver. Im Beispiel speichert der "Save"-Button die bestehende Datei (es erfolgt keine "Überschreiben?"-Sicherheitsabfrage) und der "Save .bak"-Button speichert den Inhalt als neue Datei mit genannter Endung ab. Die Übergabe der Dateien erfolgt wie beim Laden Gio.File-formatiert:

# bestehende Datei überschreiben
saver = GtkSource.FileSaver.new(buffer, sourcefile)
# Datei unter anderem Namen speichern
saver = GtkSource.FileSaver.new_with_target(buffer, sourcefile, targetfile)
# Speichern ausführen
saver.save_async(0, None, None, None, None, None)

Text hervorheben

Zunächst ist festzustellen, dass es sich bei den Funktionen suchen(/ersetzen)/markieren und Texthervorhebungen um zwei getrennt voneinander auszuführenden Mechanismen handelt, für die GtkSource.Settings eingerichtet werden müssen:

settings = GtkSource.SearchSettings()
search_context = GtkSource.SearchContext.new(buffer, settings)

Alle Vorkommen eines Strings im TextView lassen sich auf zwei Arten visualisieren, einer naheliegenden und einer eleganten.

Die naheliegende Lösung ist die Ausführung von settings.get_search_text bei der Eingabe von Text in das Suchfeld (Signal search-changed):

Die andere Möglichkeit, bei der kein Signal benötigt wird, ist die direkte Anbindung der SearchSettings-Eigenschaft "search-text" an das Sucheingabefeld:

builder.get_object("search_entry").bind_property('text', settings, 'search-text')

Text markieren

GtkSource.SearchContext wird für die Suchen-/Ersetzen-Funktion innerhalb eines GtkSource.Buffer verwendet. Dieser wurde bereits mit den SearchSettings initialisiert.

Die Markierungsfunktionen und Cursorplatzierung erbt GtkSource.Buffer von Gtk.TextBuffer, die Suche wird mit SeachContexts forward2 ausgeführt.

def find_text(self, start_offset=1):
    buf = self.buffer
    insert = buf.get_iter_at_mark(buf.get_insert())
    start, end = buf.get_bounds()
    insert.forward_chars(start_offset)
    match, start_iter, end_iter, wrapped = self.search_context.forward2(insert)

    if match:
        buf.place_cursor(start_iter)
        buf.move_mark(buf.get_selection_bound(), end_iter)
        self.view.scroll_to_mark(buf.get_insert(), 0.25, True, 0.5, 0.5)
        return True
    else:
        buf.place_cursor(buf.get_iter_at_mark(buf.get_insert()))

Durch die Signalbindung von activate im Suchfeld wird die Suche durch Drücken der Eingabetaste an der letzten Position fortgeführt. Für eine Rückwärtssuche muss analog zu forward2 oder forward_async backward2 oder backward_async verwendet werden.

StyleChooser

Das Widget zeigt die verfügbaren Stile an. Es ist nicht möglich, lokale Stile anzugeben oder sie zu verändern.

Der angewählte Style lässt sich dann einfach auf den gewünschten Buffer anwenden:

def on_signal_emitted(self, widget, event):
    buffer.set_style_scheme(widget.get_style_scheme())
/images/22_editor_gtksv.gif

Das Geheimnis der Sphinx

Ob ich die Tutorial-Artikel nicht als E-Book zusammenfassen könnte, wurde ich gefragt. Ich kann.

Folgt mir auf meiner abenteuerlichen und actiongeladenen Reise, in dem mit Kanonen auf Spatzen geschossen wird und ich den Geheimnissen der rätselhaften Sphinx auf die Spur komme.

/images/sph_cover.thumbnail.jpeg

Vorüberlegungen

Die GitHub-Page läuft mit dem statischen Seitengenerator Nikola, die standardmäßig reStructuredText-Quelldateien parst. Da kommt ein Dokumentationstool, das diese ebenso verarbeiten kann und die Ausgabe in verschiedene Formate ermöglicht, absolut gelegen. All das bietet Sphinx.

Die naheliegende, sich aber möglicherweise als naiv herausstellende, Überlegung war nun, die bestehenden Blogartikelquelldateien so vorzubereiten, dass sich mit wenig Aufwand gewünschte Ausgabeformate immer wieder neu generieren lassen.

Sphinx bietet Builder für

  • EPUB, dem offenen E-Book-Standard, nativ von allen E-Reader-Fabrikaten außer den Kindles unterstützt

  • PDF, das per LaTeX (verschiedene Engines verfügbar) erzeugt wird

Sphinx

Initialisierung

Nach der Installation erstellt man das Projektverzeichnis und initialisiert mit

$ sphinx-quickstart

das Grundgerüst. Fast alle Fragen können auf der Voreinstellung belassen werden. Im Projektverzeichnis befindet sich nun die Konfigurationsdatei conf.py sowie das Root-Dokument index.rst.

Die Dateien lassen sich nach dem Muster make Builder erzeugen, die in den Unterverzeichnissen _build/builder befinden:

$ make epub
$ make latexpdf

conf.py

Epub

#HTML-Dateien vor dem Inhalt der index.rst einfügen
epub_pre_files = [('info.xhtml', 'Info')]
html_additional_pages = {'info': 'info.html'}

#Titel erzeugen
epub_cover = ('_static/cover.png', 'epub-cover.html')

#Stichwortverzeichnis auslassen
epub_use_index = False

#Bezeichnung der Ausgabedatei
epub_basename = output_basename

#für die Generierung der info.xhtml benötigt, da sonst None
html_last_updated_fmt = '%d. %B %Y'

LaTeX

Für die PDF-Ausgabe müssen eine Reihe von TeXLive-Paketen installiert sein (siehe Dokumentation). Als Alternativen seien an dieser Stelle das in Calibre integrierte Konvertierungstool ebook-convert und epub2pdf genannt.

#Papierformat (Standard ist US-Letter), leere Seiten vermeiden
latex_elements = {
    'papersize': 'a4paper',
    'classoptions': 'oneside,openany'
}

#Logo auf der Titelseite
latex_logo = '_static/logo.png'

Sonstiges

Pygments

Syntax-Highlighting, ebenfalls von Nikola unterstützt, hier wie dort bevorzuge ich das Theme "borland".

Bezeichnung der Ausgabedatei

Der Dateiname lässt sich für die verschiedenen Builder jeweils festlegen. Um für alle verwendeten Builder jeweils die gleiche Bezeichnung zu nutzen, verwende ich hier die eigene Variable output_basename. Diese wird demzufolge nicht von Sphinx unterstützt und nur innerhalb der conf.py verwendet (in den Variablen htmlhelp_basename, latex_documents, texinfo_documents, epub_basename).

pygments_style = 'borland'
output_basename = 'gladepytutorial'

_static

In diesem Ordner befinden sich Stylesheets, Bilder und Skripte, die nach den vorgegebenen Dateien geladen werden. So kann man lokale individuelle Stylesheet-Anpassungen vornehmen, ohne das Theme selbst zu modifizieren. Hier befinden sich eine angepasste pygments.css, cover.png (Epub) und logo.png (PDF).

_templates

Analog zu _static befinden sich hier individuelle Templates. Diese werden standardmäßig mit der Template-Engine Jinja2 betrieben. Hier befindet sich info.html, die in der Epub-Ausgabe Verwendung findet.

Epub: zusätzliche Dateien einfügen

Sphinx bietet mit epub_pre_files (und analog epub_post_files) die Option, zusätzliche und nicht zur eigentlichen Dokumentation gehörenden (X)HTML-Dateien zum Epub hinzuzufügen. Diese müssen allerdings zunächst als zusätzliche HTML-Seiten generiert werden. Dafür wird in der conf.py die Variable html_additional_pages entsprechend gesetzt 1.

1

Es hat mich einen (EINEN!) Tag gekostet dies herauszufinden...

index.rst

Dies ist das Hauptdokument, das von jedem Sphinx-Builder geparst wird. Die Bezeichnung wird in der conf.py in der Variable master_doc festgelegt.

Als reguläre reST-Datei kann sie beliebig viel Inhalt aufnehmen. Es ist allerdings zu empfehlen und im Normalfall vermutlich sowieso bereits der Fall, das Dokument in mehrere Dateien aufzuteilen. Sphinx stellt dafür die eigene toctree-Directive zur Verfügung.

.. toctree::
    :maxdepth: 1
    :numbered:
    :caption: Inhalt

    teildokument1
    teildokument2
    ...

Dateien außerhalb von toctree werden per include-Directive hinzugefügt.

Es ist auch möglich, Inhalte nur von bestimmten Buildern berücksichtigen zu lassen:

.. only:: latex

    .. include:: info.rst

Bonus: Mobi

"Ich habe doch einen Kindle und hätte auch gern so ein E-Book!"

Aber klar doch.

KindleGen

Amazon möchte zwar keine Epubs 2 unterstützen, aber sie bieten mit KindleGen ein Tool an, welches diese in die eigenen Formate (KF8, Mobi) überführt.

Auf diese Weise lässt sich mit

$ kindlegen input.epub

eine Mobi-Datei erzeugen.

2

oder Google-Apps...

Problem: Encoding

Das aus dem Epub erstellte E-Book im Mobi-Format hat ein Darstellungsproblem mit einigen (Sonder-)Zeichen.

Abhilfe schafft hier die Zeile

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

an Stelle von

<meta charset="utf-8" />

innerhalb des HTML-Heads. Sphinx bietet dafür die meta-Directive, die allerdings für jede Datei gesetzt werden muss:

.. meta::
    :http-equiv=Content-Type: text/html; charset=UTF-8

Nikola

Das Resultat des ersten Durchlaufs von Sphinx mit der Übersichtsseite und drei Artikeln lässt vorsichtig optimistisch werden. Trotzdem gibt es an diversen Stellen Optimierungsbedarf:

  1. Die Nikola-eigenen Kurzverweise (slug) funktionieren nicht und erfordern eine Konvertierung in ":ref:"erenz.

  2. Die Artikelüberschrift ist kein Gliederungselement und fehlt demzufolge im Inhaltsverzeichnis

  3. Nikola-eigene Directives verursachen Fehler. Konvertierung von

    • thumbnail -> figure

    • listings -> literalinclude

  4. relative Pfade in image-Directives anpassen

  5. Animierte GIFs ignorieren (erzeugen Fehler im LaTeX-Durchlauf, aber nicht im Epub)

  6. Inhaltsverzeichnisse in den Artikel überflüssig

  7. "Kommentieren auf G+"-Button entfernen

  8. Für die Generierung der Mobi-Datei muss jede Datei eine Meta-Anweisung erhalten

Für eine zufriedenstellende Ausgabe ist es also erforderlich, die Ausgangsdateien hinsichtlich dieser Punkte per Skript zu modifizieren.

Automatisierung

Das ist er, der Elefant im Raum.

Sphinx läuft und die index.rst ist eingerichtet. Die Mission besteht nun aus folgenden Teilaufgaben:

  1. Sphinx soll sich der aktuellen Dateien der GitHub-Page bedienen.

  2. Diese Dateien sollen gemäß der oben genannten Punkte bearbeitet werden.

  3. Sphinx soll ein Epub und ein PDF erzeugen.

  4. KindleGen soll ein Mobi erzeugen.

  5. Die Dateien sollen im entsprechenden Ordner im GitHub Page-Verzeichnis abgelegt und deployt werden.

Let's do this.

Die diffizile Arbeit ist bereits erledigt: die Einrichtung von Sphinx und die Problemerfassung. Das Skript selbst arbeitet nun die oben genannten Punkte ab. Weiterhin gibt es der Übersichtlichkeit halber zwei weitere Dateien. Es befinden sich nun im Sphinx-Projektverzeichnis folgende neue Dateien:

  1. nibook.py: sammelt, kopiert, bearbeitet die Quelldateien, erstellt die E-Books und füttert die GitHub-Page (Code)

  1. index.lst: Liste von Dateinamen (ohne Endung), die im Dokument enthalten sein sollen

übersicht
artikel1
artikel2
artikel5
  1. index.tmpl: aus dieser und der index.lst wird die index.rst generiert

.. generated by nibook, posts will be inserted after ".. include-start"

.. some text documentation master file, created by
   sphinx-quickstart on Thu Oct 26 20:26:54 2017.
   You can adapt this file completely to your liking, but it should at least
   contain the root `toctree` directive.

.. meta::
   :http-equiv=Content-Type: text/html; charset=UTF-8

.. only:: latex

    .. include:: info.rst

****************************
Glade-Tutorial mit PyGObject
****************************

.. toctree::
    :maxdepth: 1
    :numbered:
    :caption: Inhalt
    :name: mastertoc

    .. include-start

Fazit

Wieder was gelernt.


Kommentare bei

Neue Widgets in alten Glade-Dateien

Problem: deaktivierte Widgets in älteren Glade-Dateien

Es kann vorkommen, dass nach dem Öffnen einer Datei in Glade Widgets ausgegraut sind.

/images/glade_widgetsinactive.thumbnail.png

Per Tooltip wird dann zum Beispiel angezeigt:

/images/glade_widgetsinactive_tooltip.thumbnail.png

Die Ursache liegt in der angegebenen Gtk+-Version gleich am Anfang der Glade-Datei:

<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.1 -->
<interface>
  <requires lib="gtk+" version="3.0"/>
  ...

Dieses Zeile wird auch beim neuerlichen Speichern mit einer aktuellen Glade-Version nicht verändert. Abhilfe kann hier ganz simpel geschaffen werden, indem "3.0" durch eine aktuellere Version ersetzt wird (derzeit "3.20").

BeeLine - weiterfahren lohnt sich

Der Navigationskompass BeeLine im weiteren Test

Dies ist die Fortsetzung zu meinem einführenden Artikel zu BeeLine.

It's alive!

BeeLine lebt. Es gibt tolle Fortschritte bei der Entwicklung. Fast könnte man meinen, sie hätten meinen ersten Artikel dazu gelesen, denn die unter "Verbesserungspotential" aufgezählten Punkte wurden nahezu vollständig umgesetzt.

Ein weiterer positiver Punkt bei BeeLine ist die Kommunikation. Einer direkten Ansprache über Twitter wegen konkreter Probleme/Bugs folgte ein weiterer Austausch per Mail mit der Aussicht auf baldige Problembehebung. Am selben Tag.

Es mag seltsam klingen, aber es wirkt sich durchaus positiv auf die Einstellung gegenüber Firmen und Produkten aus, wenn man den Leuten den Eindruck verschafft, dass dahinter tatsächlich Menschen stecken...(ja, ich schaue dich an, Google).

Verbesserungen

Die vier großen Kritikpunkte aus meinem ersten Artikel sind:

  1. fehlende Praktikabilität in der Handhabung von Wegpunkten

  2. versehentliche Beendigung von Fahrten

  3. undurchsichtige Belegung der Bedienelemente

  4. Wunsch nach besserer Routenfunktionalität (Import)

Wegpunkte

Manuelles Blättern

Durch die Wegpunkte einer Route lässt sich nun mit den N/S-Tasten blättern. Ein Druck auf die obere Taste blättert weiter, die untere zurück. Gelangt man an den letzten Wegpunkt, wird nach Bestätigung der Frage "Finished?" die Fahrt beendet.

An welchem Wegpunkt man sich befindet, sieht man auch weiterhin nicht auf dem BeeLine, wohl aber in der App.

/images/BeeLine/app_waypoint.png

App: Wegpunkteanzeige

Automatische Wegpunkteführung

In den Einstellungen lässt sich unter "Automatic Waypoint" einstellen, dass beim Passieren eines Wegpunktes automatisch der nächste angewählt wird.

Der nächste Wegpunkt wird aktiviert, wenn man sich weniger als 100 Meter dem aktuellen Wegpunkt nähert. Bleibt man weiter weg oder entfernt sich wieder, fährt zum Beispiel weit um einen Wegpunkt herum, bleibt BeeLine immer auf diesen aktivierten Wegpunkt fixiert, auch wenn bereits andere Wegpunkte näher sind.

Bei automatischer Wegpunktführung kann man aber weiterhin manuell per Tasten durch die Wegpunkte scrollen.

Diese Funktion halte ich für ein absolutes Killerfeature, denn es präzisiert die Routenführung, bleibt aber dabei unaufdringlich.

Belegung der Bedienelemente

Wie bereits erwähnt, blättert man mit der oberen und unteren Taste durch die Wegpunkte. Ein längerer Druck auf die untere Taste schaltet die integrierte Beleuchtung an oder ab. Die Tasten rechts und links blättern jeweils durch folgende Anzeigen:

Kompass <-> Geschwindigkeit <-> Uhrzeit <-> Akkuladezustand (Phone und BeeLine) <-> Kompass

Es ist mir auch nicht mehr passiert, Fahrten unbeabsichtigt beendet zu haben. Dieses Problem (Punkt 2), ob nun Bedienfehler oder tatsächlich Bug, scheint sich also auch erledigt zu haben.

Routenimport (whoop, whoop)

Eine Route lässt sich nun nicht mehr nur direkt in der BeeLine-App erstellen, sondern auch als GPX-Datei importieren. Dabei wird der Track vereinfacht und (größere) Richtungsänderungen mit Wegpunkten markiert. Die Strecken zwischen den Wegpunkten sind immer in Luftlinie (beeline) dargestellt.

/images/BeeLine/route_import.png

Links: importierte vereinfachte Route mit Wegpunkten. Rechts: Anzeige des GPS-Tracks in Locus-App

Anhand der Screenshots sieht man, dass das ziemlich gut funktioniert. So kann man für relevante Streckendetails (wichtige Richtungsänderungen an Kreuzungen, Brücken) Wegpunkte setzen, ohne komplett auf eine bestimmte Streckenführung fixiert zu sein oder auf der anderen Seite in Sackgassen zu landen.

/images/BeeLine/waypoint_route.png

Wenige Wegpunkte reichen zur Skizzierung der Strecke aus

Wünsch dir was

Ich möchte an dieser Stelle nicht in den Verdacht geraten, dass dies ein gekaufter Artikel sei, also habe ich natürlich auch wieder eine Rubrik für Kritik reserviert. Also dann:

Routen in umgekehrter Reihenfolge abfahren

Eine Option, die Richtung einer Route zu bestimmen, wäre praktisch.

Wegpunkte-Fortschritt

Es wäre cool, wenn wie in der App angezeigt würde, auf welchen Wegpunkt man sich gerade zubewegt. Ja, ich weiß, dass dies nichts über Entfernungen aussagt.

Fahrt pausieren

Eine Funktion zum Pausieren, aber nicht Beenden der Fahrt könnte sowohl bei größeren Touren (Fortsetzen an letztem Wegpunkt) als auch beim spontanen Stopp am Supermarkt (tatsächliche Durchschnittsgeschwindigkeit) hilfreich.

Kalibrierung

Wir hassen es alle: das Hufeisensymbol auf dem BeeLine - Lenker rechts, Lenker links, Vorderrad hoch und das Ganze noch einmal. Mit dem Rennrad eine Kleinigkeit, mit Gepäck am Tourenrad eine Qual.

Ich habe dazu keinen wirklich konstruktiven Vorschlag. Vielleicht reichte es ja bereits aus, die Empfindlichkeitsschwelle zu erhöhen, denn häufig erscheint das Symbol auch während der Fahrt und verschwindet dann nach kurzer Zeit wieder. Ich ignoriere es inzwischen weitgehend.

Me vs. me

  1. Ich fahre häufig die selben Routen.

  2. Jeder mag Statistiken.

Ich hätte gern eine Übersicht, wie häufig ich Routen gefahren bin, wie weit und lange und schnell ich dabei unterwegs war.

Fazit

BeeLine hat sich sehr postitiv entwickelt und ich werde es wieder häufiger benutzen. Die Ausweitung der Funktionalität rund um Routen - erstellen, importieren, speichern, Wegpunkteführung - macht das Gerät inzwischen zu einem interessanten Tool und mehr als einem bloßem Spielzeug.

Da BeeLine aber auf die Verbindung mit einem Smartphone angewiesen ist, das Standortfunktion und Bluetooth bereitstellt, ist es kein Ersatz für ein Standalone-Navigationsgerät. Bei längeren Fahrten muss man auf jeden Fall den Akkuverbrauch berücksichtigen. Powerbanks existieren.


Kommentieren auf

Stacks und Notebooks

Inhalte organisiert anzeigen

Gtk.Stack und Gtk.Notebook sind Layout-Container, die ihrerseits beliebige Widgets enthalten können.

Ein Notebook stellt ein mehrseitiges Layout mit klassischer Tab-Funktionalität zur Verfügung. Stacks bieten die gleiche Grundfunktionalität, nämlich mehrere Container innerhalb eines Widgets zu enthalten, zwischen denen man hin- und herschalten kann.

Der Hauptunterschied besteht darin, dass das Bedienelement des Stacks als separates Widget verwendet werden muss (Gtk.StackSwitcher). Verschiedene Stackswitcher können dabei auf den selben Stack zugreifen. Weiterhin lassen sich Stackswitcher in Headerbars platzieren, außerdem werden animierte Überblenden zwischen den Stack-Seiten unterstützt.

Stacks passen sich subjektiv besser in die GNOME-Umgebung ein, bieten aber nicht ganz so große Funktionalität wie Notebooks.

Das Beispiel enhält ein Fenster mit Stack, in dessen dritter Seite ein Notebook enthalten ist, das verschiedene Webseiten anzeigt.

/images/21_stacknotebook.thumbnail.png

Glade

Stack

Ein Stack, zu finden in der Sidebar unter "Container", und dessen Unterseiten lassen sich einfach in Glade erstellen und bearbeiten. Als Unterwidgets kommen im Beispiel Gtk.Image, Vte.Terminal und Gtk.Notebook zum Einsatz.

Das Stackswitcher-Widget befindet sich unter "Steuerung und Anzeige" und wird der Headerbar hinzugefügt. Es kann aber auch in reguläre Container-Widgets wie einer Box platziert und die Unterseiten horizontal oder vertikal angezeigt werden. Unter "Allgemein > Stapel" wird der Stack ausgewählt, auf den sich das Widget beziehen soll. Die anzuzeigende Seitenbezeichnung wird im jeweiligen Stack-Unterwidget unter "Packen > Titel" festgelegt. Dies funktioniert aber erst, nachdem einer Unterseite ein Widget hinzugefügt wurde. Standardmäßig ist dies zunächst leer.

Notebook

Das Notebook findet sich ebenfalls unter "Container". Die Steuerungseinheit des Tabs ist ein bei Erstellung einer Seite generiertes Label-Child-Widget. Als Container-Widgets der Unterseiten werden hier Gtk.ScrolledWindows verwendet. Diese benötigt man auch z.B. für die Anzeige von (längeren) Tabellen (siehe auch Artikel zu List-/TreeStores Nr. 1 und Nr. 2).

Die Tab-Leiste des Notebooks bietet die Möglichkeit, sowohl am Anfang als auch am Ende ein Container-Widget bereitzustellen (unter "Allgemein > Start-Aktion/End-Aktion"), in dem zum Beispiel feste Buttons untergebracht werden können. Im Beispiel wird am Anfang ein "Home"-Button eingerichtet.

Python

Für das Umherschalten zwischen Stack-Unterseiten und Notebook-Tabs werden keine Signale benötigt. Im Beispiel werden nur zwei Signale benötigt, einmal für das Abfangen des "exit"-Kommandos innerhalb des Terminals und für den Button in der Notebook-Tableiste.

WebKit2

Die Darstellung von Webseiten wird im Beispiel von WebKit2 erledigt. Das zentrale Modul dabei ist WebKit2.WebView. Ein neues WebView-Objekt selbst ist bereits ein scrollbares Gtk+-Widget in einem Gtk.Viewport, muss also laut API-Referenz nicht mehr in ein Gtk.ScrolledWindow platziert werden. Dies funktionierte im Test zwar für Gtk.Stack, nicht aber für Gtk.Notebook, weshalb dort trotzdem als "Unterlage" ein ScrolledWindow-Widget verwendet wird.

Das WebView-Widget wird nach folgendem Muster erstellt:

# create new WebView widget
webview = WebKit2.WebView()
# send URL to widget
webview.load_uri("http://google.com")
# add webview to notebook
notebook.add(webview)
# add webview to stack
stack.add_titled(webview, name, "StackSwitcher title")

webview.show()

Weiterlesen…