" 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 Fourteen :- A Simple Editor Application

In this chapter we are going to be looking at the standard way of setting up a KDE application. This method is used to put together a simple text editor application that can spell check the text it's displaying.

The KDE Way

So far in order to show how things actually work we have been doing menus and toolbars the hard way. In fact it could be said that we've been going out of our way to make life difficult for ourselves. So now we'll do things properly, the KDE way and start off with this,


using just this code,

setCentralWidget( new ChapterFourteenFilesWidget( this ) );
    
statusBar();
    
KStdAction::openNew( this, SLOT( fileNew() ), actionCollection() );
KStdAction::open( this, SLOT( fileOpen() ), actionCollection() );
KStdAction::save( this, SLOT( fileSave() ), actionCollection() );
KStdAction::saveAs( this, SLOT( fileSaveAs() ), actionCollection() );
KStdAction::quit( this, SLOT( fileQuit() ), actionCollection() );
    
KStdAction::cut( this, SLOT( editCut() ), actionCollection() );
KStdAction::copy( this, SLOT( editCopy() ), actionCollection() );
KStdAction::paste( this, SLOT( editPaste() ), actionCollection() );
    
setupGUI();

That is it, of course we have to write the function implementations ourselves but I guess we can live with that. The way it works is that by using the KStdAction to create the action it will create it with the current KDE icon settings and save it in the action collection which will also take care connecting the signal with the slot that we have provided.

The call to the setupGUI function not only creates the menus and toolbar icons as we have specified them in the constructor but it also throws in the Settings menu and the help menu for free.

The settings menu has these options,


The Hide Toolbar and Hide StatusBar items should be self explanatory, the Configure Shortcuts item opens the dialog,


and the Configure Toolbars options opens the dialog,


Unfortuanetly both these configuration dialogs have little actual effect on the program at the moment as the configuration file for the application reads,

Height 900=410
Width 1440=607

[General]
ShowAlternativeShortcutConfig=false

[MainWindow]
Height 900=410
Width 1440=607

even after you have changed items in both dialogs. The only things t hat are being saved at the moment are the options to display or hide the toolbar and the status bar. The help menu on the other hand,


The first item on the list is the ChapterFourteenFiles Handbook this launches the help for the program in the KDE Help Center, note though that it will only do this if you install the application so if you are just building and testing the application you will still need to install the application if you wish to see how the help files are progressing. See DocBooks The Simple Guide below for more information about docbooks.

The second item which you should know by now is the What's This? item which is present in every widget and provides a more detailled description of a program item than the simple tooltip.

The third item is the Report Bug item and for any programs I've written using this system it will look like this,


As you can see this gives you a simple no fuss dialog that allows you to type in your problem with the current program that you are using and send that problem straight to the registered developer of the program.

The final two options are the about boxes for the program one for the program itself,


and the second being for KDE,


Now though we need to learn somethings about docbooks.

DocBooks The Simple Guide

If you look in the Automake Manager at the project section there is a documents ( doc ) section and in this there is a English ( en ) section,


If you open it as shown above you will see that there is a file called index.docbook. The naming here is a little confusing as this is not just an index file it is going to be the help file itself.

This file is a basic layout of what you can do with a docbook but to start with we are going to strip it down to the bare essentials of what we need then it will be up to each individual to enhance their docbooks as they wish.

If you are familiar with html or xml then things are pretty similar in that eveything is en element and every element starts with and opening <element> definition and ends with a closing </element> defintion.

The essential things that we need in a docbook are,

Chapters

The start of a chapter in a docbook is defined as

<chapter id="introduction">

This is standard xml syntaxt in that we start with an opening < and the word chapter we then add the id parameter and call it introduction, with the > signalling the end of the declaration.

A chapter is ended with

</chapter>

Paragraphs

If you don't want all your text to run together in a docbook you need to wrap each of your paragraphs with

<para>
</para>

which in html would be <p> and </p>

Links

You can link to another chapter in your document by using the id name for the link

<link linkend=”chapterorsectionid”>Print Name</link>

Screenshots

All screenshots in the docbook should be in .png format which shouldn't be an issue as most image manipulation programs will save as .png files. The following is a modified version of what we see in the index.docbook file,

