Ruby Logo Home

p7

Next Previous Table of Contents

Screenshot of tutorial seven

In this step, we will attempt to increase the usability of p5, in order to learn how to use a few other standard KDE classes that should be used in nearly every application.


 
require 'Korundum'
 
class Browser < KDE::MainWindow
    k_dcop  'void setURL(QString)'
	
    slots   'fileSetDefaultPage()', 
            'changeLocation()',
            'bookLocation()',
            'gotoPreviousPage()',
            'openURLRequest(const KURL&, const KParts::URLArgs&)'
 
    TOOLBAR_ID_ADDBOOKMARK = 1
    TOOLBAR_ID_BACK = 2
    TOOLBAR_ID_QUIT = 3
 
    def initialize( name )
        super(nil, name)
        setCaption("KDE Tutorial - p7")
        @history = []

        filemenu = Qt::PopupMenu.new
        filemenu.insertItem( i18n( "&Set default page" ), 
				    self, SLOT( 'fileSetDefaultPage()' ) )
        filemenu.insertItem(i18n( "&Quit" ), $kapp, SLOT( 'quit()' ))
        about =
                i18n("p7 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)
 
        toolbar = KDE::ToolBar.new(self)

        icons = KDE::IconLoader.new()
        toolbar.insertButton(icons.loadIcon("reload", KDE::Icon::Toolbar), TOOLBAR_ID_ADDBOOKMARK,
                              SIGNAL('clicked(int)'),self,SLOT('bookLocation()'),true,
                              i18n("Add to Bookmarks"))
        toolbar.insertButton(icons.loadIcon("back", KDE::Icon::Toolbar), TOOLBAR_ID_BACK,
                              SIGNAL('clicked(int)'),self,SLOT('gotoPreviousPage()'),
                              false, i18n("Back to previous page"))
        toolbar.insertButton(icons.loadIcon("exit", KDE::Icon::Toolbar), TOOLBAR_ID_QUIT,
                              SIGNAL('clicked(int)'),$kapp,SLOT('quit()'),true,
                              i18n("Quit the application"))
        addToolBar(toolbar)
 
        vbox = Qt::VBox.new( self )
 
        @location = Qt::LineEdit.new( vbox )
 
        config = $kapp.config()
        config.setGroup("Settings")
        @location.text = config.readEntry( "defaultPage", "http://localhost")
 
        connect( @location , SIGNAL( 'returnPressed()' ),
                    self, SLOT( 'changeLocation()' ) )
 
        split = Qt::Splitter.new( vbox )
        split.setOpaqueResize()
        
        @browser = KDE::HTMLPart.new( split )
        @browser.openURL( KDE::URL.new(@location.text()) )
 
        connect( @browser.browserExtension(),
	            SIGNAL( 'openURLRequest( const KURL&, const KParts::URLArgs& )' ),
	            self, SLOT( 'openURLRequest(const KURL&, const KParts::URLArgs& )' ) )           	     
        setCentralWidget(vbox)
    end
  
    def changeLocation()
        @history.push( @browser.url().url() );
        toolBar().setItemEnabled( TOOLBAR_ID_BACK, true)
        @browser.openURL( KDE::URL.new(@location.text()) )
    end
 
    def setURL( url )
        @location.text = url
        changeLocation()
    end
 
    def openURLRequest(url, part)
        setURL( url.url() )
    end

    def gotoPreviousPage()
        @location.text = @history.pop() 
        if @history.empty?
            toolBar().setItemEnabled(TOOLBAR_ID_BACK, false)
        end
        @browser.openURL( KDE::URL.new(@location.text()) )
    end
 
    def bookLocation()
        dcopRef = KDE::DCOPRef.new("p8", "BookMarkList")
        if ! dcopRef.add(@location.text())
            Qt.qWarning("Error with DCOP\n")
        end
    end
 
    def fileSetDefaultPage()
        config = $kapp.config()
 
        config.group = "Settings"
        config.writeEntry( "defaultPage", @browser.url().url() )
    end
end

    about = KDE::AboutData.new("p7", "Tutorial - p7", "0.1")
    KDE::CmdLineArgs.init(ARGV, about)
    a = KDE::UniqueApplication.new()
	
    window = Browser.new( "Tutorial - p7" )
    window.resize( 300, 200 )
	
    a.mainWidget = window
    window.show
	
    a.exec 


p7.rb

The first thing we do is to add a DCOP interface to p7 for p8 (the next generation on bookmark lists :-) ) to use. It's very similar to the one in p6, so I won't comment on it.

    a = KDE::UniqueApplication.new()

Here we create a KDE::UniqueApplication, rather than a KDE::Application as before. This means that only a single instance of the app will ever be started, and it will always be known to DCOP as 'p7'. If we had created a KDE::Application it would be given a name 'p7-process id', such as 'p7-2469'.

    TOOLBAR_ID_ADDBOOKMARK = 1
    TOOLBAR_ID_BACK = 2
    TOOLBAR_ID_QUIT = 3

Ok, we're now looking at the beginning of p7.rb. Here we define some identifiers to identify the toolbar buttons. This isn't always needed and you may create toolbars letting the toolbar class assign default identifiers. But as we're going to enable/disable toolbar buttons, it's more clear to do it this way.

    def initialize( name )
        super(nil, name)
        setCaption("KDE Tutorial - p7")
        @history = []

        filemenu = Qt::PopupMenu.new
        filemenu.insertItem( i18n( "&Set default page" ), 
				    self, SLOT( 'fileSetDefaultPage()' ) )

