Tag Archives: gtk

PyGTK 3, great and embarassing…

So, working to get away from WX as my main GUI source and using GTK as I’ve been an Ubnutu, then Mint user with Gnome for years. Building windows in Glade3 was not too bad and the rapid prototyping with Python makes it a great tool. Sadly, the documentation for PyGTK 3 does not exist. There are differences yet the examples that are found are all for PyGTK 2. Don’t believe me? Try finding information on drawing to a window. Most notable difference is the use of Cairo instead of GDK but it just starts there. Anyhow, just venting on what should be a great set up which is made difficult by the lack of documentation.

Gnome Applets.

Being an avid Ubuntu user, I wanted to tinker in building for the Gnome interface.  An applet was the perfect idea but a tutorial on the internet was hard to find.  I found a few like these that are in C, which I’m fond of C but for rapid development and tinkering, Python works much better.  Besides, that is my primary programming language and kindly, Ubuntu came with all the required modules to build in this way.  Most tutorials for Python were out of date.  One of the best I found in Python was this one and my personal favorite which shows a good use of classes.

Onto the tutorial!

The first thing you need to do is build a server file.  This will go to /usr/lib/bonobo/servers with root access.  The reason for this file is for Gnome to be able find your file and set it as an applet.   The lines to pay attention to are:

Line 4:          This is the full path to your source code file.
Lines 9-10:  Name and describe your applet.
Line 20-23: These are the options you can set for the applet browser.

<oaf_info>
    <oaf_server iid="OAFIID:SampleApplet_Factory"
        type="exe"
        location="/home/zbert/Desktop/testing/py/applet.py">
        <oaf_attribute name="repo_ids" type="stringv">
            <item value="IDL:Bonobo/GenericFactory:1.0"/>
            <item value="IDL:Bonobo/Unknown:1.0"/>
        </oaf_attribute>
        <oaf_attribute name="name" type="string" value="Sample Applet Factory"/>
        <oaf_attribute name="description" type="string" value="Sample Applet's Factory that launches the applet"/>
    </oaf_server>
    <oaf_server iid="OAFIID:SampleApplet"
        type="factory"
        location="OAFIID:SampleApplet_Factory">
        <oaf_attribute name="repo_ids" type="stringv">
            <item value="IDL:GNOME/Vertigo/PanelAppletShell:1.0"/>
            <item value="IDL:Bonobo/Control:1.0"/>
            <item value="IDL:Bonobo/Unknown:1.0"/>
        </oaf_attribute>
        <oaf_attribute name="name" type="string" value="Sample Applet"/>
        <oaf_attribute name="description" type="string" value="Sample applet's description."/>
        <oaf_attribute name="panel:category" type="string" value="Utility"/>
        <oaf_attribute name="panel:icon" type="string" value="gnome-laptop.png"/>
    </oaf_server>
</oaf_info>

Now with the server file in place, it’s time to build the applet. I used a picture to show my applet as a small 16×16 PNG smiley face.   As for the coding, I’ve commented what needs to be done here.

#!/usr/bin/env python
### NORMAL IMPORTS
import sys
import gtk
import pygtk
import gnomeapplet

pygtk.require('2.0')

### CREATE A MENU WITH XML
def create_menu(applet):
    xml = """
    <popup name="button3">
        <menuitem name="Item 1" verb="Networks" label="_Networks...."
            pixtype = "stock" pixname="gtk-properties"/>
        <menuitem name="Item 2" verb="Help" label="_Help"
            pixtype = "stock" pixname="gtk-help"/>
        <separator/>
        <menuitem name="Item 3" verb="About" label="_About..."
            pixtype = "stock" pixname="gnome-stock-about"/>
    </popup>
    """
    verbs = [('Networks',show_networks), ('Help',show_help), ('About',show_about)]
    applet.setup_menu(xml, verbs, None)

### WHAT HAPPENS WHEN MENU ITEM IS CLICKED
def show_about(*arguments):
    print(arguments)

