p4

Next Previous Table of Contents

Now that we know how to create a menu we will make a nearly-real application with p4 . Thanks to the work of Lars Knoll, Antti Koivisto, Waldo Bastian and many others, we will be able to use a KHTML, a widget that is able to display an HTML page, and that using the kio library, is able to automatically retrieve a page from the net. Let's see how it works.


#include <kapp.h>
#include "p4.h"
 
int main( int argc, char **argv )
{
    KApplication a( argc, argv, "p4" );
 
    MainWindow *window=new MainWindow( "Tutorial - p4" );
    window->resize( 300, 200 );
 
    a.setMainWidget( window );
    window->show();
 
    return a.exec();
} 

main.cpp


#include <kmainwindow.h>
#include <kurl.h>
#include <kparts/browserextension.h> 
 
class QLineEdit;
class KHTMLPart;
 
class MainWindow : public KMainWindow
{
  Q_OBJECT
 
  public:
    MainWindow ( const char * name );
 
  public slots:
    void changeLocation();
    void openURLRequest(const KURL &url, const KParts::URLArgs & );
 
  private:
    QLineEdit *location;
    KHTMLPart *browser;
 
}; 

p4.h


#include "p4.h"
#include <qvbox.h>
#include <qlineedit.h>
#include <kapp.h>
#include <kmenubar.h>
#include <klocale.h>
#include <kpopupmenu.h>
#include <khtml_part.h>
 
MainWindow::MainWindow ( const char * name ) : KMainWindow ( 0L, name )
{
    setCaption("KDE Tutorial - p4");
    QPopupMenu * filemenu = new QPopupMenu;
    filemenu->insertItem( i18n( "&Quit" ), kapp, SLOT( quit() ) );
    QString about =
            i18n("p4 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");
 
    QPopupMenu *helpmenu = helpMenu(about);
    KMenuBar * menu = menuBar();
    menu->insertItem( i18n( "&File" ), filemenu);
    menu->insertSeparator();
    menu->insertItem(i18n("&Help"), helpmenu);
 
    QVBox * vbox = new QVBox ( this );
 
    location = new QLineEdit ( vbox );
    location->setText( "http://localhost" );
 
    browser=new KHTMLPart( vbox );
    browser->openURL( location->text() );
 
    connect( location , SIGNAL( returnPressed() ),
                this, SLOT( changeLocation() ) );
 
    connect( browser->browserExtension(),
	SIGNAL( openURLRequest( const KURL &, const KParts::URLArgs & ) ),
	this, SLOT( openURLRequest(const KURL &, const KParts::URLArgs & ) ) );

    setCentralWidget( vbox );
}                                                                               

void MainWindow::changeLocation()
{
    browser->openURL( location->text() );
} 

void MainWindow::openURLRequest(const KURL &url, const KParts::URLArgs & )
{
    location->setText(url.url());
    changeLocation();
} 

p4.cpp

The first difference with p3 is in p4.h . We aren't going to use the menu to anything but exiting the application, so we have removed the two slots for the Open and Save dialogs.

  public slots:
    void changeLocation();
    void openURLRequest(const KURL &url, const KParts::URLArgs & );
 
  private:
    QLineEdit *location;
    KHTMLPart *browser;

We are defining a changeLocation() slot to be called when the user wants to load a new page by clicking the Enter key on the location bar . The openURLRequest method is an slot which gets called when the user clicks on a url link in the html page, and the html page request us to open that url (which gets passed as a parameter). We are going to use two widgets, one is a QLineEdit widget and the other is a KHTMLPart . QLineEdit implements a line in which the user may edit some text, in this case, the html page that is displayed in the KHTMLPart.

    QVBox * vbox = new QVBox ( this );

We are using a QVBox to manage the layout of the widget. As we want to display the QLineEdit widget and the KHTMLPart one under the another, this is the perfect task for a QVBox. This widget automatically puts all its children in a vertical layout (as well as QHBox puts them in an horizontal layout), and manages to update their geometry automatically whenever the QVBox is resized. Note that you can use more complex layout classed (such as QGridLayout) to manage the geometry, or even do it manually as other toolkits do. But this simplifies the code, while being extremely powerful . Note, for example, that whenever the user resizes the window, the KHTMLPart always takes the full height while the QLineEdit always takes a fixed height, and they both always take the full width of the application's main window.

    location = new QLineEdit ( vbox );
    location->setText( "http://localhost" );

We create the a QLineEdit object, location, as a child of vbox and set some text to be shown by default.

You can browse the internet with this application, but as many people will only test this with a local web server, let's put the local host as default site. Be sure to have apache running on your machine for this application (and the next ones !) to work.

    browser=new KHTMLPart( vbox );
    browser->openURL( location->text() );

With this code, we create the browser object as a child of vbox, so it will be added under the location bar.

Calling openURL we ask our KHTMLPart to download the url pointed to by the text that is in the location bar, and display it.

    connect( location , SIGNAL( returnPressed() ),
                this, SLOT( changeLocation() ) );

When the user press the return key on the location bar, it emits a returnPressed() signal, with this code we connect it to the changeLocation() slot in this object. We can call connect directly (without using QObject::), because we are now inside a class the inherits QObject (indirectly, as we inherit KMainWindow, which inherits QWidget which inherits QObject).

    connect( browser->browserExtension(),
          SIGNAL( openURLRequest( const KURL &, const KParts::URLArgs & ) ),
          this, SLOT( openURLRequest(const KURL &, const KParts::URLArgs & ) ) );
    

We are now connecting another signal with a slot. The nice thing now is that browser emits a signal openURLRequest( const KURL &, const KParts::URLArgs & ) when it wants to open a URL (for example, because the user clicked on a url) . In fact, the signal is not emitted by the own KHTMLPart object, but by its browserExtension object, and that's why we use it as the signal emitter object.

Btw, the second parameter is not used, so we will ignore it as it's only used in very special cases.

    setCentralWidget( vbox );

We now set the vbox widget as the central widget of this KMainWindow object.

    browser->openURL( location->text() );

The changeLocation slot simply asks browser to open the url written in the location bar.

void MainWindow::openURLRequest(const KURL &url, const KParts::URLArgs & )
{
    location->setText(url.url());
    changeLocation();
}

This is the code that gets called when the browser wants to open a new url, as we remember, the url() method in a KURL object returns the complete url, so we write it into the location bar. Then we call changeLocation(), to set the url stored in the location bar in the html part.

Think of the functionality you get with only 96 lines, imagine what you can do in 1000 lines ! :-)

Next Previous Table of Contents


© 1999-2002 Antonio Larrosa