<screenshot>
<screeninfo>Here's a screenshot of &chapterfourteenfiles;</screeninfo>
	<mediaobject>
	  <imageobject>
	    <imagedata fileref="KDEChapterFourteenFilesDocbookScreenshot.png" format="PNG"/>
	  </imageobject>
	  <textobject>
	    <phrase>A Screenshot of ChapterFourteenFiles</phrase>
	  </textobject>
	</mediaobject>
</screenshot>

The sections <screeninfo> and <textobject> are entirely optional. The main required lines here are

<screenshot>
	<mediaobject>
		<imageobject>
			<imagedata> file info </imagedata>
		</imageobject>
	</mediaobject>
</screenswhot>

There is one important thing that you need to remember when adding screenshots and that is that you need to add the image file to your project in the Document Data section. You do this by right clicking on Documentation data and selecting “Add Existing Files”.


A complete reference for docbook elements is available for download at www.docbook.org.

Installing A Docbook

You can't just open a docbook to view it. You have to install your program first.


If you go to the build menu you can see that there are two Install options the first being the standard install and the second being Install ( as root user ). As you are going to be installing things into the root/opt directory you will need to install as root user. Once the project is installed, ( the program file will go to root/opt/kde3/bin and the help file will be saved in root/opt/kde3/share/doc/HTML/en/chapterfourteenfiles. ) you can run the program in the debugger and open the help correctly but remember that the help wont be updated if changed unless you install again.


Of course this is just a test to see how things work, at a later date when the program is working we will update the image and rebuild everything properly.

The index.docbook file provided is meant as a general guide of how to use docbooks. While the guide itself is quite amusing in places it cannot hide the fact that docbooks are the most ridiculously overcomplicated way to display a html page imaginable. In fact the very presence of docbooks turns this whole method into a double edged sword. It is true that the use of KStdAction will allow you to save a whole lot of time typing in generic code for the menus but the time saved and more will be lost fiddling with the docbook syntaxt.

The file will open in KDevelop if you click on it and it starts with,

<?xml version="1.0" ?>
<!DOCTYPE book PUBLIC "-//KDE//DTD DocBook XML V4.1.2-Based Variant V1.1//EN" "dtd/kdex.dtd" [
  <!ENTITY chapterfourteenfiles "<application>ChapterFourteenFiles 0.1</application>">
  <!ENTITY kappname "&chapterfourteenfiles;"><!-- Do *not* replace kappname-->
  <!ENTITY package "kde-module"><!-- kdebase, kdeadmin, etc -->
  <!ENTITY % addindex "IGNORE">
  <!ENTITY % English "INCLUDE"><!-- change language only here -->
  
  
  <!-- Do not define any other entities; instead, use the entities
       from kde-genent.entities and $LANG/user.entities. -->
]>

This is the text that defines exactly what the document type is until you are more experienced with Docbooks ignore this.

Then there are some comments before the next section which is the book info section.

<bookinfo>
<title>The &chapterfourteenfiles; Handbook</title>

<authorgroup>
<author>
<firstname></firstname>
<othername></othername>
<surname>pseudonym67</surname>
<affiliation>
<address><email>[email protected]</email></address>
</affiliation>
</author>
</authorgroup>

<!-- TRANS:ROLES_OF_TRANSLATORS -->

<copyright>
<year>1999</year>
<year>2008</year>
<holder>pseudonym67</holder>
</copyright>
<!-- Translators: put here the copyright notice of the translation -->
<!-- Put here the FDL notice.  Read the explanation in fdl-notice.docbook
     and in the FDL itself on how to use it. -->
<legalnotice>&FDLNotice;</legalnotice>

<!-- Date and version information of the documentation
Don't forget to include this last date and this last revision number, we
need them for translation coordination !
Please respect the format of the date (YYYY-MM-DD) and of the version
(V.MM.LL), it could be used by automation scripts.
Do NOT change these in the translation. -->

<date>2001-10-18</date>
<releaseinfo>0.1</releaseinfo>

<!-- Abstract about this handbook -->

<abstract>
<para>
&chapterfourteenfiles; is a small notepad type file editor program
</para>
</abstract>

