Ruby Logo Home

p3

Next Previous Table of Contents

Screenshot of tutorial three

We already created a simple KDE application in p2, but in most cases, you'd like to use a more complex user interface than a simple button :-) , so let's see how to add a standard main widget.


require 'Korundum'
 
class MainWindow < KDE::MainWindow
    slots 'fileOpen()', 'fileSave()'
 
    def initialize( name )
        super(nil, name)
        setCaption("KDE Tutorial - p3")

        filemenu = Qt::PopupMenu.new
        filemenu.insertItem( i18n( "&Open" ), self, SLOT('fileOpen()') )
        filemenu.insertItem( i18n( "&Save" ), self, SLOT('fileSave()') )
        filemenu.insertItem( i18n( "&Quit" ), $kapp, SLOT('quit()') )
		
        about =
            i18n("p3 1.0\n\n" +
                 "(C) 1999-2002 Antonio Larrosa Jimenez\n" +
                 "larrosa@kde.org\t\tantlarr@supercable.es\n" +
                 "Malaga (Spain)\n\n" +
                 "Simple KDE Tutorial\n" +
                 "This tutorial comes with ABSOLUTELY NO WARRANTY\n" +
                 "This is free software, and you are welcome to redistribute it\n" +
                 "under certain conditions\n")
        helpmenu = helpMenu( about )
		
        menu = menuBar()
        menu.insertItem( i18n( "&File" ), filemenu )
        menu.insertSeparator()
        menu.insertItem( i18n( "&Help" ), helpmenu )
 
        hello = Qt::TextEdit.new(
        i18n("<H2>Hello World !</H2><BR>This is a simple" +
	    " window with <I><font size=5><B>R<font color=red" +
	    " size=5>ich </font><font color=blue size=5>Text" +
	    "</font></B></I> capabilities<BR>Try to resize" +
	    " this window, all this is automatic !"), "", self )
        setCentralWidget(hello)
    end
 
    def fileOpen()
        filename = KDE::FileDialog.getOpenURL( nil, "*", self )
        msg = i18n("Now this app should open the url #{filename.url()}") 
        KDE::MessageBox.information( nil, msg, i18n( "Information" ), 
		"fileOpenInformationDialog" )
    end
 
    def fileSave()
        filename = KDE::FileDialog.getSaveURL( nil, "*", self )
    end
end

    about = KDE::AboutData.new("p3", "Tutorial - p3", "0.1")
    KDE::CmdLineArgs.init(ARGV, about)
    a = KDE::Application.new()
    window = MainWindow.new( "Tutorial - p3" )
    window.resize( 400, 300 )
	
    a.mainWidget = window
    window.show
	
    a.exec 


p3.rb

This code seems much more complex, but it isn't that much ;), let's have a look.

The sources in p3.rb aren't that different from p1 or p2. The only difference is that now we create a MainWindow object instead of a Qt::PushButton one and that we don't specify nil as parent widget because it's taken by default.

Also, we don't connect any signal here, as MainWindow doesn't have any clicked() signal.

class MainWindow < KDE::MainWindow

In p3.rb, we define the MainWindow class, inherited from KDE::MainWindow, which is included in the kdelibs and includes all the methods needed to create a normal KDE application with a menu, a toolbar, a status bar, etc.

 
  slots 'fileOpen()', 'fileSave()'

As we learnt in p1, slots are normal methods, so they can be public, protected or private as any other. The only difference is that we must specify corresponding slots declarations. Let's see now the real thing, in p3.rb:

        filemenu = Qt::PopupMenu.new
        filemenu.insertItem( i18n( "&Open" ), self, SLOT('fileOpen()') )
        filemenu.insertItem( i18n( "&Save" ), self, SLOT('fileSave()') )
        filemenu.insertItem( i18n( "&Quit" ), $kapp, SLOT('quit()') )

filemenu is a Qt::Popupmenu, that is, a menu that contains "items" that the user clicks on to perform a given action.

We insert these items by calling insertItem. The first parameter is the text that should be on the menu, with a & character just before the letter that we want to use to access this entry in a faster way. By using i18n, we ensure that this text will appear in the user's language.

When the user selects an entry, the menu emits a signal that can (and should!) be connected to a function to do something. For convenience, instead of using connect, we can connect this signal directly when defining the item. That's what we do in the second and third parameters. We connect the Open menu entry to the fileOpen() slot in self, the Save entry to the fileSave() slot in self, and the Quit entry to the quit() slot in the application as we did in p1 and p2.

