" Dont judge those who try and fail, judge those who fail to try "

Beginning KDevelop Programming Version 3.x

Chapter One :- Introducing KDevelop Chapter Two :- The KDE Application Chapter Three :- Common Widgets Chapter Four :- Containers And Views Chapter Five :- Database Programming With MySQL Chapter Six :- Input And Display Chapter Seven :- KDE Display Widgets Chapter Eight :- KDE Buttons And Input Chapter Nine :- KDE Containers And Views Chapter Ten :- Custom Widgets Chapter Eleven :- Events Chapter Twelve :- Drawing Chapter Thirteen :- Global Information and Configuration Files Chapter Fourteen :- A Simple Editor Application

Appendices

Appendix A :- Upgrading KDevelop

Downloads

PDF

Beginning KDevelop Programming ( 13.4 mb )

ZIP

Chapter One Source ( 1.2mb ) Chapter Two Source ( 3.8 mb ) Chapter Three Source ( 6.9 mb ) Chapter Four Source ( 6.4 mb ) Chapter Five Source ( 6.6 mb ) Chapter Six Source ( 3.6 mb ) Chapter Seven Source ( 2.2 mb ) Chapter Eight Source ( 2.2 mb ) Chapter Nine Source ( 1.1 mb ) Chapter Ten Source ( 5.3 mb ) Chapter Eleven Source ( 1.6 mb ) Chapter Twelve Source ( 5.2 mb ) Chapter Thirteen Source ( 3.8 mb ) Chapter Fourteen Source ( 616 kb )

Contributions

Contributors Page

Contacts

Author

[email protected]

Page Designer

[email protected]

Chapter Six :- Input And Display

As we have already seen such widgets as the QComboBox and the QLineEdit, etc we shall restrict this chapter to the Widgets in the Input and Display panels that we haven't seen before. This gives us room to write a couple of programs that although perhaps not being dramatically useful will give an idea of how the widgets work.

Inputs

We start with the Inputs and have a design that looks like,


Here we see the development view of the ChapterSixDatesAndTimes example which is created as a Simple Designer based KDE Application like all the examples we have seen so far. The example is split into three obvious groups the first group being the QTimeEdit widget which is adjusted with QSlider widgets in the top left. The second is the QDateEdit which is controlled by the QScrollBar's on the top right and the QDateTimeEdit widget which is controlled through the QDial widgets along the bottom.

A lot of time is spent in some manuals going into all the details of times and dates but from a programming perspective unless you are going to be writing these sorts of widgets then the majority of the time you will spend using them will be to either read or write the data. Setting the current date and time is just as simple in KDE as it is in other systems

setDate( QDate::currentDate() );
setTime( QTime::currentTime() );

should have you covered most of the time, unless you want to get really specific and we'll see how to do that shortly.

The controls on the form be they QSliders, QScrollbar or QDials operate in the same way each one has the valueChanged signal handled in the code, so that the public slots section of the header is almost a list of valueChanged handlers,

virtual void resetDateButton_clicked();
virtual void yearScrollBar_valueChanged( int yearScollBarValue );
virtual void monthScrollBar_valueChanged( int monthScrollBarValue );
virtual void dayScrollBar_valueChanged( int dayScrollBarValue );
virtual void hoursSlider_valueChanged( int hoursSliderValue );
virtual void minutesSlider_valueChanged( int minutesSliderValue );
virtual void secondsSlider_valueChanged(int secondsSliderValue );
virtual void resetTime_clicked();
virtual void resetDateButtonDials_clicked();
virtual void secondsDial_valueChanged( int secondsDialValue );
virtual void minutesDial_valueChanged( int minutesDialValue );
virtual void hoursDial_valueChanged( int hoursDialValue );
virtual void yearDial_valueChanged( int yearDialValue );
virtual void monthDial_valueChanged( int monthDialValue );
virtual void dayDial_valueChanged( int dayDialValue );

with the exception of the three buttons that are used for automatically setting the dates.

When we implement these functions in the code we follow exactly the same process for both the dates and times

QTime time;
time.setHMS( timeEdit->time().hour(), minutesSliderValue, timeEdit->time().second() );
timeEdit->setTime( time );

This code is from the minutesSlider_valueChanged function and the same format is repeated throughout the class file. We start by creating a QTime object and then setting the time. as we are only changing the time for one item, in this case minutes we get in this case both the hours and seconds values from the control itself using the QTime second and the QTime hour functions that are accessed through the QTimeEdit time function. Once we have set the time object we pass it to the QTimeEdit widget with the setTime function.

The code from one of the date functions is,