<!-- This is a set of Keywords for indexing by search engines.
Please at least include KDE, the KDE package it is in, the name
 of your application, and a few relevant keywords. -->

<keywordset>
<keyword>KDE</keyword>
<keyword>ChapterFourteenFiles</keyword>
<keyword>nothing</keyword>
<keyword>nothing else</keyword>
</keywordset>

</bookinfo>

This is setup information for the docbook and only the abstract section need concern us.

<!-- Abstract about this handbook -->

<abstract>
<para>
&chapterfourteenfiles; is a small notepad type file editor program
</para>
</abstract>

This section is where we add a small description of what our program does.

This is followed by the introduction which expands on what we have typed above.

<chapter id="introduction">
<title>Introduction</title>

<!-- The introduction chapter contains a brief introduction for the
application that explains what it does and where to report
problems. Basically a long version of the abstract.  Don't include a
revision history. (see installation appendix comment) -->

<para>
&chapterfourteenfiles; is a demonstration project that is used to give examples of how to load and save files as well
as how to cut and copy items to the clipboard as well as paste them back out again.
</para>
<para>
Any problems or feature requests to the &kde; mailing lists.
</para>
</chapter>

Note the use of the chapter keyword here. In a docbook each chapter is a page in the help So while I would suggest you use the generated file as a rough guide I would suggest that at first you keep it simple just use each chapter as a page in the help and use paragraphs and screenshots to say what you need to say. Then use the generated file as a guide to building more featured docbooks as you become more comfortable with the format.

One picky little detail here would be that as the program now as an automatic bug reporting feature as part of the help menu the text,

<para>
Any problems or feature requests to the &kde; mailing lists.
</para>

should probably refer you to that instead of the default mailing lists.

Continuing with the index.docbook we see that we can split the chapters into sections giving each section it's own subheader, the example code for this is,

<sect1 id="chapterfourteenfiles-features">
<title>More &chapterfourteenfiles; features</title>

<para>It slices! It dices! and it comes with a free toaster!</para>
<para>
The Squiggle Tool <guiicon><inlinemediaobject>
	  <imageobject>
	    <imagedata fileref="squiggle.png" format="PNG"/>
	  </imageobject>
	  <imageobject>
	    <imagedata fileref="squiggle.eps" format="EPS"/>
	  </imageobject>
	  <textobject>
	    <phrase>Squiggle</phrase>
	  </textobject>
</inlinemediaobject></guiicon> is used to draw squiggly lines all over
the &chapterfourteenfiles; main window. It's not a bug, it's a feature!
</para>

</sect1>

Note that the squiggle.png file is not added which is why we dont see it in the image,


In the index for your docbook this will look like,


The next section in the index.docbook file is the commands section which lists the menu options and keyboard shortcuts for your application. As with the above this is a single chapter.

<chapter id="commands">
<title>Command Reference</title>

<!-- (OPTIONAL, BUT RECOMMENDED) This chapter should list all of the
application windows and their menubar and toolbar commands for easy reference.
Also include any keys that have a special function but have no equivalent in the
menus or toolbars. This may not be necessary for small apps or apps with no tool
or menu bars. -->

<sect1 id="chapterfourteenfiles-mainwindow">
<title>The main &chapterfourteenfiles; window</title>

<sect2>
<title>The File Menu</title>
<para>
<variablelist>
<varlistentry>
<term><menuchoice>
<shortcut>
<keycombo action="simul">&Ctrl;<keycap>N</keycap></keycombo>
</shortcut>
<guimenu>File</guimenu>
<guimenuitem>New</guimenuitem>
</menuchoice></term>
<listitem><para><action>Creates a new document</action></para></listitem>
</varlistentry>
<varlistentry>
<term><menuchoice>
<shortcut>
<keycombo action="simul">&Ctrl;<keycap>S</keycap></keycombo>
</shortcut>
<guimenu>File</guimenu>
<guimenuitem>Save</guimenuitem>
</menuchoice></term>
<listitem><para><action>Saves the document</action></para></listitem>
</varlistentry>
<varlistentry>
<term><menuchoice>
<shortcut>
<keycombo action="simul">&Ctrl;<keycap>Q</keycap></keycombo>
</shortcut>
<guimenu>File</guimenu>
<guimenuitem>Quit</guimenuitem>
</menuchoice></term>
<listitem><para><action>Quits</action> &chapterfourteenfiles;</para></listitem>
</varlistentry>
</variablelist>
</para>

