2004.05_Superkaramba-Brighten Up Your Kde Background with Superkaramba and Python.pdf

(2715 KB) Pobierz
Layout 1
KNOW HOW
SuperKaramba
Python Goes Karamba
SuperKaramba helps you do something useful with your KDE background. Now, with just a little help from Python, you
can define exactly what that extra functionality you need is going to be. BY HAGEN HÖPFNER
O nce you start using Super-
Snake Charming
If we want to use Python to add more
functionality to themes such as the one
discussed in [1], we do not need to mod-
ify the existing code. Instead, we can
simply add another file to the theme
directory. The file will use the same
name as the theme itself, and is recog-
nizable by its extension, .py . The
SuperKaramba developers recommend
starting off with a template (see [6]), and
modifying the template. You will find the
sample theme at [4].
Unpack the latter by entering
/small_text_xmms.py
Karamba [2] to a add clock and
an MP3 player to your KDE
background [1], you will probably start
yearning for more. The good news is that
you can use the Python [3] programming
language to add a wide range of interac-
tive features to Karamba themes. For
example, you can create menus, dynami-
cally modify texts, and add drag & drop
support to your themes.
The underlying idea is as follows:
When a KDE event occurs (e.g. moving
the mouse, launching a program, or
selecting a menu item), the program
responsible for this event sends out a sig-
nal that is received and interpreted by a
function. Of course, SuperKaramba can
interpret events of this kind. The
SuperKaramba Python API , which is
described in detail at [5], allows you to
specify what
happens.
Now open the theme file, small_text_
xmms.theme , by selecting Open… in the
main SuperKaramba window, to trans-
late the Python source code into Python
byte code (see Box 1). (If you cannot see
the hidden .superkaramba directory, in
the file selection dialog, press [F8].) As
the compiler displays error and debug-
ging information on the standard output
channel, it makes sense to launch
SuperKaramba manually by typing
superkaramba (you may need to specify
the path) in an X terminal (for example
konsole ).
For example, a message such as My
Python extension has been loaded! , is
caused by the following print command
tar -C ~/.superkaramba -xjvf U
small_text_xmms.tar.bz2
in the ~/.superkaramba directory (you
may need to create the directory first).
This will create a theme directory called
small_text_xmms . Now copy the tem-
plate file, template.py , to the directory.
Make sure you change the name to
reflect the name of your theme:
print "My Python extension has U
been loaded!"
in the last line of the template. This
allows me to ensure that the Python file
translates correctly.
Sadly, this was not the case with
my Suse 9 installation. It would seem
that the distribution sets some of the
environment variables used by Python
incorrectly. Typing the following two
commands in konsole before launch-
ing SuperKaramba soon sorted out
the problem:
cp template.py ~/.superkaramba U
/small_text_xmms U
export PYTHONPATH=/usr/lib U
/python2.3/
export PYTHONHOME=/usr/lib U
/python2.3/
Drag & Drop
Our first extension will be drag & drop
for .mp3 files, as described in [1], that
allows users to drag a file from Kon-
queror to the integrated MP3 player. For
44
May 2004
www.linux-magazine.com
Brighten up your KDE background with SuperKaramba and Python
592681528.006.png 592681528.007.png
SuperKaramba
KNOW HOW
the time being, we want XMMS to play
the files.
Listing 1 shows our solution. If you do
not want to develop the template file,
simply overwrite small_text_xmms.py
with this file.
To allow a SuperKaramba theme to
support drag & drop, the theme needs to
be initialized. The best way to do this is
to create a SuperKaramba widget . This
transmits a signal that is picked up by
one of SuperKaramba’s “gages”, the so-
called callback function initWidget() .
We can enter
Table 1: SuperKaramba Signal Gages
Function
Called when
initWidget(widget)
A SuperKaramba widget is created.
widgetUpdated(widget)
The theme is updated. The update interval is defined in the .theme file.
widgetClicked(widget, x, y, button)
A mouse click occurs within the theme. x and y indicate the coordinates
(relative to the theme) where the click occurred. button indicates the mouse
button that was pressed.
widgetMouseMoved(widget, x, y, button)
A mouse movement occurs within the theme. x and y indicate the current
coordinates (relative to the theme); button provides the number of the
button and indicates the hold status.
menuItemClicked(widget, menu, id)
A menu item is selected. This passes on the menu handle (see the text) and
the menu item that was clicked ( id ).
menuOptionChanged(widget, key, value)
An item in the theme configuration menu is selected. key provides the menu
item handle, and value the new value ( true or false ).
meterClicked(widget, meter, button)
A display device is clicked. meter provides the handle, button the number of
the mouse button pressed.
def initWidget(widget):
commandOutput(widget, pid, output)
A program is called by executeInteractive() ,provided that this causes output
to stdout . pid is the process ID of the program, output contains the text out-
put.
to define the reaction in the next line
when we use the theme as our desktop
background:
itemDropped(widget, dropText)
Objects (e.g. icons) for drag & drop operations are dropped on the theme.
dropText contains the text for the object (e.g. its URL, see section “Drag and
Drop”).
startupAdded(widget, startup)
KDE launches a new application. When the program launch operation has
been completed, a startupRemoved() signal follows, and is turn followed by
taskAdded() .
karamba.acceptDrops(widget)
In this case, we want the widget to
accept drop events.
SuperKaramba uses itemDropped() to
handle the signal. The function expects
two pieces of information from the drop
signal, as indicated in Table 1: a pointer
to the widget and – in the case of files – a
multiple-line list of filenames in the
dropText variable, where each line repre-
sents a file.
Unfortunately, each filename is pre-
ceded by the file: keyword. As XMMS
cannot handle full URLs of the
file:/path/to/file.mp3 type, but expects a
filename like /path/to/file.mp3 , we need
to strip the superfluous data from drop-
Text before passing it on to the media
player.
startupRemoved(widget, startup)
See startupAdded() .
taskAdded(widget, task)
See startupAdded() .
taskRemoved(widget, task)
A program is terminated.
activeTaskChanged(widget, task)
Another application is moved to the foreground.
string.split(string.rstrip(str U
(dropText)),"\n")
we did not do this, any MP3 files that
contained the file: string, would be
hacked to pieces. The result is a list with
two entries, which we store in another
variable, temp . The first element,
temp[0] , contains only an empty string
after the first split operation.
For each iteration of the loop, we
append the filename to the existing con-
tent of the xmms_filename variable. As
the filename is the second element in the
temp list, we can access the name as
temp[1] :
We are using the newline character \n as
a separator. The innermost function,
str() , allows the content of dropText to
be handled as a string, while
string.rstrip() removes any non-standard
characters from the right.
Now we have the individual URLs, we
can use a for loop to remove the file: pre-
fixes. We will write the URLs to the
filename variable one by one, and then
call
Stripping
We will need string manipulation func-
tions [7] from import string . The next
step is to define an empty variable
xmms_filename=”” where we can store
the stripped filename list. We can then
call string.split() to split the URL list
from dropText into its URL components:
string.split( U
filename, "file:", 1)
xmms_filename=xmms_filename + U
" \"" + string.rstrip( U
temp[1]) + "\""
to remove the file: prefix from the file-
name. To be more precise, we split the
content of filename into two parts at the
first ( 1 ) instance of the file: separator. If
To allow XMMS to play MP3s with
spaces in their filenames, we need to
enclose the filenames in quotes. As
Python also uses quotes, , to separate
GLOSSARY
API: An Application Programming Interface
defines a number of functions within a soft-
ware that other programs written in a specific
language can call. In our case, Python applica-
tions can use the functions implemented in
SuperKaramba.
Stdout: The standard output channel speci-
fies where Linux applications should send
their text output. This is typically the screen,
but you can redirect standard output to a file
or a printer. In addition to stdout, Linux also
has a stderror channel for error output that
also points to the screen, and a stdin channel
for input, which typically points to the key-
board.
Widget: A generic term for the control ele-
ments of a graphical interface. These include
windows, buttons, menus, checklists, and tabs.
www.linux-magazine.com
May 2004
45
592681528.008.png
KNOW HOW
SuperKaramba
Listing 1: The theme supports drag & drop
tem is now stored in the global variable
selectmenu . This is referred to as a han-
dle , as the number is used to identify the
menu internally. The following, some-
what lengthy construct stores a menu
with two items in my_menu . The first of
these …
01 import karamba
02 import string
03
04 def initWidget(widget):
05 karamba.acceptDrops(widget)
06
07 def itemDropped(widget, dropText):
08 xmms_filename=""
09 for filename in string.split(string.rstrip(str(dropText)),"\n"):
10
temp=string.split(filename, "file:", 1)
karamba.addMenuItem(widget, U
selectmenu, "konqueror", U
"konqueror.png")
11
xmms_filename=xmms_filename + " \"" + string.rstrip(temp[1])
… creates an entry for konqueror in
selectmenu . The konqueror.png icon,
which also has to be stored in the theme
directory, completes the menu item. The
second addMenuItem() does the same
thing for an opera entry:
+ "\""
12 karamba.execute("xmms" + xmms_filename)
13
14 print "My Python extension has been loaded!"
strings, we have to escape the string
using ”\”” , a fairly complex procedure. If
xmms_filename actually includes
quotes, escaping them with \ tells XMMS
that the is to be taken literally.
After storing the file list in xmms_file-
name , we can use
IDs assigned to them.
In response to the theme window
opening, initWidget() adds a menu to
the theme:
karamba.addMenuItem(widget, U
selectmenu, "opera", U
"opera.png")
selectmenu= U
karamba.createMenu(widget)
Of course, the functionality is missing at
this point. To allow us to assign function-
ality to the appropriate menu items, we
need a method to distinguish the individ-
karamba.execute("xmms" U
+ xmms_filename)
The internal number assigned by the sys-
Listing 2: Menu-Based Interaction
to tell XMMS to call the filename of the
“dropped” MP3 file.
01 import karamba
02
03 selectmenu=0
04 my_menu=[[],[]]
05
06 def initWidget(widget):
07 global selectmenu
08 global my_menu
09 selectmenu=karamba.createMenu(widget)
10 my_menu=[
11 "konqueror", karamba.addMenuItem(widget, selectmenu, "konqueror",
"konqueror.png")],
12 ["opera", karamba.addMenuItem(widget, selectmenu, "opera",
"opera.png")]
The Menu, Please
Adding another menu to supplement the
generic right-click drop-down is another
neat way of enhancing a theme. This
could be a quick launch menu that pops
up when you double-click with the left
or center mouse button, and allows you
to launch external applications. As it
would be inelegant to define an infinite
number of clickable areas in the .theme
file, we want to use the Python API for
this task.
To quickly try this one out, replace the
contents of the ~/.superkaramba/small_
text_xmms/small_text_xmms.py file with
the instructions in Listing 2. My apolo-
gies to professional developers for the
hack with the global variables , select-
menu and my_menu , which I used here
to keep things simple.
selectmenu is initially 0 and will repre-
sent the object ID of the menu later.
my_menu=[[],[]] creates a storage
framework for a two element list. The
list will be used later within the Python
program to map the menu items to the
13
14 def widgetClicked(widget, x, y, button):
15 global selectmenu
16 karamba.popupMenu(widget, selectmenu, x, y)
17
18 def menuItemClicked(widget, menu, id):
19 global my_menu
20 for index in my_menu:
21
if index[1] == id:
22
if index[0] == 'konqueror':
23
karamba.execute("konqueror")
24
elif index[0] == 'opera':
25
karamba.execute("opera")
26
27 print "My Python extension has been loaded!"
46
May 2004
www.linux-magazine.com
592681528.009.png 592681528.001.png
SuperKaramba
KNOW HOW
We will not be evaluating the x - y
coordinates and the mouse button
number in button , but if we did, we
could handle different areas within the
theme differently, or distinguish between
left and center mouse buttons. We could
map the right mouse button, but as
right-clicking the SuperKaramba theme
opens the SuperKaramba menu, this is
only a theoretical option.
Note that mouse clicks will always
perform the action defined in the .theme
file. In our case, this means that clicking
the clock will open both the clock setting
tool and the menu (see Figure 1).
To display the latter on screen, we
need the handle, which is stored in the
selectmenu variable. We can use global
selectmenu to retrieve this from the
global data space. The karamba.popup-
Menu(widget, selectmenu, x, y) function
allows us to pop up the menu at the
same coordinates ( x, y ) as the click. If
these coordinates are missing, the menu
pops up in the top left-hand corner (0,0)
of the theme.
When a user selects a menu item,
SuperKaramba responds with menuItem-
Clicked(widget, menu, id) . This function
uses id to provide the handle for the
menu item, and menu to provide the
appropriate menu. As the system assigns
handles arbitrarily, there is no real way
GLOSSARY
Figure 1: Python creating menus.
Global variable: The object orientied pro-
gramming paradigm tends to encapsulate
functions and variables in objects. For exam-
ple, assigning a variable for the button color,
makes it easy to create multiple buttons with
different colors, as the variable is stored in the
“button” object. In contrast, global variables
are visible throughout the program. If you
then assign the color green as the button
color, any buttons you create will be green.
Multithreaded: Programs are not normally
capable of performing more than one action
at a certain time. For example, while a pro-
gram is waiting for a file to open, it cannot
perform any other activities. Threads allow a
program to perform multiple tasks simulta-
neously. Instead of sitting around waiting for
file to open, a multithreaded program would
assign the wait time to another thread.
ual items. We can store konqueror or
opera with the handle created by the
addMenuItem() item in my_menu . The
content of the variables looks like this,
depending on the handle:
(['konqueror', -22], U
['opera', -23])
We now have a menu. Of course it won’t
be displayed immediately, but when the
SuperKaramba theme is double-clicked;
that is, whenever a widgetClicked(wid-
get, x, y, button) signal is generated.
PHP hosting
Home Pro account
Email virus scanning, web mail, SMS email alerts and 1 GB
of web space on reliable, Linux servers, make this the ideal
account for great value and great features. With support for
Perl, PHP and CGI and optional MySQL databases, Home Pro
gives you everything you need to create high spec, feature
rich websites.
Also includes:
• Matrix Stats - real time data on visits to your site
• 300 POP3 email and forwarding addresses
• Easy to use website builder
• Access to URL security, streaming media and much more
• Manage everything from the web with our award
winning control panel
World class support
£ 8 . 99
that never closes
Every Fasthosts customer enjoys full access to
Xtreme Support: unsurpassed customer service,
faster turnaround for technical problems and an
unparalleled level of help and advice.
24 x 7, 365 days telephone, email & online support
Xtreme Support website - with knowledge base, FAQs and more
Trouble ticket system for a fast accurate technical response
With multiple internet connections and our advanced
UK data centre, it's no wonder we're known as
'the power behind web hosting'.
Monthly +VAT or
£70 annually
All your hosting needs
• Business packages from £14.99
• Developer packages from £19.99
• Unlimited Reseller package from £50
• Dedicated server solutions from £89
• UK's best value domain names at
www.ukreg.com
For instant advice and set up, call
0870 888 3631
or for more details and to launch your service within minutes, visit www.fasthosts.co.uk
Linux Apache
FREE
INSTANT SET - UP
592681528.002.png 592681528.003.png 592681528.004.png
KNOW HOW
SuperKaramba
to guess them, but we got around this by
storing them in global variables:
my_menu for the menu items, and select-
menu for the menu itself. As we only
have one menu, we do not need to han-
dle this distinction. In other words, we
only need main_menu from the global
data space.
for index in my_menu: allows us to
iterate through the elements in the
my_menu variable and map the lists it
contains to the index variable one by
one. During each iteration, we need to
check whether the menu item handle
passed by the signal matches the num-
ber stored in the second item of index :
…, we will launch Konqueror by calling
karamba.execute(“konqueror”) ; if not,
we use
API provides a number of additional
functions, which are documented at [5],
there are a few issues with the API. The
biggest issue is the fact that it cannot
handle dynamic sensors (see [1]). If we
wanted to add a feature to our theme to
support switching between various sen-
sors, we would be able to click to update
the text content, but we would be unable
to swap the underlying sensor display.
There is another problem here. Python
can only access elements it created itself.
If you intend to use a text element to tog-
gle a function, you need to create it with
the Python createText() function. Texts
defined by the .theme file cannot be
manipulated using the Python API.
elif index[0] == 'opera':
to check if Opera has been clicked.
If we merge the functions from List-
ings 1 and 2 to create a single file, we
can omit a few lines. For example, we
only need one instance of import
karamba at the beginning and one print
statement at the end of the file. Also, we
need to merge the content of the “ def
initWidget(widget): ” blocks to create a
single block. If one of the functions is
missing after you reload the theme,
delete the .pyc file, which is automati-
cally created in your theme directory.
if index[1] == id:
INFO
After finding the my_menu pair that cor-
responds to the menu item that was
clicked, we need to check which browser
entry it belongs to. If it is Konqueror …
The Borders of the Snake
Kingdom
Although it is amazingly simple to han-
dle such complex tasks as drag & drop in
SuperKaramba, and although the Python
[1] Introduction to SuperKaramba: Hagen
Höpfner,“Karamba on the Desktop”,
Linux Magazine Issue 41
[2] SuperKaramba:
http://netdragon.sourceforge.net/
[3] First steps with Python:
http://www.python.org/doc/Intros.html
[4] Sample theme:
http://wwwiti.cs.uni-magdeburg.de/
~hoepfner/download.html
[5] SuperKaramba Python API documenta-
tion: http://netdragon.sourceforge.net/
api.html
[6] SuperKaramba Python template: http://
netdragon.sourceforge.net/template.py
[7] Python string manipulation functions:
http://www.python.org/doc/2.3.3/lib/
module-string.html
[8] Loops and conditions in Python:
http://www.python.org/doc/2.3.3/ref/
compound.html
[9] Python Library Reference: http://www.
python.org/doc/2.3.3/lib/lib.html
if index[0] == 'konqueror':
Box 1: What is Python?
If you already speak another programming
language, you might not be too thrilled
about the prospect of having to learn a new
language just to keep SuperKaramba happy.
But for newcomers to programming, Python
has a few advantages, being a universal
language. One of the main reasons for this
is the fact that Python combines three
major programming paradigms in one.
Python can be used as an object oriented
language, just like C++ or Java, or as a pro-
cedural language like Pascal or C. At the
same time it is a scripting language like PHP
or Perl, which does not need to be compiled
by the user. It supports multiple inheritance,
can interface with databases and access net-
work protocols, and also supports
multithreaded programming.
Just like Java, Python source code is first
converted to byte code by a compiler. This
code shows up in the SuperKaramba theme
directory as an automatically generated file
with the .pyc suffix. The code is executed by
a virtual machine. Python is far quicker than
Java byte code.
If you move to Python from another pro-
gramming language, there is one thing you
will need to get used to: the definition of
contiguous blocks. Blocks are used to define
the statements that will be executed if a
particular condition is fulfilled. C uses curly
brackets for this, and in Shell programming
with Bash, the statement block of an if-then
condition is terminated with a fi .Pascal uses
the begin and end keywords. Python does
not use any of these methods: instead of a
tag, you simply indent a block of contiguous
statements.
Thus, two successive lines with the same
degree of indenting, form a block. If the
second line starts farther to the left than
the first line, it does not belong to the
block. A colon introduces a new level, as
the listings show. Lines with the same
degree of indenting that follow a def line,
belong to the definition of this function.
Unfortunately, Python needs at least one
function per level. This is why the template
file has a pass function instead of an empty
block. This function does not perform an
operation when the program is executed; it
is simply a placeholder that allows us to pop-
ulate the level as required.
On the one hand, the indenting trick ensures
that Python code is always neatly structured
and easy to read in contrast to code in other
programming languages. But it can drive
newcomers to distraction because a
function with the wrong level of indenting
simply drops out of the context of the block
where it should reside. Be aware of this
pitfall while experimenting with the
examples and creating your own extensions.
And make sure you use the right level of
indenting!
Hagen Höpfner has a
higher degree in
Computer Science
and is a member of
scientific staff at the
Otto-von-Guericke
University of Magde-
burg, Germany. Between time spent
tinkering with his collection of Linux
computers, Hagen likes to direct his
creative energy into song-writing,
composing lyrics, and playing the gui-
tar for a rock band called “Gute Frage
!?” (translates “Good Question”).
48
May 2004
www.linux-magazine.com
592681528.005.png
Zgłoś jeśli naruszono regulamin