Saving and loading documents
What's the use of an editor if it can't
load and save texts? It would be of no use at all— and
thus it is high time that we implemented this essential
functionality. Loading and saving are part of the
KalamDocument class. First, we need to
decide if we will make use of the special PyQt file classes, or
of the generic Python file classes. Let's do both for now, and
you can choose which style you prefer.
Loading
Loading first:
def open(self, fileName, format=None):
self.setPathName(fileName)
f = QFile(fileName)
if f.exists():
f.open(IO_ReadOnly)
self.setText(QTextStream(f).read())
else:
raise IOError("No such file or directory: '%s'" % fileName)
self._modified=FALSE
This is the Qt way of doing things:
first, a QFile object is created. If a
file with the name fileName already exists,
a QTextStream is used to read the text
from the file. This text is read into a
QString object, which is passed on to
setText, which we saw above. If the file
doesn't exist, an exception is raised, which is caught in the
application class, KalamApp.
The Pythonic method is a lot shorter:
def open(self, fileName, format=None):
self.setPathName(fileName)
self.setText(QString(open(str(fileName)).read()))
self._modified=FALSE
The net result is the same: the document
receives a text in QString format, and
all views are updated. There is no appreciable difference in
performance between these two methods, but if you plan to
translate the Python application to C++ at some time, it might
be preferable to work with as many Qt classes as
possible.
Saving
Saving text is slightly more critical
than loading: what you can't load, you can't mangle and lose,
but if the application refuses to save a text, a user can lose
a lot of work. Still, there is little you can do when the disk
is full, beyond preventing the application from crashing. As
long as Kalam is running, users can still
select, copy and paste text - a lesson I learned with early
versions of Word. Note that saving using
QTextStream is not currently possible.
QTextStream uses C++ operator
overloading (i.e. <<) to write to a stream, which is not
yet available in Python.
def save(self, fileName = None, format = None):
if fileName is not None and fileName <> "":
self.setPathName(fileName)
if self.pathName() == None:
raise IOError("Could not save document: no filename.")
if isinstance(self.pathName(), QString):
self.setPathName(str(self.pathName()))
s=str(self.text())
f = open(self.pathName(), "w")
f.write(s)
if s[-1:] != "\n":
f.write("\n")
f.flush()
self._modified = FALSE
There are a few necessary checks to
perform. The first is to make sure that the document actually
possesses a filename; then we check whether the filename is an
instance of QString, instead of a
Python string. Python's file object cannot use
QStrings — it needs to have a
genuine Python string. So, if the pathname is an instance of
QString, it is converted to a Python
string.
The document text is then converted to a
Python string. A Python file object is created by using the
open function, and we write the string to
it. If the last character is not a newline, we write a last
newline and flush the file. It is a good idea to end all files
with a newline, though you may wish to make this is a
user-option in the application.