Last active
December 1, 2018 11:29
-
-
Save trin94/0b61a7476f276c1f7648172d950041a5 to your computer and use it in GitHub Desktop.
Qt HTML Delegate using PyQt5
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from PyQt5.QtCore import QModelIndex, QPoint, QSize, Qt | |
from PyQt5.QtGui import QTextDocument, QAbstractTextDocumentLayout, QPainter, QLinearGradient, QColor, QPalette | |
from PyQt5.QtWidgets import QStyledItemDelegate, QStyle, QStyleOptionViewItem | |
def find_colors(option: QStyleOptionViewItem, even_row: bool): | |
if option.state & QStyle.State_Active and option.state & QStyle.State_Selected: | |
text_color = option.palette.color(QPalette.Active, QPalette.HighlightedText) | |
bg_color = option.palette.color(QPalette.Active, QPalette.Highlight) | |
elif option.state & QStyle.State_Selected: | |
text_color = option.palette.color(QPalette.Inactive, QPalette.Text) | |
bg_color = option.palette.color(QPalette.Inactive, QPalette.Highlight) | |
elif even_row and option.state & QStyle.State_Active: | |
text_color = option.palette.color(QPalette.Inactive, QPalette.Text) | |
bg_color = option.palette.color(QPalette.Active, QPalette.Base) | |
elif even_row: | |
text_color = option.palette.color(QPalette.Inactive, QPalette.Text) | |
bg_color = option.palette.color(QPalette.Inactive, QPalette.Base) | |
elif option.state & QStyle.State_Active: | |
text_color = option.palette.color(QPalette.Inactive, QPalette.Text) | |
bg_color = option.palette.color(QPalette.Active, QPalette.AlternateBase) | |
else: | |
text_color = option.palette.color(QPalette.Inactive, QPalette.Text) | |
bg_color = option.palette.color(QPalette.Inactive, QPalette.AlternateBase) | |
return text_color, bg_color | |
class HtmlDelegate(QStyledItemDelegate): | |
def __init__(self, parent=None): | |
super().__init__(parent) | |
self.__text_doc = QTextDocument() | |
self.__text_doc.setDocumentMargin(0.0) | |
def paint(self, painter: QPainter, option: QStyleOptionViewItem, index: QModelIndex): | |
new_option = QStyleOptionViewItem(option) | |
self.initStyleOption(new_option, index) | |
self.__text_doc.setHtml(new_option.text) | |
new_option.text = "" | |
style = new_option.widget.style() | |
style.drawControl(QStyle.CE_ItemViewItem, new_option, painter, new_option.widget) | |
text_rect = style.subElementRect(QStyle.SE_ItemViewItemText, new_option, new_option.widget) | |
pc = QAbstractTextDocumentLayout.PaintContext() | |
# Colors | |
tc, bg = find_colors(new_option, index.row() % 2 == 0) | |
pc.palette.setColor(QPalette.Text, tc) | |
# Points | |
text_point = QPoint(text_rect.topLeft().x() + 2, | |
text_rect.topLeft().y() + round( | |
0.5 * (option.rect.height() - self.__text_doc.size().height()))) | |
grad_point = QPoint(text_rect.topRight().x() - 43, option.rect.topRight().y()) | |
# Gradient | |
gradient = QLinearGradient(grad_point.x(), option.rect.height(), grad_point.x() + 35, option.rect.height()) | |
gradient.setColorAt(0, QColor(Qt.transparent)) | |
gradient.setColorAt(1, bg) | |
# Paint action | |
painter.save() | |
painter.translate(text_point) | |
self.__text_doc.documentLayout().draw(painter, pc) | |
painter.translate(-text_point) | |
painter.fillRect(option.rect, gradient) | |
painter.restore() | |
def sizeHint(self, option: QStyleOptionViewItem, index: QModelIndex): | |
return QSize(int(self.__text_doc.idealWidth()), int(self.__text_doc.size().height())) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from PyQt5 import QtCore, QtGui, QtWidgets | |
class Ui_MainWindow(object): | |
def setupUi(self, MainWindow): | |
MainWindow.setObjectName("MainWindow") | |
MainWindow.resize(550, 300) | |
MainWindow.setWindowTitle("HTML Delegate") | |
self.centralwidget = QtWidgets.QWidget(MainWindow) | |
self.centralwidget.setObjectName("centralwidget") | |
self.horizontalLayout = QtWidgets.QHBoxLayout(self.centralwidget) | |
self.horizontalLayout.setObjectName("horizontalLayout") | |
self.tableView = QtWidgets.QTableView(self.centralwidget) | |
self.tableView.setObjectName("tableView") | |
self.horizontalLayout.addWidget(self.tableView) | |
MainWindow.setCentralWidget(self.centralwidget) | |
self.menubar = QtWidgets.QMenuBar(MainWindow) | |
self.menubar.setObjectName("menubar") | |
MainWindow.setMenuBar(self.menubar) | |
self.statusbar = QtWidgets.QStatusBar(MainWindow) | |
self.statusbar.setObjectName("statusbar") | |
MainWindow.setStatusBar(self.statusbar) | |
self.retranslateUi(MainWindow) | |
QtCore.QMetaObject.connectSlotsByName(MainWindow) | |
def retranslateUi(self, MainWindow): | |
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from PyQt5 import QtWidgets | |
from PyQt5.QtCore import QItemSelectionModel | |
from PyQt5.QtGui import QStandardItemModel, QStandardItem | |
from PyQt5.QtWidgets import QAbstractItemView | |
from delegate import HtmlDelegate | |
from gui import Ui_MainWindow | |
# Supported subset: http://doc.qt.io/qt-5/richtext-html-subset.html | |
CONTENT = [ | |
'<b>Hello</b>', | |
'This is <span style="background-color: #FFBF00">highlighted</span> text using <i>HTML</i>. ' | |
'It is also possible using a SyntaxHighlighter in the delegate.', | |
'<tt>More stuff supported ... </tt>' | |
] | |
if __name__ == "__main__": | |
import sys | |
app = QtWidgets.QApplication(sys.argv) | |
MainWindow = QtWidgets.QMainWindow() | |
ui = Ui_MainWindow() | |
ui.setupUi(MainWindow) | |
tv = ui.tableView | |
# Model | |
mo = QStandardItemModel(tv) | |
tv.setModel(mo) | |
# Headers | |
tv.horizontalHeader().setStretchLastSection(True) | |
tv.horizontalHeader().hide() | |
tv.verticalHeader().hide() | |
# Delegate | |
tv.setItemDelegateForColumn(0, HtmlDelegate(parent=tv)) | |
# Selection | |
tv.setSelectionMode(QAbstractItemView.SingleSelection) | |
tv.setSelectionBehavior(QAbstractItemView.SelectRows) | |
# Misc | |
tv.setAlternatingRowColors(True) | |
tv.setShowGrid(False) | |
for item in map(QStandardItem, CONTENT): | |
mo.appendRow(item) | |
tv.selectionModel().setCurrentIndex(mo.index(0, 0), QItemSelectionModel.ClearAndSelect | QItemSelectionModel.Rows) | |
MainWindow.show() | |
sys.exit(app.exec_()) |
Author
trin94
commented
Nov 30, 2018
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment