Quick and dirty linux GUI programming

Posted May 28th, 2009 by kaikokan

I've been experimenting with GTK2 for a while and reading the tutorials a bit. I started a while ago by reading the source code for some perl GUI programs I found on my system. More specific I've been playing around with the podviewer and I was thinking about adding some functionality to it, to learn from the process.

Podbrowser

As I was reading about this tool I discovered the podbrowser which is a nice tool which does everything the podviewer does plus all the things I needed on top of that. I think it's based on the podviewer code as it looks a lot like it. This is also a great learning tool as it is open source and it also provides me with a gui program to browse the available perl documentation for modules installed on my system.

Reading up

While analyzing the source code of these two tools I came to the conclusion it would make it easier to understand if I would read a little more about GTK2 as it was not completely clear to me how the interface is build up. It is easy to understand, very readable code but I think trying to build something trivial myself first could build my understanding more than trying to change more complex code.

Build a trivial program

So I thought of a reasonably trivial program I could write which would still be interesting enough and which can be build upon for a while to build some skill in perl GUI programming.
I think it would be nice to be able to build a GUI for linux command line programs, that could have some value in the future. As that could quickly become to complex for my purpose and it would probably drive me to start messing with the code for the utility I want to write a GUI for, I chose instead to start writing a GUI for native built in shell commands. I know this is not the most useful thing to do, but still it may become an interesting learning tool as I can write a GUI utility which shows the available commands and their options and executes them showing the results.

I started out with the most trivial I could think of: the ls command

Here's what I did:

First of all I've been reading a bit about how the layout of this GTK2 programs is build up, there are some very good tutorials available on this stuff. It all pretty much comes down to creating boxes and filling these boxes with widgets. A lot of code is standard and very reusable, so there's really not to much you need to learn as you can just save the snippets of code and reuse them in future code.

Start with a window

As this is a GUI program obviously we need a window to start with, I just took some pieces of code from the tutorials at the GTK2-perl site on sourceforge. Especially this one proved very helpful.

Add a horizontal box

A window can only hold one widget, not very useful in most cases so I added a horizontal box to the window end to that horizontal box I added a textView widget to test my first setup. Running this first program shows the window only, but in the same time it shows the program is working for now without problems.

http://www.handlewithlinux.com/downloads/code/commandViewer-step1

While this version is not very useful, it is a useful example as it demonstrates the textView. When you run this simple program you get a very small window containing a textbox. Type some text and the window will grow as you type. The text is still editable, we'll have to set it to only display text and not showing a cursor later. For now it's interesting as it shows it already has copy-paste functionality on the text typed in the box.

Show some text

For my next step I added a few more lines of code so the program at execution loads the textView with the listing of the current directory contents and I also added a checkbox to test the layout and functionality.
In this case the checkbox is already working and actually changing the contents of a variable it's only not visible because the textView is not updated when the checkbox is toggled.

#the variable we'll use in the command
my $var1="";

#create a new checkbox
my $btn_long = Gtk2::CheckButton->new("-l long listing");

#attach a sub to the toggled signal
$btn_long->signal_connect('toggled' =>sub {
if($btn_long->get_active){
$var1="-l";
}else{
$var1="";
}
});
#add the checkbox to box1
$box1->pack_start($btn_long, TRUE, FALSE, 0);

#make it visible
$btn_long->show;

#create content for textbox and put it in the textView's buffer
#just fill variable $content with the output of the ls command
my $content = `ls $var1 -a`;

#get the buffer for the textView
my $buffer = $textView->get_buffer();

#load the $content into the buffer
$buffer->set_text($content);

complete source for step2:

http://www.handlewithlinux.com/downloads/code/commandViewer-step2

More checkboxes

In step 3 I added a second checkbox to the box and I put the code for updating the textView in a sub so I can run it from the toggle subroutine of the checkbox. Now when you toggle the checkbox the result is updated immediately.

http://www.handlewithlinux.com/downloads/code/commandViewer-step3

Better Layout

The checkboxes in step 3 are aligned horizontally as they are in the same horizontal box as the textView widget. In step 4 I added another checkbox and I put them all together in a new vertical box which I added in turn to the horizontal box. Now the checkboxes are aligned vertically.

http://www.handlewithlinux.com/downloads/code/commandViewer-step4

Scrollbars

Interesting, but now we have another problem: When we have long listings sometimes the text is not visible in the textView area anymore. We need scrollbars, luckily this is simple too. There's a scrollbar widget it's a container and it's called scrolled window. We just create a new scrolledwindow object and add the textView widget to that. Presto! We can now scroll trough our text.

http://www.handlewithlinux.com/downloads/code/commandViewer-step5

Clean exit

In the next step I add a little code to stop the program when the window is closed, and some extra comments so I'll understand what it's doing 2 weeks from now.

http://www.handlewithlinux.com/downloads/code/commandViewer-step6

Finished

In step 7 I cleaned up the code a bit, added a few extra comments and formated the code to make the sequence in which things are done a little clearer. This is the final version of the code for now:

http://www.handlewithlinux.com/downloads/code/commandViewer-step7

Lots of ideas

I have a lot of ideas for things I can build upon this, I know it's nowhere near proper code yet but it provides an interesting base for further playing around. The nice thing I think it shows very well is how incredibly easy it is to write a basic GUI interface to a linux native command. Of course this still needs a lot of work to come anywhere near the real functionality of the ls command but there's a lot I can quickly build with just these few building stones. I think I'll try to put in some more functionality and some more graphical widgets. For instance a selectbox to select different commands and dynamically update the checkboxes with options available. Maybe some pipe function to pipe the current shown buffer to another Linux command (that way I can edit the buffer in the GUI before I send it to another command.

Well that's something for the future, for now I'm finished.

Comments are very welcome, it can take a while before they get published as you may be in another timezone.

This is the fourth article in a ongoing series about learning perl GUI programming. You may be interested in the other articles too. You can find the other articles here:
1. starting perl GUI programming
2. Installing Eclipse, the Epic Perl plugin and my first Perl GUI program
3. Open Source rocks! Learning from code by debugging
4. Quick and dirty linux GUI programming
5. resources for learning Perl Graphical Programming
6. Drawing and animating directly to the Desktop with Perl
7. Dynamically-creating-gui-objects-on-demand-in-Perl


Links

Anonymous 1 year 13 weeks 6 days 3 hours ago

It would be nice if you included links to the podviewer and podbrowser programs, so the rest of us could easily find them. Thanks.

podbrowser

admin 1 year 13 weeks 6 days 1 hour ago

http://jodrell.net/projects/podbrowser

the podviewer I just found on my system, it was installed with ubuntu I guess. I think it's in cpan anyway.

apt-get install podbrowser or something might work

see xdialog

Anonymous 1 year 13 weeks 6 days 5 hours ago

Are you re-inventing the wheel? Run 'sudo apt-get install xdialog' then check /usr/share/doc/xdialog/{examples,html}. It's been around for ages, and works great in my shell scripts.

It's about learning how to do something

admin 1 year 13 weeks 6 days 1 hour ago

I'm not saying this should be the preferred method to run the ls command ;-)
Thanks for the info though