</sect2>

<sect2>
<title>The <guimenu>Help</guimenu> Menu</title>

<!-- Assuming you have a standard help menu (help, what's this, about -->
<!-- &chapterfourteenfiles;, about KDE) then the documentation is already written. -->
<!-- The following entity is valid anywhere that a variablelist is -->
<!-- valid.  -->

&help.menu.documentation;

</sect2>

</sect1>
</chapter>

As with the above it starts with the chapter definition and title

<chapter id="commands">
<title>Command Reference</title>

It then defines a section one,

<sect1 id="chapterfourteenfiles-mainwindow">
<title>The main &chapterfourteenfiles; window</title>

which will give us an indented subheading as we saw above

Then it defines the two menu items that are listed under the id section 2 or <sect2>. The contents menu which displays only the sections and chapters will show,


while the page itself will display as,


To display the individual options you first need to start a variable list element using,

<para>
<variablelist>

The items themselves are then defined as variablelistentries or

<varlistentry>
 <term>
  <menuchoice>
   <shortcut>
     <keycombo action="simul">&Ctrl;<keycap>N</keycap></keycombo>
   </shortcut>
   <guimenu>File</guimenu>
   <guimenuitem>New</guimenuitem>
  </menuchoice>
 </term>
 <listitem>
  <para>
   <action>Creates a new document</action>
  </para>
 </listitem>
</varlistentry>

We start the varlistentry which is an item of the variable list and then begin a term which is the definition of the actual item. The item is then defined as a menuchoice with a short cut defines as CTRL + N. The guimenu that the item exists on is the File menu and the guimenuitem is the New option. Finally the listitem which gives the explanation of the action taken when the menu item is selected.


When we get to the next section that details the help options there is a difference in that,

<sect2>
<title>The <guimenu>Help</guimenu> Menu</title>

<!-- Assuming you have a standard help menu (help, what's this, about -->
<!-- &chapterfourteenfiles;, about KDE) then the documentation is already written. -->
<!-- The following entity is valid anywhere that a variablelist is -->
<!-- valid.  -->

&help.menu.documentation;

</sect2>

Here the main body of text is the explanation that if we are using the standard help menu as generated by KDevelop then we just need to tell it to include the standard documentation which is done with,

&help.menu.documentation

The next section in the demonstration is the developer guide as with the demonstration guide if you are writing a program that requires a programming guide or plugins and scripting then you will be dealling with more advanced docbook topics and should read the manual at www.docbook.org.

Note we will not be using programming guides or scripting for any applications in this book. ( version 3.x ) so this section of the docbook.index file will be removed.

The next chapter is the F.A.Q. chapter which reads,

<chapter id="faq">
<title>Questions and Answers</title>

<!-- (OPTIONAL but recommended) This chapter should include all of the silly
(and not-so-silly) newbie questions that fill up your mailbox. This chapter
should be reserved for BRIEF questions and answers! If one question uses more
than a page or so then it should probably be part of the
"Using this Application" chapter instead. You should use links to
cross-reference questions to the parts of your documentation that answer them.
This is also a great place to provide pointers to other FAQ's if your users
must do some complicated configuration on other programs in order for your
application work. -->

&reporting.bugs;
&updating.documentation;

<qandaset id="faqlist">
<qandaentry>
<question>
<para>My Mouse doesn't work. How do I quit &chapterfourteenfiles;?</para>
</question>
<answer>
<para>You silly goose! Check out the <link linkend="commands">Commands
Section</link> for the answer.</para>
</answer>
</qandaentry>
<qandaentry>
<question>
<para>Why can't I twiddle my documents?</para>
</question>
<answer>
<para>You can only twiddle your documents if you have the foobar.lib
installed.</para>
</answer>
</qandaentry>
</qandaset>
</chapter>

You might have noticed by now that docbooks have a specialist tag for everything, though this shouldn't be too hard to follow from what you've seen already,