QDate date;
date.setYMD( dateEdit->date().year(), monthScrollBarValue, dateEdit->date().day() );
dateEdit->setDate( date );

As you can see they are conceptually the same except we are dealling with dates instead of times. Which just leaves the buttons which set the dates and times in there widgets using the currentDate and currentTime functions in the setDate and setTime function calls.


Tip Of The Day

When your overriding the signal handlers for your project it is possible to mess things up in a way that could be a pain if you don't know how to fix it. At one point I added a signal handler for a button click and realised that I hadn't named the button properly and it was using the default name. Because I prefer to have my variables explicitly named so there is no confusion, for me at least, about what they are and do. So I cancelled the dialog that asks you to select the class that you want to handle the signal. I was then faced with a dialog that told me that KDevelop could not find the class that implemented the .ui file.

What we need to do in this case is manually set up the implementation for the file this is done by right clicking on the .ui file in the Automake Manager,


and selecting the Create or Select Implementation option which will give us the implementation dialog we would normally get when starting to handle signals within a project.


We select the class we wish to use to implement the signals and everything is back to normal.

Displays

For the displays example we start with an application that looks like,


This is a simple enough layout in that the main area is covered with a QTextBrowser and a line of widgets below it. From left to right the little green Qt square is the QPixmapLabel which is next to a standard button and then there is a small progress bar ( QProgressBar ) and a LCD line counter, QLCDNumber.

The idea behind the application is that you browse for a file open it and then while it is opening the progress bar moves along, the LCD Number display counts the lines and the QPixmapLabel is replaced with the current icon for the local file. The driving functionality for the program is the open file button which contains the code,

        
KURL kurlFile = KFileDialog::getOpenURL();
        
if( kurlFile.isEmpty() == false )
    openFile( kurlFile );

This time we are using a static function of the KFileDialog class which just returns the KURL for the file. All we do with this function is show the KFileDialog to get a value and then call the function that does the work if a value is returned.

The main function is the openFile function which looks like this,

QFile file( fileName.pathOrURL() );
        
// first of all get the number of lines in the file
//
int nNumberOfLines = 0;
QString strLine;

        
// Set up the bits and pieces
//
progressBar->setProgress( 0 );
        
lcdNumber->display( 0 );
        
// get the pixmap for the opened file
// 

KFileItem *fileInfo = new KFileItem( KFileItem::Unknown, KFileItem::Unknown, fileName, true );
pixmapLabel1->setPixmap( fileInfo->pixmap( 0 ) );
delete fileInfo;
        
// now load the file
        
nNumberOfLines = 0;
textBrowser->clear();
        
if( file.open( IO_ReadOnly ) == true )
{
    QTextStream stream( &file );
    while( stream.atEnd() == false )
    {
       textBrowser->append( stream.readLine() );
       nNumberOfLines++;
       progressBar->setProgress( nNumberOfLines );
       lcdNumber->display( nNumberOfLines );
    }
        
    file.close();
}
else
{
    KMessageBox::error( this, "Unable to open the file " + fileName.pathOrURL() );
    return;
}

At the start of the function the file name, including path is associated with a QFile object, nothing is done yet this just initialises a QFile object so we initialise a few variables, set the progress bar and the lcd display to zero and then set the QPixmapLabel for the file.

The Pixmap for a file is discovered using the KFileItem class which is used quite extensively through the KDE code and can be set up using the

KFileItem::KFileItem( mode_t _mode, mode_t _permissions, const KURL &_url,

bool _determineMimeTypeOnDemand = false )

constructor. I point this out because it was a pig to work this one out because it is not immeadiately obvious that you can ignore the mode_t parameters by passing in KFileItem::unknown and then passing in true for the _determineMimeTypeOnDemand which has the effect of saying to the constructor here's the KURL for the file work the rest out for yourself which it does but I'd still have preferred a KFileItem( KURL url ) constructor.

Once we have this information sorted out we can try to open the file.

If the file does not open then we display a message and then exit the function. If the file opens successfully we create a QTextStream object to read the text from the file. Note that although we are using a QTextStream I have deliberately not added any filtering to restrict the type of file that is opened.

The main piece of code is in the while loop,

while( stream.atEnd() == false )
{
   textBrowser->append( stream.readLine() );
   nNumberOfLines++;
   progressBar->setProgress( nNumberOfLines );
   lcdNumber->display( nNumberOfLines );
}

which reads in the file line by line and then adds each line to the QTextBrowser and increments both the QProgressBar and the QLCDNumber widgets.


