So, basically, not to put to fine a point on it, I've started to write apps for Ubuntu in a different way, essentially, replacing Gtk (or really PyGtk) with HTML5. This is my first post about how am I doing it. I've just started a project called "Veritas" which will be a wine tasting database for my wife and I. We'll be able to enter information about each bottle that we drink, and then look at trends over time, perhaps helping us pick nicer and nicer bottles as we go.
First, though, what happened, I thought you got along great with Gtk?
Well, I do still have a soft spot in my heart for pygtk. Believe me, I've written plenty of code in it. I know the ins and outs pretty well, and I'm able to do things with it like write a response UI that doesn't block to much during run longing processes and such. PyGtk is great for building "boxy" apps, but I think a lot of people want to build slicker apps than Gtk is really designed for, or at least design them in different ways thatn Gtk supports well.
Why not Qt and QML?
This app, in fact, would be well suited for a QML app. However, I have other apps in mind, and I found QML/Qt to not be quite up to the job. For instance, I want to write a communication app to combine OpenLDAP and IRC functionality. Currently, there are no Qt libraries for LDAP or IRC, so to write such an app with QML, I'd have to write C++ Qt code to wrap whatever C libraries, and then write code to export models from that C++ code to expose it the right way in QML. That is a lot of overhead, especially considering that there are good Python libraries for LDAP, IRC, and pretty much anything desired. So, I designed myself a system that let me stick with Python for the back end code.
Also, QML lacks a widget toolkit at the moment, so there would be a lot of manual coding of things like buttons and such.
I chose HTML 5 for the widget toolkit for a few reasons.
- Webkit is very well supported Open Source used and maintained by many large companies.
- There are lots of cool widget toolkits to choose from, I'm currently looking at YUI since I think it's in pretty heavy use by some of the web teams at Canonical.
- Because I wanted to try out HTML for client programming.
My Application Architecture
First, I laid everything out total flat to start with. This is because I wanted to come to grips with making the view code talk to the model/controller code without mucking with any extra complexity. Of course, I will need to modify the layout as the actual code grows.
Currently, I am only focused on makinga client application programming system, though I may, in the future, extend the system so the model/controller back end could be on a server, and the view available via a browser. But this is firmly out of scope right now. I am, however, trying to be cognizant of making the system essentially portable by sequestering the Gtk specific code into specific files that can be replaced if I want to run it without Gtk at some point.
Therefore, there are some important differences to note if you are used to web programming.
- The back and and view code communicate via signals to each other. This is much different than web programming, where the view makes a request and waits for the server to respond with a string (for Ajax apps) or redirects to another view passing some state along with it.
- This means that the back end can send signals to the view. The view does not need to pole to see if the back end is ready, for example, the back end can just send a signal when it is.
- This also means that long running processes can block the GUI, since they are running in the same thread. I shall most likely put the Gtk main loop in it's own thread so I can run run-longing processes in seperate threads, and then communicate between them.
- The view cannot call a function on the back end, and wait for a response (for example with XmlHttpRequest). Rather it can only send the back end a signal.
- The back end is not stateless. This is greatly simplifying. Most web programming frameworks have a lot of code to maintain state by storing it and accessing it on future requests by reading cookies stored on the client.
Ok, let's get to the good stuff. To bin file is called "veritas". Running this file creates a VeritasWindow and then starts the Gtk main loop. The Gtk main loop is there because the Webkit window has to run inside something, and I chose a Gtk Window for this because of the simple integration with Ubuntu.
A VeritasWindow only does 2 things so far. It tells it's baseclass "HTMLWindow" what html file to load, and it listens for signals from that view. Later, it will create new HTML5 Windows and do other stuff in response to signals from the HTML view.
HTMLWindow is meant to be used only as a base class. First, it creates a top level menu so you can quit the app, and also, I think that apps should have menus (I haven't really thought through how menus will work in this system yet, but I'm hoping that DBUS Menu helps me out). Then it loads the HTML that the subclass told it to load. It also listens for signals from the view, parses the signals and has what is essentially a virtual function called "on_html_message" for subclasses to override. You should be able to receive messages from the view without looking at the internals of how it works. Among other things, this is platform specific.
main.html is the HTML5 code for the main window. All it does now is send a signal that it is loaded, and you can see that I added a heading. When paired with main.css the layout and look and feel of the UI will be controlled completely in the view code.
helpers.js is a file that I think I may need to handle platform specific signals sent to the view. Of course, you can always call "execute_script" and send whatever you want from the backend, but I think it's cleaner to expect well formatted signals from the back end instead.
So, that's basically all the boiler plate for making an HTML5 client app for Ubuntu. This represents a few hours of work on my part to make a re-usable and extensible system.
My next steps will be to do some database programming with sqlite, then I'll probably build a data input window for it. This certainly calls to mind Rails-like thinking (hmmm, I have the model, why can't I generate the view from that on the fly?), but, I don't think I want anything that complex. After I finish Veritas, I'll then extract the base classes and such, and perhaps create a Quickly template, then go ahead and work on my certain to be more complex communication application.