PyGTK/Hello World with Glade and Sweettepache

From OLPC
< PyGTK
Revision as of 01:10, 21 February 2008 by Tony37 (talk | contribs) (icon information)
Jump to navigation Jump to search

PyGTK/Hello World with Glade and Sweettepache

The PyGTK/Hello World Tutorial shows how to create the python program Hello World as a Sugar Activity. PyGTK/Hello World with Glade shows how to build the same activity using Glade. Glade.py provides a visual editor for designing a program's GUI (graphical user interface). The output from Glade is a file 'name.glade' where name is the name of the activity Tepache 'tepache.py' is a python program which processes the glade file to produce a skeleton module name.py. This module contains the has the code to connect with the GUI. The specific application logic is then added to complete the module.

The program sweettepache.py is a modification of tepache which, in addition to name.py, produces a nameActivity.py module for Sugar, and produces the files and folders needed to make an activity bundle. The result is a module name.py which can be tested on Ubuntu (or possibly other platform). When the module works correctly on Ubuntu, it and the activity structure can be ported unchanged to the XO.

he purpose of this page is to make sweettepache.py available and to show how it can be used to build and test sugar-compatible python code.

This project was developed on Ubuntu 7.10 and the Hello World activity was ported and tested on a G1G1 XO upgraded to release 656. An important caveat is that there has been no robust testing (after all, almost anything can work for 'Hello World').

Activity Development Process

The following is the step by step process in building and testing a Sugar Activity using Sweettepache.

Design the GUI

See PyGTK/Hello World with Glade for a description of this step. Suppose the name of your activity is 'cool'. Make a folder, cool.activity. Save the glade file in that folder as cool.glade The important point is that when the glade file is saved, its name 'cool' will be used by sweettepache as the name of the activity. Also, the folder cool.activity will be the top-level of the Sugar bundle.

Create the skeleton module

  • Copy sweettepache.py to cool.activity
  • Open a Terminal and 'cd' to the folder cool.activity
  • Execute the command: python sweettepache.py cool.glade

Instantly you have an activity bundle complete with icon!

Use the command: sweettepache.py --help to see the available flags. Two flags have been added:

  • -s makes sweettepache work identically to tepache (no sweetening).
  • -i flag requests the generic icon (activity-cool.svg) not not be written.

Only in demos do programs work correctly the first time. In reality, you will want to change the GUI. To do this, open cool.glade in Glade, make changes, and save the modified file. Run sweettepache again. Sweettepache saves a copy of your module as cool.py.bak. It also creates a copy of the module as cool.py.orig (the only difference is that sweettepache 'normalized the indents' in cool.py.orig). Sweettepache creates a temporary diff file with the new skeleton to detect your application code. It then produces a new cool.py which incorporates your code with the modified interface to the GUI.

Test on Ubuntu

It is probably a waste of time to test a program on the XO as an Activity before it works correctly on Ubuntu. Sweettepache produces a module coolActivity.py which provides the code specific to the XO. The intention is that name.py runs on Ubuntu as is. On the XO, coolActivity.py initializes the Activity and then calls cool.py. You may need to make changes to coolActivity.py. for example, to add a button to the toolbar, Sweettepache will create a copy of coolActivity.py as coolActivity.py.bak.

Test on the XO

Currently I use a USB stick. Simply copy the name.activity folder to the stick. On the Xo, open a Terminal. Change to root (su). Copy the name.activity folder from the stick to /home/olpc/Activities. Restart Sugar (Ctl + Alt + Erase). Your activity should show up on the bottom panel. Start your activity.

If, after a reasonable time it is still 'starting', it usually means that python found a syntax or other error that prevented the program from starting. Often the explanation will be found in the activiity log. Open the log viewer (this shows the logs stored in /home/olpc/.sugar/default/logs). There should be an entry for your activity. This will show messages from python as well as the output of print statements in your code.

There are two (probably temporary) gotchas. When you open a Terminal on the Xo, the focus is on the toolbar, not the prompt. When the Terminal opens, click the mouse in the Terminal window first. The second is that there seems to be no way to 'stop' an activity that is 'starting'. It requires the CTL-ALT-Erase solution.

If the problem which prevents the activity from executing is simple, it can be fixed in the Terminal. As root (su), nano is available to edit your module in /home/olpc/Activities/name.activity.

Once the program starts, you will immediately see one of the main differences between Ubuntu and Sugar, the GUI window opens full screen on Sugar. This may well require tweaking of the Glade design to make the results more attractive on the Xo.

Technical details

