DocumentDemo Example
from DevMachines import __pyside2__, __pyside6__
if __pyside2__:
from PySide2 import QtCore
from PySide2.QtCore import Qt, QRegularExpression, QFile, QFileInfo, QTextStream
from PySide2.QtGui import QSyntaxHighlighter, QTextCharFormat, QFont
from PySide2.QtWidgets import QTextEdit, QFileDialog, QApplication
if __pyside6__:
from PySide6 import QtCore
from PySide6.QtCore import Qt, QRegularExpression, QFile, QFileInfo, QTextStream
from PySide6.QtGui import QSyntaxHighlighter, QTextCharFormat, QFont
from PySide6.QtWidgets import QTextEdit, QFileDialog, QApplication
class HighlightingRule():
def __init__(self):
self.pattern = None
self.format = None
class Highlighter(QSyntaxHighlighter):
def __init__(self, parent):
QSyntaxHighlighter.__init__(self, parent)
self.highlightingRules = []
self.keywordFormat = QTextCharFormat()
self.classFormat = QTextCharFormat()
self.singleLineCommentFormat = QTextCharFormat()
self.multiLineCommentFormat = QTextCharFormat()
self.quotationFormat = QTextCharFormat()
self.functionFormat = QTextCharFormat()
self.keywordFormat.setForeground(Qt.darkBlue)
self.keywordFormat.setFontWeight(QFont.Bold)
keywordPatterns = [
"\\bchar\\b", "\\bclass\\b", "\\bconst\\b",
"\\bdouble\\b", "\\benum\\b", "\\bexplicit\\b",
"\\bfriend\\b", "\\binline\\b", "\\bint\\b"
"\\blong\\b", "\\bnamespace\\b", "\\boperator\\b",
"\\bprivate\\b", "\\bprotected\\b", "\\bpublic\\b",
"\\bshort\\b", "\\bsignals\\b", "\\bsigned\\b",
"\\bslots\\b", "\\bstatic\\b", "\\bstruct\\b",
"\\btemplate\\b", "\\btypedef\\b", "\\btypename\\b",
"\\bunion\\b", "\\bunsigned\\b", "\\bvirtual\\b"
"\\bvoid\\b", "\\bvolatile\\b"]
for pattern in keywordPatterns:
rule = HighlightingRule()
rule.pattern = QRegularExpression(pattern)
rule.format = self.keywordFormat
self.highlightingRules.append(rule)
self.classFormat.setFontWeight(QFont.Bold)
self.classFormat.setForeground(Qt.darkMagenta)
rule.pattern = QRegularExpression("\\bQ[A-Za-z]+\\b")
rule.format = self.classFormat
self.highlightingRules.append(rule)
self.singleLineCommentFormat.setForeground(Qt.red)
rule.pattern = QRegularExpression("//[^\n]*")
rule.format = self.singleLineCommentFormat
self.highlightingRules.append(rule)
self.multiLineCommentFormat.setForeground(Qt.darkGreen)
self.quotationFormat.setForeground(Qt.darkGreen)
rule.pattern = QRegularExpression("\".*\"")
rule.format = self.quotationFormat
self.highlightingRules.append(rule)
# self.functionFormat.setFontItalic(True)
self.functionFormat.setForeground(Qt.blue)
rule.pattern = QRegularExpression("\\b[A-Za-z0-9_]+(?=\\()")
rule.format = self.functionFormat
self.highlightingRules.append(rule)
self.commentStartExpression = QRegularExpression("/\\*")
self.commentEndExpression = QRegularExpression("\\*/")
def highlightBlock(self, text):
for rule in self.highlightingRules:
expression = rule.pattern
matchIterator = expression.globalMatch(text)
while matchIterator.hasNext():
match = matchIterator.next()
self.setFormat(match.capturedStart(), match.capturedLength(), rule.format)
self.setCurrentBlockState(0)
startIndex = 0
if self.previousBlockState() != 1:
startIndex = self.commentStartExpression.match(text).capturedStart()
while startIndex >= 0:
match = self.commentEndExpression.match(text, startIndex)
endIndex = match.capturedStart()
commentLength = 0
if endIndex == -1:
self.setCurrentBlockState(1)
commentLength = len(text) - startIndex
else:
commentLength = endIndex - startIndex + match.capturedLength()
self.setFormat(startIndex, commentLength, self.multiLineCommentFormat)
startIndex = self.commentStartExpression.match(text, startIndex + commentLength).capturedStart()
class MdiChild(QTextEdit):
sequenceNumber = 1
def __init__(self):
QTextEdit.__init__(self)
self.currentFileName = ""
self.highlighter = Highlighter(self.document())
font = QFont()
font.setFamily("Courier")
font.setFixedPitch(True)
font.setPointSize(10)
self.setFont(font)
self.untitled = True
self.connect(self.document(), QtCore.SIGNAL("modificationChanged(bool)"), self, QtCore.SLOT("updateDocumentModified(bool)"))
self.setAttribute(Qt.WA_DeleteOnClose)
def newFile(self):
self.untitled = True
self.sequenceNumber = self.sequenceNumber + 1
self.setCurrentFileName("Source{0}.cpp".format(self.sequenceNumber), False)
def loadFile(self, fileName):
file = QFile(fileName)
if not file.open(QFile.ReadOnly | QFile.Text):
QMessageBox.warning(self, self.tr("MDI"), "Cannot read file {0}:\n{1}.".format(fileName, file.errorString()))
return False
stream = QTextStream(file)
QApplication.setOverrideCursor(Qt.WaitCursor)
self.setPlainText(stream.readAll())
QApplication.restoreOverrideCursor()
self.setCurrentFileName(fileName, True)
return True
def save(self):
if self.untitled:
return self.saveAs()
else:
return self.saveFile(self.currentFileName)
def saveAs(self):
fileName = QFileDialog.getSaveFileName(self, self.tr("Save As"), self.currentFileName)[0]
if fileName == "":
return False
return saveFile(fileName)
def saveFile(self, fileName):
file = QFile(fileName)
if not file.open(QFile.WriteOnly | QFile.Text):
QMessageBox.warning(self, self.tr("MDI"), "Cannot write file {0}:\n{1}.".format(QDir.toNativeSeparators(fileName), file.errorString()))
return False
out = QTextStream(file)
QApplication.setOverrideCursor(Qt.WaitCursor)
out << self.toPlainText()
QApplication.restoreOverrideCursor()
setCurrentFileName(fileName, True)
return True
def userFriendlyCurrentFile(self):
return QFileInfo(self.currentFileName).fileName()
def closeEvent(self, event):
if self.aboutToBeClosed():
event.accept()
else:
event.ignore()
def updateDocumentModified(self, modified):
title = self.userFriendlyCurrentFile()
if modified:
title = title + "[*]"
self.setWindowTitle(title);
self.setWindowModified(modified)
def aboutToBeClosed(self):
if not self.document().isModified():
return True
ret = QMessageBox.warning(self, self.tr("MDI"), "'{0}' has been modified.\n Do you want to save your changes?".format(self.userFriendlyCurrentFile()),
QMessageBox.Save | QMessageBox.Discard | QMessageBox.Cancel)
if ret == QMessageBox.Save:
return self.save()
elif ret == QMessageBox.Cancel:
return False
return True
def currentFileName(self):
return self.currentFileName
def setCurrentFileName(self, fileName, titled):
if titled:
self.currentFileName = QFileInfo(fileName).canonicalFilePath()
else:
self.currentFileName = fileName
self.untitled = titled
self.updateDocumentModified(self.document().isModified())