If we want a Python-savvy text editor with syntax highlighting, we need not create one ourselves. The Tkinter-based IDLE application provides both a "sandbox" in which we can experiment with Python code, and a perfectly good Python code editor. And for more power, we can use Eric4, itself written in PyQt and using QScintilla for its text editing. However, no off-the-shelf editor will necessarily work in just the way we want, and since creating our own is instructive and revealing of what is involved, we will create a simple Python Editor to learn how to use QTextEdit and QSyntaxHighlighter. As the screenshot in Figure 13.1 shows, the Python Editor is a simple main-window-style application with two menus and toolbars. Since we have covered the creation of such applications before, we will focus just on those parts that are relevant to rich text editing, starting with the beginning of the main window's initializer.
def_init_(self, filename=None, parent=None):
font = QFont("Courier", 11) font.setFixedPitch(True) self.editor = TextEdit() self.editor.setFont(font)
self.highlighter = PythonHighlighter(self.editor.document()) self.setCentralWidget(self.editor)
We begin by creating a fixed-pitch font (a font where every character is the same width). Then we create a TextEdit, a custom QTextEdit class that differs from QTextEdit in that it converts Tab key presses into insertions of four spaces. Next we create a PythonHighlighter, a QSyntaxHighlighter subclass, passing it the text editor's QTextDocument—this is the object in which the editor's text and formatting are actually stored. We make the editor the main window's central widget.
The rest of the initializer is concerned with the creation of the actions, menus, and toolbars, things that we are very familiar with and can therefore skip. The only other methods we will look at are two of the three basic file-handling ones, since they involve the text editor.
if not self.okToContinue(): return document = self.editor.document() document.clear() document.setModified(False) self.filename = None self.setWindowTitle("Python Editor - Unnamed") self.updateUi()
This method simply retrieves and clears the QTextDocument that actually holds the text, and sets the modified flag to False. The result is a blank QTextEdit with no unsaved changes. The updateUi() method is used to enable and disable actions depending on the application's state; see the Enabling and Disabling Actions sidebar on page 385.
def loadFile(self): fh = None try:
fh = QFile(self.filename)
if not fh.open(QIODevice.ReadOnly):
raise IOError, unicode(fh.errorString()) stream = QTextStream(fh) stream.setCodec("UTF-8") self.editor.setPlainText(stream.readAll()) self.editor.document().setModified(False) self.setWindowTitle("Python Editor - %s" % \ QFileInfo(self.filename).fileName()) except (IOError, OSError), e:
QMessageBox.warning(self, "Python Editor — Load Error", "Failed to load %s: %s" % (self.filename, e))
If a file is loaded—for example, by the user invoking the File^Open action—this method is called. The file-handling code is similar to what we have seen before; the only real difference is that we set the QTextDocument's modified flag to False.
The code for saving (not shown) is very similar to that for loading. We get the file handle, create a QTextStream, set the encoding to UTF-8, and output the entire text using QTextEdit.toPlainText(). We also set the QTextDocument's modified flag to False.
def event(self, event):
if event.type() == QEvent.KeyPress and \ event.key() == Qt.Key_Tab: cursor = self.textCursor() cursor.insertText(" ") return True return QTextEdit.event(self, event)
The preceding code shows the complete TextEdit subclass. Every QTextDocument can be manipulated through a QTextCursor object, which is the programmatic equivalent of a user interacting with the document using key presses and mouse actions.
Was this article helpful?
Video Marketing Will Never Be The Same Again. Here's How YOU - Or ANYONE - Can Leverage On The Internet's 4th MOST TRAFFICKED WEBSITE TO BOOST YOUR POPULARITY amp PUBLICITY FOR BUSINESS via Video Marketing! With The Emergence Of Web Video Popularity, You CANNOT Afford To Miss Out On This Exponentially Growing Trend - Because It Could Make Or Break Your Popularity amp Business Growth!