# &kdevelop;i programmeerimise käsiraamat

2002-12-05
2.0
Ralf Nolden

    Ralf.Nolden@post.rwth-aachen.de

Caleb Tennis

    caleb@aei-tech.com

1999 Ralf Nolden
2002 Caleb Tennis
&FDLNotice;

C++ rakenduste kujundamise käsiraamat KDE töökeskkonnas &kdevelop;i IDE-ga

KDE KDevelop IDE arendus programmeerimine

## Sissejuhatus

Mida enam on UNIX muutunud populaarseks isegi algajate arvutikasutajate seas, kes hindavad stabiilsust ja funktsionaalsust, seda enam on siiski tekkinud ka neid, kes on mõnevõrra pettunud, sest rakendustel puudub ühtne välimus ja nad ei toimi kaugeltki ühtmoodi. KDE pakub arendajatele peaaegu perfektse võimaluse luua UNIX-i töölaudadele esmaklassilisi rakendusi, mis suudavad võita laia tunnustuse juba ainuüksi oma kvaliteediga. Nii on KDE muutunud ka üha menukamaks baasiks rakenduste loomisel ning arendajad kasutavad meelsasti kõiki pakutavaid võimalusi.

### Mida oleks vaja eelnevalt teada

Me eeldame käesoleva programmeerimise käsiraamatu puhul, et selle lugeja tunneb juba programmeerimiskeelt C++. Kui sina seda veel ei tunne, tasuks kõigepealt see endale vähemalt teatud määral selgeks teha. Infot C++ kohta leiab väga paljudest kohtadest: nii kohalikust raamatupoest trükitud kujul kui ka mitmelt poolt internetist. Graafilise kasutajaliidese kujundamise osas pole eelteadmised vajalikud, sest käsiraamat püüabki hõlmata KDE rakenduste kujundamist, mille hulka käib nii Qt tööriistakomplekti ja KDE teekide kui ka kasutajaliideste kujundamise tutvustamine. Kuid see-eest tasuks mõnevõrra tutvuda rakendusega &kdevelop;. Seda on kõige mõistlikum teha &kdevelop;i kasutaja käsiraamatut lugedes, mis sisaldab korraliku ülevaate kõige kohta, mida see arenduskeskkond (IDE) pakub.

### Käsiraamatu info

Käesoleva käsiraamatu siht on pakkuda arendajatele sissejuhatust KDE rakenduste arendamisse integreeritud arenduskeskkonna KDevelop abil.

Nii annamegi järgnevates peatükkides ülevaate, kuidas luua projekte, selgitame, milline lähtekood sel juhul vaikimisi juba ette luuakse, ning tutvustame, kuidas laiendada etteantud lähtekoodi võimalusi näiteks tööriistaribade, menüüribade ja vaadetega.

Lisaks tutvustame üksikasjalikult vidinate loomist ning vaatleme kõigi pakutavate vidinate omaduste seadistamise võimalusi.

Lõpuks võtame vaatluse alla veel mitmed teemad, mis täiendavad sinu teadmisi projektide kujundamise ning veel mitme otsesest programmeerimisest veidi kõrvale jäävate teemade osas, näiteks API dokumentatsiooni lisamine ja käsiraamatute loomine.

#### Järgmises peatükis

Me vaatleme Qt ja KDE teeke ja selgitame põhikontseptsioone. Samuti vaatleme õpperakenduste loomist Qt tööriistakomplektiga KDevelopi abil, mis annab algajatele kiiresti võimaluse näha oma esimesi edusamme ning sel moel õppida kasutama mitmeid &kdevelop;i suurepäraseid omadusi.

#### Järgmistes peatükkides

Saad teada, kuidas:

- Luua rakendus Rakenduse nõustajaga

- Mida sisaldab projekti mall

- Mida kujutab endast mallina loodav kood

- Kuidas luua omaenda vaateid

- Kuidas laiendada oma rakenduse võimalusi dialoogide ning menüü- ja tööriistaribadega

- Kuidas muuta oma rakendus kasutajasõbralikuks mitmekülgset abi pakkudes

- Kuidas kirjutada dokumentatsiooni

### Lisainfo

Qt/KDE programmeerimise kohta leiab lisainfot paljudest allikatest:

- Programming with Qt, autor: Matthias Kalle Dalheimer

- KDevelopi kasutaja käsiraamat (kuulub KDevelopi IDE koosseisu)

- Qt teegi dokumentatsioon võrgus

- KDE arendajate veebilehekülg

Lisaks saab abi otsida mitmetest meililistidest, mille aadressid leiab mainitud veebilehekülgedelt, ning Useneti uudistegruppidest, mis on pühendatud KDE ja UNIX-i kasutamisele ning programmeerimiskeeltele C ja C++.

KDevelopi IDE kohta võib abi leida meililistist kdevelop@kdevelop.org. Pane tähele, et KDevelopi meeskond on pühendunud vahendite loomisele, mis lubavad sul rakendusi programmeerida, mistõttu see meililist pole mitte tehnilise abi foorum, kust otsida abi siis, kui sinu arendatud rakendused ei tööta teostamisvigade või sinu operatsioonisüsteemi seadistusprobleemide tõttu. Küll aga soovitame kõigil kasutajatel pöörduda meililisti alati, kui tekib probleeme IDE enda kasutamisega, samuti võib sinna anda teada vigadest ja ettepanekutest, kuidas arenduskeskkonda veel paremaks muuta.

## KDE ja Qt teegid