We note that $kapp is a convenient global variable that can be used to access the current KDE::Application instance. If you have an older version of Korundum (KDE 3.3.0 or before), you will need to replace $kapp with 'KDE::Application.kApplication()', which is a bit more long winded, but means the same thing.

        about =
            i18n("p3 1.0\n\n" +
                 "(C) 1999-2002 Antonio Larrosa Jimenez\n" +
                 "larrosa@kde.org\t\tantlarr@supercable.es\n" +
                 "Malaga (Spain)\n\n" +
                 "Simple KDE Tutorial\n" +
                 "This tutorial comes with ABSOLUTELY NO WARRANTY\n" +
                 "This is free software, and you are welcome to redistribute it\n" +
                 "under certain conditions\n")
        helpmenu = helpMenu( about )

We first concatenate all those strings inside a String.

Then, we create another popup menu, but we use the KDE::MainWindow method, helpMenu. By doing this, we get a standard help menu with entries for the documentation, an about dialog, etc. The about dialog includes all the text that we've written in the about string.

        menu = menuBar()
        menu.insertItem( i18n( "&File" ), filemenu )
        menu.insertSeparator()
        menu.insertItem( i18n( "&Help" ), helpmenu )

We are prepared to finish the creation of our menu. First, we get the menubar used in our main window by using menuBar(). As there's no menubar yet, this method will create it for us and will return an empty KDE::MenuBar object that we can fill. KDE::MenuBar provides a standard KDE menu, with the common look across applications.

Then, we insert the two Qt::PopupMenus that we already have, with a separator in between, and we're done creating the menu.

        hello = Qt::TextEdit.new(
        i18n("<H2>Hello World !</H2><BR>This is a simple" +
	    " window with <I><font size=5><B>R<font color=red" +
	    " size=5>ich </font><font color=blue size=5>Text" +
	    "</font></B></I> capabilities<BR>Try to resize" +
	    " this window, all this is automatic !"), "", self )
        setCentralWidget(hello)

I wanted this application to do something nice and simple, so we are going to add a Qt::TextEdit widget. This widget is a useful Rich Text viewer, where we can specify the type of font and colour among other styles. After creating it with the above text, we set it as the central widget for this window.

But, what is a central widget? A central widget is the widget that the user can see under the menu (or toolbar, if any). That is, the document that the user has opened, or anything that is not standard part of KDE::MainWindow (that is, the menu, toolbars and status bar)

    filename = KDE::FileDialog.getOpenURL( nil, "*", self )

We are now looking at the fileOpen slot implementation. This code opens a open file dialog that allows the user to open an existing file.

The three parameters indicate the directory to start the browse on (we don't care what it is, so it takes the current one as default), the filters (to browse only through files with a given regular expression), and the parent object.

Now we have the url the user wants to open stored on filename.

Note that you're encouraged to allow the user to open any URL not just local files. For this, we have used a getOpenURL dialog, which lets the user select any url. Check below for an example on how to use the KIO library.

    msg = i18n("Now this app should open the url #{filename.url()}")

We can manipulate strings with the String class, in fact, we're using this to compose a message that we're going to show (as opening a file isn't inside the objectives of this tutorial).

Btw, filename.url() is a String containing the url stored on the KDE::URL object, that is, protocol+hostname+path+query+everything :-).

    KDE::MessageBox.information( nil, msg, i18n( "Information" ), "fileOpenInformationDialog" )

With the KDE::MessageBox class, and its class methods, we can create a variety of message boxes. In this example, we use a information box to display which file it should have opened. The third parameter is the caption message and the fourth one is an identifier, that is used to store in a config file ( usually ~/.kde/share/config/p3rc ) if the user wants or prefer not to see this dialog anymore (thing that he can decide by using a checkbox in the dialog)

Note that we haven't written any way to get back to show the dialog again! This is done simply by calling KDE::MessageBox.enableAllMessages(), but I think it would be a nice exercise for the reader of this tutorial to add a menu that makes this call on top of p3 :-) .

    filename = KDE::FileDialog.getSaveURL( nil, "*", self )

Finally, in fileSave we call the analogue to getOpenURL, getSaveURL.

We should note that if we use getOpenURL, we should make use of the KIO library to get a remote file if that's what the user wants, this is basically done by doing something like this:

    tmpFile = ""
    if KIO::NetAccess.download( "ftp://ftp.kde.org/myfile.tgz", tmpFile )
      # Do whatever you want with a _local_ file stored as tmpFile 
	  ...
      KIO::NetAccess.removeTempFile( tmpFile )
    end

But that is out of the scope of this tutorial (altough I may increase it in the future with an example on libkio).

Well, I hope it wasn't too difficult .

Next Previous Table of Contents


© 1999-2002 Antonio Larrosa © 2004 Richard Dale