We start with some standard text and then get straight in with the Q and A set with the id “Faqlist”, each item is then divided into a qandaentry with a question and an answer. One thing this does show is how to put a link to a different chapter by using,

<link linkend="commands">Commands Section</link>

To link back to the command section.

The Credits chapter is,

<chapter id="credits">

<!-- Include credits for the programmers, documentation writers, and
contributors here. The license for your software should then be included below
the credits with a reference to the appropriate license file included in the KDE
distribution. -->

<title>Credits and License</title>

<para>
&chapterfourteenfiles;
</para>
<para>
Program copyright 2008 pseudonym67 <email>[email protected]</email>
</para>
<para>
Contributors:
<itemizedlist>
<listitem><para>Konqui the KDE Dragon <email>[email protected]</email></para>
</listitem>
<listitem><para>Tux the Linux Penguin <email>[email protected]</email></para>
</listitem>
</itemizedlist>
</para>

<para>
Documentation copyright 2008 pseudonym67 <email>[email protected]</email>
</para>

<!-- TRANS:CREDIT_FOR_TRANSLATORS -->

&underFDL;               <!-- FDL: do not remove -->

<!-- Determine which license your application is licensed under, 
     and delete all the remaining licenses below:

     (NOTE:  All documentation are licensed under the FDL, 
     regardless of what license the application uses) -->

&underGPL;        	 <!-- GPL License -->
&underBSDLicense;        <!-- BSD License -->
&underArtisticLicense;   <!-- BSD Artistic License -->
&underX11License;        <!-- X11 License  -->

</chapter>

This contains the credits for the writing/testing etc for the application and the licensing information.

Finally we get to the appendix which lists all the technical information about requirements and installation etc for the application.

That completes the quick guide to the docbook file, we will come back to it later when the application is finished so that we can update it correctly.

Menus

So far we have seen that when we add a KStdAction to our program all we need to define is the slot to deal with the action and once we call setupGui the linking will be done for us. For most applications however, there will be men items required to do specific actions that are not a part of those included in KStdAction. So you need to know how to add you own menus. The initial response when faced with this situation is to add something like this,

KAction *nonStdAction = new KAction( i18n( "Test Action" ), 	BarIconSet( "kbugbuster" ), KShortcut::null(), this, SLOT( testAction() ), 	actionCollection(), "TestAction" );
    
nonStdAction->plug( toolBar(), 3 );
    
KPopupMenu *testMenu = new KPopupMenu( this, "testmenu" );
nonStdAction->plug( testMenu );
menuBar()->insertItem( i18n( "Test Menu" ), testMenu, -1, 2 );

This is the standard way of adding a menu item and connecting it to a slot function and as you can see from the program it works fine as long as we add the code after the call to the setupGui function. Note that if it is added before the call to setup gui the menu item simply will not appear. There is however, another way and that is by using the resource file which is in your project and is found in the Data In shellrc section of the automake manager.


If you open it you'll get,

<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
<kpartgui name="chapterfourteenfiles" version="1">
<MenuBar>
  <Menu name="custom"><text>C&amp;ustom</text>
    <Action name="custom_action" />
  </Menu>
</MenuBar>
</kpartgui>

Basically the idea here is to create a system where you can add gui items to you program on the fly using xml files. Here as you can see we add an item to the menu bar called custom and it contains one action called custom_action. The Menu name is the actual menu that will appear on you menu bar and the Action is the name of a menu item, as you can see there is only one Action defined here but you can add as many as you like. As an example I've changed the rc file for this project to,

<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
<kpartgui name="chapterfourteenfiles" version="1">
<MenuBar>
  <Menu name="custom"><text>C&amp;ustom</text>
    <Action name="custom_action" />
    <Menu name="customSubMenu"><text>Sub Menu</text>
        <Action name="subMenu_action" />
    </Menu>
    <Action name="AnotherTest" />
  </Menu>
</MenuBar>
</kpartgui>

This shows the original menu item and then adds a submenu with a single item and then adds a new action below that it looks like,


