Posts mit dem Label pyside werden angezeigt. Alle Posts anzeigen
Posts mit dem Label pyside werden angezeigt. Alle Posts anzeigen

Donnerstag, 18. Juli 2013

The way forward with Python on Qt 5 (with a bit of history)

As you have probably heard on Twitter from the official Jolla account, the first Jolla will ship with Wayland. In that discussion, some worries are brought up about Python support with Qt 5. Here are my personal thoughts of how I see mobile Python development moving forward with the new technology. So first some background information:

If you want to write Python applications on a mobile platform, you usually need some way to interface with the native graphical toolkit. On Maemo 4 and Maemo 5, this was done via PyGTK and some additional bindings for the Hildon UI elements. PyGTK is licensed under the terms of the GNU LGPL, so you could use it to develop open and closed source applications.

When MeeGo 1.2 Harmattan (the system running on the N9) came up, the toolkit with which third party application developers wrote their applications changed from Gtk to Qt (or to be more precise, QML). Just like pure Gtk didn't provide all the UI elements for mobile (and therefore Hildon was used on top of Gtk), pure QML provided very little, and so Qt Quick Components were used for the Harmattan user interface (that includes things like buttons, toolbars, menus, dialogs, etc...). These could only be used from QML, so you had to use QML if you wanted your application to look anything like native (ignoring the MeeGo Touch Framework here, as it wasn't really used for third party apps, with the notable exception of sociality-mtf).

With Qt and QML being the new toolkit of choice, Python developers needed a different "bridge" to go from the Python world to the toolkit world. PyQt already existed for some time then, it had two license options: GNU GPL (basically requiring all your code that uses PyQt to also become GPL'd) and commercial. As the Wikipedia article of PySide says, after Nokia failed to reach an agreement with Riverbank Computing (the developers of PyQt) to change the license to LGPL, they started their own Python bindings named "PySide", which are licensed under the terms of the GNU LGPL. There's a wiki page with PySide-PyQt differences on the Qt Wiki.

As MeeGo at Nokia was ramped down, the core team of PySide had less and less time to spend on improving it. PySide is still kept up to date (the latest release is from July 9, 2013), and it already supports Python 3, but nobody has yet ported it to Qt 5. The most recent post I found about PySide and Qt 5 from one of the core developers was from November 2011. For using Python with Qt 5, there are two possibilities at the moment: Use PyQt under the terms of the GNU GPL, or get a commercial PyQt license. Another option to get LGPL'd bindings would be to add support for Qt 5 to PySide, but that needs somebody to adapt PySide to work with Qt 5.

But let's step back a little now. In my experience with writing Python applications for mobile operating systems (starting with Maemo 4 all the way to MeeGo 1.2 Harmattan), there are really two parts: The frontend, which is specified in terms of whatever the toolkit of the day happens to be, and the backend, which (in case of Python applications) is written in Python.

In Qt 5 / QtQuick, the user interface language is QML, which includes a declarative language and JavaScript for scripting. Writing QtQuick applications with Python doesn't mean replacing JavaScript, it means replacing the "backend" - code that would usually be written in C++ and take care of storage and communication. In fact, as QML grew more powerful over the years, you had to "go down to the C++ level" (or Python in our case) less often. And compared to imperative user interfaces (where you still go through your tree of UI widgets with code and then set some button text to some value), in declarative user interfaces the backend really only provides services to the frontend (that button gets the label from the backend in this way, and when the data in the backend changes, so does the button's text).

So, what we really need is a way to provide services to the QML UI by using Python. There's no need for having access to all classes in all Qt modules - even in Qt4 / PySide times, the classes that I used most often were QApplication (for the event loop), QDeclarativeView (for displaying the QML UI) and QObject (for providing signals and slots to interface the backend to the view). Things like access to the contacts database or GPS location can usually be done directly from QML (and displayed there) - it might be that you don't even need to have that data in your backend (and if you do, the UI can for example send the phone number of the contact "down to" the Python backend for further processing).

