diff options
Diffstat (limited to 'examples/widgets/richtext/syntaxhighlighter/syntaxhighlighter.py')
-rw-r--r-- | examples/widgets/richtext/syntaxhighlighter/syntaxhighlighter.py | 180 |
1 files changed, 180 insertions, 0 deletions
diff --git a/examples/widgets/richtext/syntaxhighlighter/syntaxhighlighter.py b/examples/widgets/richtext/syntaxhighlighter/syntaxhighlighter.py new file mode 100644 index 000000000..6b913f177 --- /dev/null +++ b/examples/widgets/richtext/syntaxhighlighter/syntaxhighlighter.py @@ -0,0 +1,180 @@ +#!/usr/bin/env python + +############################################################################ +## +## Copyright (C) 2013 Riverbank Computing Limited. +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: http://www.qt.io/licensing/ +## +## This file is part of the PySide examples of the Qt Toolkit. +## +## $QT_BEGIN_LICENSE:BSD$ +## You may use this file under the terms of the BSD license as follows: +## +## "Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions are +## met: +## * Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## * Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in +## the documentation and/or other materials provided with the +## distribution. +## * Neither the name of The Qt Company Ltd nor the names of its +## contributors may be used to endorse or promote products derived +## from this software without specific prior written permission. +## +## +## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +## +## $QT_END_LICENSE$ +## +############################################################################# + +"""PySide2 port of the widgets/richtext/syntaxhighlighter example from Qt v5.x""" + +import sys +import re +from PySide2 import QtCore, QtGui, QtWidgets + +import syntaxhighlighter_rc + + +class MainWindow(QtWidgets.QMainWindow): + def __init__(self, parent=None): + QtWidgets.QMainWindow.__init__(self, parent) + + self.highlighter = Highlighter() + + self.setupFileMenu() + self.setupEditor() + + self.setCentralWidget(self.editor) + self.setWindowTitle(self.tr("Syntax Highlighter")) + + def newFile(self): + self.editor.clear() + + def openFile(self, path=""): + fileName = path + + if fileName=="": + fileName,_ = QtWidgets.QFileDialog.getOpenFileName(self, self.tr("Open File"), "", + "qmake Files (*.pro *.prf *.pri)") + + if fileName!="": + inFile = QtCore.QFile(fileName) + if inFile.open(QtCore.QFile.ReadOnly | QtCore.QFile.Text): + self.editor.setPlainText(unicode(inFile.readAll())) + + def setupEditor(self): + variableFormat = QtGui.QTextCharFormat() + variableFormat.setFontWeight(QtGui.QFont.Bold) + variableFormat.setForeground(QtCore.Qt.blue) + self.highlighter.addMapping("\\b[A-Z_]+\\b", variableFormat) + + singleLineCommentFormat = QtGui.QTextCharFormat() + singleLineCommentFormat.setBackground(QtGui.QColor("#77ff77")) + self.highlighter.addMapping("#[^\n]*", singleLineCommentFormat) + + quotationFormat = QtGui.QTextCharFormat() + quotationFormat.setBackground(QtCore.Qt.cyan) + quotationFormat.setForeground(QtCore.Qt.blue) + self.highlighter.addMapping("\".*\"", quotationFormat) + + functionFormat = QtGui.QTextCharFormat() + functionFormat.setFontItalic(True) + functionFormat.setForeground(QtCore.Qt.blue) + self.highlighter.addMapping("\\b[a-z0-9_]+\\(.*\\)", functionFormat) + + font = QtGui.QFont() + font.setFamily("Courier") + font.setFixedPitch(True) + font.setPointSize(10) + + self.editor = QtWidgets.QTextEdit() + self.editor.setFont(font) + self.highlighter.addToDocument(self.editor.document()) + + def setupFileMenu(self): + fileMenu = QtWidgets.QMenu(self.tr("&File"), self) + self.menuBar().addMenu(fileMenu) + + newFileAct = QtWidgets.QAction(self.tr("&New..."), self) + newFileAct.setShortcut(QtGui.QKeySequence(self.tr("Ctrl+N", "File|New"))) + self.connect(newFileAct, QtCore.SIGNAL("triggered()"), self.newFile) + fileMenu.addAction(newFileAct) + + openFileAct = QtWidgets.QAction(self.tr("&Open..."), self) + openFileAct.setShortcut(QtGui.QKeySequence(self.tr("Ctrl+O", "File|Open"))) + self.connect(openFileAct, QtCore.SIGNAL("triggered()"), self.openFile) + fileMenu.addAction(openFileAct) + + fileMenu.addAction(self.tr("E&xit"), QtWidgets.qApp, QtCore.SLOT("quit()"), + QtGui.QKeySequence(self.tr("Ctrl+Q", "File|Exit"))) + + +class Highlighter(QtCore.QObject): + def __init__(self, parent=None): + QtCore.QObject.__init__(self, parent) + + self.mappings = {} + + def addToDocument(self, doc): + self.connect(doc, QtCore.SIGNAL("contentsChange(int, int, int)"), self.highlight) + + def addMapping(self, pattern, format): + self.mappings[pattern] = format + + def highlight(self, position, removed, added): + doc = self.sender() + + block = doc.findBlock(position) + if not block.isValid(): + return + + if added > removed: + endBlock = doc.findBlock(position + added) + else: + endBlock = block + + while block.isValid() and not (endBlock < block): + self.highlightBlock(block) + block = block.next() + + def highlightBlock(self, block): + layout = block.layout() + text = block.text() + + overrides = [] + + for pattern in self.mappings: + for m in re.finditer(pattern,text): + range = QtGui.QTextLayout.FormatRange() + s,e = m.span() + range.start = s + range.length = e-s + range.format = self.mappings[pattern] + overrides.append(range) + + layout.setAdditionalFormats(overrides) + block.document().markContentsDirty(block.position(), block.length()) + + +if __name__ == '__main__': + app = QtWidgets.QApplication(sys.argv) + window = MainWindow() + window.resize(640, 512) + window.show() + window.openFile(":/examples/example") + sys.exit(app.exec_()) |