The image above is of the application running and displaying one of it's own .moc files. And the the image below is of the application displaying it's own makefile. The application will expand to full screen but the pictures are clearer if I don't have to shrink them.


Files And Some Common Dialogs

The final demonstration project for chapter six is the KDEChapterSixFiles project which displays some of the information that we get from using the KFileItem class that we used in the previous example and we'll also see how to use some of the common dialogs, such as the KFileDialog which we have already seen and introduces the KFontDialog and the KColorDialog classes. The design for the program looks like,


It is a simple layout with the main portion of the program being taken up by a QTextBrowser with some buttons at the bottom to get the file and set the font and the colour for the text. It should be noted from the start that although the colour can be set first if you have already opened the file it will not redraw the file and therefore change the colour until you open another file.

This is a picture of the standard program,


As you can see the program is giving a readout on it's own executable, it doesn't try to list all the information available to the KFileItem only the bits that would be meaningful to someone using the file. As you can see I've included the Status Bar Info and the Tool Tip Text which give some insight to how things are done from within KDE itself.

As with the previous code we get the file information from the KFileDialog using,

KURL fileName = KFileDialog::getOpenURL();
if( fileName.isEmpty() == true )
{
      KMessageBox::error( this, strNoFile, strChapterSix );
      return;
}

Which gives us the dialog,






and then get the KFileItem using,

KFileItem *fileInfo = new KFileItem( KFileItem::Unknown, KFileItem::Unknown, fileName, true );
        
if( fileInfo == 0 )
{
      KMessageBox::error( this, strAllocationWarning, strChapterSix );
      return;
}

The code then reads through the KFileItem and writes the information to the QTextBrowser, a small sample of the technique used is shown,

textBrowser2->clear();
textBrowser2->setColor( QColor( itemNameColour() ) );
textBrowser2->append( strFileName );
textBrowser2->moveCursor( QTextEdit::MoveLineEnd, false );
textBrowser2->setColor( QColor( itemTypeColour() ) );
textBrowser2->insert( fileInfo->name() );
textBrowser2->setColor( QColor( itemNameColour() ) );
textBrowser2->append( strDirectory );
textBrowser2->moveCursor( QTextEdit::MoveEnd, false );
textBrowser2->setColor( QColor( itemTypeColour() ) );
textBrowser2->insert( fileInfo->localPath() );
textBrowser2->setColor( QColor( itemNameColour() ) );
textBrowser2->append( strPermissions );

This code is from the very start, so the first thing that we do is clear the previous file, if any from the QTextBrowser and then set the colour of the text to the itemNameColour This is always black as there is no way from the running program to change this. We then append the string of the filename which is declared as,

QString strFileName = i18n( "File Name = " );

and then move the cursor to the end of the current line before changing the text colour once again and then using file name obtained from the KFileItem. The next couple of hundred lines are basically a case of wash, rinse and repeat the above.

To change the font we click the Font button and get the dialog,


which is the standard type of font dialog you would expect on any system showing the available fonts, their styles and available sizes.

As with the KFileDialog getting the fonts is simply a case of using the get function, in this case getFont,

QFont tempFont;
if( KFontDialog::getFont( tempFont ) == KFontDialog::Accepted )
{
     setAppFont( tempFont );
}

When OK is clicked on the dialog the font details are saved in the temporary font, creatively named tempFont. This is then passed to the setAppFont function which just stores the font details so that we can use it when we write out the information for the next file that is opened.

If we click on the Colour button we get,


Which isn't quite the standard KColorDialog because we have,


A number of ways of representing the colours in the dialog and KDE automatically saves the setup for the dialog so if you set it for Web colours one time the next time you open the dialog it will default to the Web colours you set previously. You can of course ignore these and just enter the colour values you want or simply select from the colour chooser on the left.

I personally find the Named Colors are fine for what I need so I mostly stick with them. The available colours are listed in rgb.txt which on Suse 10 is found in usr/X11R6/lib/X11 or a good visual representation can be found at http://sedition.com/perl/rgb.html

The code for getting the colour is,

QColor tempColour;
if( KColorDialog::getColor( tempColour ) == KColorDialog::Accepted )
{
     setItemTypeColour( tempColour.name() );
}

And follows exactly the same format that was used for setting the font.

This is the program running after the font has been set to bold and the colour has been changed to purple.


Summary

In this chapter we have looked at the inputs and displays which apart from showing how to use the controls themselves have presented us with little difficulty and little that we haven't already seen but you may have noticed that most of the classes up until now have begun with a Q and are part of the Qt library. In the next section we will start to look at the KDE classes that are built both on top of the Qt library and designed to work with it.