### THE ASTERIK ALLOWS MULTIPLE ARGUMENTS TO BE PASSED
def show_networks(*arguments):
    print(arguments)

### ALL OF THESE SHOW IN THE DEBUG (-d) OPTION
def show_help(*arguments):
    print(arguments)

### WHERE IT ALL HAPPENS
def applet_factory(applet, iid):
    # CREATE THE XML MENU
    create_menu(applet)
    # CREATE AN IMAGE OBJECT
    im = gtk.Image()
    # SET THE FILE FOR THE IMAGE
    im.set_from_file("/home/zbert/Desktop/testing/py/face2.png")
    # ENABLE TRANSPARENCY
    applet.set_background_widget(applet)
    # CREATE AN EVENT FOR CLICKING THE IMAGE
    applet.connect('button-press-event',button_press)
    # ADD IT ALL TO THE APPLET
    applet.add(im)
    # SHOW IT!
    applet.show_all()
    # DEBUG EVENT
    print('Factory started')
    return True

### CREATE A DIALOG TO POP UP WHEN APPLET IS CLICKED
def test(*arguments):
    print(arguments)
    dia = gtk.Dialog("Message",None,gtk.DIALOG_MODAL)
    lbl = gtk.Label("this is a message")
    dia.vbox.pack_start(lbl)
    lbl.show()
    dia.run()
    dia.connect("destroy",dia.destroy)

### HANDLE THE IMAGE CLICK
def button_press(button, event):
    # LEFT BUTTON ACTIVATES THE CUSTOM MENU
    if event.button == 1:
        print "button 1"
        # CREATE A CUSTOM MENU
        m = gtk.Menu()
        i = gtk.MenuItem("Hello")
        i.show()
        # CONNECT THIS MENU ITEM TO THE DIALOG
        i.connect("activate",test,"Hello")
        m.append(i)
        # FINISH THE POPUP MENU
        m.popup(None, None, None, event.button, event.time, None)
    # RIGHT BUTTON ACTIVATES THE STANDARD MENU
    elif event.button == 2:
        # DEBUG
        print "button 2"

### STANDARD ENTRY
if __name__ == '__main__':
    # DEBUG
    print('Starting factory')
    # RUN THE APPLET AS A GTK WINDOW IN DEBUG (-d) MODE
    if len(sys.argv) > 1 and sys.argv[1] == '-d': #
        mainWindow = gtk.Window()
        mainWindow.set_title('Applet window')
        mainWindow.connect('destroy',gtk.main_quit)
        applet = gnomeapplet.Applet()
        applet_factory(applet, None)
        applet.reparent(mainWindow)
        mainWindow.show_all()
        gtk.main()
        sys.exit()
    # LET GNOME TAKE CARE OF IT AS AN APPLET
    else:
        gnomeapplet.bonobo_factory('OAFIID:SampleApplet_Factory',
            gnomeapplet.Applet.__gtype__,
            'Sample Applet', '0.1',
            applet_factory)

You can see in these pictures how the applet sits like any other in the corner.  A left click will bring up our custom coded menu with one selection, ‘Hello’ which when clicked brings up a GTK Dialog that is made in the button_press() event.  If you right click, you get the standard menu, plus our XML menu which, when in Debug (-d) mode, you will see the arguments sent by a click outputted in your terminal.  As I mentitoned, there are a handful of great resources for this that detail current Python modules with information on setting this up as I did or in a class for bigger projects.  I hope this tutorial has been helpful, and let me know what you think of these lessons with the comments interface!

Update.

So for anyone reading this blog, I am still here, just have not added anything this week.  I’m working and have not been able to update the blog but I will soon have links and information to my linux Cribbage game.  This is near completion and I have written it using pygtk.  It is using card and game modules that I had designed for a text based run of the program and figuring no one would want to use the text based, I’ve switched to a GTK interface, which is obviously, much better.