I've used the kbugbuster icon for all the demonstration menu for no other reason than that I like it, although I may have over done it. It should be noted that unless you add actions to the code no menu options will be shown but the custom menu item will be. if you don't want to use this way of doing the menus you must remember to remove the <MenuBar> </MenuBar> section from the rc file as if you don't when the application is installed the Custom menu will show up with no menu items.

The code for the menu items shown above is.

KAction *testCustomAction = new KAction( i18n( "Custom Action" ), 	BarIconSet( "kbugbuster" ), KShortcut::null(), this, SLOT( testAction() ), 	actionCollection(), "custom_action" );
KAction *testCustomAction2 = new KAction( i18n( "Sub Menu Option" ), BarIconSet( 	"kbugbuster" ), KShortcut::null(), this, SLOT( testAction() ), 	actionCollection(), "subMenu_action" );
KAction *testCustomAction3 = new KAction( i18n( "Another Test" ), 	BarIconSet( "kbugbuster" ), KShortcut::null(), this, SLOT( testAction() ), 	actionCollection(), "AnotherTest" );

Chapterfourteenfiles

You may have noticed by now that the idea behind the Chapterfourteenfiles project is to give an example of saving and loading files and use the spell check features of KDE. The idea is that we will have a simple notepad type application which can save and load files and use all the cut copy and paste options that should come with this type of application. Fortuanetly the cut copy and paste functionality is already a part of the KTextEdit that we are using, so all we need to do is link up the items with.

void ChapterFourteenFiles::editCut()
{
    mainWidget->editBox->cut();
}

void ChapterFourteenFiles::editCopy()
{
    mainWidget->editBox->copy();
}

void ChapterFourteenFiles::editPaste()
{
    mainWidget->editBox->paste();
}

As you may remember before the docbook sidetrack we declared our actions using KStdAction,

KStdAction::cut( this, SLOT( editCut() ), actionCollection() );
KStdAction::copy( this, SLOT( editCopy() ), actionCollection() );
KStdAction::paste( this, SLOT( editPaste() ), actionCollection() );

then it was just a matter of calling the KEditBox functions. We do this by changing the way that out KApplication class works slightly. If you remember the standard way of setting the main widget is with the code,

setCentralWidget( new WidgetClass( this ) );

The change we make is to add the main widget to the class header with,

ChapterFourteenFilesWidget *mainWidget;

and then in the constructor,

mainWidget = new ChapterFourteenFilesWidget( this );
setCentralWidget( mainWidget );

This sets up the main widget for the application in exactly the way that we are used to but allows us to seperate the functions that are application specific from the functions that are widget specific.

Loading And Saving

We've already seen how to load a file before using the QTextStream class and as we are dealling with plain text files here then we can use identical code,

KURL urlOpenFile = KFileDialog::getOpenURL( 0, "*.*|All Files" );
if( urlOpenFile.pathOrURL() == QString::null )
{
     /// on cancel reload current file
     QFile file( currentFile() );
     if( file.open( IO_ReadOnly ) == true )
     {   
         QTextStream stream( &file );
        		
         mainWidget->editBox->append( stream.read() );
	
	   file.close();
		
	   mainWidget->editBox->setModified( false );
     }
        
     return;
}

Here we use a standard dialog to get the name of the file to be opened and then open the QFile object and pass it to a QTextStream before reading the entire contents into the edit box. Saving is very similar although for some reason the QTextStream doesn't have a write function so we have to use the C++ output operator

QFile file( currentFile() );
if( file.open( IO_WriteOnly | IO_Truncate ) == true )
{
    QTextStream stream( &file );
        
    stream << mainWidget->editBox->text();
        
    file.close();
        
    statusBar()->message( currentFile() + " saved", 3000 );
}
else
{
    KMessageBox::error( this, "Unable to open the file for saving " + 	currentFile() );
}

Here we write the contents of the KTextEdit out to the file, opening the file with IO_WriteOnly and IO_Truncate so that if we are saving to a current file that contains text the contents are replaced with the contents of the edit box.

Using The Spell Check

If you look at the tools menu you will see two options,


The first is Spelling which is the main spell checker which will bring up the spell check dialog the second is the background spell checker which doesn't show a dialog but indicates an incorrectly spelled word by highlighting it in red.

Tip Of The Day

