aboutsummaryrefslogtreecommitdiffstats
path: root/examples/widgets/richtext
diff options
context:
space:
mode:
Diffstat (limited to 'examples/widgets/richtext')
-rwxr-xr-xexamples/widgets/richtext/orderform.py297
-rwxr-xr-xexamples/widgets/richtext/syntaxhighlighter.py203
-rw-r--r--examples/widgets/richtext/syntaxhighlighter/examples/example79
-rw-r--r--examples/widgets/richtext/syntaxhighlighter/syntaxhighlighter.py180
-rw-r--r--examples/widgets/richtext/syntaxhighlighter/syntaxhighlighter.qrc5
-rw-r--r--examples/widgets/richtext/syntaxhighlighter/syntaxhighlighter_rc.py183
-rw-r--r--examples/widgets/richtext/textobject/files/heart.svg55
-rwxr-xr-xexamples/widgets/richtext/textobject/textobject.py130
8 files changed, 1132 insertions, 0 deletions
diff --git a/examples/widgets/richtext/orderform.py b/examples/widgets/richtext/orderform.py
new file mode 100755
index 000000000..e068db2b2
--- /dev/null
+++ b/examples/widgets/richtext/orderform.py
@@ -0,0 +1,297 @@
+#!/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/orderform example from Qt v5.x"""
+
+from PySide2 import QtCore, QtGui, QtWidgets, QtPrintSupport
+
+
+class MainWindow(QtWidgets.QMainWindow):
+ def __init__(self):
+ super(MainWindow, self).__init__()
+
+ fileMenu = QtWidgets.QMenu("&File", self)
+ newAction = fileMenu.addAction("&New...")
+ newAction.setShortcut("Ctrl+N")
+ self.printAction = fileMenu.addAction("&Print...", self.printFile)
+ self.printAction.setShortcut("Ctrl+P")
+ self.printAction.setEnabled(False)
+ quitAction = fileMenu.addAction("E&xit")
+ quitAction.setShortcut("Ctrl+Q")
+ self.menuBar().addMenu(fileMenu)
+
+ self.letters = QtWidgets.QTabWidget()
+
+ newAction.triggered.connect(self.openDialog)
+ quitAction.triggered.connect(self.close)
+
+ self.setCentralWidget(self.letters)
+ self.setWindowTitle("Order Form")
+
+ def createLetter(self, name, address, orderItems, sendOffers):
+ editor = QtWidgets.QTextEdit()
+ tabIndex = self.letters.addTab(editor, name)
+ self.letters.setCurrentIndex(tabIndex)
+
+ cursor = editor.textCursor()
+ cursor.movePosition(QtGui.QTextCursor.Start)
+ topFrame = cursor.currentFrame()
+ topFrameFormat = topFrame.frameFormat()
+ topFrameFormat.setPadding(16)
+ topFrame.setFrameFormat(topFrameFormat)
+
+ textFormat = QtGui.QTextCharFormat()
+ boldFormat = QtGui.QTextCharFormat()
+ boldFormat.setFontWeight(QtGui.QFont.Bold)
+
+ referenceFrameFormat = QtGui.QTextFrameFormat()
+ referenceFrameFormat.setBorder(1)
+ referenceFrameFormat.setPadding(8)
+ referenceFrameFormat.setPosition(QtGui.QTextFrameFormat.FloatRight)
+ referenceFrameFormat.setWidth(QtGui.QTextLength(QtGui.QTextLength.PercentageLength, 40))
+ cursor.insertFrame(referenceFrameFormat)
+
+ cursor.insertText("A company", boldFormat)
+ cursor.insertBlock()
+ cursor.insertText("321 City Street")
+ cursor.insertBlock()
+ cursor.insertText("Industry Park")
+ cursor.insertBlock()
+ cursor.insertText("Another country")
+
+ cursor.setPosition(topFrame.lastPosition())
+
+ cursor.insertText(name, textFormat)
+ for line in address.split("\n"):
+ cursor.insertBlock()
+ cursor.insertText(line)
+
+ cursor.insertBlock()
+ cursor.insertBlock()
+
+ date = QtCore.QDate.currentDate()
+ cursor.insertText("Date: %s" % date.toString('d MMMM yyyy'),
+ textFormat)
+ cursor.insertBlock()
+
+ bodyFrameFormat = QtGui.QTextFrameFormat()
+ bodyFrameFormat.setWidth(QtGui.QTextLength(QtGui.QTextLength.PercentageLength, 100))
+ cursor.insertFrame(bodyFrameFormat)
+
+ cursor.insertText("I would like to place an order for the following "
+ "items:", textFormat)
+ cursor.insertBlock()
+ cursor.insertBlock()
+
+ orderTableFormat = QtGui.QTextTableFormat()
+ orderTableFormat.setAlignment(QtCore.Qt.AlignHCenter)
+ orderTable = cursor.insertTable(1, 2, orderTableFormat)
+
+ orderFrameFormat = cursor.currentFrame().frameFormat()
+ orderFrameFormat.setBorder(1)
+ cursor.currentFrame().setFrameFormat(orderFrameFormat)
+
+ cursor = orderTable.cellAt(0, 0).firstCursorPosition()
+ cursor.insertText("Product", boldFormat)
+ cursor = orderTable.cellAt(0, 1).firstCursorPosition()
+ cursor.insertText("Quantity", boldFormat)
+
+ for text, quantity in orderItems:
+ row = orderTable.rows()
+
+ orderTable.insertRows(row, 1)
+ cursor = orderTable.cellAt(row, 0).firstCursorPosition()
+ cursor.insertText(text, textFormat)
+ cursor = orderTable.cellAt(row, 1).firstCursorPosition()
+ cursor.insertText(str(quantity), textFormat)
+
+ cursor.setPosition(topFrame.lastPosition())
+
+ cursor.insertBlock()
+
+ cursor.insertText("Please update my records to take account of the "
+ "following privacy information:")
+ cursor.insertBlock()
+
+ offersTable = cursor.insertTable(2, 2)
+
+ cursor = offersTable.cellAt(0, 1).firstCursorPosition()
+ cursor.insertText("I want to receive more information about your "
+ "company's products and special offers.", textFormat)
+ cursor = offersTable.cellAt(1, 1).firstCursorPosition()
+ cursor.insertText("I do not want to receive any promotional "
+ "information from your company.", textFormat)
+
+ if sendOffers:
+ cursor = offersTable.cellAt(0, 0).firstCursorPosition()
+ else:
+ cursor = offersTable.cellAt(1, 0).firstCursorPosition()
+
+ cursor.insertText('X', boldFormat)
+
+ cursor.setPosition(topFrame.lastPosition())
+ cursor.insertBlock()
+ cursor.insertText("Sincerely,", textFormat)
+ cursor.insertBlock()
+ cursor.insertBlock()
+ cursor.insertBlock()
+ cursor.insertText(name)
+
+ self.printAction.setEnabled(True)
+
+ def createSample(self):
+ dialog = DetailsDialog('Dialog with default values', self)
+ self.createLetter('Mr Smith',
+ '12 High Street\nSmall Town\nThis country',
+ dialog.orderItems(), True)
+
+ def openDialog(self):
+ dialog = DetailsDialog("Enter Customer Details", self)
+
+ if dialog.exec_() == QtWidgets.QDialog.Accepted:
+ self.createLetter(dialog.senderName(), dialog.senderAddress(),
+ dialog.orderItems(), dialog.sendOffers())
+
+ def printFile(self):
+ editor = self.letters.currentWidget()
+ printer = QtPrintSupport.QPrinter()
+
+ dialog = QtPrintSupport.QPrintDialog(printer, self)
+ dialog.setWindowTitle("Print Document")
+
+ if editor.textCursor().hasSelection():
+ dialog.addEnabledOption(QtPrintSupport.QAbstractPrintDialog.PrintSelection)
+
+ if dialog.exec_() != QtWidgets.QDialog.Accepted:
+ return
+
+ editor.print_(printer)
+
+
+class DetailsDialog(QtWidgets.QDialog):
+ def __init__(self, title, parent):
+ super(DetailsDialog, self).__init__(parent)
+
+ self.items = ("T-shirt", "Badge", "Reference book", "Coffee cup")
+
+ nameLabel = QtWidgets.QLabel("Name:")
+ addressLabel = QtWidgets.QLabel("Address:")
+ addressLabel.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop)
+
+ self.nameEdit = QtWidgets.QLineEdit()
+ self.addressEdit = QtWidgets.QTextEdit()
+ self.offersCheckBox = QtWidgets.QCheckBox("Send information about "
+ "products and special offers:")
+
+ self.setupItemsTable()
+
+ buttonBox = QtWidgets.QDialogButtonBox(QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Cancel)
+
+ buttonBox.accepted.connect(self.verify)
+ buttonBox.rejected.connect(self.reject)
+
+ mainLayout = QtWidgets.QGridLayout()
+ mainLayout.addWidget(nameLabel, 0, 0)
+ mainLayout.addWidget(self.nameEdit, 0, 1)
+ mainLayout.addWidget(addressLabel, 1, 0)
+ mainLayout.addWidget(self.addressEdit, 1, 1)
+ mainLayout.addWidget(self.itemsTable, 0, 2, 2, 1)
+ mainLayout.addWidget(self.offersCheckBox, 2, 1, 1, 2)
+ mainLayout.addWidget(buttonBox, 3, 0, 1, 3)
+ self.setLayout(mainLayout)
+
+ self.setWindowTitle(title)
+
+ def setupItemsTable(self):
+ self.itemsTable = QtWidgets.QTableWidget(len(self.items), 2)
+
+ for row, item in enumerate(self.items):
+ name = QtWidgets.QTableWidgetItem(item)
+ name.setFlags(QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable)
+ self.itemsTable.setItem(row, 0, name)
+ quantity = QtWidgets.QTableWidgetItem('1')
+ self.itemsTable.setItem(row, 1, quantity)
+
+ def orderItems(self):
+ orderList = []
+
+ for row in range(len(self.items)):
+ text = self.itemsTable.item(row, 0).text()
+ quantity = int(self.itemsTable.item(row, 1).data(QtCore.Qt.DisplayRole))
+ orderList.append((text, max(0, quantity)))
+
+ return orderList
+
+ def senderName(self):
+ return self.nameEdit.text()
+
+ def senderAddress(self):
+ return self.addressEdit.toPlainText()
+
+ def sendOffers(self):
+ return self.offersCheckBox.isChecked()
+
+ def verify(self):
+ if self.nameEdit.text() and self.addressEdit.toPlainText():
+ self.accept()
+ return
+
+ answer = QtWidgets.QMessageBox.warning(self, "Incomplete Form",
+ "The form does not contain all the necessary information.\n"
+ "Do you want to discard it?",
+ QtWidgets.QMessageBox.Yes, QtWidgets.QMessageBox.No)
+
+ if answer == QtWidgets.QMessageBox.Yes:
+ self.reject()
+
+
+if __name__ == '__main__':
+
+ import sys
+
+ app = QtWidgets.QApplication(sys.argv)
+ window = MainWindow()
+ window.resize(640, 480)
+ window.show()
+ window.createSample()
+ sys.exit(app.exec_())
diff --git a/examples/widgets/richtext/syntaxhighlighter.py b/examples/widgets/richtext/syntaxhighlighter.py
new file mode 100755
index 000000000..8a14632fe
--- /dev/null
+++ b/examples/widgets/richtext/syntaxhighlighter.py
@@ -0,0 +1,203 @@
+#!/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"""
+
+from PySide2 import QtCore, QtGui, QtWidgets
+
+
+class MainWindow(QtWidgets.QMainWindow):
+ def __init__(self, parent=None):
+ super(MainWindow, self).__init__(parent)
+
+ self.setupFileMenu()
+ self.setupHelpMenu()
+ self.setupEditor()
+
+ self.setCentralWidget(self.editor)
+ self.setWindowTitle("Syntax Highlighter")
+
+ def about(self):
+ QtWidgets.QMessageBox.about(self, "About Syntax Highlighter",
+ "<p>The <b>Syntax Highlighter</b> example shows how to " \
+ "perform simple syntax highlighting by subclassing the " \
+ "QSyntaxHighlighter class and describing highlighting " \
+ "rules using regular expressions.</p>")
+
+ def newFile(self):
+ self.editor.clear()
+
+ def openFile(self, path=None):
+ if not path:
+ path = QtWidgets.QFileDialog.getOpenFileName(self, "Open File",
+ '', "C++ Files (*.cpp *.h)")
+
+ if path:
+ inFile = QtCore.QFile(path[0])
+ if inFile.open(QtCore.QFile.ReadOnly | QtCore.QFile.Text):
+ text = inFile.readAll()
+
+ try:
+ # Python v3.
+ text = str(text, encoding='ascii')
+ except TypeError:
+ # Python v2.
+ text = str(text)
+
+ self.editor.setPlainText(text)
+
+ def setupEditor(self):
+ font = QtGui.QFont()
+ font.setFamily('Courier')
+ font.setFixedPitch(True)
+ font.setPointSize(10)
+
+ self.editor = QtWidgets.QTextEdit()
+ self.editor.setFont(font)
+
+ self.highlighter = Highlighter(self.editor.document())
+
+ def setupFileMenu(self):
+ fileMenu = QtWidgets.QMenu("&File", self)
+ self.menuBar().addMenu(fileMenu)
+
+ fileMenu.addAction("&New...", self.newFile, "Ctrl+N")
+ fileMenu.addAction("&Open...", self.openFile, "Ctrl+O")
+ fileMenu.addAction("E&xit", QtWidgets.qApp.quit, "Ctrl+Q")
+
+ def setupHelpMenu(self):
+ helpMenu = QtWidgets.QMenu("&Help", self)
+ self.menuBar().addMenu(helpMenu)
+
+ helpMenu.addAction("&About", self.about)
+ helpMenu.addAction("About &Qt", QtWidgets.qApp.aboutQt)
+
+
+class Highlighter(QtGui.QSyntaxHighlighter):
+ def __init__(self, parent=None):
+ super(Highlighter, self).__init__(parent)
+
+ keywordFormat = QtGui.QTextCharFormat()
+ keywordFormat.setForeground(QtCore.Qt.darkBlue)
+ keywordFormat.setFontWeight(QtGui.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"]
+
+ self.highlightingRules = [(QtCore.QRegExp(pattern), keywordFormat)
+ for pattern in keywordPatterns]
+
+ classFormat = QtGui.QTextCharFormat()
+ classFormat.setFontWeight(QtGui.QFont.Bold)
+ classFormat.setForeground(QtCore.Qt.darkMagenta)
+ self.highlightingRules.append((QtCore.QRegExp("\\bQ[A-Za-z]+\\b"),
+ classFormat))
+
+ singleLineCommentFormat = QtGui.QTextCharFormat()
+ singleLineCommentFormat.setForeground(QtCore.Qt.red)
+ self.highlightingRules.append((QtCore.QRegExp("//[^\n]*"),
+ singleLineCommentFormat))
+
+ self.multiLineCommentFormat = QtGui.QTextCharFormat()
+ self.multiLineCommentFormat.setForeground(QtCore.Qt.red)
+
+ quotationFormat = QtGui.QTextCharFormat()
+ quotationFormat.setForeground(QtCore.Qt.darkGreen)
+ self.highlightingRules.append((QtCore.QRegExp("\".*\""),
+ quotationFormat))
+
+ functionFormat = QtGui.QTextCharFormat()
+ functionFormat.setFontItalic(True)
+ functionFormat.setForeground(QtCore.Qt.blue)
+ self.highlightingRules.append((QtCore.QRegExp("\\b[A-Za-z0-9_]+(?=\\()"),
+ functionFormat))
+
+ self.commentStartExpression = QtCore.QRegExp("/\\*")
+ self.commentEndExpression = QtCore.QRegExp("\\*/")
+
+ def highlightBlock(self, text):
+ for pattern, format in self.highlightingRules:
+ expression = QtCore.QRegExp(pattern)
+ index = expression.indexIn(text)
+ while index >= 0:
+ length = expression.matchedLength()
+ self.setFormat(index, length, format)
+ index = expression.indexIn(text, index + length)
+
+ self.setCurrentBlockState(0)
+
+ startIndex = 0
+ if self.previousBlockState() != 1:
+ startIndex = self.commentStartExpression.indexIn(text)
+
+ while startIndex >= 0:
+ endIndex = self.commentEndExpression.indexIn(text, startIndex)
+
+ if endIndex == -1:
+ self.setCurrentBlockState(1)
+ commentLength = len(text) - startIndex
+ else:
+ commentLength = endIndex - startIndex + self.commentEndExpression.matchedLength()
+
+ self.setFormat(startIndex, commentLength,
+ self.multiLineCommentFormat)
+ startIndex = self.commentStartExpression.indexIn(text,
+ startIndex + commentLength);
+
+
+if __name__ == '__main__':
+
+ import sys
+
+ app = QtWidgets.QApplication(sys.argv)
+ window = MainWindow()
+ window.resize(640, 512)
+ window.show()
+ sys.exit(app.exec_())
diff --git a/examples/widgets/richtext/syntaxhighlighter/examples/example b/examples/widgets/richtext/syntaxhighlighter/examples/example
new file mode 100644
index 000000000..db8e7b189
--- /dev/null
+++ b/examples/widgets/richtext/syntaxhighlighter/examples/example
@@ -0,0 +1,79 @@
+TEMPLATE = app
+LANGUAGE = C++
+TARGET = assistant
+
+CONFIG += qt warn_on
+QT += xml network
+
+PROJECTNAME = Assistant
+DESTDIR = ../../bin
+
+FORMS += finddialog.ui \
+ helpdialog.ui \
+ mainwindow.ui \
+ settingsdialog.ui \
+ tabbedbrowser.ui \
+ topicchooser.ui
+
+SOURCES += main.cpp \
+ helpwindow.cpp \
+ topicchooser.cpp \
+ docuparser.cpp \
+ settingsdialog.cpp \
+ index.cpp \
+ profile.cpp \
+ config.cpp \
+ finddialog.cpp \
+ helpdialog.cpp \
+ mainwindow.cpp \
+ tabbedbrowser.cpp
+
+HEADERS += helpwindow.h \
+ topicchooser.h \
+ docuparser.h \
+ settingsdialog.h \
+ index.h \
+ profile.h \
+ finddialog.h \
+ helpdialog.h \
+ mainwindow.h \
+ tabbedbrowser.h \
+ config.h
+
+RESOURCES += assistant.qrc
+
+DEFINES += QT_KEYWORDS
+#DEFINES += QT_PALMTOPCENTER_DOCS
+!network:DEFINES += QT_INTERNAL_NETWORK
+else:QT += network
+!xml: DEFINES += QT_INTERNAL_XML
+else:QT += xml
+include( ../../src/qt_professional.pri )
+
+win32 {
+ LIBS += -lshell32
+ RC_FILE = assistant.rc
+}
+
+macos {
+ ICON = assistant.icns
+ TARGET = assistant
+# QMAKE_INFO_PLIST = Info_mac.plist
+}
+
+#target.path = $$[QT_INSTALL_BINS]
+#INSTALLS += target
+
+#assistanttranslations.files = *.qm
+#assistanttranslations.path = $$[QT_INSTALL_TRANSLATIONS]
+#INSTALLS += assistanttranslations
+
+TRANSLATIONS = assistant_de.ts \
+ assistant_fr.ts
+
+
+unix:!contains(QT_CONFIG, zlib):LIBS += -lz
+
+
+target.path=$$[QT_INSTALL_BINS]
+INSTALLS += target
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_())
diff --git a/examples/widgets/richtext/syntaxhighlighter/syntaxhighlighter.qrc b/examples/widgets/richtext/syntaxhighlighter/syntaxhighlighter.qrc
new file mode 100644
index 000000000..e5f9abf1e
--- /dev/null
+++ b/examples/widgets/richtext/syntaxhighlighter/syntaxhighlighter.qrc
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource prefix="/" >
+ <file>examples/example</file>
+</qresource>
+</RCC>
diff --git a/examples/widgets/richtext/syntaxhighlighter/syntaxhighlighter_rc.py b/examples/widgets/richtext/syntaxhighlighter/syntaxhighlighter_rc.py
new file mode 100644
index 000000000..81321bb65
--- /dev/null
+++ b/examples/widgets/richtext/syntaxhighlighter/syntaxhighlighter_rc.py
@@ -0,0 +1,183 @@
+#############################################################################
+##
+## 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$
+##
+#############################################################################
+
+# Resource object code
+#
+# Created: Wed Dec 28 19:56:58 2005
+# by: The Resource Compiler for PyQt (Qt v4.1.0)
+#
+# WARNING! All changes made in this file will be lost!
+
+from PySide2 import QtCore
+
+qt_resource_data = b"\
+\x00\x00\x06\x79\
+\x54\
+\x45\x4d\x50\x4c\x41\x54\x45\x20\x3d\x20\x61\x70\x70\x0a\x4c\x41\
+\x4e\x47\x55\x41\x47\x45\x20\x3d\x20\x43\x2b\x2b\x0a\x54\x41\x52\
+\x47\x45\x54\x20\x20\x20\x20\x20\x20\x20\x20\x20\x3d\x20\x61\x73\
+\x73\x69\x73\x74\x61\x6e\x74\x0a\x0a\x43\x4f\x4e\x46\x49\x47\x20\
+\x20\x20\x20\x20\x20\x20\x20\x2b\x3d\x20\x71\x74\x20\x77\x61\x72\
+\x6e\x5f\x6f\x6e\x0a\x51\x54\x20\x20\x20\x20\x20\x20\x20\x20\x20\
+\x20\x20\x20\x2b\x3d\x20\x78\x6d\x6c\x20\x6e\x65\x74\x77\x6f\x72\
+\x6b\x0a\x0a\x50\x52\x4f\x4a\x45\x43\x54\x4e\x41\x4d\x45\x20\x20\
+\x20\x20\x20\x20\x20\x20\x3d\x20\x41\x73\x73\x69\x73\x74\x61\x6e\
+\x74\x0a\x44\x45\x53\x54\x44\x49\x52\x20\x20\x20\x20\x20\x20\x20\
+\x20\x20\x20\x20\x20\x3d\x20\x2e\x2e\x2f\x2e\x2e\x2f\x62\x69\x6e\
+\x0a\x0a\x46\x4f\x52\x4d\x53\x20\x2b\x3d\x20\x66\x69\x6e\x64\x64\
+\x69\x61\x6c\x6f\x67\x2e\x75\x69\x20\x5c\x0a\x20\x20\x20\x20\x20\
+\x20\x20\x20\x68\x65\x6c\x70\x64\x69\x61\x6c\x6f\x67\x2e\x75\x69\
+\x20\x5c\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x6d\x61\x69\x6e\x77\
+\x69\x6e\x64\x6f\x77\x2e\x75\x69\x20\x5c\x0a\x20\x20\x20\x20\x20\
+\x20\x20\x20\x73\x65\x74\x74\x69\x6e\x67\x73\x64\x69\x61\x6c\x6f\
+\x67\x2e\x75\x69\x20\x5c\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x74\
+\x61\x62\x62\x65\x64\x62\x72\x6f\x77\x73\x65\x72\x2e\x75\x69\x20\
+\x5c\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x74\x6f\x70\x69\x63\x63\
+\x68\x6f\x6f\x73\x65\x72\x2e\x75\x69\x0a\x0a\x53\x4f\x55\x52\x43\
+\x45\x53\x20\x2b\x3d\x20\x6d\x61\x69\x6e\x2e\x63\x70\x70\x20\x5c\
+\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x68\x65\x6c\x70\x77\x69\x6e\
+\x64\x6f\x77\x2e\x63\x70\x70\x20\x5c\x0a\x20\x20\x20\x20\x20\x20\
+\x20\x20\x74\x6f\x70\x69\x63\x63\x68\x6f\x6f\x73\x65\x72\x2e\x63\
+\x70\x70\x20\x5c\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x64\x6f\x63\
+\x75\x70\x61\x72\x73\x65\x72\x2e\x63\x70\x70\x20\x5c\x0a\x20\x20\
+\x20\x20\x20\x20\x20\x20\x73\x65\x74\x74\x69\x6e\x67\x73\x64\x69\
+\x61\x6c\x6f\x67\x2e\x63\x70\x70\x20\x5c\x0a\x20\x20\x20\x20\x20\
+\x20\x20\x20\x69\x6e\x64\x65\x78\x2e\x63\x70\x70\x20\x5c\x0a\x20\
+\x20\x20\x20\x20\x20\x20\x20\x70\x72\x6f\x66\x69\x6c\x65\x2e\x63\
+\x70\x70\x20\x5c\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x63\x6f\x6e\
+\x66\x69\x67\x2e\x63\x70\x70\x20\x5c\x0a\x20\x20\x20\x20\x20\x20\
+\x20\x20\x66\x69\x6e\x64\x64\x69\x61\x6c\x6f\x67\x2e\x63\x70\x70\
+\x20\x5c\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x68\x65\x6c\x70\x64\
+\x69\x61\x6c\x6f\x67\x2e\x63\x70\x70\x20\x5c\x0a\x20\x20\x20\x20\
+\x20\x20\x20\x20\x6d\x61\x69\x6e\x77\x69\x6e\x64\x6f\x77\x2e\x63\
+\x70\x70\x20\x5c\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x74\x61\x62\
+\x62\x65\x64\x62\x72\x6f\x77\x73\x65\x72\x2e\x63\x70\x70\x0a\x0a\
+\x48\x45\x41\x44\x45\x52\x53\x20\x20\x20\x20\x20\x20\x20\x20\x2b\
+\x3d\x20\x68\x65\x6c\x70\x77\x69\x6e\x64\x6f\x77\x2e\x68\x20\x5c\
+\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x74\x6f\x70\x69\x63\x63\x68\
+\x6f\x6f\x73\x65\x72\x2e\x68\x20\x5c\x0a\x20\x20\x20\x20\x20\x20\
+\x20\x20\x64\x6f\x63\x75\x70\x61\x72\x73\x65\x72\x2e\x68\x20\x5c\
+\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x74\x74\x69\x6e\x67\
+\x73\x64\x69\x61\x6c\x6f\x67\x2e\x68\x20\x5c\x0a\x20\x20\x20\x20\
+\x20\x20\x20\x20\x69\x6e\x64\x65\x78\x2e\x68\x20\x5c\x0a\x20\x20\
+\x20\x20\x20\x20\x20\x20\x70\x72\x6f\x66\x69\x6c\x65\x2e\x68\x20\
+\x5c\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x66\x69\x6e\x64\x64\x69\
+\x61\x6c\x6f\x67\x2e\x68\x20\x5c\x0a\x20\x20\x20\x20\x20\x20\x20\
+\x20\x68\x65\x6c\x70\x64\x69\x61\x6c\x6f\x67\x2e\x68\x20\x5c\x0a\
+\x20\x20\x20\x20\x20\x20\x20\x20\x6d\x61\x69\x6e\x77\x69\x6e\x64\
+\x6f\x77\x2e\x68\x20\x5c\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x74\
+\x61\x62\x62\x65\x64\x62\x72\x6f\x77\x73\x65\x72\x2e\x68\x20\x5c\
+\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x63\x6f\x6e\x66\x69\x67\x2e\
+\x68\x0a\x0a\x52\x45\x53\x4f\x55\x52\x43\x45\x53\x20\x2b\x3d\x20\
+\x61\x73\x73\x69\x73\x74\x61\x6e\x74\x2e\x71\x72\x63\x0a\x0a\x44\
+\x45\x46\x49\x4e\x45\x53\x20\x2b\x3d\x20\x51\x54\x5f\x4b\x45\x59\
+\x57\x4f\x52\x44\x53\x0a\x23\x44\x45\x46\x49\x4e\x45\x53\x20\x2b\
+\x3d\x20\x20\x51\x54\x5f\x50\x41\x4c\x4d\x54\x4f\x50\x43\x45\x4e\
+\x54\x45\x52\x5f\x44\x4f\x43\x53\x0a\x21\x6e\x65\x74\x77\x6f\x72\
+\x6b\x3a\x44\x45\x46\x49\x4e\x45\x53\x20\x20\x20\x20\x20\x20\x20\
+\x20\x2b\x3d\x20\x51\x54\x5f\x49\x4e\x54\x45\x52\x4e\x41\x4c\x5f\
+\x4e\x45\x54\x57\x4f\x52\x4b\x0a\x65\x6c\x73\x65\x3a\x51\x54\x20\
+\x2b\x3d\x20\x6e\x65\x74\x77\x6f\x72\x6b\x0a\x21\x78\x6d\x6c\x3a\
+\x20\x44\x45\x46\x49\x4e\x45\x53\x20\x20\x20\x20\x20\x20\x20\x20\
+\x20\x20\x20\x20\x20\x20\x20\x20\x2b\x3d\x20\x51\x54\x5f\x49\x4e\
+\x54\x45\x52\x4e\x41\x4c\x5f\x58\x4d\x4c\x0a\x65\x6c\x73\x65\x3a\
+\x51\x54\x20\x2b\x3d\x20\x78\x6d\x6c\x0a\x69\x6e\x63\x6c\x75\x64\
+\x65\x28\x20\x2e\x2e\x2f\x2e\x2e\x2f\x73\x72\x63\x2f\x71\x74\x5f\
+\x70\x72\x6f\x66\x65\x73\x73\x69\x6f\x6e\x61\x6c\x2e\x70\x72\x69\
+\x20\x29\x0a\x0a\x77\x69\x6e\x33\x32\x20\x7b\x0a\x20\x20\x20\x20\
+\x4c\x49\x42\x53\x20\x2b\x3d\x20\x2d\x6c\x73\x68\x65\x6c\x6c\x33\
+\x32\x0a\x20\x20\x20\x20\x52\x43\x5f\x46\x49\x4c\x45\x20\x3d\x20\
+\x61\x73\x73\x69\x73\x74\x61\x6e\x74\x2e\x72\x63\x0a\x7d\x0a\x0a\
+\x6d\x61\x63\x20\x7b\x0a\x20\x20\x20\x20\x49\x43\x4f\x4e\x20\x3d\
+\x20\x61\x73\x73\x69\x73\x74\x61\x6e\x74\x2e\x69\x63\x6e\x73\x0a\
+\x20\x20\x20\x20\x54\x41\x52\x47\x45\x54\x20\x3d\x20\x61\x73\x73\
+\x69\x73\x74\x61\x6e\x74\x0a\x23\x20\x20\x20\x20\x51\x4d\x41\x4b\
+\x45\x5f\x49\x4e\x46\x4f\x5f\x50\x4c\x49\x53\x54\x20\x3d\x20\x49\
+\x6e\x66\x6f\x5f\x6d\x61\x63\x2e\x70\x6c\x69\x73\x74\x0a\x7d\x0a\
+\x0a\x23\x74\x61\x72\x67\x65\x74\x2e\x70\x61\x74\x68\x20\x3d\x20\
+\x24\x24\x5b\x51\x54\x5f\x49\x4e\x53\x54\x41\x4c\x4c\x5f\x42\x49\
+\x4e\x53\x5d\x0a\x23\x49\x4e\x53\x54\x41\x4c\x4c\x53\x20\x2b\x3d\
+\x20\x74\x61\x72\x67\x65\x74\x0a\x0a\x23\x61\x73\x73\x69\x73\x74\
+\x61\x6e\x74\x74\x72\x61\x6e\x73\x6c\x61\x74\x69\x6f\x6e\x73\x2e\
+\x66\x69\x6c\x65\x73\x20\x3d\x20\x2a\x2e\x71\x6d\x0a\x23\x61\x73\
+\x73\x69\x73\x74\x61\x6e\x74\x74\x72\x61\x6e\x73\x6c\x61\x74\x69\
+\x6f\x6e\x73\x2e\x70\x61\x74\x68\x20\x3d\x20\x24\x24\x5b\x51\x54\
+\x5f\x49\x4e\x53\x54\x41\x4c\x4c\x5f\x54\x52\x41\x4e\x53\x4c\x41\
+\x54\x49\x4f\x4e\x53\x5d\x0a\x23\x49\x4e\x53\x54\x41\x4c\x4c\x53\
+\x20\x2b\x3d\x20\x61\x73\x73\x69\x73\x74\x61\x6e\x74\x74\x72\x61\
+\x6e\x73\x6c\x61\x74\x69\x6f\x6e\x73\x0a\x0a\x54\x52\x41\x4e\x53\
+\x4c\x41\x54\x49\x4f\x4e\x53\x20\x20\x20\x20\x20\x20\x20\x20\x3d\
+\x20\x61\x73\x73\x69\x73\x74\x61\x6e\x74\x5f\x64\x65\x2e\x74\x73\
+\x20\x5c\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
+\x20\x20\x20\x20\x20\x61\x73\x73\x69\x73\x74\x61\x6e\x74\x5f\x66\
+\x72\x2e\x74\x73\x0a\x0a\x0a\x75\x6e\x69\x78\x3a\x21\x63\x6f\x6e\
+\x74\x61\x69\x6e\x73\x28\x51\x54\x5f\x43\x4f\x4e\x46\x49\x47\x2c\
+\x20\x7a\x6c\x69\x62\x29\x3a\x4c\x49\x42\x53\x20\x2b\x3d\x20\x2d\
+\x6c\x7a\x0a\x0a\x0a\x74\x61\x72\x67\x65\x74\x2e\x70\x61\x74\x68\
+\x3d\x24\x24\x5b\x51\x54\x5f\x49\x4e\x53\x54\x41\x4c\x4c\x5f\x42\
+\x49\x4e\x53\x5d\x0a\x49\x4e\x53\x54\x41\x4c\x4c\x53\x20\x2b\x3d\
+\x20\x74\x61\x72\x67\x65\x74\x0a\
+"
+
+qt_resource_name = b"\
+\x00\x08\
+\x0e\x84\x7f\x43\
+\x00\x65\
+\x00\x78\x00\x61\x00\x6d\x00\x70\x00\x6c\x00\x65\x00\x73\
+\x00\x07\
+\x0c\xe8\x47\xe5\
+\x00\x65\
+\x00\x78\x00\x61\x00\x6d\x00\x70\x00\x6c\x00\x65\
+"
+
+qt_resource_struct = b"\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\
+\x00\x00\x00\x16\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
+"
+
+def qInitResources():
+ QtCore.qRegisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data)
+
+def qCleanupResources():
+ QtCore.qUnregisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data)
+
+qInitResources()
diff --git a/examples/widgets/richtext/textobject/files/heart.svg b/examples/widgets/richtext/textobject/files/heart.svg
new file mode 100644
index 000000000..ba5f050b0
--- /dev/null
+++ b/examples/widgets/richtext/textobject/files/heart.svg
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) --><svg viewBox="100 200 550 500" height="595.27559pt" id="svg1" inkscape:version="0.40+cvs" sodipodi:docbase="C:\Documents and Settings\Jon Phillips\My Documents\projects\clipart-project\submissions" sodipodi:docname="heart-left-highlight.svg" sodipodi:version="0.32" width="595.27559pt" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://web.resource.org/cc/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:svg="http://www.w3.org/2000/svg">
+<metadata>
+<rdf:RDF xmlns:cc="http://web.resource.org/cc/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+<cc:Work rdf:about="">
+<dc:title>Heart Left-Highlight</dc:title>
+<dc:description>This is a normal valentines day heart.</dc:description>
+<dc:subject>
+<rdf:Bag>
+<rdf:li>holiday</rdf:li>
+<rdf:li>valentines</rdf:li>
+<rdf:li></rdf:li>
+<rdf:li>valentine</rdf:li>
+<rdf:li>hash(0x8a091c0)</rdf:li>
+<rdf:li>hash(0x8a0916c)</rdf:li>
+<rdf:li>signs_and_symbols</rdf:li>
+<rdf:li>hash(0x8a091f0)</rdf:li>
+<rdf:li>day</rdf:li>
+</rdf:Bag>
+</dc:subject>
+<dc:publisher>
+<cc:Agent rdf:about="http://www.openclipart.org">
+<dc:title>Jon Phillips</dc:title>
+</cc:Agent>
+</dc:publisher>
+<dc:creator>
+<cc:Agent>
+<dc:title>Jon Phillips</dc:title>
+</cc:Agent>
+</dc:creator>
+<dc:rights>
+<cc:Agent>
+<dc:title>Jon Phillips</dc:title>
+</cc:Agent>
+</dc:rights>
+<dc:date></dc:date>
+<dc:format>image/svg+xml</dc:format>
+<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
+<cc:license rdf:resource="http://web.resource.org/cc/PublicDomain"/>
+<dc:language>en</dc:language>
+</cc:Work>
+<cc:License rdf:about="http://web.resource.org/cc/PublicDomain">
+<cc:permits rdf:resource="http://web.resource.org/cc/Reproduction"/>
+<cc:permits rdf:resource="http://web.resource.org/cc/Distribution"/>
+<cc:permits rdf:resource="http://web.resource.org/cc/DerivativeWorks"/>
+</cc:License>
+</rdf:RDF>
+</metadata>
+<defs id="defs3"/>
+<sodipodi:namedview bordercolor="#666666" borderopacity="1.0" id="base" inkscape:current-layer="layer1" inkscape:cx="549.40674" inkscape:cy="596.00159" inkscape:document-units="px" inkscape:guide-bbox="true" inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:window-height="615" inkscape:window-width="866" inkscape:window-x="88" inkscape:window-y="116" inkscape:zoom="0.35000000" pagecolor="#ffffff" showguides="true"/>
+<g id="layer1" inkscape:groupmode="layer" inkscape:label="Layer 1">
+<path d="M 263.41570,235.14588 C 197.17570,235.14588 143.41575,288.90587 143.41575,355.14588 C 143.41575,489.90139 279.34890,525.23318 371.97820,658.45392 C 459.55244,526.05056 600.54070,485.59932 600.54070,355.14588 C 600.54070,288.90588 546.78080,235.14587 480.54070,235.14588 C 432.49280,235.14588 391.13910,263.51631 371.97820,304.33338 C 352.81740,263.51630 311.46370,235.14587 263.41570,235.14588 z " id="path7" sodipodi:nodetypes="ccccccc" style="fill:#e60000;fill-opacity:1.0000000;stroke:#000000;stroke-width:18.700001;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"/>
+<path d="M 265.00000,253.59375 C 207.04033,253.59375 160.00000,300.63407 160.00000,358.59375 C 160.00000,476.50415 278.91857,507.43251 359.96875,624.00000 C 366.52868,614.08205 220.00000,478.47309 220.00000,378.59375 C 220.00000,320.63407 267.04033,273.59375 325.00000,273.59375 C 325.50453,273.59375 325.99718,273.64912 326.50000,273.65625 C 309.22436,261.07286 288.00557,253.59374 265.00000,253.59375 z " id="path220" sodipodi:nodetypes="ccccccc" style="fill:#e6e6e6;fill-opacity:0.64556962;stroke:none;stroke-width:18.700001;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"/>
+</g>
+</svg>
diff --git a/examples/widgets/richtext/textobject/textobject.py b/examples/widgets/richtext/textobject/textobject.py
new file mode 100755
index 000000000..3e7b75ddc
--- /dev/null
+++ b/examples/widgets/richtext/textobject/textobject.py
@@ -0,0 +1,130 @@
+#!/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/textobject example from Qt v5.x"""
+
+from PySide2 import QtCore, QtGui, QtWidgets, QtSvg
+
+
+class SvgTextObject(QtCore.QObject, QtGui.QTextObjectInterface):
+
+ def intrinsicSize(self, doc, posInDocument, format):
+ renderer = QtSvg.QSvgRenderer(format.property(Window.SvgData).toByteArray())
+ size = renderer.defaultSize()
+
+ if size.height() > 25:
+ size *= 25.0 / size.height()
+
+ return QtCore.QSizeF(size)
+
+ def drawObject(self, painter, rect, doc, posInDocument, format):
+ renderer = QtSvg.QSvgRenderer(format.property(Window.SvgData).toByteArray())
+ renderer.render(painter, rect)
+
+
+class Window(QtWidgets.QWidget):
+
+ SvgTextFormat = QtGui.QTextFormat.UserObject + 1
+
+ SvgData = 1
+
+ def __init__(self):
+ super(Window, self).__init__()
+
+ self.setupGui()
+ self.setupTextObject()
+
+ self.setWindowTitle(self.tr("Text Object Example"))
+
+ def insertTextObject(self):
+ fileName = self.fileNameLineEdit.text()
+ file = QtCore.QFile(fileName)
+
+ if not file.open(QtCore.QIODevice.ReadOnly):
+ QtWidgets.QMessageBox.warning(self, self.tr("Error Opening File"),
+ self.tr("Could not open '%1'").arg(fileName))
+
+ svgData = file.readAll()
+
+ svgCharFormat = QtGui.QTextCharFormat()
+ svgCharFormat.setObjectType(Window.SvgTextFormat)
+ svgCharFormat.setProperty(Window.SvgData, svgData)
+
+ cursor = self.textEdit.textCursor()
+ cursor.insertText(u"\uFFFD", svgCharFormat)
+ self.textEdit.setTextCursor(cursor)
+
+ def setupTextObject(self):
+ svgInterface = SvgTextObject(self)
+ self.textEdit.document().documentLayout().registerHandler(Window.SvgTextFormat, svgInterface)
+
+ def setupGui(self):
+ fileNameLabel = QtWidgets.QLabel(self.tr("Svg File Name:"))
+ self.fileNameLineEdit = QtWidgets.QLineEdit()
+ insertTextObjectButton = QtWidgets.QPushButton(self.tr("Insert Image"))
+
+ self.fileNameLineEdit.setText('./files/heart.svg')
+ QtCore.QObject.connect(insertTextObjectButton, QtCore.SIGNAL('clicked()'), self.insertTextObject)
+
+ bottomLayout = QtWidgets.QHBoxLayout()
+ bottomLayout.addWidget(fileNameLabel)
+ bottomLayout.addWidget(self.fileNameLineEdit)
+ bottomLayout.addWidget(insertTextObjectButton)
+
+ self.textEdit = QtWidgets.QTextEdit()
+
+ mainLayout = QtWidgets.QVBoxLayout()
+ mainLayout.addWidget(self.textEdit)
+ mainLayout.addLayout(bottomLayout)
+
+ self.setLayout(mainLayout)
+
+
+if __name__ == '__main__':
+
+ import sys
+
+ app = QtWidgets.QApplication(sys.argv)
+ window = Window()
+ window.show()
+ sys.exit(app.exec_())