" 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 8 :- KDE Buttons And Input

As we progress through the KDE specific widgets we are starting to see more and more familiar widgets from your day to day use of KDE and in this chapter as it is concerned with the inputs we will come across a few widgets that anyone who uses KDE will see on a day to day basis.

While the KDE Buttons section is simple containing only four items,


The KDE Input section is somewhat larger containing twenty three items, a few of which are shown here.


So let's get started.

Text And Fonts

We'll start by looking at the KTextEdit and use that to look at the Input options with fonts using the KFontCombo and also the KPushButton. We wont be explicitly using the KFontChooser as it looks like,


which if you were paying attention a couple of chapters ago is simply the KFontDialog without the dialog widget. We could implement it in our own dialog but then we would just be rewriting the KFontDialog. So if you can ever think of a reason to change the font without being able to open a dialog widget then here it is. Seeing as I can't we'll move swiftly on.

The first example for this chapter is the ChapterEightText example which uses the KTextEdit, KPushButton and the KFontCombo widgets. The KPushButton is essentially a QPushButton that inherits the KGuiItem class. If you look at the KGuiItem class in the help you can see that it's function is to provide the extensions to basic Q classes that are used as standard throughout the KDE environment. Clicking on the KPushButton will open the standard font selection dialog widget which contains the KFontChooser widget shown above using the code,

QFont tempFont;
if( KFontDialog::getFont( tempFont ) == KFontDialog::Accepted )
{
     textEdit->setFont( tempFont );
}
 

As with the KPushButton the KTextEdit is derived from the appropriate class, in this case QTextEdit, and extended to fit in with the requirements of the KDE environment, so setting the font is as simple as calling the QTextEdit setFont function with the new font.

The KFontCombo widget is a standard drop down Combo Box widget that is prefilled with the avaiable KDE system fonts changing the font using this widget is just a matter of selecting it from the list.


In order to get the selected font we respond to the KFontCombo textChanged signal,

void ChapterEightTextWidget::fontCombo_textChanged( const QString &font )
{
        QFont tempFont( font );
        textEdit->setFont( tempFont );  
}

As the textChanged signal passes the name of the font we create a new QFont object using the font name before passing the font to the setFont function.


Which means the text in the KTextEdit is changed to the selected font, although wether it is readable or not depends really on which font you choose.

Dates And Times

For the dates and times example we look at the four date widgets which are the KDatePicker, the KDateTable, the KDateWidget and the KDateTimeWidget which is just a KDateWidget with the KTimeWidget which is also included.


Fortuanetly for this project the constructors for the controls are set up correctly by KDevelop so we can concentrate on what it is they can do.

As can be seen from the image above the KDatePicker is a fully functioning calender widget, whereas the KDateTable is a cut down version of the same widget. The functions of these are pretty self explanatory. The only thing that we really need to know here is if we were say writing a diary where people could click on the date then we would do it by catching the tableClicked() signal in the editor and handling the signal in the ChapterEightDatesAndTimesWidget class. So the header would contain something like.

   
virtual void kDatePicker1_tableClicked();

and the function would be handled in the cpp file with

void ChapterEightDatesAndTimesWidget::kDatePicker1_tableClicked()
{
        QDate dateSelected = kDatePicker1->getDate();
        KMessageBox::information( this, "The Date you have selected is " + dateSelected.toString() );
}

As you can see all I do is display a message confirming the date that has been clicked on. At this point if you were writing a diary say you would display a text widget so that the user could enter the text they required.

The three controls on the bottom of the form are the KDateWidget which allows the selection of a date the KTimeWidget that allows the user to enter a time value but in this case is used to display the current time and the KDateTimeWidget which is the two previous widgets linked together.

Timers

Timers are a useful tool to be aware of when programming and can help in many time dependant situations. Simply put in linux terms a timer is a signal that will be fired at whatever interval you tell it to or only once if you wish.

To set up a timer you need to add somethings to your class header file.

class QTimer;

class ChapterEightDatesAndTimesWidget : public ChapterEightDatesAndTimesWidgetBase
{

public slots:
    /*$PUBLIC_SLOTS$*/
    virtual void updateClock();

private:
        QTimer *clockTimer;
};

The above is an edited version of the class header showing just the requirements for the timer to be set up. First of all we declare the timer class at the top of the header file. This just tells the compiler to allow the use of the timer class for now and it will be derfined later. It is defined by including the header file for the QTimer class in the cpp file. Next we declare a new slot that we are going to use whenever the timer is fired and finaly we declare the timer itself.

In the cpp file we first of all include the correct header file.

#include <qtimer.h>

Then in the constructor we set the timer up.

clockTimer = new QTimer( this );
connect( clockTimer, SIGNAL( timeout() ), this, SLOT( updateClock() ) );
clockTimer->start( 1000, FALSE );

First we create the timer telling it that this class will be it's parent and as such will be responsible for deleting the timer when it's constructor is called. Then we connect the timer signal with the correct slot by calling the connect function with the clockTimer that we have just created and stating that we want to catch the signal timeout(), which is the only signal a QTimer will emit so no chance of confusion there. We then set this class as the reciever for the signal and the updateClock() function as the receiving slot. Finally we start the timer telling it to fire every second or to be exact every 1000 milliseconds and then set the single shot parameter to false to tell the timer to continue firing for as long as the program is running or until we tell it to stop.