Normally, glade generates the root window for an application. However, Sugar provides the toplevel window. The result is that the GUI definition from glade must be connected to the sugar window. This means that the glade file is processed on sugar beginning at the top widget below the level of the window (for example, a vbox container). This widget is then packed into an existing vbox container supplied by sugar. The details of this are apparently changing from release to release. The first tutorial (PyGTK/Hello World) didn't use Glade. The page PyGTK/Hello World with Glade explains the issue clearly. However, now that solution doesn't work because of the pre-existing vbox in the sugar window. There are, of course, no guarantees that a later release of Sugar will not break sweettepaches solution.

One additional advantage of the sweettepache strategy is that all of the details of building an activity structure can be encapsulated in a form which is easily changed. The last half of sweettepache is the 'boilerplate' code it generates. These lines are customized for a specific application by entries of the form %(class)s which produces a variable output depending on the contents of 'self.data'. The entry %(t)s produces a tab or four spaces (as needed by python). Caution: the trailing s is needed (it means produce a string).

This scheme makes it easy to modify the copy of sweettepache in the activity folder to generate specific code such as an additional button on the taskbar.

Finally, the activity.name.svg icon was created with Inkscape. It shows a simple text, Test GUI. It is very easy to change the text to the name of your activity with Inkscape. When you move your activity folder to the XO in /home/olpc/Activities, the icon will show up on the bottom frame as soon as you restart Sugar (CTL-ALT-Erase). On my XO, the activities from /home/olpc/Activities seem to appear in the middle of the list. My XO shows ten activities at a time. The arrows on the bottom frame can be used to move the list to the left or right. The name for your activity (from activity.info) shows up when the mouse rolls over the tab/icon (this is very helpful when there are two activities installed with the same icon.)

The module 'holamundo.py' produced by sweettepache

This is the sugar-independent part of the activity. The lines at the end (#--main\ to #--main) are generated by sweettepache.py. They are not executed on the XO. By looking at the two modules, you can see how the Sugar and Ubuntu specific code are isolated from each other.

 #!/usr/bin/env python
 # -*- coding: UTF8 -*-

 # Python module Holamundo.py
 # Autogenerated from Holamundo.glade
 # Generated on Wed Feb 20 12:48:26 2008

 # Warning: Do not modify any context comment such as #--
 # They are required to keep user's code

 import os

 import gtk

 from SimpleGladeApp import SimpleGladeApp
 from SimpleGladeApp import bindtextdomain

 app_name = "holamundo"
 app_version = "0.0.1"

 glade_dir = ""
 locale_dir = ""

 bindtextdomain(app_name, locale_dir)


 class Window1(SimpleGladeApp):

     def __init__(self, path="Holamundo.glade",
                  root="window1",
                  domain=app_name, **kwargs):

         path = os.path.join(glade_dir, path)
         SimpleGladeApp.__init__(self, path, root, domain, **kwargs)

     #-- Window1.new {
     def new(self):
         print "A new %s has been created" % self.__class__.__name__
     #-- Window1.new }

     #-- Window1 custom methods {
     #   Write your own methods here
     #-- Window1 custom methods }

     #-- Window1.on_boton_clicked {
     def on_boton_clicked(self, widget, *args):
         print "on_boton_clicked called with self.%s" % widget.get_name()
     #-- Window1.on_boton_clicked }
         widget = self.get_widget('texto')
         widget.set_text('Hola Mundo!')


 #-- main {

 def main():
     window1 = Window1()
     widget = window1.get_widget('window1')
     widget.connect("destroy", lambda w: gtk.main_quit())
     widget.show()
     window1.run()

 if __name__ == "__main__":
     main()

 #-- main }

The module 'holamundoActivity.py' produced by sweettepache

Note: This code is only excuted on the XO. It performs the same functions as 'main' in holamundo.py. The 'glade' window is intialized by the line glade=holamundo.window1(root='vbox'). This line assumes that your GUI starts with a vbox and that you did not change the name. The next four lines connect the 'glade' defined window with the Sugar application.

 import holamundo

 from sugar.activity import activity

 class holamundoActivity(activity.Activity):
     def __init__(self, handle):
         activity.Activity.__init__(self, handle)

         self.testname = 'holamundo'
         self.set_title(self.testname)
        
         glade = holamundo.Window1(root='vbox1')
         self.vbox = glade.get_widget('vbox1')
         widgets = self.get_children()
         widget = widgets[0]
         widget.pack_start(self.vbox)

	 toolbox = activity.ActivityToolbox(self)
	 self.set_toolbox(toolbox)
	 toolbox.show() 

The sweettepache program source

Sweettepache.py source

Changes made to tepache to produce sweettepache

References