Thursday, December 29, 2011

In Vino Veritas and HTML5 Client Apps


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.

Why HTML5?
I chose HTML 5 for the widget toolkit for a few reasons.
  • I already know HTML/CSS/Javascript pretty well, and I know that cool things can be done with it. I bet a lot you all know it pretty well too.
  • 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.
  • Currently, I have nothing like server side tags that are the bread and butter of most web programming frameworks. This typically works via string replacement, so I could either find a library to add this functionality, or make it easier to do string replacement with the HTML. This is typically desirable for a web app since you want to configure the HTML before it is sent from the server. Less important in a client app, but still, some string replacement of HTML may save some effort in writing complex javascript against the browser DOM.
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.

Conclusion
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.

8 comments:

  1. Sounds cool!

    Are you familiar with the UserWebKit work that the Novacut team is doing? It seems somewhat similar and also hooks into CouchDB for data storage:

    https://launchpad.net/userwebkit

    One of my concerns with HTML as desktop applications is consistency. With GTK+, apps have the same general look and feel. With HTML, we will probably end up seeing apps that all look and act differently from each other.

    ReplyDelete
  2. @Odd-rationale - thanks, you beat me to! I think in the past I was too concerned about UI consistency, or at least I took the wrong approach to it. I'm not a UI designer, but as a programmer I thought, hey, if you make designers work with a uniform set of building blocks (a traditional toolkit like Gtk), then you'll get magically consistent UI!

    But if there's one thing my experience with Novacut has taught me, it's that great UI designers don't want LEGO, they want paint and a blank canvas. And that forcing them to work with LEGO is no more likely to produce consistent UI across apps than paint and canvas. In both cases, a lot of very deliberate, coordinated design work is needed to achieve consistency.

    @Rick - awesome, really exciting! I've been meaning to talk to you about UserWebKit because I think it would be a cool option inside Quickly. For Novacut, a big goal is to run the same UI code whether using the locally running native app, or accessing the web-version of Novacut through a modern browser. So this has really driven our architecture, and is why we've stuck to serving all our UI assets over HTTP and want to interact with the database via XmlHttpRequest.

    How do you think you'll approach translation? This is something we haven't figured out with Novacut yet. Initially I took a very template-heavy approach, and my thought was to hook translation in at the template level. But UI designers didn't like this because it made it hard to iterate quickly on the UI in a natural, web-friendly sort of way. So I undertook a big refactor to "Make UI development not suck" in Novacut:

    https://bugs.launchpad.net/dmedia/+bug/837233

    Anyway, this video shows how things work with UserWebKit - http://vimeo.com/29748141

    Cheers!

    ReplyDelete
  3. Really interesting project, Rick! I imagine that this was inspired in part by your new geography? ;) Stay well. Randall.

    ReplyDelete
  4. It is possible to write a program in Python while using QML for the frontend. Basically swap out the C++ for Python.

    If one really wants to use C++ and do not fancy reinventing the wheel there might be solutions available for IRC and LDAP needs (I have no idea about their quality):
    - libircclient-qt (used by IRC Chatter http://wiki.meego.com/IRC_Chatter)
    - libkldap

    The variety of widgets available today in YUI3 [1] seems very nice and lacking to QML, even to the Qt Quick components [2 & 3]!

    [1] http://yuilibrary.com/yui/widgets/
    [2] http://labs.qt.nokia.com/2011/03/10/qml-components-for-desktop/
    [3] http://doc.qt.nokia.com/qt-components-symbian/qt-components.html

    ReplyDelete
  5. Thanks for sharing your info. I really appreciate your efforts and I will be waiting for your further write ups thanks once again.
    http://www.avatarhtml5player.com

    ReplyDelete
  6. very nice thanks for sharing

    hey friend see snow on google
    Type “Let It Snow” on @Google If you click and drag you can wipe the snow away. It is great. source: http://le-titsnow.blogspot.com

    ReplyDelete
  7. Thanks for sharing your info. I really appreciate your efforts and I will be waiting for your further write ups thanks once again. html5

    ReplyDelete