There is one oddity about the tools menu here and that is that the Tools menu is not decalred by the programmer as such. It is declared by the code,

KStdAction::spelling( this, SLOT( spellCheck() ), actionCollection() );

While the code for the Spell Check On option is more what we are used to in that it reads,

KToggleAction *spellCheckerAction = new KToggleAction( i18n( "Spell Check On" ), 0, KShortcut::null(), this, SLOT( spellCheckerOn() ), actionCollection(), "enableSpellCheck" );

The Tools menu is created by default when we call the KStdAction::spelling function, adding our action to the action collection and then call setupGui. So how do we get the Spell Check On item to appear on the menu at all. The answer is in the resource file for the menus,

<Menu name="tools"><text>&amp;Tools</text>
   <Action name="enableSpellCheck" />
</Menu> 

As you can see the enableSpellCheck action is added to the “tools” menu. When the setupGui function sets up the menu it names the menus with the menu name in lower case and removes any ampersand characters so if you wanted to add a custom option to the file menu you would add it to the resource file with the menu name “file”.

Setting Up The Spell Checker

The set up for the spell checker is a bit technical. If you want to get it working properly there are a couple of things you must do in the right order. Initially we declare,

KSpell *spellingCheck;

in our class definition and then initialise it in our contructor.

spellingCheck = new KSpell( this, "Check Spelling", this, 	SLOT( spellCheckReciever( KSpell * ) ) );  

Now you see here that there is a slot in the constructor called spellCheckReciever which is important because what happens is that unlike other objects the KSpell class is going to take a while to initialise and when it is done it will send a ready( KSpell * ) signal. You must receive this signal or no spell checking for you. So our spell check receiver function reads,

void ChapterFourteenFiles::spellCheckReciever( KSpell *spellChecker )
{
    connect( spellChecker, SIGNAL( done( const QString& ) ), this, 	SLOT( spellCheckerDone( const QString & ) ) );    
}

Here once the KSpell object is initialised then and only then do we set up a slot on it to respond to the signal done. ( You should note that the KSpell * passed to this function is the KSpell * defined as spellingCheck as you would see if you set a debug breakpoint in this function. ) The done signal is sent when the KSpell object has finished checking the spelling. The way it works is that when you call the KSpell check function you pass it a string and when it has finished checking the string it passes the corrected string to your done slot which in this case is spellCheckerDone,

void ChapterFourteenFiles::spellCheckerDone( const QString &buffer )
{
    mainWidget->editBox->clear();
    mainWidget->editBox->append( buffer );
}

When the text is returned we remove all text from the edit box and then replace it with the text sent to us from the spell checker.

One final thing you need to do when using the spell checker is call the cleanup function so that any resources allocated by it can be cleaned up. You should do this in the destructor with,

spellingCheck->cleanUp();

Be warned though if you put this function call anywhere else in your code the spell checker will stop working, if it works at all.

Using The Spell Checker

To start with if you select the Spell Check on option it triggers this code,

if( mainWidget->editBox->checkSpellingEnabled() == true )
{
   mainWidget->editBox->setCheckSpellingEnabled( false );
}
else
{
   mainWidget->editBox->setCheckSpellingEnabled( true );
}

which turns on and off the background spell checker for the KTextEdit which looks like this,


and that's all there is to the background spell checker in default mode, However, because we have added the KSpell class as shown above we have two further options the first being to start the spell checker to check the spelling of the entire document using the menu option, “Spelling” or we can individually check each word by double clicking on it.

The dialog when you start the spelling check through the menu is,


This is what you get when you start the spelling checker with one of our header files loaded the first word it picks up on is the word ui and then gives you the options you wold expect of any spelling check software. The code for this is,

spellingCheck = new KSpell( this, "Check Spelling", this, 	SLOT( spellCheckReciever( KSpell * ) ) ); 
    
setDoubleClicked( false );
QString string = mainWidget->editBox->text();
spellingCheck->check( string );

We initialise the spellingCheck object passing it the SLOT for the reciever function which is called when the object is ready as discussed above and then get all the text from the edit box and pass it to the spellingCheck object with the check function.

The spellCheckReciever function simply sets up the slot that is to be called when we have finished with the spelling check.

