Chapter 9 :- KDE Containers and Views
In this chapter we will be looking at the KDE supplied containers and views although there will be a couple of exceptions, these being the KCModule container which is a special type of widget that is used in the KDE Control Center. It is the KDE equivalent of a Windows Control Panel module and as such deals with the way KDE as a whole works. Once again if you are at that level of writing for KDE then you probably wont need to read this project.
The second widget to be avoided is the KTabWidget. This at first appearances seems to be set up as a wizard type widget as it doesn't allow access to the tab labels through the gui and on display only shows a single tab. So I decided to use it as a wizard type widget but it didn't respond to
if( nIndex < 4 ) kTabWidget->setCurrentPage( nIndex +1 ); else kTabWidget->setCurrentPage( 0 );
So I decided to use QTabWidget for the first project for this chapter instead.
Views
This project is very similar to what we saw in Chapter Four where a seies of views are displayed within a single project. This project uses the KIconView, the KListBox, the KEditListBox, the KListView and the KActionSelector all used as seperate tabs in a QTabWidget like so.
There are no problems with setting up any one these widgets and the code is almost identical for some of the views as we saw in Chapter Four. So the code that fills the KIconView is,
QString strDirectory = KFileDialog::getExistingDirectory( QString::null, this, "Select A Directory" ); QDir dir( strDirectory ); const QFileInfoList *fileInfoList = dir.entryInfoList(); QFileInfoListIterator it( *fileInfoList ); QFileInfo *ptrFileItem; iconView->clear(); QFileInfoListIterator iconIt( *fileInfoList ); while( ( ptrFileItem = iconIt.current() ) != 0 ) { // only using the files // if( ptrFileItem->isFile() == true ) { KURL fileURL( ptrFileItem->absFilePath() ); KFileItem fileItem( KFileItem::Unknown, KFileItem::Unknown, fileURL, true ); new QIconViewItem( iconView, ptrFileItem->fileName(), fileItem.pixmap( 0 ) ); } ++iconIt; }
Here we use the template that is used for the views with exception of the KActionSelector. By using the KFileDialog we select a directory and then iterate through the items in the directory in this case creating a new QIconViewItem within the KIconView for each item present.
The KListBox follows the same format with the exception that the important part of the iteration reads,
if( ptrFileItem->isFile() == true ) { listBox->insertItem( ptrFileItem->fileName() ); }
The KEditListBox is exactly the same from the coding point of view as the list box. The main exception here is how the KEditListBox looks and works.
As you can see the KEditListBox widget is a standard list box with a edit box widget across the top and four buttons on the right hand side. These are the Add, Remove, Move Up and the Move Down buttons. You can type directly into the KEditBox and then click the Add button to add new items. If you select an item from the list box the name will appear in the KEditBox at the top and you can change what is there and these changes will be reflected in the KListBox widget. You can delete any selected item in the KListBox with the Remove button and change the position of any item within the list with the Move Up and the Move Down buttons. As there is no code in the project to save any changes, should you run this program you can play about with it as much as you want.
The code for the KEditListBox is identical to that for the KListBox
if( ptrFileItem->isFile() == true ) { editListBox->insertItem( ptrFileItem->fileName() ); }
The code for the KListView is more complicated but is still the code we have seen previously
QListViewItem *listViewItem = new QListViewItem( listView ); KURL fileURL( ptrFileItem->absFilePath() ); KFileItem fileItem( KFileItem::Unknown, KFileItem::Unknown, fileURL, true ); listViewItem->setPixmap( ColumnOne, fileItem.pixmap( 0 ) ); listViewItem->setText( ColumnTwo, ptrFileItem->fileName() ); if( ptrFileItem->isSymLink() == true ) listViewItem->setText( ColumnThree, "true" ); else listViewItem->setText( ColumnThree, "false" ); if( ptrFileItem->isDir() == true ) listViewItem->setText( ColumnFour, "true" ); else listViewItem->setText( ColumnFour, "false" ); if( ptrFileItem->isFile() == true ) listViewItem->setText( ColumnFive, "true" ); else listViewItem->setText( ColumnFive, "false" ); if( ptrFileItem->isReadable() == true ) listViewItem->setText( ColumnSix, "true" ); else listViewItem->setText( ColumnSix, "false" ); if( ptrFileItem->isWritable() == true ) listViewItem->setText( ColumnSeven, "true" ); else listViewItem->setText( ColumnSeven, "false" ); if( ptrFileItem->isHidden() == true ) listViewItem->setText( ColumnEight, "true" ); else listViewItem->setText( ColumnEight, "false" ); ++it;
For each file we create a new QListViewItem in the KListView and then after loading the Icon for the file and setting the filename we chack the the true or false value of certain aspects of the file for the remaining columns.
The final Item in the program is the KActionSelector,
The idea here is that you have a number of available actions or tasks to do in the Available side of the, not all of which will need to be done at any given time. The ones that are required at the present time will be moved into the Selected side of the box. It is then up to the programmer the decide how and when these should be run. One important thing to note here is that the Available and Selected are standard list boxes so when using them you need to be aware that you you are using words or phrases that both mean something to people reading them but can also be picked up in the code.
For this test implementation I've added the names of the other views and then added a button that can be used to to take the user straight to the highlighted view.
For the running application images I've used the Opt/kde3/applications/kde directory which holds all the desktop icons for the kde applicatiions.
Containers
For this project we are going to be looking at the kinds of containers that you can add to your KDE project. There is a minor but here because I mentioned previously why I wasn't going to be looking at the,
KCModule and the KTabWidget but we are not going to bed dealing with the KDialog at least not the one shown in the toolbox Container (KDE) section for the simple reason that attempting to add a dialog to you widget form in this way will just add a frame on the existing widget. When what we really want are seperate Dialog forms. To get those we need to look at the New File Section.
which not only allows us to add new C++ source and header files but a range of new widgets to our program.
Tip Of The Day
When dealling with these dialogs remember that the ui file you are working with creates the class at compile time. This means that you cannot handle the dialog functions or any buttons that you may add within the dialog code. If you want to keep the code for you dialog seperate from the main code of your program then create a file within the project to handle the dialog and any signal responses that you wish to add by subclassing the .ui file in the automake manager you do this by right clicking on the .ui file and selecting the subclassing wizard. Ultimately though it is up to you where you choose to handle any signals emitted by your dialog.
This project is another no frills this is simply how you do it project showing how the various dialogs above work or not as the case may be. The project itself simply consists of a row of buttons that call the various containers. usually with the code
ConfigurationDialog *dlg = new ConfigurationDialog(); dlg->show();
which shows the call for the configuration dialog.
When adding these widgets to your code you will start off with the New File Dialog that requests the name for your widget
You will then be given another dialog that asks what project you would like the files to be placed in.
If you accept the default then the files will be added directly to your current project.
The first item in the above list is the configuration dialog that running as it comes looks like,
As the name suggests this dialog is a template that you can use to adjust any settings for your project.
The second button starts the empty dialog which is basically the form that we have been using for the starting point for our projects.
For some reason the next dialog the buttons bottom dialog doesn't show but it's not like it would be any great difficulty to create this yourself as you can see from it's companion dialog the buttons right dialog
The next form is the Main Window form which is interesting from the point of view that you might expect it to be the default form for the type of application that we have been looking at so far. It is basically the same form only with menus added.
So if you want a form with menus create the project as normal then add one of these and call this form first. This would be done in the main.cpp file where you would replace the definition of mainWin
ChapterNineContainers *mainWin = 0; if (app.isRestored()) { RESTORE(ChapterNineContainers); } else { // no session.. just start up normally KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); /// @todo do something with the command line args here mainWin = new ChapterNineContainers(); app.setMainWidget( mainWin ); mainWin->show(); args->clear(); }
So for example if you created a project and added a new MainWindow called for arguments sake MyNewMainWindow, you would just replace the occurances of ChapterNineContainers with MyNewMainWindow.
Menu Items
If you open the .ui file after adding it to your project you will be met with the Action Editor.
As you can see this is the list of the standard menu items that you would expect to find on any main window. The menu items are objects of the QAction class which is a class designed to make the implementation of menu items for menus and toolbars easier by grouping the required functionality together. You select a new action by selecting the option from the button on the left of the toolbar or by right clicking on the editor itself. When you have added a new action you select the properties and edit it as you would any other form object.
In the case of the Main Window widget you should always subclass it as you want the signals for the messages,
As you can see the subclass wizard gives you the option of which signals to handle in the derived class. Which will then add the selected ones to you header file,
virtual void helpAbout(); virtual void helpContents(); virtual void helpIndex(); virtual void editFind(); virtual void editPaste(); virtual void editCopy(); virtual void editCut(); virtual void editRedo(); virtual void editUndo(); virtual void fileExit(); virtual void filePrint(); virtual void fileSaveAs(); virtual void fileSave(); virtual void fileOpen(); virtual void fileNew();
with the coressponding functions defined in the .cpp file. You will of course be required to fill these in yourself but you can't have everything.
One word of warning is that in the subclass dialog above you can see at the top that I am subclassing form1 which is what all newly created forms are called. This is a big mistake as you then have to manually track down the references to form one and change them to the base class in this case TestWindow.
The tab dialog not surprisingly is a dialog with tabs,
while the widget is just another form the same as the empty dialog
The wizard is probably the most useful of the bunch, I've added some pages and edited the page names so you can see that it works,
Summary
That wraps up our tour of the basic widgets available in KDE. Hopefully I've achieved my goal of showing how to us almost all of the available widgets, with one or two exceptions. The more observant will have noticed that I've missed out the graphics section. The reason for this is that most of the widgets in the Graphics section, such as the KHSSelector for example are best used in the KColorDialog and their user interfaces aren't designed for use outside of the KDE main code. If you want to play around with these to see they all work from the interface.
In the next section we'll look at using a few of the different projects that are available from the New Projects/C++/KDE list and discovering how they work so that by the time we hit part four and take a look at the KDE libraries we should have all the basics covered.