We're going to name this object Browser. There's now another item on the File menu, it will be used to set the actual page to be the default one that will be downloaded when running the application. This will show us how to store a configuration variable.

        toolbar = KDE::ToolBar.new(self)

KDE::ToolBar is the class that implements a tool bar in KDE. By using it you automatically get the standard look of tool bars, a little handle to move it in and out of the window, etc.

        icons = KDE::IconLoader.new()
        toolbar.insertButton(icons.loadIcon("reload", KDE::Icon::Toolbar), TOOLBAR_ID_ADDBOOKMARK,
                              SIGNAL('clicked(int)'),self,SLOT('bookLocation()'),true,
                              i18n("Add to Bookmarks"))
        toolbar.insertButton(icons.loadIcon("back", KDE::Icon::Toolbar), TOOLBAR_ID_BACK,
                              SIGNAL('clicked(int)'),self,SLOT('gotoPreviousPage()'),
                              false, i18n("Back to previous page"))
        toolbar.insertButton(icons.loadIcon("exit", KDE::Icon::Toolbar), TOOLBAR_ID_QUIT,
                              SIGNAL('clicked(int)'),$kapp,SLOT('quit()'),true,
                              i18n("Quit the application"))

We are going to add three buttons, the first one will be used instead of the big (and if you allow me, ugly) button that we used on p5. The second button will be used to go back to the previous visited page, so we are going to need a way to handle the history of visited pages. Finally, the third button will be used to quit the application (note: The user interface authorities recommend not to put a button on the toolbar to quit the application, anyway, as this is not a real application, we are going to omit this serious advice).

icons.loadIcon("reload", KDE::Icon::Toolbar) is a method that automatically searches the reload icon (wherever it may be, given that it's on a standard place for toolbar icons, like $KDEDIR/share/toolbar or $KDEDIR/share/apps/<appname>/toolbar ) and returns a valid QPixmap object that stores it.

The next parameter is the identifier we are going to use later to refer to this button, then comes the signal we are going to connect and the object that will receive it, followed by the slot that will be called. Note that most times, you won't need to worry about toolbar buttons, so you can just use 0 as the identifier for every button as you don't need to assign an unique indentifier to each one. An exception to this is when you want to enable/disable a button, as we want to do with the back button.

        addToolBar(toolbar)

We have finished constructing the toolbar, so we add it to the main widget with addToolBar. addToolBar doesn't follow the same naming style as setMenu because you're not restricted to just use a toolbar (as you are with menus), so you're not setting it, but adding it.

        config = $kapp.config()
        config.setGroup("Settings")
        @location.text = config.readEntry( "defaultPage", "http://localhost")

We already know what $kapp is, but we haven't used the config() method before. This method returns the active KDE::Config object of this application. KDE::Config is used to store the configuration variables of an application. It automatically stores the keys on the application configuration file and restores them when running the application again.

Once we have the config object, we set the active group to Settings to work on it. Groups are used to better structure the configuration file.

Finally, instead of using the "http://localhost" string as the default location, we read the application configuration. defaultPage is the name of the key we want to read, and "http://localhost" is the default value that is returned in case the config file doesn't store any value for defaultPage

You can also read integer values with KDE::Config.readNumEntry, boolean values with KDE::Config.readBoolEntry, etc.

    def setURL( url )
        @location.text = url
        changeLocation()
    end

This method is now used to generically set a given url. Currently this function can be called by the DCOP interface or when the user clicks on a link. We first set the location text to display the url, and then call the changeLocation method.

    def changeLocation()
        @history.push( @browser.url().url() );
        toolBar().setItemEnabled( TOOLBAR_ID_BACK, true)
        @browser.openURL( KDE::URL.new(@location.text()) )
    end

changeLocation (which is also connected to the enterPressed() signal in the location object) is used as the central place to load a new page once the url is already on the location bar. It is done this way to implement history capabilities into p7.

We note now that we defined a @history array in the constructor.

Now we get the default toolbar (if there were more, we could get the other ones by using an identifier as a parameter to toolBar), and enable the back button to let the user click on it.

Finally, we open the new url in the @browser widget by getting the url from the location bar.

    def gotoPreviousPage()
        @location.text = @history.pop() 

When the user wants to go back to the previous page we just take out the last inserted element from the history stack (with pop as it's a stack after all :-) ) and put it on the location bar. The string is removed from the stack, so the next time we call pop, we take the previous url, and so on until the stack is empty.

        if @history.empty?
            toolBar().setItemEnabled(TOOLBAR_ID_BACK, false)
        end
        @browser.openURL( KDE::URL.new(@location.text()) )
    end

If the stack is empty, we better disable the back button, once we add another element, the button is enabled again in changeLocation(). Then, we open the popped url in the browser.

    def fileSetDefaultPage()
        config = $kapp.config()
 
        config.group = "Settings"
        config.writeEntry( "defaultPage", @browser.url().url() )
    end

Finally, we implement the method that is connected to the Set default page menu item. This method stores the current url in the configuration file of this application.

First we get the KDE::Config object and set the Settings group as we did in the constructor. Then, we write a new entry with writeEntry.

The first parameter is the name of the key and the second one is the value we set it to. We can use writeEntry with different data type variables in the second parameter (Integer, Boolean, Float, String, Array of Strings, Qt::Font, etc).

We are now reaching the end of the tutorial, but first, we have to make a little change to p8 so that it communicates with p7 in order to set the current page when you click on a url in the bookmark list (in other case, there's not much point in having a bookmark list :-) )

Next Previous Table of Contents


© 1999-2002 Antonio Larrosa © 2004 Richard Dale