Norra firma TrollTech (http://www.trolltech.com) pakub niinimetatud GUI tööriistakomplekti nimetusega Qt. GUI tähendab "graafiline kasutajaliides", mistõttu Qt-põhised rakendused pakuvad nuppe, aknaid ja muud sellist, mis võimaldavad kasutajal visuaalselt ära kasutada rakenduste pakutavaid funktsioone. Sellist tööriistakomplekti on vaja graafiliste rakenduste loomiseks, mis töötaksid UNIX-süsteemides X Window liidesega, sest X ei sisalda ise eelmääratletud kasutajaliidest. Ehkki kasutajaliidese loomiseks on ka teisi tööriistakomplekte, pakub Qt teatud tehnilisi võimalusi, mis muudavad rakenduste kujundamise äärmiselt lihtsaks. Lisaks on Qt tööriistakomplekt saadaval ka Microsoft Windowsi süsteemidele, nii et arendajad võivad oma rakendusi luua kasutamiseks mõlemal platvormil.

KDE meeskond (http://www.kde.org) otsustas samuti anda oma panuse UNIX-süsteemide muutmisel kasutajasõbralikumaks ning valis välja Qt tööriistakomplekti enda X Window süsteemi aknahalduri ja veel arvukate KDE tarkvara hulka kuuluvate tööriistade loomiseks. K töökeskkonna ehk KDE põhikomponentideks on aknahaldur kwm, failihaldur kfm ning käivitamispaneel kpanel, kuid selle koosseisu kuulub veel terve rida esmaklassilisi utiliite ja rakendusi. Kui KDE ilmavalgust nägi, pälvis see paljude arendajate tähelepanu. KDE teegid pakuvad olulisemaid meetodeid ja klasse, mis lubavad anda nende abil loodud rakendustele ühtse välimuse. See omakorda annab lõppkasutajale suurepärase võimaluse koondada pärast põhitõdede selgekstegemist oma tähelepanu rakenduste funktsionaalsusele, mitte aga dialoogide või nuppude kirevuse tundmaõppimisele. KDE programmid on põimitud töölauaga ja võivad suhelda failihalduriga lihtsalt lohistamise teel, võivad ära kasutada seansihalduse võimalusi ja veel palju muud, mida kõike võimaldavadki KDE teegid.

Nii Qt tööriistakomplekt kui ka KDE teegid on kirja pandud programmeerimiskeeles C++, mistõttu ka neid teeke kasutavad rakendused on enamasti C++ keeles. Järgnevalt võtamegi ette lühiretke läbi teekide selgitamaks, mida need pakuvad ja kuidas üldiselt luuakse Qt ja KDE rakendusi.

### Qt GUI tööriistakomplekt

Nagu öeldud, on Qt teek tööriistakomplekt, mis pakub graafilisi elemente, mida kasutatakse GUI rakenduste loomiseks ja mida läheb vaja programmeerimisel X Window süsteemide jaoks. Lisaks pakub tööriistakomplekt:

- Täielikku klasside ja meetodite kogumit, mida saab kasutada ka mittegraafiliste programmeerimisülesannete tarbeks

- Häid lahendusi kasutaja interaktsiooniks virtuaalsete meetodite ning signaali/pesa mehhanismi vahendusel

- Valikut eelmääratletud GUI elemente ehk "vidinaid", mille abil on hõlpus luua kasutajale nähtavaid elemente

- Lisaks täielikku valikut eelmääratletud dialooge, mida rakendustes sageli tarvitatakse, näiteks edenemis- ja failidialoogid

Seepärast on Qt klasside tundmine väga oluline ka siis, kui soovid programmeerida ainult KDE rakendusi. Selgitamaks GUI rakenduste konstrueerimise ja kompileerimise põhikontseptsiooni, vaatame kõigepealt puhta Qt programmi näidet, seejärel aga laiendame selle KDE programmiks.

#### Esimene Qt rakendus

Nagu ikka, peavad C++ programmid sisaldama funktsiooni `main()`, mis on rakenduse käivitamise alguspunkt. Et meie soovi kohaselt peavad programmid olema graafiliselt nähtavad akendes ja võimaldama kasutaja interaktsiooni, tuleb esmalt teada saada, kuidas nad ennast kasutajale näitavad. Vaatame näiteks esimest õppematerjali, mis leidub Qt võrgudokumentatsioon ja selgitab nii kõige elementaarsemaid töösamme kui ka seda, miks ja kuidas ilmub rakenduse aken:

    #include <qapplication.h>
    #include <qpushbutton.h>

    int main( int argc, char **argv )
    {
    QApplication a( argc, argv );

    QPushButton hello( "Hello world!", 0 );
    hello.resize( 100, 30 );

    a.setMainWidget( &hello );
    hello.show();
    return a.exec();
    }

See rakendus lihtsalt joonistab akna, milles on nupp, millel on tekst "Hello world". Nagu kõigi Qt rakenduste puhul, tuleb esmalt luua klassi QApplication eskemsplar, mida tähistab muutuja a.

Seejärel loob programm klassi QPushButton eksemplari nimega hello, mis ongi nupp. hello konstruktor saab parameetrina stringi, mis on vidina sisu, mida näeb nupu tekstina.

Seejärel kutsutakse hello nupule välja meetod resize(). See muudab vidina (antud juhul on selleks QPushButton) loomisel määratud vaikesuurust, andes sellele mõõtmetekst 100 pikslit pikkuses ja 30 pikslit kõrguses. Lõpuks kutsutakse välja meetod setMainWidget() a jaoks ning meetod show() hello jaoks. QApplication käivitatakse lõpuks meetodiga a.exec(), see siseneb põhisilmusesse ning ootab, kuni saab tagastada operatsioonisüsteemile täisarvväärtuse, mis annab märku, et rakendus on töö lõpetanud.

#### Qt dokumentatsioon

Heidame nüüd põgusa pilgu Qt teegi dokumentatsioonile. Selleks käivita &kdevelop; ja vali dokumentatsioonikaardil "Qt". Dokumentatsioonisirvija avanedes näed Qt dokumentatsiooni avalehekülge. See on põhikoht, kust hankida infot Qt, selle klasside ja funktsioonide kohta. Eespool näiteks toodud programm on ühtlasi esimene dokumentatsiooni õppematerjalide osas (Tutorials) tutvustatav programm. Klasside tundmaõppimiseks - praegu pakuvad meile huvi nähtud QApplication ja QPushButton - vali klasside tähestikuline register ja otsi sealt vajalikud nimed üles. Neile klõpsates näedki antud klassi kirjeldust.

Teine võimalus on uurida Trolltechi Qt dokumentatsiooni võrgus.

QApplication korral on näha konstruktor ja kõik muud meetodid, mida see klass pakub. Linki järgides leiad veel rohkem infot meetodite kasutamise ja tähenduse kohta, mis on sageli päris kasulik, kui sa ei suuda näiteks õiget kasutamist iseseisvalt välja mõelda või soovid näha näited. Lausutu kehtib ka KDE dokumentatsiooni kohta, mis on samalaadselt üles ehitatud. See tähendab, et põhimõtteliselt saab kõik, mida vähegi on vaja teada klasside kohta, teada otse dokumentatsioonisirvijast.

##### Näidise tõlgendamine

Võttes alustuseks ette klassi QApplication, siis meie esimeses näites olid kasutusel järgmised meetodid:

- konstruktor QApplication()

- meetod setMainWidget()

- meetod exec()

Nende meetodite kasutamise tõlgendamine on väga lihtne:

1. Luuakse klassi QApplication eksemplar konstruktoriga, et me saaksime ära kasutada Qt pakutavaid GUI elemente

2. Luuakse vidin, millest saab meie programmiakna sisu

3. Vidin määratakse peavidinaks a jaoks

4. Käivitatakse QApplication eksemplar

Meie programmi teine objekt on nupp ehk klassi QPushButton eksemplar. Kahest eksemplari loomiseks mõeldud konstruktorist kasutame teist: see aktsepteerib teksti, mis on nupu sisu ehk antud juhul tekstistring "Hello world!" Seejärel kutsume välja meetodi resize(), et muuta nupu suurust vastavalt selle sisule - nupp peab olema suurem, et kogu string oleks näha.

Aga meetod show()? Siin näed, et nagu enamiku vidinate korral, tugineb QPushButton üheleainsale pärilusele ehk nagu ütleb dokumentatsioon: Inherits QButton. Klõpsa lingile QButton. Nüüd näed veel õige mitut vidinat, mis tuginevad klassile QButton, mida me kasutame hiljem signaali/pesa mehhanismi selgitamisel. Igal juhul ei ole siin kirjas meetodit show(), mis tähendab, et ka selle peab tagama pärilus. Klass, mille järglane on QButton, kannab nime QWidget. Klõpsa taas lingile ja näed tervet rida meetodeid,mida pakub klass QWidget. Nende hulka kuulub ka meetod show(). Nüüd on võimalik mõista, mida meie näidises nupuga ette võetakse:

1. Luuakse QPushButton eksemplar, kasutades teist konstruktorit nupu teksti määramiseks

2. Muudetakse vidina suurust sisu mahutamiseks

3. Määratakse vidin QApplication eksemplari a põhividinaks

4. Antakse vidinale korraldus näidata ennast ekraanil, kutsudes välja meetodi show(), mis on klassi QWidget järglane

Pärast meetodi exec() väljakutsumist on rakendus kasutajale nähtav: aken nupuga, millel on kiri "Hello world!" Märkus: GUI programmid käituvad mõnikord veidi teistmoodi protseduurrakendused. Peamiseks erinevuseks on asjaolu, et rakendus siseneb niinimetatud "põhisilmusesse". See tähendab, et programm peab ootama kasutaja tegevust ja seejärel sellele reageerima, samuti seda, et Qt rakenduse korral peab programm olema põhisilmuses, enne kui saab alustada sündmuste käsitlemist. Järgmises osas räägime lühidalt, mida see tähendab programmeerijale ja mida pakub Qt kasutaja sündmuste töötlemiseks.

Juba kogemustega kasutajatele: konstruktoris pole deklareeritud nupu eellast, seepärast on see tipptaseme vidin, mis töötab kohalikus silmuses, mistõttu ei pea ootama põhisilmust. Vaata klassi QWidget ja KDE teegi dokumentatsiooni.

#### Kasutaja interaktsioon

Pärast eelnenud osade läbilugemist peaksid juba teadma:

- Mida pakub Qt teek GUI rakenduste jaoks

- Kuidas luuakse programm Qt abil

- Kust ja kuidas leida dokumentatsioonisirvijas infot klasside kohta, mida tahad kasutada

Nüüd äratame oma rakenduse "ellu" kasutaja sündmusi töötlema asudes. Üldiselt on kasutajal kaks võimalust programmiga suhelda: hiir ja klaviatuur. Mõlemal juhul peab graafiline kasutajaliides pakkuma meetodeid, mis tuvastavad toimingud, ja meetodeid, mis neile toimingutele reageerides midagi ette võtavad.

X Window saadab kõik interaktsioonisündmused vastavale rakendusele. QApplication saadab need siis aktiivsele aknale klassina QEvent, misjärel vidinad peavad otsustama, mida nendega peale hakata. Vidin saab sündmuse ja töötleb meetodit QWidget::event(QEvent*), mis otsustab, milline sündmus käivitati ja kuidas reageerida: niisiis on peamine sündmuste käsitleja event(). Nüüd suunab event() sündmuse niinimetatud sündmusefiltrisse, mis määrab, mis toimus ja mida sündmusega peale hakata. Kui ükski filter antud sündmusega ei tegele, kutsutakse välja spetsialiseeritud sündmuste käsitlejad. Need on järgmised:

- Klaviatuurisündmused - klahvid TAB ja Shift:

  - virtual void focusInEvent(QFocusEvent *)

  - virtual void focusOutEvent(QFocusEvent *)

- Kõik muud klaviatuurisisestused:

  - virtual void keyPressEvent(QKeyEvent *)

  - virtual void keyReleaseEvent(QKeyEvent *)

- Hiire liikumine:

  - virtual void mouseMoveEvent(QMouseEvent *)

  - virtual void enterEvent(QEvent *)

  - virtual void leaveEvent(QEvent *)

- Hiirenupu toimingud:

  - virtual void mousePressEvent(QMouseEvent *)

  - virtual void mouseReleaseEvent(QMouseEvent *)

  - virtual void mouseDoubleClickEvent(QMouseEvent *)

- Vidinat sisaldava akna sündmused:

  - virtual void moveEvent(QMoveEvent *)

  - virtual void resizeEvent(QResizeEvent *)

  - virtual void closeEvent(QCloseEvent *)

Pane tähele, et kõik sündmuse funktsioonid on virtuaalsed ja kaitstud. Seepärast saad taasteostada sündmusi, mida vajad omaenda vidinates, ja määrata, kuidas vidin peab reageerima. QWidget sisaldab ka mõningaid virtuaalseid meetodeid, mis võivad sinu programmis kasuks tulla. Nii või teisiti on äärmiselt tulus klassi QWidget hästi tundma õppida.

#### Objekti interaktsioon signaalide ja pesadega

Nüüd jõuame Qt tööriistakomplekti kõige suurema eelise juurde, milleks on signaalide/pesade mehhanism. See pakub väga käepärase ja tulusa lahenduse objektide interaktsioonile, mis X Window tööriistakomplektides lahendatakse tavaliselt tagasikutsete (callback) funktsioonidega. Et selline kommunikatsioon eeldab väga ranget programmeerimist ning muudab mõnikord kasutajaliidese loomise üpris keerukaks (seda tutvustab ka Qt dokumentatsioon ning selgitab põhjalikult K. Dalheimeri raamat 'Programming with Qt'), leiutas Trolltech uue süsteemi, milles objektid emiteerivad signaale, mida saab siduda pesadena (slot) deklareeritud meetoditega. C++ programmeerija peab sellest teadma põhimõtteliselt vaid mõnda asja:

- signaale/pesasid kasutava klassi deklaratsiooni alguses peab seisma makro Q_OBJECT (ilma semikoolonita) ja see peab olema tuletatud klassist QObject

- signaali võib emiteerida võtmesõna emit, nt. emit signaal(parameetrid), mis tahes klassi liikmesfunktsioonist, mis võimaldab signaale/pesasid

- kõik signaalid, mida kasutavad klassid, mis ei ole päritud, tuleb lisada klassi deklaratsiooni signaalide sektsiooni

- kõik meetodid, mida saab siduda signaaliga, deklareeritakse sektsioonides täiendava võtmesõnaga slot, nt public slots, klassi deklaratsioonides

- metaobjekti kompilaator moc peab töötlema päisefaili, et laiendada makrod ja luua teostus (mida pole tingimata vaja teadagi). moc'i väljundfailid kompileerib samuti C++ kompilaator.

Veel üks viis kasutada signaale ilma klassist QObject tuletamata näeb ette klassi QSignal kasutamist. Uuri dokumentatsioonist ise täpsemalt, kuidas seda kasutada. Järgnevalt eeldame, et tuletatud on klassist QObject.

Nii võib sinu klass saata kõikjale signaale ja pakkuda pesasid, millega signaalid saavad ühenduse luua. Signaale kasutades ei pruugi muretseda, kes neid saab: sa lihtsalt emiteerid signaali, millele reageerib see pesa, millega sa soovid signaali ühendada. Pesasid võib samas kasutada teostuse ajal tavaliste meetoditena.

Signaali ühendamiseks pesaga tuleb kasutada meetodit connect(), mida pakub QObject, või olemasolu korral spetsiaalseid meetodeid, mida objektid pakuvad ühenduse võimaldamiseks teatud signaalidega.

##### Näidiskasutamine

Selgitamaks, kuidas luua objekti interaktsioon, võtame taaas oma esimese näidise ja laiendame seda lihtsa ühenduse võrra:

    #include <qapplication.h>
    #include <qpushbutton.h>

    int main( int argc, char **argv )
    {
    QApplication a( argc, argv );

    QPushButton hello( "Hello world!" , 0);
    hello.resize( 100, 30 );

    a.setMainWidget( &hello );

    QObject::connect(&hello, SIGNAL( clicked() ), &a, SLOT( quit() ));

    hello.show();
    return a.exec();
    }

Nagu näed, saab üheainsa lisandusega anda nupule suurema interaktiivsuse. Selleks on vaja ainult lisada meetod connect(): connect(&hello, SIGNAL( clicked() ), &a, SLOT( quit() )). Mida see tähendab? Klassi QObject deklaratsioon ütleb meetodi connect() kohta järgmist:

bool connect ( const QObject * sender, const char * signal, const QObject * receiver, const char * member )

See tähendab, et sul tuleb määrata QObject eksemplari viit, mis on signaali saatja, mis tähendab, et sa emiteerid selle signaali esimese parameetrina. Seejärel tuleb määrata signaal, millega soovid ühenduse luua. Viimased kaks parameetrit on vastuvõttev objekt, mis pakub pesa, ning sellele järgneb liikmesfunktsioon, mis ongi tegelik pesa, mis käivitatakse signaali emiteerimisel.

Signaalide ja pesade abil saavad sinu programmi objektid üksteisega suhelda ilma vajaduseta otseselt sõltuda vastuvõtva objekti tüübist. Selle mehhanismi kasutamisest tuleb käsiraamatus veel pikemalt juttu. Rohkem infot signaalide ja pesade mehhanismi kohta leiab ka KDE teegi ja Qt dokumentatsioonist.

### Mida pakub KDE

#### KDE 3.x teegid

KDE põhiteegid, mida kasutada omaenda KDE rakenduste loomisel, on järgmised:

- teek kdecore, mis sisaldab kõik mittenähtavate elementide klasse, mis tagavadrakenduste funktsionaalsuse

- teek kdeui, mis sisaldab kasutajaliidese elemente, näiteks menüüribad, tööriistaribad jne.

- teek kfile, mis sisaldab faili valimise dialooge

Lisaks pakub KDE spetsiifilisemateks ülesanneteks järgmisi teeke:

- teek kdefx, mis sisaldab pilte, pildiefekte. QStyle laiendust KStyle

- teek khtml, mis sisaldab KDE html-komponenti

- teeki kjs, mis sisaldab KDE JavaScripti toetust

- teeki kio, mis sisaldab süvataseme ligipääsu võrgufailidele

- teeki kparts, mis sisaldab korduvkasutatavate, põimitavate, laiendatavate rakenduste toetust

Järgnevalt vaatame, mida on vaja meie esimese Qt rakenduse muutmiseks KDE rakenduseks.

#### KDE näidisrakendus

Järgnevalt näed, et KDE rakenduse kirjutamine pole sugugi raskem kui Qt rakenduse kirjutamine. KDE omaduste ärakasutamiseks tuleb lihtsalt tarvitada mõningaid muid klasse. Võtame näitena ette eespool kirjeldatud Qt rakenduse muutmise KDE rakenduseks:

    #include <kapplication.h>
    #include <qpushbutton.h>

    int main( int argc, char **argv )
    {
    KApplication a( argc, argv );

    QPushButton hello( "Hello world!", 0 );
    hello.resize( 100, 30 );

    a.setTopWidget( &hello );

    QObject::connect(&hello, SIGNAL( clicked() ), &a, SLOT( quit() ));

    hello.show();
    return a.exec();
    }

Kõigepealt asendasime klassi QApplication klassiga KApplication. Seejärel pidime muutma varasema meetodi setMainWidget() meetodiks setTopWidget, mida KApplication kasutab põhividina määramiseks. Ja ongi kõik! Sinu esimene KDE rakendus on valmis - pead veel ainult kompilaatorile teatama KDE kaasamise asukohta ja linkuriga linkima teegi kdecore võtmega -lkdecore.

Nüüd, kus tead, mida funktsioon `main()` üldiselt pakub ja kuidas muuta rakendus nähtavaks ning võimaldada kasutaja ja objekti interaktsiooni, on aeg minna järgmise peatüki kallale, kus loome oma esimese rakenduse &kdevelop;iga. Samuti saab seal testida kõike, millest oleme juttu teinud, ning näha oma silmaga, mis kuidas toimib.

Usutavasti oled järginud juhiseid ning uurinud Qt dokumentatsiooni, eriti just klasside QApplication, QWidget ja QObject kohta, ning teegi kdecore dokumentatsiooni klassi KApplication kohta. KDE teegi käsiraamat sisaldab samuti põhjalikku kirjeldust konstruktorite QApplication ja KApplication väljakutsumise kohta, kaasa arvatud käsureaargumentide töötlemine.

## Uue rakenduse loomine

### Rakenduse nõustaja

&kdevelop;i Rakenduse nõustaja eesmärk on võimaldada vähese vaevaga luua &kdevelop;is uus tarkvaraprojekt. Seetõttu luuaksegi kõik projektid algul nõustajaga ning alles seejärel hakkad neid ehitama ja laiendama malli pakutavat lähtekoodi. Vastavalt projekti eesmärgile saab valida mitme projektitüübi seast:

- KDE rakenduse raamistik: sisaldab standardse KDE rakenduse terve raamistiku lähtekoodi

- QMake'i projekt: sisaldab rakenduse raamistikku, mis tugineb Trolltechi qmake'i konfiguratsioonisüsteemile

- Lihtne "Tere, maailm" programm: sisaldab C++ terminalipõhist programmi ilma GUI toetuseta

- Terve rida muid programmimalle

Peatükis räägime, kuidas avada Rakenduse nõustaja ja mida teha KDE rakenduse projekti loomiseks. See on ka esimene samm, millega luua näidisprojekti esialgne versioon. Kõigi teiste projektitüüpide korral on sammud üldiselt samasugused, aga mitte kõik valikud ei pruugi kattuda.

### Rakenduse nõustaja käivitamine ja projekti loomine

#### Rakenduse nõustaja esimene lehekülg

Oma KDE rakenduse loomise alustamiseks ava &kdevelop;. Vali menüüst Projekt käsk Uus projekt. Ilmub Rakenduse nõustaja, mille esimesel leheküljel näed puukujulises struktuuris saadaolevaid projektitüüpe. Vali puust C++ ning selle alt KDE ja Rakenduse raamistik.

Meie näidisprojektiks on rakenduse KScribble loomine. Nimeta selliselt oma rakendus ja muuta dialoogi allosas olevat infot enda vajaduste kohaselt. Seejärel klõpsa nupule Edasi.

Rakenduse nõustaja

#### Versioonikontrolli info

Sellel leheküljel saad otsustada, kas sinu projekt kasutab mõnda versioonikontrollisüsteemi (näiteks CVS). Meie näidisprojekt ei kasuta, nii et jäta kasti alles Puudub ja klõpsa nupule Edasi.

#### Päise- ja lähtekoodifailide mallid

Järgmisel kahel leheküljel näed päiseid, mis lisatakse iga päise- ja lähtekoodifaili algusse, mida sa &kdevelop;iga lood. Jäta praegu siin kõik nii nagu on ning klõpsa nupule Edasi ja lõpuks Lõpeta. Kui nupp Lõpeta ei ole aktiivne, on valikutega midagi lahti. Kasuta nuppu Tagasi, et vaadata üle kõik varasemad leheküljed ja parandada vead.

#### Lõpetamine

Lõpetamise järel Rakenduse nõustaja sulgub ning ilmub teadeteaken, kus näed, mida &kdevelop; parajasti teeb. Lõpuks peaks sinna ilmuma teade **** Õnnestus *****. See tähendab, et rakenduse raamistik on edukalt laaditud.

### Esimene ehitamine

Nüüd, kus projekt on genereeritud, vaatame lähtekoodi üle, et saada mingi aim, milline näeb välja rakenduse raamistik. See mitte ainult ei aita meil arendamisega alustada, vaid annab ka teada, kus ja mida hiljem muuta.

Me eeldame siinkohal, et sa tead, kuidas &kdevelop;is liikuda. Vajaduse korral uuri seda KDevelopi kasutaja käsiraamatust.

Automake'i haldur näitab projekti faile selliselt:

Meie projekti failid

Enne lähtekoodi süüvimist laseme &kdevelop;il oma uue rakenduse ehitada. Selleks vali menüüst Projekt käsk Ehita projekt või vajuta F8. Ilmub teadeteaken, mis näitab kompileerimisfaasi väljundteateid.

    1 cd /home/caleb/kscribble && WANT_AUTOCONF_2_5=1 WANT_AUTOMAKE_1_6=1 gmake k
    2 gmake all-recursive
    3 gmake[1]: Entering directory `/home/caleb/kscribble'
    4 Making all in doc
    5 gmake[2]: Entering directory `/home/caleb/kscribble/doc'
    6 Making all in .
    7 gmake[3]: Entering directory `/home/caleb/kscribble/doc'
    8 gmake[3]: Nothing to be done for `all-am'.
    9 gmake[3]: Leaving directory `/home/caleb/kscribble/doc'
    10 Making all in en
    11 gmake[3]: Entering directory `/home/caleb/kscribble/doc/en'
    12 /usr/local/kde3/bin/meinproc --check --cache index.cache.bz2 /home/caleb/kscribble/doc/en/index.docbook
    13 gmake[3]: Leaving directory `/home/caleb/kscribble/doc/en'
    14 gmake[2]: Leaving directory `/home/caleb/kscribble/doc'
    15 Making all in po
    16 gmake[2]: Entering directory `/home/caleb/kscribble/po'
    17 gmake[2]: Nothing to be done for `all'.
    18 gmake[2]: Leaving directory `/home/caleb/kscribble/po'
    19 Making all in src
    20 gmake[2]: Entering directory `/home/caleb/kscribble/src'
    21 source='main.cpp' object='main.o' libtool=no \
    22 depfile='.deps/main.Po' tmpdepfile='.deps/main.TPo' \
    23 depmode=gcc3 /bin/sh /home/caleb/kscribble/admin/depcomp \
    24 g++ -DHAVE_CONFIG_H -I. -I/home/caleb/kscribble/src -I.. -I/usr/local/kde3/include
       -I/usr/lib/qt/include -I/usr/X11R6/include -DQT_THREAD_SUPPORT -D_REENTRANT -Wnon-virtual-dtor
       -Wno-long-long -Wundef -Wall -pedantic -W -Wpointer-arith -Wmissing-prototypes -Wwrite-strings
       -ansi -D_XOPEN_SOURCE=500 -D_BSD_SOURCE -Wcast-align -Wconversion -O2 -fno-exceptions -fno-check-new
       -c -o main.o `test -f 'main.cpp' || echo '/home/caleb/kscribble/src/'`main.cpp
    25 /usr/lib/qt/bin/moc /home/caleb/kscribble/src/kscribble.h -o kscribble.moc
    26 source='kscribble.cpp' object='kscribble.o' libtool=no \
    27 depfile='.deps/kscribble.Po' tmpdepfile='.deps/kscribble.TPo' \
    28 depmode=gcc3 /bin/sh /home/caleb/kscribble/admin/depcomp \
    29 g++ -DHAVE_CONFIG_H -I. -I/home/caleb/kscribble/src -I.. -I/usr/local/kde3/include
       -I/usr/lib/qt/include -I/usr/X11R6/include -DQT_THREAD_SUPPORT -D_REENTRANT -Wnon-virtual-dtor
       -Wno-long-long -Wundef -Wall -pedantic -W -Wpointer-arith -Wmissing-prototypes -Wwrite-strings
       -ansi -D_XOPEN_SOURCE=500 -D_BSD_SOURCE -Wcast-align -Wconversion -O2 -fno-exceptions -fno-check-new
       -c -o kscribble.o `test -f 'kscribble.cpp' || echo '/home/caleb/kscribble/src/'`kscribble.cpp
    30 kscribble.cpp: In member function `void KScribble::setupActions()'
    31 kscribble.cpp:107: warning: unused variable `KAction*custom'
    32 /usr/lib/qt/bin/moc /home/caleb/kscribble/src/kscribbleview.h -o kscribbleview.moc
    33 source='kscribbleview.cpp' object='kscribbleview.o' libtool=no \
    34 depfile='.deps/kscribbleview.Po' tmpdepfile='.deps/kscribbleview.TPo' \
    35 depmode=gcc3 /bin/sh /home/caleb/kscribble/admin/depcomp \
    36 g++ -DHAVE_CONFIG_H -I. -I/home/caleb/kscribble/src -I.. -I/usr/local/kde3/include
       -I/usr/lib/qt/include -I/usr/X11R6/include -DQT_THREAD_SUPPORT -D_REENTRANT -Wnon-virtual-dtor
       -Wno-long-long -Wundef -Wall -pedantic -W -Wpointer-arith -Wmissing-prototypes -Wwrite-strings -ansi
       -D_XOPEN_SOURCE=500 -D_BSD_SOURCE -Wcast-align -Wconversion -O2 -fno-exceptions -fno-check-new -c
       -o kscribbleview.o `test -f 'kscribbleview.cpp' || echo '/home/caleb/kscribble/src/'`kscribbleview.cpp
    37 kscribbleview.cpp: In member function `void KScribbleView::print(QPainter*,
    38  int, int)':
    39 kscribbleview.cpp:79: warning: unused parameter `QPainter*p'
    40 kscribbleview.cpp:79: warning: unused parameter `int height'
    41 kscribbleview.cpp:79: warning: unused parameter `int width'
    42 /usr/lib/qt/bin/moc /home/caleb/kscribble/src/pref.h -o pref.moc
    43 source='pref.cpp' object='pref.o' libtool=no \
    44 depfile='.deps/pref.Po' tmpdepfile='.deps/pref.TPo' \
    45 depmode=gcc3 /bin/sh /home/caleb/kscribble/admin/depcomp \
    46 g++ -DHAVE_CONFIG_H -I. -I/home/caleb/kscribble/src -I.. -I/usr/local/kde3/include
       -I/usr/lib/qt/include -I/usr/X11R6/include -DQT_THREAD_SUPPORT -D_REENTRANT -Wnon-virtual-dtor
       -Wno-long-long -Wundef -Wall -pedantic -W -Wpointer-arith -Wmissing-prototypes -Wwrite-strings
       -ansi -D_XOPEN_SOURCE=500 -D_BSD_SOURCE -Wcast-align -Wconversion -O2 -fno-exceptions -fno-check-new
       -c -o pref.o `test -f 'pref.cpp' || echo '/home/caleb/kscribble/src/'`pref.cpp
    47 /usr/local/kde3/bin/dcopidl /home/caleb/kscribble/src/kscribbleiface.h
    > kscribbleiface.kidl ||
       ( rm -f kscribbleiface.kidl ; /bin/false )
    48 /usr/local/kde3/bin/dcopidl2cpp --c++-suffix cpp --no-signals --no-stub kscribbleiface.kidl
    49 source='kscribbleiface_skel.cpp' object='kscribbleiface_skel.o' libtool=no \
    50 depfile='.deps/kscribbleiface_skel.Po' tmpdepfile='.deps/kscribbleiface_skel.TPo' \
    51 depmode=gcc3 /bin/sh /home/caleb/kscribble/admin/depcomp \
    52 g++ -DHAVE_CONFIG_H -I. -I/home/caleb/kscribble/src -I.. -I/usr/local/kde3/include
       -I/usr/lib/qt/include -I/usr/X11R6/include -DQT_THREAD_SUPPORT -D_REENTRANT -Wnon-virtual-dtor
       -Wno-long-long -Wundef -Wall -pedantic -W -Wpointer-arith -Wmissing-prototypes -Wwrite-strings
       -ansi -D_XOPEN_SOURCE=500 -D_BSD_SOURCE -Wcast-align -Wconversion -O2 -fno-exceptions -fno-check-new
       -c -o kscribbleiface_skel.o `test -f 'kscribbleiface_skel.cpp' ||
       echo '/home/caleb/kscribble/src/'`kscribbleiface_skel.cpp
    53 /bin/sh ../libtool --silent --mode=link --tag=CXX g++ -Wnon-virtual-dtor -Wno-long-long -Wundef -Wall
       -pedantic -W -Wpointer-arith -Wmissing-prototypes -Wwrite-strings -ansi -D_XOPEN_SOURCE=500
       -D_BSD_SOURCE -Wcast-align -Wconversion -O2 -fno-exceptions -fno-check-new -o kscribble -R
       /usr/local/kde3/lib -R /usr/lib/qt/lib -R /usr/X11R6/lib -L/usr/X11R6/lib -L/usr/lib/qt/lib
       -L/usr/local/kde3/lib main.o kscribble.o kscribbleview.o pref.o kscribbleiface_skel.o -lkio
    54 source='kscribble_client.cpp' object='kscribble_client.o' libtool=no \
    55 depfile='.deps/kscribble_client.Po' tmpdepfile='.deps/kscribble_client.TPo' \
    56 depmode=gcc3 /bin/sh /home/caleb/kscribble/admin/depcomp \
    57 g++ -DHAVE_CONFIG_H -I. -I/home/caleb/kscribble/src -I.. -I/usr/local/kde3/include
       -I/usr/lib/qt/include -I/usr/X11R6/include -DQT_THREAD_SUPPORT -D_REENTRANT -Wnon-virtual-dtor
       -Wno-long-long -Wundef -Wall -pedantic -W -Wpointer-arith -Wmissing-prototypes -Wwrite-strings
       -ansi -D_XOPEN_SOURCE=500 -D_BSD_SOURCE -Wcast-align -Wconversion -O2 -fno-exceptions -fno-check-new
       -c -o kscribble_client.o `test -f 'kscribble_client.cpp' || echo
       '/home/caleb/kscribble/src/'`kscribble_client.cpp
    58 /bin/sh ../libtool --silent --mode=link --tag=CXX g++ -Wnon-virtual-dtor -Wno-long-long -Wundef
       -Wall -pedantic -W -Wpointer-arith -Wmissing-prototypes -Wwrite-strings -ansi -D_XOPEN_SOURCE=500
       -D_BSD_SOURCE -Wcast-align -Wconversion -O2 -fno-exceptions -fno-check-new -o kscribble_client -R
       /usr/local/kde3/lib -R /usr/lib/qt/lib -R /usr/X11R6/lib -L/usr/X11R6/lib -L/usr/lib/qt/lib
       -L/usr/local/kde3/lib kscribble_client.o -lkdecore
    59 gmake[2]: Leaving directory `/home/caleb/kscribble/src'
    60 gmake[2]: Entering directory `/home/caleb/kscribble'
    61 gmake[2]: Nothing to be done for `all-am'.
    62 gmake[2]: Leaving directory `/home/caleb/kscribble'
    63 gmake[1]: Leaving directory `/home/caleb/kscribble'
    64 *** Success ***

Nagu näed, panime siin iga rea ette järjekorranumbri. Teadeteaknas neid ei näe, kuid nii on sul lihtsam meie edasist arutlust jälgida. Kõigepealt tuleb tähele panna, et gmake töötab rekursiivselt. See tähendab, et see alustab kataloogist, kus see välja kutsuti ning läheb üksteise järel selle alamkataloogidesse, naaseb seejärel kataloogi, kus tööd alustas, töötleb seda ja seejärel lõpetab.

Esimene huvipakkuv rida on 24. Pane tähele, et sel real kutsub make välja meie C++ kompilaatori g++, et kompileerida meie projekti esimene lähtekoodifail, antud juhul main.cpp. g++ kompilaatorile saab anda terve rea käsureavõtmeid, millest mõningaid kasutatakse vaikimisi, teiste kasutamist saab aga &kdevelop;is seadistada.

Enne järgmise faili (kscribble.cpp, rida 29) kompileerimist kutsutakse moc (metaobjekti kompilaator) välja kscribble.h jaoks (rida 25). Põhjuseks on see, et KScribble klassid kasutavad signaale/pesasid, mistõttu makro Q_OBJECT tuleb laiendada, mida meie eest teebki moc. Tekkinud faili kscribble.moc kasutab kscribble.cpp failis leiduva #include-lausega.

### Lähtekoodi mall

Mõistmaks, kuidas KDE rakendus töötab, tuleb meil esmalt uurida lähemalt lähtekoodi malli, mille lõi meie jaoks Rakenduse nõustaja. Nagu nägime, anti meie käsutusse valik lähtekoodi- ja päisefaile, mis ehitasid rakenduse esialgse koodi. Seepärast on kõige lihtsam koodi selgitada teostust rida realt järgides, nagu seda töödeldakse programmi käivitamisel, kuni see siseneb põhisilmusesse ja on valmis vastu võtma kasutaja sisestust. Seejärel vaatame funktsionaalsust, mis võimaldab kasutaja interaktsiooni, ning tutvume sellega, kuidas mitmed asjad töötavad. Sestap on arvatavasti just raamistikku kõige parem selgitada, sest see on samalaadne sisuliselt kõigis KDE rakendustes ning tagab sulle oskuse lugeda ka teiste projektide lähtekoodi. Lisaks saad teada, mida ja millises koodi osas muuta, et sinu rakendus käituks just nii, nagu sa seda soovid.

#### Funktsioon main()

Kuna rakendus alustab oma tegevust sisenemisega funktsiooni `main()`, alustame meiegi koodi uurimist siin. KScribble funktsioon `main()` on teostatud failis main.cpp ja selle leiab ka klassisirvijast, kui valida kataloog "Globaalsed funktsioonid".

    1  int main(int argc, char **argv)
    2  {
    3      KAboutData about("kscribble", I18N_NOOP("KScribble"), version, description,
    4                       KAboutData::License_GPL, "(C) 2002 Sinu nimi", 0, 0, "sina@sina.ee");
    5      about.addAuthor( "Sinu nimi", 0, "sina@sina.ee" );
    6      KCmdLineArgs::init(argc, argv, &about);
    7      KCmdLineArgs::addCmdLineOptions(options);
    8      KApplication app;
    9
    10    // register ourselves as a dcop client
    11    app.dcopClient()->registerAs(app.name(), false);
    12
    13    // see if we are starting with session management
    14    if (app.isRestored())
    15        RESTORE(KScribble)
    16    else
    17    {
    18        // no session.. just start up normally
    19        KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
    20        if (args->count() == 0)
    21        {
    22            KScribble *widget = new KScribble;
    23            widget->show();
    24        }
    25        else
    26        {
    27            int i = 0;
    28            for (; i < args->count(); i++)
    29            {
    30                KScribble *widget = new KScribble;
    31                widget->show();
    32                widget->load(args->url(i));
    33            }
    34        }
    35        args->clear();
    36    }
    37
    38    return app.exec();
    39 }

Kõigepealt luuakse, nagu ikka KApplication objekt, kuid me oleme lisanud mõned KDE meetodid, mis määravad antud rakenduse programmi ja autori kohta käiva info.

#### Kasutaja rakenduse käivitamine

... (veel kirjutamata)

#### Konstruktor

Vaatame nüüd konstruktorit ja seda, kuidas selle eksemplar välja kutsutakse

    1  KScribble::KScribble()
    2      : KMainWindow( 0, "KScribble" ),
    3        m_view(new KScribbleView(this)),
    4        m_printer(0)
    5  {
    6      // accept dnd
    7      setAcceptDrops(true);
    8
    9      // tell the KMainWindow that this is indeed the main widget
    10     setCentralWidget(m_view);
    11
    12     // then, setup our actions
    13     setupActions();
    14
    15     // and a status bar
    16     statusBar()->show();
    17
    18     // allow the view to change the statusbar and caption
    19     connect(m_view, SIGNAL(signalChangeStatusbar(const QString&)),
    20             this,   SLOT(changeStatusbar(const QString&)));
    21     connect(m_view, SIGNAL(signalChangeCaption(const QString&)),
    22             this,   SLOT(changeCaption(const QString&)));
    23
    24  }

Pane tähele, et KScribble on klassi KMainWindow järglane, mis on KDE rakenduste üks baasklasse. Me initsialiseerime klassi KScribbleView oma keskse vidinana, loome klassi KStatusBar meetodiga statusBar() (rida 16) ning ühendame mõned signaalid ja pesad.

## Rakenduse vaate kujundamine

### Sissejuhatus

Graafilise kasutajaliidesega rakendust luues on põhimureks rakenduse niinimetatud "vaate" väljatöötamine. Vaade on üldiselt vidin, mis esitab dokumendi andmeid ja pakub meetodeid dokumendi sisu käsitlemiseks. Seda teeb kasutaja sündmustega, mida ta emiteerib klaviatuuri või hiirega. Keerulisemateks toiminguteks kasutatakse tihtipeale tööriistaribasid ja menüüriba, mis suhtlevad vaate ja dokumendiga. Olekuriba aga pakub infot dokumendi, vaate või rakenduse oleku kohta. Vaatame näitena, kuidas konstrueeritakse redaktor ja mis kus asub.

Redaktor peab üldiselt pakkuma kasutajale liidese tekstidokumendi sisu vaatamiseks ja/või muutmiseks. Kui käivitad näiteks Kate, näed sellist visuaalset liidest:

- menüüriba: pakub keerukaid toiminguid, samuti failide avamise, salvestamise ja sulgemise ning rakendusest väljumise võimalust

- Tööriistariba: pakub ikoone sagedamini vajaminevate funktsioonide kiireks kasutamiseks

- Olekuriba: näitab kursori asukohainfot ehk rida ja veergu, kus asub kursor

- Vaade ise akna keskel, mis näitab dokumenti ning pakub andmete töötlemiseks klaviatuuriga ja hiirega ühendatud kursorit

On selge, et vaade on rakenduse kõige unikaalsem komponent ja et vaate kujundamisest sõltub suuresti rakenduse kasutatavus ja vastuvõetavus. See tähendab, et arendaise üks esimesi samme on määrata kindlaks rakenduse eesmärk ning leida, millist laadi vaade tagab kasutajale parimad võimalused rakendusega tööd teha nii, et ta peaks kulutama minimaalselt aega kasutajaliidese tundmaõppimiseks.

Teatud asjade jaoks,näiteks teksti redigeerimine ja HTML-failide näitamine, pakuvad vaateid Qt ja KDE teegid. Nende kõrgtaseme vidinate mõningatest aspektidest tuleb juttu järgmises osas. Enamiku rakenduste puhul tuleb siiski kujundada ja teostada uued vidinad. Nii peab programmeerija olema ka kujundaja, mis nõuab omajagu loovat annet. Kuid mõistagi on kõige olulisem nii-öelda sisetunne. Tasuks meeles pidada, et suur osa kasutajatest põrkab tagasi rakendustest, mis ei ole:

- visuaalselt kenad

- rikkalike omadustega

- hõlpsasti kasutatavad

- kiiresti omandatavad

Ja ei pruugi mainidagi, et kujunduse üks peamisi sihte on stabiilsus. Vigu ei ole muidugi võimalik kunagi täielikult vältida, kuid oskuslikult seatud kujunduseesmärkide ja objektorienteeritud disaini agara kasutamisega võib saavutada väga palju. C++ muudab programmeerimise lõbuks, kui oskad ära kasutada selle võimalusi: pärilus, info peitmine, juba olemasoleva koodi korduvkasutus.

KDE või Qt projekti luues peab sul alati olema vaade, mis on klassi QWidget järglane kas otsese päriluse kaudu või siis teegividina kaudu, mida soovid tarvitada. Seepärast konstrueerib juba Rakenduse nõustaja vaate, mis on klassi sinurakendusView eksemplar ja klassi QWidget järglane.

See peatükk kirjeldabki, kuidas kasutada teegividinaid &kdevelop;is loodud KDE või Qt rakenduste vaadete loomiseks, seejärel aga vaatame teeke ja vaateid, mida nad pakuvad.

### Teegivaadete kasutamine

Kui sinu rakenduse kujundus on juba paigas, tuleks võtta ette olemasolev kood, mis muudab elu märksa lihtsamaks. Ühe osana sellest tasuks otsida vidinat, mida saab kasutada vaatena või vähemalt vaate osana kas otse või päriluse kaudu. KDE ja Qt teegid sisaldavad mitmeid vidinaid, mida saab selleks otstarbeks pruukida. Nende kasutamiseks on sinu ees kaks võimalust:

1. Eemaldada uus vaateklass ja luua teegividina eksemplar ning määrata see siis vaateks.

2. Muuta pakutava vaateklassi pärilust, et see oleks kasutatava teegividina järglane.

Mõlemal juhul tuleb silmas pidada, et kui rakenduse raamistik pole parajasti lingitud vidinat sisaldava teegiga, tabab linkurit ebaõnn. Kui oled otsustanud kasutada teatud vidinat, otsi teek, millega see linkida. Seejärel vali &kdevelop;is menüükäsk "Projekt"->"Projekti seadistused". Ava kaart "Linkuri seadistused" ja uuri linnukesi, mis märgivad parajasti kasutavaid teeke. Kui sinu vidina teek on juba märgitud, võid jätta projekti seadistused puutumata ning asuda muudatuste kallale, mida sinu valik endaga kaasa toob. Kui aga mitte ja linkuri seadistused pakuvad võimalust kastikest märkides teeki lisada, siis märgi kast ja klõpsa nupule "OK". Muudel juhtudel tuleb teek lisada allpool võtmega -l. Teekide puhul, mida sinu rakendus peab otsima, enne kui configure-skript loob sihtmasinas Makefile'id, lisa vastav otsimismakro faili configure.in, mis paikneb sinu projekti juurkataloogis. Pane tähele, et sa pead käivitama, käsud "Ehitamine"->"Käivita automake" ja "Ehitamine"->"Käivita configure", enne kui Makefile'id hakkavad sisaldama teegimakro korrektse laiendamise määratlust.

Kui lisatava teegi kaasatavaid faile (include) ei ole kehtivas asukohas (seda saab näha ehitamise korral väljundaknas -I võtmetega), tuleb asukoht lisada projekti seadistuste dialoogi kaardil "Kompilaatori seadistused" võtmega -I või vastav automake'i makro "Lisaseadistuste" all.

#### Qt vaated

Qt võrgudokumentatsiooni avaleheküljelt leiab lingi "Widget Screenshots", millele klõpsates saab näha, kuidas näevad välja Qt pakutavad vidinad. Neid saab otsekohe kasutada ning kombineerida keerukamate vidinate loomiseks, mille alusel luua rakenduste vaateid või dialooge. Järgnevalt vaatleme mõningaid vidinaid, mida saab edukalt ära kasutada rakenduste vaadete loomiseks, kuid tasub meeles pidada, et ka KDE teegid sisaldavad vidinaid, mida saab samaks otstarbeks pruukida. Neist tuleb juttu järgmises osas.

Anname mõned nõuanded, milliseid Qt komponente milleks kasutada:

1. Kui sinu vaade pole piisavalt suur kõigi andmete näitamiseks, peab kasutajal olema võimalus kerida dokumenti vaate vasakus ja alumises servas asuvate ribadega. Selleks pakub Qt klassi QScrollView, mis tekitab keritava alampiirkonna. Nagu juba mainitud, tuleb oma vidin muuta QScrollView järglaseks või kasutada eksemplari oma dokumendi vaatevidina haldamiseks.

2. Et luua ise kerimisvaade, muuda vidin View klassi QWidget järglaseks ja lisa püstine ja rõhtne QScrollBars (seda teeb teha KDE vidinaga KHTMLView).

3. Tekstitöötluseks kasuta klassi QTextEdit. See pakub täieliku tekstiredaktori vidina, mis suudab juba teksti lõigata, kopeerida ja asetada ning mida haldab kerimisvaade.

4. Tabelisse paigutatud andmete esitamiseks kasuta klassi QTable. Et ka klassi QTable haldab kerimisvaade, sobib see hästi tabelitöötlusrakendustele.

5. Kahe erineva vidina või vidina eksemplari näitamiseks ühel ja samal ajal kasuta klassi QSplitter. See võimaldab paanida vaateid rõhtsate või püstiste eraldajate abil. Selle heaks näiteks on KMail: peavaade on eraldajaga jagatud vertikaalselt, parempoolne aken aga omakorda rõhtsalt.

6. QListView esitab infot nimekirja ja puu kujul. See on tulus failipuude või mis tahes muu hierarhilise info näitamiseks, millega kasutaja saab suhelda.

Nagu näha, pakub juba ainuüksi Qt terve rea vidinaid, mida saab otsekohe kasutada, nii et kui sul ei ole väga erilisi vajadusi, ei pea sa neid hakkama ise looma. Standardvidinate kasutamise lisaboonuseks on see, et kasutajad juba teavad, kuidas neid kasutada, ning võivad sestap koondada tähelepanu esitatavale andmetele.

#### KDE vaated

KDE teegid loodi selleks, et rakenduste kujundamine KDE töökeskkonna jaoks oleks veelgi lihtsam ja nende funktsionaalsus suurem kui see, mida saanuks pakkuda ainuüksi QT kasutamisel. Teek kdeui pakub:

1. KListView: QListView võimsam versioon

2. KIconView: ikoonifailide graafiline näitaja

Teek khtml omalt poolt pakub täieliku HTML-i tõlgendava vidina, mida saab kohe kasutada. See on keritav, nii et ka selle pärast ei pea muretsema. Üks võimalikke kasutamiskohti on HTML-redaktori eelvaatlusvidin. Seda kasutavad HTML-failide näitamiseks mitmed rakendused, näiteks Konqueror.

### Omaenda vaadete loomine

Veel kirjutamata

## Menüü- ja tööriistaribade seadistamine

### Sissejuhatus

Menüü- ja tööriistaribad on üks rakenduste tähtsamaid komponente, mis pakuvad meetodeid dokumendi struktuuri töötlemiseks. Üldreeglina tuleks kõik funktsioonid teha kättesaadavaks menüüriba kaudu. Need meetodid, mida rakendus oma töö käigus mingil hetkel kasutada ei saa, peavad olema sel hetkel mittekasutatavad.

Lisaks võib rakendusel olla ainult üks menüüriba, küll aga mitu tööriistariba. Tööriistaribad peavad samad pakkuma ainult kõige sagedamini kasutatavaid käske piltide ehk ikoonide kujul, tagades kiire ligipääsu meetoditele, muu hulgas ka liitkastide näol, kus saab valida mingeid väärtusi.

### Kuidas see töötab?

Meie rakendus on klassi KMainWindow järglane, mis automaatselt tegeleb menüüriba ja tööriistaribade loomisega. Meetodis KScribble::setupActions() on meetodi KMainWindow::createGUI() väljakutse. See meetod laeb ressursifaili, milleks antud juhul on kscribbleui.rc, mis käivitamise ajal initsialiseerib menüüd. Pane tähele, et kscribbleui.rc on Automake'i halduris näha ühe projektifailina. Selle avamisel näeb järgmist:

    1 <!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
    2 <kpartgui name="kscribble" version="1">
    3 <MenuBar>
    4   <Menu name="custom"
    ><text
    >C&ustom</text>
    5     <Action name="custom_action" />
    6   </Menu>
    7 </MenuBar>
    8 </kpartgui
    >

Selgitus...

Teine võimalus menüü- ja tööriistaribade sisu muuta on neid vahetult käsitleda nende klassi pakutavate meetoditega. Näiteks meetod menuBar() tagastab KMenuBar vidina, mis ongi meie programmi menüüriba. Otsides dokumentatsioonis infot klassi KMenuBar ja selle eellasklassi QMenuBar kohta, leiad suure hulga meetodeid insertItem(), mis võimaldavad lisada menüüribale elemente.

KMainWindow meetodid statusBar() ja toolBar() pakuvad samuti kasutatavaid vidinaid.

### Kiirklahvide seadistamine

Rakendusele annab märksa professionaalsema ilme, kui lisad sellele kiirklahvid. Neid tarvitavad küll peamiselt kogenumad kasutajad, kes soovivad rakenduses tavapärasest veelgi kiiremini töötada ega pelga selleks väikest vaeva kiirklahvide meeldejätmise nimel. Selleks pakuvad KDE teegid klassi KAction, mis pakub kiirklahve ja ligipääsu globaalselt seadistatud standardsetele kiirklahvidele.

Vaikimisi kasutavad &kdevelop;i genereeritud rakenduse raamistikud ainult standardseid kiirklahve, näiteks F1 abidokumendi avamiseks, Ctrl+N uue faili loomiseks jne.

Kui sinu rakenduses on hulk kiirklahve, tuleb need muuta seadistatavaks menüüsse Seadistused lisatava eraldi kirjega või vähemalt koos teiste rakenduste seadistustega dialoogis, mida pakub QWidget. KDE teek pakubki klassi KKeyChooser kaardidialoogide jaoks ning klassi KKeyDialog kiirklahvide seadistamise dialoogile.

## Abi

### Sissejuhatus

Arendusprotsessi väga tähtis osa on abivõimaluste pakkumine kasutajale kõikjal ja kõiges, kus seda vähegi võib tarvis minna. Enamik arendajaid kipub seda kõige viimaseks jätma või üldse unustama, kuid tasuks meeles pidada, et enamik tavalisi kasutajaid pole kaugeltki UNIX-i eksperdid. Nad võivad väga kergesti sattuda segadusse ja pettuda, kui ei leia ühtegi võimalust uue rakendusega tuttavaks saada. Kellegi sundimine rakendust omandama aga ainult praktilise kogemuse varal ei ole küll mõistlik. Seepärast pakuvad KDE ja Qt teegid kõikvõimalikke vahendeid, millega anda rakendustele märksa professionaalsem ilme ka selle poolest, et kasutaja pärast on arvukalt abivõimalusi. Need võivad olla järgmised:

- Kohtspikrid

- Olekuriba teated

- Mis see on nupud

Lisaks peaks rakendus pakkuma ka võimalust avada HTML-põhine käsiraamat kõigest tavapärase klahvile F1 vajutamisega. Kontekstipõhise abisüsteemi pakub automaatselt klass KMainWindow, ehkki rakenduse autor peab mõistagi ise looma abidokumendi sisu.

Et ka &kdevelop; pakub igakülgset abi ning Rakenduse nõustajagi loodud KDE raamistik sisaldab selle toetust, tutvustamegi käesolevas peatükis seda, kus ja kuidas lisada abivõimalused.

Rakenduse loomise käigust tuleks kõiges kasutada võimalikult ühtset lähenemist ning vajalikud sammud ette võtta kohe koodi laiendamisel. See väldib vajadust hiljem taas koodi süveneda, et selgusele jõuda, mida sinu rakendus õigupoolest teeb või miks on mingi koodiosa just selline, nagu ta on.

### Kohtspikrid

Hästi lihtne abivõimalus on kohtspikrid. Need on väiksed abiteated, mis ilmuvad nähtavale, kui kasutaja viib hiire vidina kohale, mis pakub kohtspikrit, ning kaovad siis, kui hiir vidina kohalt lahkub. Kõige enam kasutatakse kohtspikreid tööriistaribadel, kus need tuleb hoida võimalikult väiksetena, sest tööriistaribasid saab seadistada oma infot pakkuma mitmel moel: kas ainult nuppudena, nuppudena, millel on tekst paremal pool ikooni või selle all, või ka ainult tekstina. See esitamisvõimalus peaks olema kasutaja poolt seadistatav, aga ei pruugi tingimata olla. Teksti näidatakse nii või teisiti ka kohtspikrina ning tööriistariba koosneb tavaliselt nuppudest ja muudest vidinatest, näiteks tekstikastidest ja liitkastidest. Selle täielikku kirjeldust näeb klassi KToolBar dokumentatsioonis, mis asub kdeui teegis.

Vaatame näitena ühe tavalise rakenduse nuppu "Uus fail":

Siin pakub kohtspikri teate osa i18n("New File"). Seda sisaldab makro i18n(), mida pakub kapp.h kohtspikrite tõlkimise võimaldamiseks kasutaja valitud keelde.

Kohtspikreid saab lisada ka suvalisele kohandatud vidinale Qt pakutavat klassi QToolTip kasutades. Selle näiteks võib olla:

### Olekuriba laiendamine

Et rakendused, mis on KMainWindow järglased, sisaldavad ka olekuriba, pakub see ka valikut olekuriba teateid kõigi menüü- ja tööriistariba elementide tarbeks. Olekuriba abiteade on lühike teade, mis laiendab kohtspikrit või asendab menüüriba elementide kohtspikreid. Nagu nimigi ütleb, näidatakse seda olekuribal, kui kasutaja avab menüü ja valib sealt mõne kirje.

### Mis see on? nupp

Nupp Mis see on? palub abiakna, mis näitab kasutajale soovi korral abi teatud vidina kohta töövaates või tööriistaribal. See asub tööriistaribal ja aktiveerub, kui kasutaja nupule klõpsab. Kursor võtab küsimärgiga noole kuju, sarnanedes sel moel nupu enda ikoonile. Kasutaja saab sellega klõpsata huvipakkuva vidina peale, mis avabki abiakna. Võid näiteks katsetada, mida teeb nupp Mis see on? &kdevelop;is.

Mis see on? abi lisamiseks vidinale tuleb kasutada staatilist meetodit QWhatsThis::add(QWidget *widget, const QString &text)

## Dokumentatsioon

### Sissejuhatus

Arvestades seda, et projektidel puudub sageli täielik kasutaja dokumentatsioon, sisaldavad kõik &kdevelop;i projektid juba valmis käsiraamatut, mida saab hõlpsasti laiendada. See täidab veel ühe KDE eesmärgi: pakkuda kasutajatele, kes ei pruugi rakendusega kuigi tuttavad olla, piisavalt mitmekülgset ja võimalusel ammendavat abi. Käesolev peatükk kirjeldabki, kuidas laiendada pakutavat dokumentatsioonimalli ja kuidas muuta see kasutajale kättesaadavaks.

### Kasutaja dokumentatsioon

Sinu projekti dokumentatsioon asub kataloogis projektikataloog/doc/en või ka mõnes muus kataloogis, kui sinu emakeel pole inglise keel. Selles asub fail index.docbook, milles sisaldubki dokumentatsioon. Selles failis kasutatavat vormingut selgitab KDE dokumentatsiooni veebilehekülg.

### Programmeerija dokumentatsioon

Teine tähtis dokumentatsiooni komponent on sinu klasside liidese kirjeldamine. See võimaldab nii sul endal kui ka teistel programmeerijatel kasutada sinu klasse nende HTML-dokumentatsioonist abi otsides. Selle loomiseks sobib KDoc. &kdevelop; toetab täielikult KDoci kasutamist, luues KDE teegi dokumentatsiooni. Dokumenteeritud on juba ette ka sinu rakenduse raamistik. Pakutava koodiga tutvumiseks on äärmiselt kasulik alustada kaasatud dokumentatsiooni uurimist. Järgnevalt kirjeldame, mida on vaja teha API dokumentatsiooni loomiseks, kuidas &kdevelop; aitab seda teha ja millised spetsiaalseid silte pakub KDoc.

## Internatsionaliseerimine

### Sissejuhatus

i18n on internatsionaliseerimissüsteem, mida kasutatakse rakenduse või projekti internatsionaliseeritud ehk lihtsamalt öeldes tõlgitud versioonide pakkumiseks. Rakenduse kirjutamisel toetavad nad enamasti ainult keelt, milles töötab autor ning see kajastub visuaalselt menüükirjetes, pealdistes ja mitmel pool mujal. Internatsionaliseerimise siht ongi pakkuda rakendusi ja teegi funktsioone kasutaja emakeeles ning seeläbi võimaldada ka neil kasutajatel, kes ei kõnele autoriga sama keelt, ometi nautida ilma probleemideta kogu funktsionaalsust.

## Autorid

(... veel kirjutamata ...)

## Bibliograafia

GNU Make Manual

Richard M. Stallman
Roland McGrath

GNU Automake

David MacKenzie
Tom Tromey

GNU Autoconf

David MacKenzie
Ben Elliston

Using the GNU Compiler Collection

Richard M. Stallman

GNU Libtool

Gordon Matzigkeit
Alexandre Oliva
Thomas Tanner
Gary V. Vaughan

GNU Autoconf, Automake, and Libtool

1st edition
October 2000
Gary V. Vaughan
Ben Elliston
Tom Tromey
Ian Lance Taylor
New Riders Publishing ISBN 1578701902

Advanced Programming in the UNIX(R) Environment

1st edition
June 1992
W. Richard Stevens
Addison-Wesley Pub Co ISBN 0201563177

Thinking in C++, Volume 1: Introduction to Standard C++

2nd Edition
April 15, 2000
Bruce Eckel
Prentice Hall ISBN 0139798099

Open Source Development with CVS

2nd Edition
October 12, 2001
Karl Fogel
Moshe Bar
The Coriolis Group ISBN 158880173X

Programming PHP

1st edition
March 2002
Rasmus Lerdorf
Kevin Tatroe
O'Reilly & Associates ISBN 1565926102

Programming Python

2nd Edition
March 2001
Mark Lutz
O'Reilly & Associates ISBN 0596000855

Gui Programming With Python : Using the Qt Toolkit

Bk&Cd-r edition
January 2002
Boudewijn Rempt
Opendocs Llc ISBN 0970033044

Programming Perl

The Camel book

3rd Edition
July 2000
Larry Wall
Tom Christiansen
Jon Orwant
O'Reilly & Associates ISBN 0596000278

Learning Perl

The Lama book

3rd Edition
July 15, 2001
Randal L. Schwartz
Tom Phoenix
O'Reilly & Associates ISBN 0596001320
&underFDL;