Development/Tutorials/Saving and loading (fi): Difference between revisions
Line 278: | Line 278: | ||
====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ä | |||
<tt>{{class|KFileDialog}}::[http://api.kde.org/4.0-api/kdelibs-apidocs/kio/html/classKFileDialog.html#8891356c249c5911e1ab15cc2739a89b getSaveFileName()]</tt>:n palauttama tiedoston nimi. | |||
<code cppqt> | <code cppqt> | ||
Line 287: | Line 288: | ||
</code> | </code> | ||
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()==== |
Revision as of 09:23, 14 January 2008
Development/Tutorials/Saving_and_loading
Languages: عربي | Asturianu | Català | Česky | Kaszëbsczi | Dansk | Deutsch | English | Esperanto | Español | Eesti | فارسی | Suomi | Français | Galego | Italiano | 日本語 | 한국어 | Norwegian | Polski | Português Brasileiro | Română | Русский | Svenska | Slovenčina | Slovenščina | српски | Türkçe | Tiếng Việt | Українська | 简体中文 | 繁體中文
Tutorial Series | Beginner Tutorial |
Previous | Perehdytys 3 - KActions ja XMLGUI |
What's Next | Tutorial 5 - Using KCmdLineArgs |
Further Reading | KIO::NetAccess QFile |
Lyhyesti
Nyt kun meillä on perus tekstieditori, on aika tehdä siitä jollain tavalla hyödyllinen. Jokaisen tekstieditorilla pitäisi pystyä vähintäänkin tallettamaan tehdyt työt levylle sekä avata tekstitiedostoja käsittelyä varten.
KDE tarjoaa joukon luokkia tiedostojen kanssa työskentelyä varten jotka helpottavat ohjelmistokehittäjän elämää. KIO-kirjasto mahdollistaa helpon tiedostojen käsittelyn verkkoprotokollien yli sekä se tarjoaa vakioidun tiedosto valikon tiedostojen avaamista ja tallettamista 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 tallennus mahdollisuuden 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 tarvitsee määritellä nämä funktiot slot:ksi. Tämä on toteutettu rivillä 19. Koska käytämme slot:a tässä otsikkotiedostossa, meidän tarvitsee lisätä myös Q_OBJECT makro.
Haluamme myös pitää muistissa avaamamme tiedoston nimen, joten meidän tarvitsee esitellä myös QString fileName.
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"?>
<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
<gui name="tutorial4" version="1">
<ToolBar name="mainToolBar" >
<text>Main Toolbar</text>
<Action name="clear" />
</ToolBar>
<MenuBar>
<Menu name="file" >
<Action name="clear" />
</Menu>
</MenuBar>
</gui>
Tämä on muuten identtinen tutorial3ui.rc kanssa, paitsi nimi on muutettu 'tutorial4':ksi. Koska kaikki uudet toiminnot ovat KStandardAction:ta jotka 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 tallettamisen. 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. Samaan tapaan kuin Perehdytyksessä 3, lopeta-toiminnon kanssa, käytämme tähänkin tarkoitukseen KStandardActions:a riveillä 37-47. Kaikki uudet toiminnot on kytketty sopiviin sloteihin jotka esittelimme otsikkotiedostossa 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 talletettuna minnekkään.
textArea->clear() tyhjentää tekstialueen käyttäen samaa KAction:n clear-funktiota johon kytkimme Tyhjennä-toimionnon Perehdytyksessä 3.
Tiedoston tallettaminen
saveFileAs(QString)
Siirrymme nyt ensimmäiseen tiedostoja käsittelevään koodiin. Seuraavaksi syvennymme funktioon jonka tehtävänä on tallentaa tekstialueen sisältö paramterinä annetulla tiedostonimellä. KDE tarjoaa turvalliseen tiedoston tallettamiseen 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 kun meillä on tiedosto johon kirjoittaa, meidän pitää muotoilla teksti alueen sisältö sellaiseen muotoon joka on mahdollista kirjoittaa tiedostoon. Tätä tarkoitusta varten luomme QByteArray:n johon syötämme tekstialueen sisällön tekstinä, ilman muotoiluja, seuraavasti:
QByteArray outputByteArray;
outputByteArray.append(textArea->toPlainText());
Nyt meillä on KSaveFile::write():n kanssa käytettävä QByteArray calmiina. Normaalin QFile:n käyttäminen olisi myös mahdollista, ja se tallettaisi muutokset välittömästi, mutta jos tällöin tapahtuisi jokin virhe tallentamisen aikana, tulisi tiedostosta viallinen. Tästä syystä KSaveFile luo ensin väliaikaisen tiedoston, ja vasta kun kutsutaan KSaveFile::finalize()-funktiota, luodaan varsinainen tiedosto.
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();
}
}
There's nothing exciting or new in this function, just the logic to decide whether or not to show the save dialog. If fileName is not empty, then the file is saved to fileName. But if it is, then the dialog is shown to allow the user to select a file name.
Loading a file
Finally, we get round to being able to load a file from disc. The code for this is all contained in MainWindow::openFile().
First we must ask the user for the name of the file they wish to open. We do this using another one of the KFileDialog functions, this time getOpenFileName():
QString fileNameFromDialog = KFileDialog::getOpenFileName();
Then we use the KIO library to retrieve our file. This allows us to open the file with QFile even if it's stored in a remote location like an FTP site. We make the following call to NetAccess's download() function
KIO::NetAccess::download(fileNameFromDialog, tmpFile, this)
The first argument is the name of the file you wish to download. The second is a QString which, after the download is complete, will contain the location of the temporary copy of the file. It is this tmpFile we will work with from now on.
The function returns true or false depending on whether the transfer was successful. If it failed, we display a message box giving the error:
KMessageBox::error(this, KIO::NetAccess::lastErrorString());
Otherwise, we continue with opening the file.
We create a QFile by passing the temporary file created by NetAccess::download() to its constructor and then open it in read-only mode
QFile file(tmpFile);
file.open(QIODevice::ReadOnly);
In order to display the contents of the file, we must use a QTextStream. We create one by passing the contents of our file to its constructor and then call QFile's readAll() function to get the text from the file. This is then passed to the setPlainText() function of our text area.
textArea->setPlainText(QTextStream(&file).readAll());
We then store the path of the file we just opened:
fileName = fileNameFromDialog;
and finally, we remove the temporary file that was created by NetAccess::download():
KIO::NetAccess::removeTempFile(tmpFile);
Make, Install And Run
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)
Since we are now using the KIO library, we must tell CMake to link against it. We do this by passing ${KDE4_KIO_LIBS} to the target_link_libraries() function.
With this file, the tutorial can built and run in the same way as tutorial 3. For more information, see tutorial 3.
mkdir build && cd build cmake .. -DCMAKE_INSTALL_PREFIX=$HOME make install $HOME/bin/tutorial4
Moving On
Now you can move on to the KCmdLineArgs tutorial.