connect( spellChecker, SIGNAL( done( const QString& ) ), this, 	SLOT( spellCheckerDone( const QString & ) ) );

When the spelling check is done we check first of all to see if the value returned from the speeling check dialog was KS_CANCEL which would mean we do nothing. Then we check if we double clicked on a single word and if not we simply replace all the text,

if( doubleClicked() == false )
{
   mainWidget->editBox->clear();
   mainWidget->editBox->append( buffer );
}

If we are doing a spelling check on a single word things are more complicated because we can't simply replace all the text. When we double click on a word we get the textEditDoubleClicked function,

spellingCheck = new KSpell( this, "Check Spelling", this, 	SLOT( spellCheckReciever( KSpell * ) ) ); 
if( mainWidget->editBox->hasSelectedText() == true )
{
   setDoubleClicked( true );
   setPara( para );
   setPos( pos );
   QString strHighlighted = mainWidget->editBox->selectedText();
   setOriginalWord( strHighlighted );
   spellingCheck->check( strHighlighted );
}

We start by creating a KSpell object as before and then saving all the information we need about the current word and it's position within the document, before passing the word to the spell checker.


As you can see here I've opened one of the header files and double clicked the word QVBoxLayout which you can see heighlighted and chosen to replace it with the word layout.

When we hit either Replace or Replace All the spellCheckerDone function will be called with the return values KS_REPLACE or KS_REPLACEALL, KS_REPLACE which is used to replace a single word and KS_REPLACEALL which replaces all the spellings of a given word in the text.

There are two ways we can replace words we can work directly with the edit box and replace each individual word by highlighting the word and then cutting it out of the edit box and adding the spelling corrected word at its current position, like so,

if( spellingCheck->dlgResult() == KS_REPLACE )
{
   // replace a single word
   mainWidget->editBox->setCursorPosition( para(), pos() );
   mainWidget->editBox->removeSelection();
   mainWidget->editBox->moveCursor( QTextEdit::MoveWordBackward, true );
   mainWidget->editBox->removeSelectedText();
   mainWidget->editBox->removeSelection();
   mainWidget->editBox->moveCursor( QTextEdit::MoveWordForward, true );
   mainWidget->editBox->removeSelectedText();
   mainWidget->editBox->insert( buffer + " " );
            
   statusBar()->message( i18n( "Replaced " + originalWord() + " with " + 	buffer ), 3000 );
}

or you could just do it the easy way and use the QString functionality,

if( spellingCheck->dlgResult() == KS_REPLACEALL )
{
   QString strText = mainWidget->editBox->text();
            
   strText.replace( originalWord(), buffer, true );
            
   mainWidget->editBox->clear();
            
   mainWidget->editBox->append( strText );
            
   statusBar()->message( i18n( "Replaced all occurances of " + originalWord() + 	" with " + buffer ), 3000 );
                
}

Finishing The Docbook

The rest of the docbook is mostly just editing the content that is already there so it all points to the correct places and removing things that don't apply. The only code that's added is the menu items for the Test Menu, Custom and Tools menu. There is nothing we didn't look at earlier in these menus with the Tools menu looking like,

<sect2>
<title>The <guimenu>Tools</guimenu> Menu</title>
<variablelist>
    <varlistentry>
        <term>
            <menuchoice>
                <guimenu>Tools</guimenu>
                <guimenuitem>Spell Checker</guimenuitem>
            </menuchoice>
        </term>
        <listitem>
            <para>
                <action>Launch the KDE spell check</action>
            </para>
        </listitem>
    </varlistentry>
    <varlistentry>
        <term>
            <menuchoice>
                <guimenu>Tools</guimenu>
                <guimenuitem>Spell Checker On</guimenuitem>
            </menuchoice>
        </term>
        <listitem>
            <para>
                <action>Background spell checking ( misspelt words highlighted in red )</action>
            </para>
        </listitem>
    </varlistentry>
</variablelist>
</sect2>

and the finished project,


Summary

In this chapter we have built a simple editor application and shown how to get the program running correctly and how to get the spell checker working, we have also been given a preview of how all the projects for KDE will be written for the version 4.x editon of this book.