Development/Tutorials/Saving and loading (de): Difference between revisions
Rememberme (talk | contribs) |
Rememberme (talk | contribs) m (→saveFile()) |
||
Line 312: | Line 312: | ||
</code> | </code> | ||
Es gibt nichts neues oder aufregendes | Es gibt nichts neues oder aufregendes an dieser Funktion, nur die Logik zu entscheiden den Speicher-Dialog zu zeigen, oder nicht. Wenn <tt>fileName</tt> nicht leer ist, dann wird die Datei zu <tt>fileName</tt> gespeichert. Andernfalls wird der Dialog angezeigt damit der Benutzer einen Dateinamen bestimmen kann. | ||
===Loading a file=== | ===Loading a file=== |
Revision as of 11:58, 31 December 2007
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 | Українська | 简体中文 | 繁體中文
Dieser Abschnitt muss verbessert werden: Bitte hilf mit, verwirrende Abschnitte zu bereinigen und Abschnitte zu reparieren die ein todo beinhalten
Noch nicht vollständig übersetzt.
Anleitungsserie | Anleitung für Anfänger |
Voriges Kapitel | Anleitung 3 - KActions benutzen |
Nächstes Kapitel | Anleitung 5 - KCmdLineArgs benutzen |
Weiterführende Texte | KIO::NetAccess QFile |
Navigation | Deutsche Startseite |
Zusammenfassung
Nun da wir ein rudimentäres Text Editor Interface erstellt haben, ist es an der Zeit etwas Nützliches zu machen. Grundsätzlich muss ein Text Editor Dateien laden, nach Bearbeitung oder Erzeugung speichern und neue Dateien erstellen können.
KDE stellt eine Anzahl von Klassen bereit um das Arbeiten mit Dateien für die Entwickler deutlich zu vereinfachen. Die KIO Bibliothek ermöglicht es Dateien auf einfache Weise über Netzwerk-transparente Protokolle anzusteuern und stellt auch Standard Datei-Dialoge bereit.
Der Code
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 hat sich seit der dritten Anleitung nicht verändert, ausser das jeder Bezug zu 'tutorial 3' zu 'tutorial 4' geändert wurde.
mainwindow.h
- ifndef MAINWINDOW_H
- define MAINWINDOW_H
- include <KXmlGuiWindow>
- include <KTextEdit>
class MainWindow : public KXmlGuiWindow
{
Q_OBJECT //neu seit Anleitung 3
public:
MainWindow(QWidget *parent=0);
private:
KTextEdit* textArea;
void setupActions();
QString fileName; //neu
private slots: //neu
void newFile(); //neu
void openFile(); //neu
void saveFile(); //neu
void saveFileAs(); //neu
void saveFileAs(const QString &outputFileName); //neu
};
- endif
Da wir unserem Programm die Fähigkeit geben wollen, Dateien zu laden und zu speichern müssen wir Funktionen hinzufügen, die diese Arbeit erledigen werden. Da die Funktionen durch Qt's signal/slot-Mechanismus aufgerufen werden, müssen wir definieren, dass diese Funktionen Slots sind, wie wir dies auf Zeile 19 machen. Da wir Slots in diesem Header-File benutzen, müssen wir auch das Q_OBJECT Makro hinzufügen.
Wir werden auch den Dateinamen der momentan geöffneten Datei verfügbar haben wollen, also definieren wir einen QString fileName.
mainwindow.cpp
- include "mainwindow.h"
- include <KApplication>
- include <KAction>
- include <KLocale>
- include <KActionCollection>
- include <KStandardAction>
- include <KFileDialog> //neu
- include <KMessageBox> //neu
- include <KIO/NetAccess> //neu
- include <KSaveFile> //neu
- include <QTextStream> //neu
MainWindow::MainWindow(QWidget *parent)
: KXmlGuiWindow(parent),
fileName(QString()) //neu
{
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()); //neu
KStandardAction::save(this, SLOT(saveFile()),
actionCollection()); //neu
KStandardAction::saveAs(this, SLOT(saveFileAs()),
actionCollection()); //neu
KStandardAction::openNew(this, SLOT(newFile()),
actionCollection()); //neu
setupGUI();
}
//Neu ab hier
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>
Dies ist identisch mit tutorial3ui.rc aus Anleitung 3 ausser dass name zu 'tutorial4' geändert wurde. Wir müssen keine Informationen über irgendeine der KStandardActions hinzuzufügen da die Platzierung dieser Aktionen automatisch durch KDE erfolgt.
Erklärung
Nun kommen wir zum Code, der das Laden und Speichern erledigen wird. Das wird alles in mainwindow.cpp passieren.
Als erstes fügen wir
fileName(QString())
der MainWindow Konstruktor-Liste auf Zeile 16 hinzu. Das stellt sicher, dass fileName von Anfang an leer ist.
Hinzufügen der Aktionen
Als nächstes werden wir das äusserliche Interface für den Benutzer bereitstellen, so dass er der Anwendung mitteilen kann zu laden und zu speichern. Wie mit der quit Aktion in Anleitung 3 werden wir KStandardActions verwenden. Auf Zeilen 37 bis 47 werden wir die Aktionen auf die selbe Weise hinzufügen wie für die quit Aktion. Für jedes einzelne werden wir es mit dem richtigen Slot verbinden den wir in der Header Datei definiert haben.
Erstellen eines neuen Dokuments
Die erste Funktion die wir erstellen ist newFile().
void MainWindow::newFile()
{
fileName.clear();
textArea->clear();
}
fileName.clear() setzt den fileName QString auf leer um zu zeigen, dass dieses Dokument noch keine Präsenz auf der Festplatte hat. textArea->clear() leert dann das zentrale Textfeld unter Verwendung der gleichen Funktion mit der wir die clear KAction in Anleitung 3 verbunden haben.
TODO:Der Rest muss noch übersetzt werden.
Speichern einer Datei
saveFileAs(QString)
Jetzt kommen wir zum ersten Datei-Handhabungs-Code. Wir werden eine Funktion einführen, die die Inhalte des Textfeldes in den Dateinamen, der als Parameter gegeben ist, speichert. KDE stellt die KSaveFile Klasse bereit, mit der man sicher Dateien speichern kann. Sie ist von Qt's QFile abgeleitet.
Der Prototyp für unsere Funktion ist
void MainWindow::saveFileAs(const QString &outputFileName)
Wir erstellen dann unser KSaveFile Objekt und öffnen es mit
KSaveFile file(outputFileName);
file.open();
Nun da wir unsere Datei zum beschreiben haben, müssen wir den Text im Textfeld so formatieren, dass er in eine Datei geschrieben werden kann. Dazu erstellen wir ein QByteArray und füllen es mit der einfachen Text Version von was auch immer im Textfeld ist:
QByteArray outputByteArray;
outputByteArray.append(textArea->toPlainText());
Jetzt haben wir unser QByteArray, das wir dazu verwenden mit KSaveFile::write() in die Datei zu schreiben. Wenn wir ein normales QFile benutzen würden, würde dies die Änderungen sofort ausführen. Falls aber während dem Schreiben ein Fehler passieren würde, würde die Datei beschädigt werden. Darum speichert KSaveFile zuerst in eine temporäre Datei und dann, wenn man KSaveFile::finalize() aufruft, werden die Änderungen in die eigentliche Datei geschrieben.
file.write(outputByteArray);
file.finalize();
file.close();
Schliesslich setzen wir MainWindows's fileName Element dazu auf den Dateinamen zu zeigen, in den wir gerade geschrieben haben.
fileName = outputFileName;
saveFileAs()
Dies ist die Funktion mit der der saveAs Slot verbunden ist. Sie ruft einfach eine normale saveFileAs(QString) Funktion auf und übergibt den Dateinamen der von KFileDialog::getSaveFileName() zurückgegeben wird.
void MainWindow::saveFileAs()
{
saveFileAs(KFileDialog::getSaveFileName());
}
Dies ist unser erster eigentlicher Gebrauch der KIO Bibliothek. KFileDialog Stellt eine Anzahl statischer Funktionen bereit um den gemeinsamen Dateidialog, der von allen KDE Anwendungen genutzt wird, anzuzeigen.
KFileDialog::getSaveFileName() aufzurufen wird einen Dialog anzeigen wo der Benutzer den Namen der Datei eingeben kann in die er speichern will oder einen neuen Namen angeben. Diese Funktion gibt den vollständigen Dateinamen zurück, den wir dann saveFileAs(QString) übergeben.
saveFile()
void MainWindow::saveFile()
{
if(!fileName.isEmpty())
{
saveFileAs(fileName);
}
else
{
saveFileAs();
}
}
Es gibt nichts neues oder aufregendes an dieser Funktion, nur die Logik zu entscheiden den Speicher-Dialog zu zeigen, oder nicht. Wenn fileName nicht leer ist, dann wird die Datei zu fileName gespeichert. Andernfalls wird der Dialog angezeigt damit der Benutzer einen Dateinamen bestimmen kann.
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.