Development/Tutorials/Saving and loading (fi): Difference between revisions
(kielenhuoltoa) |
No edit summary |
||
(10 intermediate revisions by 3 users not shown) | |||
Line 1: | Line 1: | ||
{{TutorialBrowser| | {{TutorialBrowser| | ||
Line 5: | Line 5: | ||
series=Beginner Tutorial| | series=Beginner Tutorial| | ||
name= | name=Tallentaminen ja avaaminen| | ||
pre=[[Development/Tutorials/Using_KActions (fi)| | pre=[[Development/Tutorials/Using_KActions (fi)|Opas 3 - KActions ja XMLGUI]]| | ||
next=[[Development/Tutorials/KCmdLineArgs|Tutorial 5 - Using KCmdLineArgs]]| | next=[[Development/Tutorials/KCmdLineArgs|Tutorial 5 - Using KCmdLineArgs]]| | ||
Line 18: | Line 18: | ||
Nyt kun meillä on yksinkertainen tekstieditori, on aika tehdä siitä jollain tavalla hyödyllinen. Jokaisella tekstieditorilla pitäisi pystyä ainakin tallentamaan tehdyt työt levylle sekä avaamaan tekstitiedostoja käsittelyä varten. | Nyt kun meillä on yksinkertainen tekstieditori, on aika tehdä siitä jollain tavalla hyödyllinen. Jokaisella tekstieditorilla pitäisi pystyä ainakin tallentamaan tehdyt työt levylle sekä avaamaan tekstitiedostoja käsittelyä varten. | ||
KDE tarjoaa tiedostojen kanssa työskentelyä varten joukon luokkia, jotka helpottavat ohjelmistokehittäjän elämää. KIO-kirjasto mahdollistaa helpon tiedostojen käsittelyn verkkoprotokollien | KDE tarjoaa tiedostojen kanssa työskentelyä varten joukon luokkia, jotka helpottavat ohjelmistokehittäjän elämää. KIO-kirjasto mahdollistaa helpon tiedostojen käsittelyn verkkoprotokollien kautta sekä tarjoaa vakioidun tiedostovalikon tiedostojen avaamista ja tallentamista varten. | ||
[[image:introtokdetutorial4.png|frame|center]] | [[image:introtokdetutorial4.png|frame|center]] | ||
Line 25: | Line 25: | ||
===main.cpp=== | ===main.cpp=== | ||
< | <syntaxhighlight lang="cpp-qt" line> | ||
#include <KApplication> | #include <KApplication> | ||
#include <KAboutData> | #include <KAboutData> | ||
Line 46: | Line 46: | ||
return app.exec(); | return app.exec(); | ||
} | } | ||
</ | </syntaxhighlight> | ||
<tt>main.cpp</tt>-tiedostoa ei ole muutettu mitenkään paitsi kaikki ''tutorial 3'':t on vaihdettu ''tutorial 4'':ksi. | <tt>main.cpp</tt>-tiedostoa ei ole muutettu mitenkään paitsi kaikki ''tutorial 3'':t on vaihdettu ''tutorial 4'':ksi. | ||
===mainwindow.h=== | ===mainwindow.h=== | ||
< | <syntaxhighlight lang="cpp-qt" line> | ||
#ifndef MAINWINDOW_H | #ifndef MAINWINDOW_H | ||
#define MAINWINDOW_H | #define MAINWINDOW_H | ||
Line 78: | Line 78: | ||
#endif | #endif | ||
</ | </syntaxhighlight> | ||
Tiedostojen avaus ja | Tiedostojen avaus- ja tallennusmahdollisuuden aikaansaamiseksi meidän tarvitsee lisätä funktiot, jotka tekevät tarvittavat asiat. Koska näitä funktoita tullaan kutsumaan Qt:n [http://doc.trolltech.com/latest/signalsandslots.html signal/slot]-yhdistämismekanismin kautta, meidän on määriteltävä nämä funktiot <tt>slot</tt>:ksi. Tämä on toteutettu rivillä 19. Koska käytämme <tt>slot</tt>:a tässä otsikkotiedostossa, on myös [http://doc.trolltech.com/latest/qobject.html#Q_OBJECT <tt>Q_OBJECT</tt>] -makro lisättävä. | ||
Haluamme myös pitää muistissa avaamamme tiedoston nimen, joten | Haluamme myös pitää muistissa avaamamme tiedoston nimen, joten myösmyös <tt>{{qt|QString}} fileName</tt> on esiteltävä. | ||
===mainwindow.cpp=== | ===mainwindow.cpp=== | ||
< | <syntaxhighlight lang="cpp-qt" line> | ||
#include "mainwindow.h" | #include "mainwindow.h" | ||
Line 196: | Line 196: | ||
} | } | ||
} | } | ||
</ | </syntaxhighlight> | ||
===tutorial4ui.rc=== | ===tutorial4ui.rc=== | ||
< | <syntaxhighlight lang="xml" line> | ||
<?xml version="1.0" encoding="UTF-8"?> | <?xml version="1.0" encoding="UTF-8"?> | ||
<gui name="tutorial4" | |||
<gui name="tutorial4" version="1" | version="1" | ||
xmlns="http://www.kde.org/standards/kxmlgui/1.0" | |||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |||
xsi:schemaLocation="http://www.kde.org/standards/kxmlgui/1.0 | |||
http://www.kde.org/standards/kxmlgui/1.0/kxmlgui.xsd" > | |||
<MenuBar> | <MenuBar> | ||
<Menu name="file" > | <Menu name="file" > | ||
Line 212: | Line 213: | ||
</Menu> | </Menu> | ||
</MenuBar> | </MenuBar> | ||
<ToolBar name="mainToolBar" > | |||
<text>Main Toolbar</text> | |||
<Action name="clear" /> | |||
</ToolBar> | |||
</gui> | </gui> | ||
</ | </syntaxhighlight> | ||
Tämä on muuten identtinen <tt>tutorial3ui.rc</tt> kanssa, paitsi <tt>nimi</tt> on muutettu 'tutorial4':ksi. Koska kaikki uudet toiminnot ovat <tt>KStandardAction</tt> | Tämä on muuten identtinen <tt>tutorial3ui.rc</tt> kanssa, paitsi <tt>nimi</tt> on muutettu 'tutorial4':ksi. Koska kaikki uudet toiminnot ovat <tt>KStandardAction</tt> -toimintoja, joita KDE osaa automaattisesti käsitellä, tähän tiedostoon ei tarvitse lisätä mitään. | ||
==Selvitys== | ==Selvitys== | ||
Selvitetään nyt hieman koodia joka tekee avaamisen sekä ja | Selvitetään nyt hieman koodia, joka tekee avaamisen sekä ja tallentamisen. Kaikki tarvittava on sijoitettu <tt>mainwindow.cpp</tt>-tiedostoon. | ||
Ensimmäisenä, rivillä 16, meidän pitää lisätä | Ensimmäisenä, rivillä 16, meidän pitää lisätä | ||
< | <syntaxhighlight lang="cpp-qt"> | ||
fileName(QString()) | fileName(QString()) | ||
</ | </syntaxhighlight> | ||
<tt>MainWindow</tt>:n muodostajaan. Tällä varmistetaan että tiedoston nimi on tyhjä aloitettaessa. | <tt>MainWindow</tt>:n muodostajaan. Tällä varmistetaan, että tiedoston nimi on tyhjä aloitettaessa. | ||
===Toimintojen lisääminen=== | ===Toimintojen lisääminen=== | ||
Ensinnäkin meidän pitää lisätä liittymä ohjelman ulkopuolelle, jotta käyttäjät voivat kertoa ohjelmalle avataanko vai talletetaanko tiedosto. | Ensinnäkin meidän pitää lisätä liittymä ohjelman ulkopuolelle, jotta käyttäjät voivat kertoa ohjelmalle, avataanko vai talletetaanko tiedosto. Käytämme tähänkin tarkoitukseen <tt>KStandardActions</tt>:a riveillä 37-47 samaan tapaan kuin oppaassa 3 toteuttaessamme <tt>lopeta</tt>-toimintoa. Kaikki uudet toiminnot on kytketty sopiviin sloteihin, jotka esittelimme otsaketiedostossa riveillä 20-24. | ||
===Uusi asiakirja=== | ===Uusi asiakirja=== | ||
Ensimmäisenä funktio jonka loimme on <tt>newFile()</tt>-funktio. | Ensimmäisenä funktio jonka loimme on <tt>newFile()</tt>-funktio. | ||
< | <syntaxhighlight lang="cpp-qt"> | ||
void MainWindow::newFile() | void MainWindow::newFile() | ||
{ | { | ||
Line 239: | Line 246: | ||
textArea->clear(); | textArea->clear(); | ||
} | } | ||
</ | </syntaxhighlight> | ||
<tt>fileName.clear()</tt> asettaa <tt>fileName</tt> (QString) merkkijonon tyhjäksi kuvaamaan että tätä tiedostoa ei ole olemassa | <tt>fileName.clear()</tt> asettaa <tt>fileName</tt> (QString) merkkijonon tyhjäksi kuvaamaan, että tätä tiedostoa ei ole olemassa tallennettuna minnekkään. | ||
<tt>textArea->clear()</tt> tyhjentää tekstialueen käyttäen samaa <tt>KAction</tt>:n <tt>clear</tt>-funktiota johon kytkimme | <tt>textArea->clear()</tt> tyhjentää tekstialueen käyttäen samaa <tt>KAction</tt>:n <tt>clear</tt>-funktiota johon kytkimme tyhjennä-toiminnon oppaassa 3. | ||
===Tiedoston | ===Tiedoston tallentaminen=== | ||
====saveFileAs(QString)==== | ====saveFileAs(QString)==== | ||
Siirrymme nyt ensimmäiseen tiedostoja käsittelevään koodiin. Seuraavaksi syvennymme funktioon jonka tehtävänä on tallentaa tekstialueen sisältö | Siirrymme nyt ensimmäiseen tiedostoja käsittelevään koodiin. Seuraavaksi syvennymme funktioon, jonka tehtävänä on tallentaa tekstialueen sisältö parametrina annetulla tiedostonimellä. KDE tarjoaa turvalliseen tiedoston tallentamiseen Qt:n {{qt|QFile}}:a johdetun {{class|KSaveFile}}-luokan. | ||
Funktion prototyyppi on: | Funktion prototyyppi on: | ||
< | <syntaxhighlight lang="cpp-qt"> | ||
void MainWindow::saveFileAs(const QString &outputFileName) | void MainWindow::saveFileAs(const QString &outputFileName) | ||
</ | </syntaxhighlight> | ||
Seuraavaksi luomme <tt>KSaveFile</tt>-objektin ja avaamme sen | Seuraavaksi luomme <tt>KSaveFile</tt>-objektin ja avaamme sen | ||
< | <syntaxhighlight lang="cpp-qt"> | ||
KSaveFile file(outputFileName); | KSaveFile file(outputFileName); | ||
file.open(); | file.open(); | ||
</ | </syntaxhighlight> | ||
Nyt | Nyt meillä on tiedosto, johon voimme kirjoittaa. Seuraavaksi pitää tekstialueen sisältö muotoilla muotoon, joka on mahdollista kirjoittaa tiedostoon. Tätä tarkoitusta varten luomme {{qt|QByteArray}}:n, johon syötämme tekstialueen sisällön paljaana tekstinä (ilman muotoiluja) seuraavasti: | ||
< | <syntaxhighlight lang="cpp-qt"> | ||
QByteArray outputByteArray; | QByteArray outputByteArray; | ||
outputByteArray.append(textArea->toPlainText()); | outputByteArray.append(textArea->toPlainText()); | ||
</ | </syntaxhighlight> | ||
Nyt meillä on <tt>KSaveFile::write()</tt>:n kanssa käytettävä <tt>QByteArray</tt> | Nyt meillä on <tt>KSaveFile::write()</tt>:n kanssa käytettävä <tt>QByteArray</tt> valmiina. Normaalin <tt>QFile</tt>:n käyttäminen olisi myös mahdollista, ja se tallentaisi muutokset välittömästi. Jos tällöin kuitenkin tapahtuisi jokin virhe tallentamisen aikana, tulisi tiedostosta viallinen. Tästä syystä <tt>KSaveFile</tt> luo ensin väliaikaisen tiedoston, ja varsinainen tiedosto luodaan vasta kun kutsutaan <tt>KSaveFile::finalize()</tt>-funktiota. | ||
< | |||
<syntaxhighlight lang="cpp-qt"> | |||
file.write(outputByteArray); | file.write(outputByteArray); | ||
file.finalize(); | file.finalize(); | ||
file.close(); | file.close(); | ||
</ | </syntaxhighlight> | ||
Ja lopuksi asetetaan <tt>MainWindows</tt>:n <tt>fileName</tt> osoittamaan tiedostoon jonka juuri tallensimme: | Ja lopuksi asetetaan <tt>MainWindows</tt>:n <tt>fileName</tt> osoittamaan tiedostoon, jonka juuri tallensimme: | ||
< | <syntaxhighlight lang="cpp-qt"> | ||
fileName = outputFileName; | fileName = outputFileName; | ||
</ | </syntaxhighlight> | ||
====saveFileAs()==== | ====saveFileAs()==== | ||
Tähän funktioon on yhdistetty <tt>saveAs</tt>(Tallenna nimellä) toiminto. Tämä funktio kutsuu <tt>saveFileAs(QString)</tt>-funktiota jolle lähetetään parametrinä | Tähän funktioon on yhdistetty <tt>saveAs</tt>(Tallenna nimellä) toiminto. Tämä funktio kutsuu <tt>saveFileAs(QString)</tt>-funktiota, jolle lähetetään parametrinä | ||
<tt>{{class|KFileDialog}}::[http://api.kde.org/4.0-api/kdelibs-apidocs/kio/html/classKFileDialog.html#8891356c249c5911e1ab15cc2739a89b getSaveFileName()]</tt>:n palauttama tiedoston nimi. | <tt>{{class|KFileDialog}}::[http://api.kde.org/4.0-api/kdelibs-apidocs/kio/html/classKFileDialog.html#8891356c249c5911e1ab15cc2739a89b getSaveFileName()]</tt>:n palauttama tiedoston nimi. | ||
< | <syntaxhighlight lang="cpp-qt"> | ||
void MainWindow::saveFileAs() | void MainWindow::saveFileAs() | ||
{ | { | ||
saveFileAs(KFileDialog::getSaveFileName()); | saveFileAs(KFileDialog::getSaveFileName()); | ||
} | } | ||
</ | </syntaxhighlight> | ||
Tässä kohdassa käytämme ensimmäisen kerran KIO-kirjastoa. {{class|KFileDialog}}-luokka tarjoaa meille joukon funktioita joita kaikki KDE ohjelmat käyttävät yleisten tiedostovalikoiden näyttämiseen. <tt>KFileDialog::getSaveFileName()</tt>-funktion kutsuminen tuo esille tiedostovalikon jossa käyttäjä voi valita tai vaihtaa tiedoston nimeä tai tallennussijaintia. Funktio palauttaa täydellisen tiedoston nimen, jonka me välitimme <tt>saveFileAs(QString)</tt>-funktiolle. | Tässä kohdassa käytämme ensimmäisen kerran KIO-kirjastoa. {{class|KFileDialog}}-luokka tarjoaa meille joukon funktioita, joita kaikki KDE ohjelmat käyttävät yleisten tiedostovalikoiden näyttämiseen. <tt>KFileDialog::getSaveFileName()</tt>-funktion kutsuminen tuo esille tiedostovalikon,jossa käyttäjä voi valita tai vaihtaa tiedoston nimeä tai tallennussijaintia. Funktio palauttaa täydellisen tiedoston nimen, jonka me välitimme <tt>saveFileAs(QString)</tt>-funktiolle. | ||
====saveFile()==== | ====saveFile()==== | ||
< | <syntaxhighlight lang="cpp-qt"> | ||
void MainWindow::saveFile() | void MainWindow::saveFile() | ||
{ | { | ||
Line 304: | Line 312: | ||
} | } | ||
} | } | ||
</ | </syntaxhighlight> | ||
Tässä funktiossa ei ole mitään erityistä tai uutta. Tässä vain päätellään, näytetäänkö tallennusvalikko vai ei. Jos <tt>fileName</tt> ei ole tyhjä, tallennetaan tiedosto mitään kysymättä nimellä, joka on sijoitettuna <tt>fileName</tt>:n kutsumalla saveFileAs(QString)-funktiota, muuten kutsutaan yllä olevaa saveFileAs()-funktiota. | Tässä funktiossa ei ole mitään erityistä tai uutta. Tässä vain päätellään, näytetäänkö tallennusvalikko vai ei. Jos <tt>fileName</tt> ei ole tyhjä, tallennetaan tiedosto mitään kysymättä nimellä, joka on sijoitettuna <tt>fileName</tt>:n kutsumalla saveFileAs(QString)-funktiota, muuten kutsutaan yllä olevaa saveFileAs()-funktiota. | ||
Line 313: | Line 321: | ||
Ensin meidän pitää kysyä käyttäjältä, mikä tiedosto halutaan avata. Tätä tarkoitusta varten käytetään toista <tt>KFileDialog</tt>-funktiota, <tt>getOpenFileName()</tt>: | Ensin meidän pitää kysyä käyttäjältä, mikä tiedosto halutaan avata. Tätä tarkoitusta varten käytetään toista <tt>KFileDialog</tt>-funktiota, <tt>getOpenFileName()</tt>: | ||
< | <syntaxhighlight lang="cpp-qt"> | ||
QString fileNameFromDialog = KFileDialog::getOpenFileName(); | QString fileNameFromDialog = KFileDialog::getOpenFileName(); | ||
</ | </syntaxhighlight> | ||
Seuraavaksi käytämme KIO-kirjastoa tiedoston avaamiseen. KIO-kirjaston avulla voimme avata tiedoston QFilen avulla, paikalliselta levyltä tai etäkoneelta, vaikkapa FTP:n yli. Tiedoston avaamiseksi käytämme {{class|NetAccess}}:n <tt>download()</tt>-funktiota: | Seuraavaksi käytämme KIO-kirjastoa tiedoston avaamiseen. KIO-kirjaston avulla voimme avata tiedoston QFilen avulla, paikalliselta levyltä tai etäkoneelta, vaikkapa FTP:n yli. Tiedoston avaamiseksi käytämme {{class|NetAccess}}:n <tt>download()</tt>-funktiota: | ||
< | <syntaxhighlight lang="cpp-qt"> | ||
KIO::NetAccess::download(fileNameFromDialog, tmpFile, this) | KIO::NetAccess::download(fileNameFromDialog, tmpFile, this) | ||
</ | </syntaxhighlight> | ||
Ensimmäinen argumentti on avattavan tiedoston nimi. Toinen on QString, joka tiedoston hakemisen jälkeen sisältää väliaikaisen tiedoston sijainnin. Tämän <tt>tmpFile</tt>:n kanssa jatkamme tästä eteenpäin. | Ensimmäinen argumentti on avattavan tiedoston nimi. Toinen on QString, joka tiedoston hakemisen jälkeen sisältää väliaikaisen tiedoston sijainnin. Tämän <tt>tmpFile</tt>:n kanssa jatkamme tästä eteenpäin. | ||
Funktio palauttaa boolen arvon <tt>tosi</tt> tai <tt>epätosi</tt>, riippuen onnistuiko tiedoston siirto. Jos tiedoston haku epäonnistui, näytetään virheilmoitus: | Funktio palauttaa boolen arvon <tt>tosi</tt> tai <tt>epätosi</tt>, riippuen onnistuiko tiedoston siirto. Jos tiedoston haku epäonnistui, näytetään virheilmoitus: | ||
< | <syntaxhighlight lang="cpp-qt"> | ||
KMessageBox::error(this, KIO::NetAccess::lastErrorString()); | KMessageBox::error(this, KIO::NetAccess::lastErrorString()); | ||
</ | </syntaxhighlight> | ||
Muussa tapauksessa jatketaan tiedoston avaamista. | Muussa tapauksessa jatketaan tiedoston avaamista. | ||
Luomme uuden QFile:n välittämällä sen muodostajaan <tt>NetAccess::download()</tt>:n luoman väliaikaistiedoston | Luomme uuden QFile:n välittämällä sen muodostajaan <tt>NetAccess::download()</tt>:n luoman väliaikaistiedoston, minkä jälkeen avataan se kirjoitussuojattuna: | ||
< | <syntaxhighlight lang="cpp-qt"> | ||
QFile file(tmpFile); | QFile file(tmpFile); | ||
file.open(QIODevice::ReadOnly); | file.open(QIODevice::ReadOnly); | ||
</ | </syntaxhighlight> | ||
Tuodaksemme avaamamme tiedoston sisällön ruudulle näkyviin, tarvitsee meidän käyttää {{class|QTextStream}}-luokkaa. {{class|QTextStream}}:n muodostajalle välitämme äsken avaamamme tiedoston (QFile file) ja kutsumme QFile:n <tt>readAll()</tt>-funktiota saadaksemme tekstin tiedostosta. Seuraavaksi välitämme tämän kaiken | Tuodaksemme avaamamme tiedoston sisällön ruudulle näkyviin, tarvitsee meidän käyttää {{class|QTextStream}}-luokkaa. {{class|QTextStream}}:n muodostajalle välitämme äsken avaamamme tiedoston (QFile file) ja kutsumme QFile:n <tt>readAll()</tt>-funktiota saadaksemme tekstin tiedostosta. Seuraavaksi välitämme tämän kaiken tekstialueen <tt>setPlainText()</tt>-funktiolle: | ||
< | <syntaxhighlight lang="cpp-qt"> | ||
textArea->setPlainText(QTextStream(&file).readAll()); | textArea->setPlainText(QTextStream(&file).readAll()); | ||
</ | </syntaxhighlight> | ||
Tallennetaan avatun tiedoston nimi(polkuineen): | Tallennetaan avatun tiedoston nimi(polkuineen): | ||
< | <syntaxhighlight lang="cpp-qt"> | ||
fileName = fileNameFromDialog; | fileName = fileNameFromDialog; | ||
</ | </syntaxhighlight> | ||
Ja lopuksi poistetaan <tt>NetAccess::download()</tt>:n luoma väliaikaistiedosto: | Ja lopuksi poistetaan <tt>NetAccess::download()</tt>:n luoma väliaikaistiedosto: | ||
< | <syntaxhighlight lang="cpp-qt"> | ||
KIO::NetAccess::removeTempFile(tmpFile); | KIO::NetAccess::removeTempFile(tmpFile); | ||
</ | </syntaxhighlight> | ||
==Käännä, Asenna ja Suorita== | ==Käännä, Asenna ja Suorita== | ||
===CMakeLists.txt=== | ===CMakeLists.txt=== | ||
< | <syntaxhighlight lang="ini" line> | ||
project(tutorial4) | project(tutorial4) | ||
Line 373: | Line 381: | ||
install(FILES tutorial4ui.rc | install(FILES tutorial4ui.rc | ||
DESTINATION ${DATA_INSTALL_DIR}/tutorial4) | DESTINATION ${DATA_INSTALL_DIR}/tutorial4) | ||
</ | </syntaxhighlight> | ||
Koska otimme nyt KIO-kirjaston käyttöön, | Koska otimme nyt KIO-kirjaston käyttöön, täytyy CMakelle kertoa, että linkittäjän tarvitsee ottaa myös tämä mukaan. Tätä varten lisäämme <tt>target_link_libraries()</tt>-funktioon tiedon <tt>${KDE4_KIO_LIBS}</tt>. | ||
=== Komennot === | === Komennot === | ||
Itse käännös, asennus ja suoritus tehdään samoin kuin | Itse käännös, asennus ja suoritus tehdään samoin kuin oppaassa 3. | ||
mkdir build && cd build | mkdir build && cd build |
Latest revision as of 09:45, 15 July 2012
Tutorial Series | Beginner Tutorial |
Previous | Opas 3 - KActions ja XMLGUI |
What's Next | Tutorial 5 - Using KCmdLineArgs |
Further Reading | KIO::NetAccess QFile |
Lyhyesti
Nyt kun meillä on yksinkertainen tekstieditori, on aika tehdä siitä jollain tavalla hyödyllinen. Jokaisella tekstieditorilla pitäisi pystyä ainakin tallentamaan tehdyt työt levylle sekä avaamaan tekstitiedostoja käsittelyä varten.
KDE tarjoaa tiedostojen kanssa työskentelyä varten joukon luokkia, jotka helpottavat ohjelmistokehittäjän elämää. KIO-kirjasto mahdollistaa helpon tiedostojen käsittelyn verkkoprotokollien kautta sekä tarjoaa vakioidun tiedostovalikon tiedostojen avaamista ja tallentamista varten.
Koodi
main.cpp
#include <KApplication>
#include <KAboutData>
#include <KCmdLineArgs>
#include "mainwindow.h"
int main (int argc, char *argv[])
{
KAboutData aboutData( "tutorial4", "tutorial4",
ki18n("Tutorial 4"), "1.0",
ki18n("A simple text area which can load and save."),
KAboutData::License_GPL,
ki18n("Copyright (c) 2007 Developer") );
KCmdLineArgs::init( argc, argv, &aboutData );
KApplication app;
MainWindow* window = new MainWindow();
window->show();
return app.exec();
}
main.cpp-tiedostoa ei ole muutettu mitenkään paitsi kaikki tutorial 3:t on vaihdettu tutorial 4:ksi.
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <KXmlGuiWindow>
#include <KTextEdit>
class MainWindow : public KXmlGuiWindow
{
Q_OBJECT // *uusi*
public:
MainWindow(QWidget *parent=0);
private:
KTextEdit* textArea;
void setupActions();
QString fileName; // tiedoston nimi *uusi*
private slots: // *uusi*
void newFile(); // uusi tiedosto *uusi*
void openFile(); // avaa tiedosto *uusi*
void saveFile(); // tallenna tiedosto *uusi*
void saveFileAs(); // tallenna tiedosto nimellä *uusi*
void saveFileAs(const QString &outputFileName); // *uusi*
};
#endif
Tiedostojen avaus- ja tallennusmahdollisuuden aikaansaamiseksi meidän tarvitsee lisätä funktiot, jotka tekevät tarvittavat asiat. Koska näitä funktoita tullaan kutsumaan Qt:n signal/slot-yhdistämismekanismin kautta, meidän on määriteltävä nämä funktiot slot:ksi. Tämä on toteutettu rivillä 19. Koska käytämme slot:a tässä otsikkotiedostossa, on myös Q_OBJECT -makro lisättävä.
Haluamme myös pitää muistissa avaamamme tiedoston nimen, joten myösmyös QString fileName on esiteltävä.
mainwindow.cpp
#include "mainwindow.h"
#include <KApplication>
#include <KAction>
#include <KLocale>
#include <KActionCollection>
#include <KStandardAction>
#include <KFileDialog> // *uusi*
#include <KMessageBox> //*uusi*
#include <KIO/NetAccess> //*uusi*
#include <KSaveFile> //*uusi*
#include <QTextStream> //*uusi*
MainWindow::MainWindow(QWidget *parent)
: KXmlGuiWindow(parent),
fileName(QString()) //*uusi*
{
textArea = new KTextEdit;
setCentralWidget(textArea);
setupActions();
}
void MainWindow::setupActions()
{
KAction* clearAction = new KAction(this);
clearAction->setText(i18n("Clear"));
clearAction->setIcon(KIcon("document-new"));
clearAction->setShortcut(Qt::CTRL + Qt::Key_W);
actionCollection()->addAction("clear", clearAction);
connect(clearAction, SIGNAL(triggered(bool)),
textArea, SLOT(clear()));
KStandardAction::quit(kapp, SLOT(quit()),
actionCollection());
KStandardAction::open(this, SLOT(openFile()),
actionCollection()); //*uusi*
KStandardAction::save(this, SLOT(saveFile()),
actionCollection()); //*uusi*
KStandardAction::saveAs(this, SLOT(saveFileAs()),
actionCollection()); //*uusi*
KStandardAction::openNew(this, SLOT(newFile()),
actionCollection()); //*uusi*
setupGUI();
}
// * uutta tästä eteenpäin *
void MainWindow::newFile()
{
fileName.clear();
textArea->clear();
}
void MainWindow::saveFileAs(const QString &outputFileName)
{
KSaveFile file(outputFileName);
file.open();
QByteArray outputByteArray;
outputByteArray.append(textArea->toPlainText());
file.write(outputByteArray);
file.finalize();
file.close();
fileName = outputFileName;
}
void MainWindow::saveFileAs()
{
saveFileAs(KFileDialog::getSaveFileName());
}
void MainWindow::saveFile()
{
if(!fileName.isEmpty())
{
saveFileAs(fileName);
}
else
{
saveFileAs();
}
}
void MainWindow::openFile()
{
QString fileNameFromDialog = KFileDialog::getOpenFileName();
QString tmpFile;
if(KIO::NetAccess::download(fileNameFromDialog, tmpFile,
this))
{
QFile file(tmpFile);
file.open(QIODevice::ReadOnly);
textArea->setPlainText(QTextStream(&file).readAll());
fileName = fileNameFromDialog;
KIO::NetAccess::removeTempFile(tmpFile);
}
else
{
KMessageBox::error(this,
KIO::NetAccess::lastErrorString());
}
}
tutorial4ui.rc
<?xml version="1.0" encoding="UTF-8"?>
<gui name="tutorial4"
version="1"
xmlns="http://www.kde.org/standards/kxmlgui/1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.kde.org/standards/kxmlgui/1.0
http://www.kde.org/standards/kxmlgui/1.0/kxmlgui.xsd" >
<MenuBar>
<Menu name="file" >
<Action name="clear" />
</Menu>
</MenuBar>
<ToolBar name="mainToolBar" >
<text>Main Toolbar</text>
<Action name="clear" />
</ToolBar>
</gui>
Tämä on muuten identtinen tutorial3ui.rc kanssa, paitsi nimi on muutettu 'tutorial4':ksi. Koska kaikki uudet toiminnot ovat KStandardAction -toimintoja, joita KDE osaa automaattisesti käsitellä, tähän tiedostoon ei tarvitse lisätä mitään.
Selvitys
Selvitetään nyt hieman koodia, joka tekee avaamisen sekä ja tallentamisen. Kaikki tarvittava on sijoitettu mainwindow.cpp-tiedostoon.
Ensimmäisenä, rivillä 16, meidän pitää lisätä
fileName(QString())
MainWindow:n muodostajaan. Tällä varmistetaan, että tiedoston nimi on tyhjä aloitettaessa.
Toimintojen lisääminen
Ensinnäkin meidän pitää lisätä liittymä ohjelman ulkopuolelle, jotta käyttäjät voivat kertoa ohjelmalle, avataanko vai talletetaanko tiedosto. Käytämme tähänkin tarkoitukseen KStandardActions:a riveillä 37-47 samaan tapaan kuin oppaassa 3 toteuttaessamme lopeta-toimintoa. Kaikki uudet toiminnot on kytketty sopiviin sloteihin, jotka esittelimme otsaketiedostossa riveillä 20-24.
Uusi asiakirja
Ensimmäisenä funktio jonka loimme on newFile()-funktio.
void MainWindow::newFile()
{
fileName.clear();
textArea->clear();
}
fileName.clear() asettaa fileName (QString) merkkijonon tyhjäksi kuvaamaan, että tätä tiedostoa ei ole olemassa tallennettuna minnekkään. textArea->clear() tyhjentää tekstialueen käyttäen samaa KAction:n clear-funktiota johon kytkimme tyhjennä-toiminnon oppaassa 3.
Tiedoston tallentaminen
saveFileAs(QString)
Siirrymme nyt ensimmäiseen tiedostoja käsittelevään koodiin. Seuraavaksi syvennymme funktioon, jonka tehtävänä on tallentaa tekstialueen sisältö parametrina annetulla tiedostonimellä. KDE tarjoaa turvalliseen tiedoston tallentamiseen Qt:n QFile:a johdetun KSaveFile-luokan.
Funktion prototyyppi on:
void MainWindow::saveFileAs(const QString &outputFileName)
Seuraavaksi luomme KSaveFile-objektin ja avaamme sen
KSaveFile file(outputFileName);
file.open();
Nyt meillä on tiedosto, johon voimme kirjoittaa. Seuraavaksi pitää tekstialueen sisältö muotoilla muotoon, joka on mahdollista kirjoittaa tiedostoon. Tätä tarkoitusta varten luomme QByteArray:n, johon syötämme tekstialueen sisällön paljaana tekstinä (ilman muotoiluja) seuraavasti:
QByteArray outputByteArray;
outputByteArray.append(textArea->toPlainText());
Nyt meillä on KSaveFile::write():n kanssa käytettävä QByteArray valmiina. Normaalin QFile:n käyttäminen olisi myös mahdollista, ja se tallentaisi muutokset välittömästi. Jos tällöin kuitenkin tapahtuisi jokin virhe tallentamisen aikana, tulisi tiedostosta viallinen. Tästä syystä KSaveFile luo ensin väliaikaisen tiedoston, ja varsinainen tiedosto luodaan vasta kun kutsutaan KSaveFile::finalize()-funktiota.
file.write(outputByteArray);
file.finalize();
file.close();
Ja lopuksi asetetaan MainWindows:n fileName osoittamaan tiedostoon, jonka juuri tallensimme:
fileName = outputFileName;
saveFileAs()
Tähän funktioon on yhdistetty saveAs(Tallenna nimellä) toiminto. Tämä funktio kutsuu saveFileAs(QString)-funktiota, jolle lähetetään parametrinä KFileDialog::getSaveFileName():n palauttama tiedoston nimi.
void MainWindow::saveFileAs()
{
saveFileAs(KFileDialog::getSaveFileName());
}
Tässä kohdassa käytämme ensimmäisen kerran KIO-kirjastoa. KFileDialog-luokka tarjoaa meille joukon funktioita, joita kaikki KDE ohjelmat käyttävät yleisten tiedostovalikoiden näyttämiseen. KFileDialog::getSaveFileName()-funktion kutsuminen tuo esille tiedostovalikon,jossa käyttäjä voi valita tai vaihtaa tiedoston nimeä tai tallennussijaintia. Funktio palauttaa täydellisen tiedoston nimen, jonka me välitimme saveFileAs(QString)-funktiolle.
saveFile()
void MainWindow::saveFile()
{
if(!fileName.isEmpty())
{
saveFileAs(fileName);
}
else
{
saveFileAs();
}
}
Tässä funktiossa ei ole mitään erityistä tai uutta. Tässä vain päätellään, näytetäänkö tallennusvalikko vai ei. Jos fileName ei ole tyhjä, tallennetaan tiedosto mitään kysymättä nimellä, joka on sijoitettuna fileName:n kutsumalla saveFileAs(QString)-funktiota, muuten kutsutaan yllä olevaa saveFileAs()-funktiota.
Tiedoston avaaminen
Lopulta olemme valmiita tarkastelemaan tiedoston avaamista levyltä. Kaikki koodi tätä tarkoitusta varten on sijoitettu MainWindow::openFile()-funktioon.
Ensin meidän pitää kysyä käyttäjältä, mikä tiedosto halutaan avata. Tätä tarkoitusta varten käytetään toista KFileDialog-funktiota, getOpenFileName():
QString fileNameFromDialog = KFileDialog::getOpenFileName();
Seuraavaksi käytämme KIO-kirjastoa tiedoston avaamiseen. KIO-kirjaston avulla voimme avata tiedoston QFilen avulla, paikalliselta levyltä tai etäkoneelta, vaikkapa FTP:n yli. Tiedoston avaamiseksi käytämme NetAccess:n download()-funktiota:
KIO::NetAccess::download(fileNameFromDialog, tmpFile, this)
Ensimmäinen argumentti on avattavan tiedoston nimi. Toinen on QString, joka tiedoston hakemisen jälkeen sisältää väliaikaisen tiedoston sijainnin. Tämän tmpFile:n kanssa jatkamme tästä eteenpäin.
Funktio palauttaa boolen arvon tosi tai epätosi, riippuen onnistuiko tiedoston siirto. Jos tiedoston haku epäonnistui, näytetään virheilmoitus:
KMessageBox::error(this, KIO::NetAccess::lastErrorString());
Muussa tapauksessa jatketaan tiedoston avaamista.
Luomme uuden QFile:n välittämällä sen muodostajaan NetAccess::download():n luoman väliaikaistiedoston, minkä jälkeen avataan se kirjoitussuojattuna:
QFile file(tmpFile);
file.open(QIODevice::ReadOnly);
Tuodaksemme avaamamme tiedoston sisällön ruudulle näkyviin, tarvitsee meidän käyttää QTextStream-luokkaa. QTextStream:n muodostajalle välitämme äsken avaamamme tiedoston (QFile file) ja kutsumme QFile:n readAll()-funktiota saadaksemme tekstin tiedostosta. Seuraavaksi välitämme tämän kaiken tekstialueen setPlainText()-funktiolle:
textArea->setPlainText(QTextStream(&file).readAll());
Tallennetaan avatun tiedoston nimi(polkuineen):
fileName = fileNameFromDialog;
Ja lopuksi poistetaan NetAccess::download():n luoma väliaikaistiedosto:
KIO::NetAccess::removeTempFile(tmpFile);
Käännä, Asenna ja Suorita
CMakeLists.txt
project(tutorial4)
find_package(KDE4 REQUIRED)
include_directories(${KDE4_INCLUDES})
set(tutorial4_SRCS
main.cpp
mainwindow.cpp
)
kde4_add_executable(tutorial4 ${tutorial4_SRCS})
target_link_libraries(tutorial4 ${KDE4_KDEUI_LIBS}
${KDE4_KIO_LIBS})
install(TARGETS tutorial4 DESTINATION ${BIN_INSTALL_DIR})
install(FILES tutorial4ui.rc
DESTINATION ${DATA_INSTALL_DIR}/tutorial4)
Koska otimme nyt KIO-kirjaston käyttöön, täytyy CMakelle kertoa, että linkittäjän tarvitsee ottaa myös tämä mukaan. Tätä varten lisäämme target_link_libraries()-funktioon tiedon ${KDE4_KIO_LIBS}.
Komennot
Itse käännös, asennus ja suoritus tehdään samoin kuin oppaassa 3.
mkdir build && cd build cmake .. -DCMAKE_INSTALL_PREFIX=$HOME make install $HOME/bin/tutorial4
Seuraavaksi
Seuraavana perehdytys: Komentoriviparametrit. (keskeneräinen, englanniksi)