The implementation of the updateClock slot is then

void ChapterEightDatesAndTimesWidget::updateClock()
{
        clockWidget->setTime( QTime::currentTime() );
        dateTimeWidget->setDateTime( QDateTime::currentDateTime() );
        
}

The implementation simply sets the time controls of the widget to the current time.


Numbers

This project is by far the simplest project in the book and illustrates the for number spin box widgets, these are the KIntNumInput widget, the KIntSpinBox, the KDoubleNumInput widget and the KDoubleSpinBox widget. These are all straight forward number displays that if they are working properly there isn't really much of interest to be said about them.


As you can see all we are doing is displaying the widgets and then adding the integers and the double values and displaying the results in QLCDNumber displays. The way this is done is by accepting the valueChanged signal for each box and then updating the display. So the signal handler that catches the valueChanged signal for the KIntSpinBox widget would read.

void ChapterEightNumbersWidget::kIntSpinBox_valueChanged( int number )
{
        intValue->display( kIntNumInput->value() + number );
}

Which gives a running program that looks like,


Tip Of The Day

This tip is more of a familiarity breeds contempt issue than any real problem with anything else and it can be easily duplicated but is really frustrating if you do it to yourself without realising what it is. Setup a start project like so,


Now add a button. Note though that any widget will do I'm just picking on the buttons here.


Now Add a signal handler.


Now add a message box, not forgetting to add the include for the header.

KMessageBox::information( this, "The button has been clicked" );

Now if you run the code and click the button you will get nothing, no messagebox nothing. This is because although you have saved the code in your implementation classes you haven't saved the form that tells the code generator to basically generate the connect call that will wire in the signal to the slot you have set up in the implementation class with the result that you are looking at perfectly reasonable but unworking code and trying to work out what is wrong with it when the back plumbing hasn't beed done.

Of course this is just a simple demonstration the place this is more likely to show up is when you are in the process of implementing a gui and get called away or have to stop for some other reason.

File Viewer

For the final project in this chapter we are going to implement a small file viewer to show how some of the widgets work. These widgets are the KURLRequester, the KHistoryCombo and the KURLComboRequester. The project also implements the KArrowButton widget but we don;t implement the KIconButton or the KKeyButton widgets. The reason these buttons are left out is because in the case of the KIconButton I cannot think of a single use for a button whose only function is to choose the icon that it is going to display and in the case of the KKeyButton I was simply unable to get it working effectively.

The project in development looks like this,


The project simply displays a text box for the files and the three widgets that we are going to use to select the files to be displayed. The top widget is the KURLRequester, the middle widget is the KURLComboRequester and the bottom widget is the KHistoryCombo. The reason for the space on the right hand side is because this is where the four KArrowButton widgets that we also use will appear. As with some of the other widgets the KArrowButton will not work from the Gui interface so we have to add the buttons manually with the code.

kArrowButtonUp = new KArrowButton( this, Qt::UpArrow, "ArrowUp" );
kArrowButtonUp->setGeometry( QRect( 750, 80, 20, 20 ) );
kArrowButtonUp->setProperty( "arrowType", 0 );
        
connect( kArrowButtonUp, SIGNAL( pressed() ), this, SLOT( kArrowButtonUp_pressed() ) );

This is the code from the ChapterEightFileViewerWidget class that implements the Up Button. There are the four buttons up, down, left and right that are used to allow the user to move the cursor around the text file once it is loaded.

The values for the call to setGeometry were taken by adding the KArrowButton to the Gui as normal and then copying the setup information from the generated ChapterEightFileViewerWidgetBase class in the debug directory before deleting the KArrowButton from the Gui as the constructor code generated is incorrect.

The call to setProperty is to tell the KArrowButton which way the pointer it draws should be pointing and the connect sets up the reciever for the pressed signal emitted by this button as the kArrowButtonUp_pressed slot.

The idea behind KURLRequester and KURLComboRequester is that you click the button to the right and a standard file dialog opens so that you can select the file with the selected file then being displayed in the box to the left. So whenever a file is selected the Requester widget will send a urlSelected signal which we receive,

void ChapterEightFileViewerWidget::kURLComboRequester2_urlSelected( const QString& fileName )
{
        openFile( fileName );
        historyCombo->addToHistory( fileName );
}

We then open the filename, including the path to the history combo and continue. There is, however, just one problem and that is that when we try to change the file displayed using the combo widget nothing happens yet when we use the combo box in the history combo things change. The reason for this is that the urlSelected signal is only sent when the file is changed by the dialog and not when you use the drop down box. In fact the only signal we can catch is the textChanged signal which is only sent from and editable combo box widget. The confusing thing about this is that while the KURLComboRequester could arguably be editable there is no logical reason for the KHistoryCombo to be editable at all. This is in all honesty just plain confusing and hopefully will be sorted in KDE 4.0 until then it's probably better to just ignore these.


Summary

In this chapter we've briefly ran through the bulk of the KDE specific widgets that largely are just extensions of the widgets that we have seen before. As a result for the main parts these widgets have very specific tasks that either fit with a specific project or not rather than being general purpose. For the next chapter we look at the larger widgets that are contained in the Views ( KDE ) and Container ( KDE ) sections.