This tutorial will show you how to build a simple web browser for the GNOME desktop using the Python programming language. It is based off the tutorial that Erik Dasque has written for Mono and C#.
For this tutorial you're going to need the following tools.
The first task that we'll need to do is to start with Glade. Glade is a user interface builder for GTK+. The version that we'll be using is Glade-2. You can start it from the command line using the command glade-2. When you start it up you'll see a set of windows like the ones below in figure 1.
Click on the new and tell it that you want to start a new GNOME project. This will make the tool palette go undimmed and you'll now be able to create your user interface. On the palette click on Gnome button and select the Gnome Application Window, as shown in figure 2

This will bring up a simple window that says glade-2 for the title. Click on the toolbar in an area where there are no buttons currently. This will select the toolbar and its properties will come up in the property window. Change the size of the toolbar from 3 to 6. We'll be adding three more widgets to the toolbar.

The next step is to populate the toolbar with new buttons. To do this we'll go back to the palette and select GTK+ Basic. We want to add two buttons in the first two spots and a text entry in the third spot. When you've done this, your window should look like the one in figure 4

The next step is to convert the buttons we've just created to stock buttons. In this case we'll want to use the forward and back stock buttons. Click on the buttons, this will bring up their properties in the property window. Click on the Stock Button pull down and select Forward and Back for the respective buttons.

As right now we're focusing on keeping the browser simple, most of the widgets aren't going to be hooked up to anything. But we do want to hook up the location bar so we can type URLs and look at different web pages. To do this, click on the text entry we added to make it active in the properties window. The select the signals tab. Click on the ellipsis by the signal field and select activate. A text entry emits the activate signal when the enter key is pressed in it. This will make a default handler of on_entry1_activate, which is fine. Click on the Add button to add it. If you don't click the Add button it won't be added and you're work will be for naught.

The final step we'll want to do in glade is to add a holder for our Mozilla widget. Unfortunately, Glade doesn't have the ability to add the widget natively, but that's not a big deal. We do this by adding a frame to the application window. Select the frame widget from the bottom of the GTK+ Basic widgets, then click to add it into the open spot in the application. The click on the label and hit the delete key to remove the label from the widget. When you're done, you should have a window that looks like the one shown below in figure 7.

Click on the save button in Glade window that has app1 listed. Save the program as pygtkmozembed. The rest of the options don't really matter because we're not actually generating the code for C or C++. Just hit OK.
Now on to the meat of the program, the Python. Although, you'll soon see that there isn't much to this, Glade has taken care of a lot of the work we thought we'd have to do. To start off we need some initial code that will be helpful. The code shown in snippet 1 make it so the program can run by itself, imports all the libraries we need and also sets some constants for our program that will be useful.
#!/usr/bin/env python import gtk import gnome.ui import gtk.glade import gtkmoz APPNAME="PyGtkMozEmbed" APPVERSION="0.1"
The next thing we'll want to do is to create a simple wrapper that will initialize GNOME application and load all of the widgets. We'll call this class WidgetsWrapper as it wraps around all of our widgets. The code for this appears in snippet 2.
class WidgetsWrapper: def __init__(self): gnome.init(APPNAME, APPVERSION) self.widgets = gtk.glade.XML("pygtkmozembed.glade") self.mozillaWidget = gtkmoz.MozEmbed() self.widgets.get_widget("frame1").add(self.mozillaWidget) self.mozillaWidget.set_size_request(800,600) self.mozillaWidget.show() self.mozillaWidget.load_url("http://www.mozilla.org/") signalDic = { "on_entry1_activate" : self.on_entry1_activate, "on_quit1_activate" : self.on_quit1_activate} self.widgets.signal_autoconnect(signalDic)
Briefly this what the program does up to this point. First is registers itself as a Gnome application. Then it loads up all of the widgets from our glade file we just created. This is what will allow us to handle signals that are sent by widgets. Then it creates a widget called mozillaWidget which will hold our instance of a Mozilla web browser. Before we can use the widget, we need to add it to our program, which is what the line after that does. Finally, the widget is told to make itself visible and then load the mozilla home page as a start page.
We're to the point where we should have something that is usable. Add the following little bit of glue code at the end of your program and we'll have a runnable program. If you want to test it at this point, you'll be able to run it and browse the Mozilla.org webpage and any pages that link to it, but you can't use the address bar yet.
if __name__ == "__main__": widgets = WidgetsWrapper() gtk.mainloop()
But we're not happy with that. There are a couple of issues. First the program doesn't exit nicely. You can kill the window, but you still need to use Ctrl-C to kill the program. Secondly, the address bar doesn't work. This is where our signals take hold. To do that, we first add the code in snippet 4 to our WidgetsWrapper.__init__ and then we add the methods in snippet 5 to our WidgetsWrapper class.
signalDic = { "on_entry1_activate" : self.on_entry1_activate,
"on_quit1_activate" : self.on_quit1_activate}
self.widgets.signal_autoconnect(signalDic)
def on_entry1_activate(self, widget):
self.mozillaWidget.load_url(widget.get_text())
def on_quit1_activate(self, widget):
gtk.main_quit()
signal_autoconnect takes a dict and connects the signals to the appropriate functions. In a future tutorial I'll show a niftier way to do this, but this will work fine for now.
Then we simply create the methods. Both of the methods just take one argument, the widget that emitted the signal. For our text entry, we just want to load the new URL that has been entered. The other method allows you to use the file->quit menu option to exit the program.
#!/usr/bin/env python import gtk import gnome.ui import gtk.glade import gtkmoz APPNAME="PyGtkMozEmbed" APPVERSION="0.1" class WidgetsWrapper: def __init__(self): gnome.init(APPNAME, APPVERSION) self.widgets = gtk.glade.XML("pygtkmozembed.glade") self.mozillaWidget = gtkmoz.MozEmbed() self.widgets.get_widget("frame1").add(self.mozillaWidget) self.mozillaWidget.set_size_request(800,600) self.mozillaWidget.show() self.mozillaWidget.load_url("http://www.mozilla.org/") signalDic = { "on_entry1_activate" : self.on_entry1_activate, "on_quit1_activate" : self.on_quit1_activate} self.widgets.signal_autoconnect(signalDic) def on_entry1_activate(self, widget): self.mozillaWidget.load_url(widget.get_text()) def on_quit1_activate(self, widget): gtk.main_quit() if __name__ == "__main__": widgets = WidgetsWrapper() gtk.mainloop()
Now you'll want to try and run the program. The simplest way is just to type python pygtkmozembed.py. However, there is a chance you'll get an error about not being able to find libraries. This is because either you haven't added the Mozilla library to your /etc/ld.so.conf or it's not in your LD_LIBRARY_PATH environment variable. In that case you might want to try running the program by typing LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/lib/mozilla-1.6 python pygtkmozembed.py. With the program running you should see something like the picture in figure 8.
Of course, I'd be remiss if I didn't show that I can do all sorts of other langauges too. This is all due to the fact that we used stock widgets in our program. If you run the program using the command line LANG=ar_SA python pygtkmozembed.com the menus will be Arabic and the text will appear right to left.
At this point, our program works well enough, and this covers everything that Erik covered in his tutorial. In the future I'll probably add some updates that show how to do some more interesting stuff such as activating the forward and back widgets. Also, you'll notice that there is no progress given on the loading of a web page, and no errors are hooked up. Those will be covered in the future too.