But before I'll tell you where I think mobile Python development should be heading, let's bring up yet another disadvantage of using PySide (probably applies to PyQt as well) for mobile applications: Startup time and responsiveness. Startup time is slow, because PySide libraries are big (they are - at least on the N9 - bigger than the Qt libraries they are binding), and the dynamic linker has to resolve all Qt symbols at load time instead of just the ones you end up using. Instead of seeing the QML UI right away, your application first has to load up the Python interpreter, then load up the PySide modules and other modules and then finally load and display the QML UI. And because of Python's Global Interpreter Lock, function calls from QML to Python will make the UI block and not be totally responsive, even if you are using threads.

So, in my opinion, mobile Python applications with Qt 5 have to be fast to load, lightweight and responsive. Fast to load can be achieved by making sure the libraries that get loaded are small, and that ideally the QML UI can already be displayed before the Python interpreter is even loaded and/or initialized. Lightweight can be achieved by not binding all the Qt classes, but only the ones you really need for creating QML applications. And responsive can be achieved by making sure that the interface between QML and Python is asynchronous, so the UI never blocks even if Python is working hard in the background to fulfill the requests of the user interface.

I currently have a prototype running on Python 3.3 (Python 2.6 and 2.7 is also supported still, but for me, this is a great opportunity to migrate some of my old code to Python 3, and new code should be written in Python 3, because, as you know, Python 2 sucks) and Qt 5 (I've just ported it to Qt 5 today, but it runs just as well on Qt 4 - with all the advantages like startup time and asynchronousness still being valid). In some unscientific tests that I carried out a few weeks ago, I've brought down startup time of gPodder on the N9 down from ~ 12 seconds (using Python 2 and PySide) to ~ 3 seconds (using Python 3.3 and the lightweight "PyOtherSide" approach). No code release yet, as this is tailored towards my gPodder experiment right now and has many things hardcoded, but once I clean it up (maybe as a QML plugin) and define the API in more detail, I plan to release it.

In the mean time, here are some (relatively old) videos of PyOtherSide running with Python 3 and Qt 4 on MeeGo Harmattan, Blackberry 10 and Android (so yes, it is portable).

Dienstag, 5. März 2013

Porting Harmattan Apps to Sailfish Silica (and back)

So the Sailfish SDK was released last week, and as explained in the last blog post, gPodder is already running on Sailfish Silica Components. Of course, this has only been possible because Silica is quite similar in API design to Harmattan Qt Components (whenever I write "Harmattan" in this blog post, I usually talk about Harmattan Qt components, and whenever I write "Sailfish" it usually means "Sailfish Silica Components"). But of course porting "from" Harmattan "to" Sailfish with no way back would be kind of annoying - either Harmattan gets dropped, or somebody has to maintain two codebases, something I'd rather avoid. So, just like in "good old" Maemo 4 and Maemo 5 times, the goal here is to convert a Harmattan-only codebase to Harmattan-and-Sailfish, so that both can be maintained in the same codebase and improvements to Harmattan benefit the Sailfish port and vice versa.

In fact, while porting gPodder from Harmattan to Sailfish, it reminded me of porting from Maemo 4 to Maemo 5 - same toolkit (then Gtk+, now Qt/QML), similar extensions (then Hildon, now Components) but different concepts (then normal menus in Maemo 4 vs. HildonAppMenu in Maemo 5, now toolbars and context menus in Harmattan vs. pulley menus in Silica).

Obviously, as gPodder is written in Python here, this applies mostly to PySide-based applications, but the real difference is in the QML (there's really only one short snippet in the Python code that decides which QML import path to use). The approach taken is somewhat simliar to what the Jolla guys have been presenting at FOSDEM 2013, but I don't recall everything and have tailored the approach to better fit my workflow.

Before we start, be sure to know that qt-components is in the Sailfish Emulator (once you install it via "zypper in qt-components" as root), so that could be a shortcut for quick porting exercises and as an interim solution.

For starters, I've cleaned up gPodder's QML UI to make better use of Qt Components (historically, gPodder's QML UI was started at a time where Harmattan Qt Components were not even out or announced, so wazd and me came up with our own style - yes, that's pre-feb11 even!). So, instead of custom transitions and state management, everything is a Page, and transitions happen via the PageStack (the Silica equivalents are also called Page and PageStack). So, assuming you only have pages and so on, you could theoretically already use this or that depending on which platform you are on. Unfortunately, QML doesn't have conditional imports or something like that, so we have to add some abstraction layer.

Here's the basic idea:
  1. Create a new "Components" set - I'm calling mine "org.gpodder.qmlui"
  2. You define which items your components have, and a common API
  3. You implement your components twice: Once for Harmattan, once for Sailfish
  4. At runtime (or even compile time if you would want that) you decide which set of components you use
  5. Your application GUI code only imports QtQuick, maybe QtMultimediaKit (if you need it - it's available on both platforms) and your custom components (org.gpodder.qmlui in my case)
Just in case you are already running to the gPodder Git repo now to check it out, here's a short disclaimer: The UI isn't fully ported yet, so there's still a few remaining "com.nokia.meego" (Harmattan Qt Components) imports in my QML UI, but that's just temporary until I have found a good replacement for things like Sheet and MultiSelectionDialog in Silica.

My custom components at this time look like this:
Most of these are just thin wrappers around the "native" components on the target platform. For example, WindowWindow.qml (harmattan, sailfish) is just a wrapper for PageStackWindow (on Harmattan) and ApplicationWindow (on Sailfish). Where I said "import com.nokia.meego 1.0" and "PageStackWindow {}" previously, I now say "import org.gpodder.qmlui 1.0" and "WindowWindow {}". In the case of the Harmattan implementation, this is just the same as before, but on Sailfish, an ApplicationWindow will be used.

Other wrappers just deal with API differences. For example, ScrollDecorator exists in both Harmattan and Sailfish, but in Harmattan the property is called "flickableItem" and on Sailfish it's "flickable". So my ScrollScroll (harmattan, sailfish - also, noticed a naming pattern there? ;) takes care of hiding the differences, and I just use "flickable" on a ScrollScroll, and it will do The Right Thing on the platform it's currently running on.

When the API is the same (e.g. for Button), you still need to create pass-through components because of the different import path: Button (harmattan, sailfish).

But there's also some more elaborate differences. For example, I want to have menus - a toolbar menu on Harmattan and a pulley menu on Sailfish. So I defined a very simple Action (I'd be surprised if such a component doesn't already exist, but I didn't find one when I wasn't looking (sic)) that basically has a text and some signal attached to it. In my application code, I define actions as a property on my PagePage (which is a Page with some special code to transform actions into whatever the platform representation is). See the main page actions for an example. The ActionMenu (harmattan, sailfish) then takes care of creating a ContextMenu (Harmattan) or PullDownMenu (Sailfish) and PagePage (harmattan, sailfish) takes care of creating a toolbar on Harmattan and forwarding a reference to the listview to which the PullDownMenu should be attached to (in Harmattan, I still need to pass the listview there, but it's not used).

The same customization also happens for the ListList (harmattan, sailfish), which is a ListView (Harmattan) or SilicaListView (Sailfish), but also takes care of displaying a header (which still needs to be styled correctly on Sailfish) if the platform requires it.

Once you've created your custom set of components, you have to create a qmldir file that lists the components available and in which version of the components they are available. Read up on Declarative Modules in the official documentation.

So there you have it. One QML codebase, two UX targets that are well-integrated. You can see the results in the just-released gPodder 3.5.0, which is more Harmattan-ish on the N9 than before (although some items have moved from the toolbar into the menu for simplicity reasons, and I actually think it's cleaner now) and also looks and feels quite native on Sailfish (it's not done yet, and I'm sure the UI will evolve and adapt once Silica gets more mature and we see more Sailfish apps).

What I'd like to see in the Sailfish SDK: Different Ambiance backgrounds (darker, brighter, different hues) so that developers like me can test if their apps look good atop more than just the nice blue default background.

As a last hint (I couldn't find that in the API docs, but in the component gallery): Sailfish Silica's Label Component has a "truncationMode" property. If you set it to "TruncationMode.Fade", you never want to see elided text again, because it looks so sexy! :)

Sonntag, 4. Dezember 2011

This weekend's releases: Tap Tap N950, qw.py and the IP Address Widget

Over the weekend, I've pushed out some code for your enjoyment: First up is the incomplete but maybe interesting QML source code of the Tap Tap N950 prototype. I probably won't find time to work on this, but it would be sad to let the small piece of code rot - maybe someone wants to pick up the development of it. I'll answer any questions related to the code in the thread :)

Next up is the open source release of the qw prototype "qw.py", which has been developed during the Super GameDev Weekend 2010 at the Metalab Vienna last December (the next one is at the upcoming weekend; stop by if you are in Vienna!) - nearly 1 year ago. This is not the same as qw The Game in Ovi Store, but it's an earlier version, which still contains multi-player support (4 players on one PC keyboard), and it's written in Python, so it should be easily hackable.

And last but maybe not least is the IP Address "Widget" for Harmattan. This small hack (which is inspired by the earlier Calenderr calendar icon hack) makes use of the fact that the Harmattan UX reloads the icon of an application whenever the .desktop file or the icon file itself changes. The details (and a .deb for easy installation) can be found on the website - basically it shows a way to have semi-interactive "widgets" on the app list on Harmattan. I'm sure that creative readers can come up with some cool ideas :)

Donnerstag, 7. Juli 2011

New gPodder versions for your N8x0 and N9x0

It's been over two months since I've released a new stable release of gPodder. Now it's time again to catch up with some of the fixes that have landed in the "master" branch of gPodder (while we are still adding cool stuff to the "tres" branch, where the QML UI and other improvements happen). Anyway, gPodder 2.16 "Over There" should be available in Maemo Extras for both Diablo and Fremantle soon, please test the package and (in case of Fremantle / Maemo 5) also vote for it, so it can land in Extras eventually.

For the Nokia N950 (and also for the N9), there's already a very early alpha build of the QML for you to try - please note that you might have to remove your database and downloads to be compatible with any changes when the final version is out. There's a thread on forum.meego.com with instructions on how to get it and a screenshot - please also use this forum thread for feedback and any questions that you may have.

In related Maemo/MeeGo news, That Rabbit Game has been packaged for MeeGo Tablet and should be available in AppUp already. There's also a pure OpenGL ES port for webOS, although it's missing some features of the Qt version. If you haven't been following gaming news, our multi-touch game Mong (which is going to have its new name "Plonk" soon) is available for MeeGo tablets and I'll have a Harmattan package for you to try really soon! There is also the Harmattan Event Feed Library for Python which should make posting data to the event feed awesome. And if you really want to port your PySide apps to Android, try PySide for Android, which has just been released today. Yes, lots of stuff happening - expect more in the coming days/weeks :)

Mittwoch, 11. Mai 2011

gPodder on the N900 MeeGo 1.2 Developer Edition

If you want to try the MeeGo N900 Developer Edition for the N900 but think that clicking through the Widgets Gallery gets boring after 45 minutes, why not try out the QML UI of gPodder on it? It's pretty easy. This post assumes that you are using the alpha release of the N900 Developer Edition from a microSD card and boot via USB.

Thankfully, Python 2.6 is already preinstalled, but you need recent PySide packages for gPodder to work (PySide exposes the Qt framework to the Python world), you can get them from PySide binaries for MeeGo. You don't need to upgrade Qt, simply installing the PySide packages is enough:

zypper addrepo http://download.meego.com/live/home:/renatofilho/Trunk/ pyside
zypper install python-pyside


What you need now is a recent Git checkout of gPodder's "tres" branch. I suggest you do that on your computer:

git clone git://repo.or.cz/gpodder.git
cd gpodder
git checkout tres


Now there are two pure Python dependencies for gPodder that you also need. As there are no packages for them in MeeGo yet, you also have to provide them manually. The first one is the Universal Feedparser. Grab a recent release from the downloads page and copy the file feedparser.py to the src/ folder in your gPodder checkout. The second dependency is mygpoclient, a client library for the gpodder.net web service. You can check out the latest version from Git:

git clone git://repo.or.cz/mygpoclient.git

In the checkout, you will find a folder called mygpoclient - copy this to src/ in your gPodder checkout. Now you have a complete, self-contained gPodder checkout on your computer. Use rsync or scp -r to copy it over to your N900 (you can use USB Networking for that).

Now that you have everything on your N900, you have to add some subscriptions manually (mostly because the QML doesn't yet have the UI required to subscribe to new feeds) - use bin/gpo to start the command-line utility, then do something like subscribe fb:linuxoutlaws to subscribe to an example podcast. Quit the command line application and start the QML UI using bin/gpodder --qml, which should - after some loading time - show gPodder/QML on your MeeGo 1.2 Developer Edition environment.

If you have made it this far, don't stop here - try out the examples from the PySide/QML Tutorial and familiarize yourself with Python development on MeeGo - it's easy and fun!

Freitag, 4. Februar 2011

gPodder/QML status (with screenshot and video)

Ohai February. The winter term is over; time for some gPodder QML hacking. This means that gPodder gets a new UI, and the structure of the application and the usual workflows also change a bit, based on the experiences with gPodder on Maemo 5. One of the most important changes will be that content will be played inside gPodder, as this provides even more control over playback and resuming than what the MAFW integration with the Maemo Media Player can provide.

Most of this has been done in the last two days. Thanks to Python, PySide and QML, I'm able to reuse the gPodder codebase (feed parsing, downloading, etc..) and just slap a lightweight QML UI on top of it.

Andrew Zhilin (aka wazd) has helped a lot with the design and the artwork, but see for yourself (this is a screenshot, not a mock-up):

And here is a video of the current performance on a N900:

Feedback, as always, welcome :)

Samstag, 8. Januar 2011

New tutorial: PySide/QML on MeeGo

In addition to my old PySide tutorials, there is now a proper PDF guide for PySide development on MeeGo available. Except for packaging, all steps apply to Maemo as well, and this is the document that includes the first gPodder QML UI code example (the final gPodder QML UI will be totally different and "much cooler", though).

As part of the new year's cleanup, I also dug out the old MTF UI demo of gPodder and put its source online here - for third party applications, QML is now the preferred UI over MeeGo Touch, so this might not be of much use for you now, but maybe somebody can put it to good use.

Dienstag, 7. Dezember 2010

PySide/QML tutorials online, workshop next Sunday

To get myself accustomed to PySide UI development using Qt Quick (aka QML) and to check out what works already and what does not, I've experimented with creating some common elements that I'd use in an application (i.e. a QML version of gPodder - a blingy demo already exists) and decided to share my experiences and results as tutorials.

Here are all the tutorials in their current state:

Screenshots are available on Flickr:

I'd like to get some feedback on whether or not the tutorials worked for you and were helpful and what else you would like to see. You can try out all the examples on your N900 today! Just install python-pyside and python-qtmobility (for the last example) from Extras-Devel and copy the examples from the Wiki. The usual disclaimers for software in Extras-Devel apply.

In related news, there will be a PySide/QML workshop at the December meeting of the Python User Group Austria, so if you happen to be in or around Vienna on Sunday, 2010-12-12, stop by at the Metalab and meet fellow Pythonistas.

Freitag, 20. August 2010

gPodder running in the MeeGo Handset UX for N900

Three days ago, a new MeeGo Handset UX image has been released for the N900. I wanted to try out gPodder on it to see how far I could come without any coding...

It was quite easy to get things going: Download the image, dd it to a MicroSD card, boot the kernel (detailed instructions) and set up USB networking. After that, I could ssh into the environment (the root password is meego) and have a look around.

Instead of using apt-cache and apt-get to search for and install packages, I utilized yum to search for and install PyGTK. Then, I used rsync to copy my Git checkout of gPodder to the device. There are two additional dependencies for gPodder that aren't yet available in the MeeGo repositories, namely feedparser and mygpoclient, so I just copied the Python modules from my Laptop into the src/ folder of the gPodder checkout. Then, just switch to the MeeGo user (su - meego), make sure that the DISPLAY variable is set (export DISPLAY=:0) and start gPodder from the source folder (with bin/gpodder - it automatically loads the modules from the right path) - gPodder says hello MeeGo.

The basic functions work, it's just that the Desktop UI isn't suited for mobile devices (the MeeGo compositor/decorator also has several problems, but that seems to be a more general problem). Python bindings for Hildon aren't (yet ?) available, so I could not test the Maemo 4 or Maemo 5 UIs, but I would like to do a proper Qt/MeeGo Touch-based UI for gPodder, anyway. Let's hope the PyMaemo or PySide teams are quick to release bindings and make them available in the MeeGo repositories, so Python developers can create usable UIs for MeeGo handsets :) Oh, and two MeeGo-Python facts: It comes pre-installed in the N900 image, and the version shipped is 2.6.

In short: Apart from the UI framework, everything is already in place (and working) for Python on MeeGo. With the recent release of Qt Mobility for PySide, let's hope that MeeGo Touch bindings are not that far away.