QTableView & QDelegate -- QTextEdit opening on left corner - qt

I am working on QTableview inside a QStandardItemModel. I am using QTextEdit inside a class derived from Qdeligates. This allows me to insert newline inside tableview.
Most of the things are working fine but now i am facing a challenge that when ever i click a cell to edit QTextEdit is opening on the left corner of the GUI. When I click cell row 0, column 3 text edit opens on the left corner.
How can i make my QTextEdit to open near the cell which i am editing ?
Also what should i put inside this function updateEditorGeometry ?
Here is my initialising code for tableview :--
ui->testCaseTableView->verticalHeader()->resizeSections(QHeaderView::ResizeToContents); //---> original
ui->testCaseTableView->verticalHeader()->setResizeMode(QHeaderView::ResizeToContents);
ui->testCaseTableView->horizontalHeader()->setStretchLastSection(true);
//Set model & deligate
ui->testCaseTableView->setModel(model);
ui->testCaseTableView->setItemDelegate(mydeligate);
Here is my code for the deligate :---
QWidget* textViewDeligate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QTextEdit *tableEdit = new QTextEdit(parent);
return tableEdit;
}
void textViewDeligate::setEditorData ( QWidget * editor, const QModelIndex & index ) const
{
QString value = index.model()->data(index,Qt::EditRole).toString();
QTextEdit *tableEditCopy = static_cast<QTextEdit*>(editor);
tableEditCopy->setPlainText(value);
}
void textViewDeligate::setModelData ( QWidget * editor, QAbstractItemModel * model, const QModelIndex & index ) const
{
QTextEdit *tableEditCopy = static_cast<QTextEdit*>(editor);
QString str = tableEditCopy->toPlainText();
model->setData(index, str, Qt::EditRole);
}
void textViewDeligate::updateEditorGeometry ( QWidget *editor, const QStyleOptionViewItem & option, const QModelIndex & index ) const
{
}

You need to setup the editor geometry of all widgets you create yourself. This is so that the widgets get given the correct dimensions of the tables' cells.
void textViewDeligate::updateEditorGeometry ( QWidget *editor, const QStyleOptionViewItem & option, const QModelIndex & index ) const
{
editor->setGeometry(option.rect);
}

This was what improved it further :---
editor->setGeometry(option.rect.x(),option.rect.y(),editor->sizeHint().width(),editor->sizeHint().height());

Related

Remove CellWidget from QTableWidget when focus out

I have a QTableWidget in which some cells have QComboBox as cellWidget. I want to create the comboBox only when the user clicks in the cell. For this, I have caught itemClicked signal and created the comboBox and set it as cellWidget.
Now, I want to delete this comboBox in two scenarios - if the user selects some value from the comboBox, or the user simply focusses out (click anywhere in the dialog).
For the first case, I have use the signal QComboBox::activated which is invoked when something is selected in the drop-down. There I delete the comboBox and it works fine.
However, I am not sure how to proceed for the second case (delete the comboBox when the user focusses out of the drop-down without selecting anything).
I tried capturing eventFilter for focusOut for the tablewidget as well as the comboBox, but it didn't help.
You can use QItemDelegate for this purpose:
comboboxdelegate.h
class ComboBoxDelegate : public QItemDelegate
{
Q_OBJECT
public:
ComboBoxDelegate(QObject *parent = nullptr) :
QItemDelegate(parent)
{
}
QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QComboBox *editor = new QComboBox(parent);
editor->addItems(QStringList() << "1" << "2" << "3" << "4"); // fill it with your own values
return editor;
}
void setEditorData(QWidget *editor, const QModelIndex &index) const
{
QString text = index.model()->data(index, Qt::EditRole).toString();
QComboBox *cb = static_cast<QComboBox*>(editor);
cb->setCurrentText(text);
}
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
QComboBox *cb = static_cast<QComboBox*>(editor);
QString text = cb->currentText();
model->setData(index, text, Qt::EditRole);
}
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
editor->setGeometry(option.rect);
}
};
mainwindow.cpp
...
ui->tableWidget->setItemDelegate(new ComboBoxDelegate);
...

Qt - Triggering an event when selection of abstract item delegate changes

I am trying to make a tableview with a row which has a separate dropdown for each column. The user can only select a combination of values. That is, if the user selects "A" from the first drop down, the values in the other drop downs should be updated to that which can match "A".
I have made my AbsractItemDelegate class and the values are being assigned fine. But I am stuck up at how I can trigger an event when a value changes in one of the drop downs.
Thanks.
The following is my delegate class implementation:
FillComboBox::FillComboBox(QStringList the_list) : QItemDelegate() {
//list = new QStringList();
list = the_list; }
QWidget* FillComboBox::createEditor(QWidget* parent,
const QStyleOptionViewItem& /* option */,
const QModelIndex& /* index */) const {
QComboBox* editor = new QComboBox(parent);
editor->addItems(list);
editor->setCurrentIndex(2);
return editor; }
void FillComboBox::setEditorData(QWidget* editor,
const QModelIndex &index) const {
QString text = index.model()->data(index, Qt::EditRole).toString();
QComboBox* combo_box = dynamic_cast<QComboBox*>(editor);
combo_box->setCurrentIndex(combo_box->findText(text)); }
void FillComboBox::setModelData(QWidget* editor, QAbstractItemModel* model,
const QModelIndex &index) const {
QComboBox* combo_box = dynamic_cast<QComboBox*>(editor);
QString text = combo_box->currentText();
model->setData(index, text, Qt::EditRole); }
void FillComboBox::updateEditorGeometry(QWidget* editor,
const QStyleOptionViewItem &option, const QModelIndex &/* index */) const {
editor->setGeometry(option.rect); }
You can update the data of the "other" item as soon as the current item's data is updating, i.e. in FillComboBox::setModelData(). Please find the pseudo code that implements desired behavior (see comments):
void FillComboBox::setModelData(QWidget* editor, QAbstractItemModel* model,
const QModelIndex &index) const
{
QComboBox* combo_box = dynamic_cast<QComboBox*>(editor);
QString text = combo_box->currentText();
model->setData(index, text, Qt::EditRole);
// Find the model index of the item that should be changed and its data too
int otherRow = ...; // find the row of the "other" item
int otherColumn = ...; // find the column of the "other" item
QModelIndex otherIndex = model->index(otherRow, otherColumn);
QString newText = text + "_new";
// Update other item too
model->setData(otherIndex, newText, Qt::EditRole);
}

How to change delegate’s sizeHint on TableView’s cell focus?

I've got some troubles with custom delegate's sizeHint:
I want to "unfold" cell (row with this cell) on it's focus; otherwise return default size;
QTableVew connected to resize rows on mouse press:
connect(m_scheduleView, &QTableView::pressed, m_scheduleView, &QTableView::resizeRowsToContents);
QSize DBScheduleItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
if (option.state & QStyle::State_HasFocus) {
... // this block never executes;
return // some calculated size;
}
return QSize(width, height); // default size;
}
Code in conditional block has never executed, but the same condition on delegate's paint() executes properly:
void DBScheduleItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
if (option.state & QStyle::State_HasFocus)
painter->fillRect(...);
}
So, how to catch cell focus in sizeHint?
This is related to https://bugreports.qt.io/browse/QTBUG-5392 .
A possible work-around that is also used in the source code of Qt Creator itself (specifically in the TaskView widget) is to keep track of the current/selected item(s) yourself by connecting to the QItemSelectionModel.

Determine if QTableView has an open editor

Is there any way to determine if a QTableView has an open editor in the current cell? I need to handle the following situation:
A user double-clicks a cell and edits the data, but leaves the cell in the "edit" state.
On another part of the UI, an action is taken that changes the selected row of the underlying model.
Back on my view, I want to determine if the newly selected row is the same as the open row. If not, I need to take an action. (Prompt the user? Commit automatically? Revert?)
I see how to get the current item, and can get the delegate on that item, but I don't see any isEditMode() property I was hoping to find.
Can someone point me in the right direction?
Just check whether the return value of
State QAbstractItemView::state () const
is
QTableView::EditingState
Connect to underlying model dataChanged signal
void QAbstractItemModel::dataChanged ( const QModelIndex & topLeft, const QModelIndex & bottomRight )
You can check if the cell where data has changed is the same than the currentIndex
QModelIndex QAbstractItemView::currentIndex () const
You cannot know if the current cell had an open editor straight, but can check if the view is in QAbstractItemView::EditingState
State QAbstractItemView::state () const
It should be enough to do what you want.
You can subclass QTableView in order to be able to access the state() function, which is unfortunately protected. However, I did not try that.
If you already have an QStyledItemDelegate subclass, you can use it to track whether an editor is currently open. However, you can't just use setEditorData/setModelData, because setModelData won't be called, when the user cancels editing. Instead, you can track the creation and destruction of the editor itself.
class MyItemDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
MyItemDelegate( QObject* parent = nullptr );
~MyItemDelegate();
QWidget* createEditor( QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index ) const;
void setEditorData( QWidget* editor, const QModelIndex& index ) const;
void setModelData( QWidget* editor, QAbstractItemModel* model, const QModelIndex& index ) const;
bool isEditorOpen() const { return *m_editorCount > 0; }
protected:
int* m_editorCount;
protected slots:
void onEditorDestroyed( QObject* obj );
};
Implementation:
MyItemDelegate::MyItemDelegate( QObject* parent ) :
QStyledItemDelegate( parent )
{
m_editorCount = new int;
*m_editorCount = 0;
}
MyItemDelegate::~MyItemDelegate()
{
delete m_editorCount;
}
QWidget* MyItemDelegate::createEditor( QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index ) const
{
// create an editor, can be changed as needed
QWidget* editor = QStyledItemDelegate::createEditor( parent, option, index );
connect( editor, SIGNAL(destroyed(QObject*)), SLOT(onEditorDestroyed(QObject*)));
printf( "editor %p created\n", (void*) editor );
(*m_editorCount)++;
return editor;
}
void MyItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
...
}
void MyItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
...
}
void MyItemDelegate::onEditorDestroyed( QObject* obj )
{
printf( "editor %p destroyed\n", (void*) obj );
(*m_editorCount)--;
}
On some occasions, e.g. when moving to the next item in the tree using the cursor keys, Qt will create the new editor first and then destroy the old one. Hence, m_editorCount must be an integer instead of a bool.
Unfortunately, createEditor() is a const function. Therefore, you cannot create an int-member. Instead, create a pointer to an int and use that.
Subclass your delegate so that it includes an accessor that tells you when it's editing:
void MyDelegate::setEditorData ( QWidget * editor, const QModelIndex & index ) const {
// _isEditing will have to be mutable because this method is const
_isEditing = true;
QStyledItemDelegate::setEditorData(editor, index);
}
void MyDelegate::setModelData ( QWidget * editor, QAbstractItemModel * model, const QModelIndex & index ) const {
QStyledItemDelegate::setModelData(editor, model, index);
_isEditing = false;
}
bool MyDelegate::isEditing() const { return _isEditing; }
Then you can just check the delegate to see what's going on. Alternatively and/or if you don't like the mutable, you can emit signals so you know what state the delegate is in.
If you know the index of the item being edited, you can call indexWidget() and attempt to cast it. If it's valid, you not only know you're editing, but you also have your editor widget handy.
EditWidget *editWidget = qobject_cast<EditWidget*>(tableView->indexWidget(tableView->currentIndex()));
if(editWidget)
{
//yep, ur editing bro
}
Here is an idea, its even helpful to get the edit/combo widget before the edit begins...
just emit a signal and consume it in the mainwindow... this is what I used one to get combo box in QTableWidget before editing...
first create a signal in ComoBoxItemDelegate...
signals:
void OnComboEdit(QComboBox* pCombo) const;
then emit the signal in the createEditor method...
QWidget* ComboBoxItemDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
// Create the combobox and populate it
QComboBox* cb = new QComboBox(parent);
emit OnComboEdit(cb);
return cb;
}
and in the MainWindow declare a function to receive the singal...
void MainWindow::OnComboEidt(QComboBox *pCB) const
{
qDebug() << "Combo Eidt Singal Received";
}
Then finally in the constructor of MainWindow connect it...
ComboBoxItemDelegate* cbid = new ComboBoxItemDelegate(ui->tableWidget);
connect(cbid, &ComboBoxItemDelegate::OnComboEdit, this, &MainWindow::OnComboEidt);
ui->tableWidget->setItemDelegateForColumn(0, cbid);

How to make item view render rich (html) text in Qt

Suppose my model has items with the following string for Qt::DisplayRole
<span>blah-blah <b>some text</b> other blah</span>
I want QTreeView (actually, any item view) to render it like a rich text. Instead, item views render it like a pure text by default. How to achieve the desired rendering?
Actually, this is a search results model. User enters a text, some document is searched against that text and the user is presented with search results, where the words being searched should be bolder than surrounding text.
I guess you can use setItemDelegate method of the treeview to setup custom painter for your treeview items. In the delegate's paint method you can use QTextDocument to load item's text as html and render it. Please check if an example below would work for you:
treeview initialization:
...
// create simple model for a tree view
QStandardItemModel *model = new QStandardItemModel();
QModelIndex parentItem;
for (int i = 0; i < 4; ++i)
{
parentItem = model->index(0, 0, parentItem);
model->insertRows(0, 1, parentItem);
model->insertColumns(0, 1, parentItem);
QModelIndex index = model->index(0, 0, parentItem);
model->setData(index, "<span>blah-blah <b>some text</b> other blah</span>");
}
// create custom delegate
HTMLDelegate* delegate = new HTMLDelegate();
// set model and delegate to the treeview object
ui->treeView->setModel(model);
ui->treeView->setItemDelegate(delegate);
...
custom delegate implementation
class HTMLDelegate : public QStyledItemDelegate
{
protected:
void paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const;
QSize sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const;
};
void HTMLDelegate::paint(QPainter* painter, const QStyleOptionViewItem & option, const QModelIndex &index) const
{
QStyleOptionViewItemV4 options = option;
initStyleOption(&options, index);
painter->save();
QTextDocument doc;
doc.setHtml(options.text);
options.text = "";
options.widget->style()->drawControl(QStyle::CE_ItemViewItem, &options, painter);
painter->translate(options.rect.left(), options.rect.top());
QRect clip(0, 0, options.rect.width(), options.rect.height());
doc.drawContents(painter, clip);
painter->restore();
}
QSize HTMLDelegate::sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const
{
QStyleOptionViewItemV4 options = option;
initStyleOption(&options, index);
QTextDocument doc;
doc.setHtml(options.text);
doc.setTextWidth(options.rect.width());
return QSize(doc.idealWidth(), doc.size().height());
}
hope this helps, regards
update0: changes to HTMLDelegate to make icons visible and different pen color for selected items
void HTMLDelegate::paint(QPainter* painter, const QStyleOptionViewItem & option, const QModelIndex &index) const
{
QStyleOptionViewItemV4 options = option;
initStyleOption(&options, index);
painter->save();
QTextDocument doc;
doc.setHtml(options.text);
options.text = "";
options.widget->style()->drawControl(QStyle::CE_ItemViewItem, &options, painter);
// shift text right to make icon visible
QSize iconSize = options.icon.actualSize(options.rect.size());
painter->translate(options.rect.left()+iconSize.width(), options.rect.top());
QRect clip(0, 0, options.rect.width()+iconSize.width(), options.rect.height());
//doc.drawContents(painter, clip);
painter->setClipRect(clip);
QAbstractTextDocumentLayout::PaintContext ctx;
// set text color to red for selected item
if (option.state & QStyle::State_Selected)
ctx.palette.setColor(QPalette::Text, QColor("red"));
ctx.clip = clip;
doc.documentLayout()->draw(painter, ctx);
painter->restore();
}
My answer is mostly inspired by #serge_gubenko's one. However, there were made several improvements so that the code is finally useful in my application.
class HtmlDelegate : public QStyledItemDelegate
{
protected:
void paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const;
QSize sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const;
};
void HtmlDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QStyleOptionViewItemV4 optionV4 = option;
initStyleOption(&optionV4, index);
QStyle *style = optionV4.widget? optionV4.widget->style() : QApplication::style();
QTextDocument doc;
doc.setHtml(optionV4.text);
/// Painting item without text
optionV4.text = QString();
style->drawControl(QStyle::CE_ItemViewItem, &optionV4, painter);
QAbstractTextDocumentLayout::PaintContext ctx;
// Highlighting text if item is selected
if (optionV4.state & QStyle::State_Selected)
ctx.palette.setColor(QPalette::Text, optionV4.palette.color(QPalette::Active, QPalette::HighlightedText));
QRect textRect = style->subElementRect(QStyle::SE_ItemViewItemText, &optionV4);
painter->save();
painter->translate(textRect.topLeft());
painter->setClipRect(textRect.translated(-textRect.topLeft()));
doc.documentLayout()->draw(painter, ctx);
painter->restore();
}
QSize HtmlDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QStyleOptionViewItemV4 optionV4 = option;
initStyleOption(&optionV4, index);
QTextDocument doc;
doc.setHtml(optionV4.text);
doc.setTextWidth(optionV4.rect.width());
return QSize(doc.idealWidth(), doc.size().height());
}
Here's the PyQt conversion of the combination of the above answers that worked for me. I would expect this to work virtually identically for PySide as well.
from PyQt4 import QtCore, QtGui
class HTMLDelegate(QtGui.QStyledItemDelegate):
def paint(self, painter, option, index):
options = QtGui.QStyleOptionViewItemV4(option)
self.initStyleOption(options,index)
style = QtGui.QApplication.style() if options.widget is None else options.widget.style()
doc = QtGui.QTextDocument()
doc.setHtml(options.text)
options.text = ""
style.drawControl(QtGui.QStyle.CE_ItemViewItem, options, painter);
ctx = QtGui.QAbstractTextDocumentLayout.PaintContext()
# Highlighting text if item is selected
#if (optionV4.state & QStyle::State_Selected)
#ctx.palette.setColor(QPalette::Text, optionV4.palette.color(QPalette::Active, QPalette::HighlightedText));
textRect = style.subElementRect(QtGui.QStyle.SE_ItemViewItemText, options)
painter.save()
painter.translate(textRect.topLeft())
painter.setClipRect(textRect.translated(-textRect.topLeft()))
doc.documentLayout().draw(painter, ctx)
painter.restore()
def sizeHint(self, option, index):
options = QtGui.QStyleOptionViewItemV4(option)
self.initStyleOption(options,index)
doc = QtGui.QTextDocument()
doc.setHtml(options.text)
doc.setTextWidth(options.rect.width())
return QtCore.QSize(doc.idealWidth(), doc.size().height())
This one is in PySide. Rather than doing a lot of custom drawing, I pass the QPainter to the QLabel and make it draw itself. Highlighting code borrowed from other answers.
from PySide import QtGui
class TaskDelegate(QtGui.QItemDelegate):
#https://doc.qt.io/archives/qt-4.7/qitemdelegate.html#drawDisplay
#https://doc.qt.io/archives/qt-4.7/qwidget.html#render
def drawDisplay(self, painter, option, rect, text):
label = QtGui.QLabel(text)
if option.state & QtGui.QStyle.State_Selected:
p = option.palette
p.setColor(QtGui.QPalette.WindowText, p.color(QtGui.QPalette.Active, QtGui.QPalette.HighlightedText))
label.setPalette(p)
label.render(painter, rect.topLeft(), renderFlags=QtGui.QWidget.DrawChildren)
Writing up yet another answer for how this can be done in C++. The difference to the answers provided so far is that this is for Qt5 and not Qt4. Most importantly however the previous answers neglected that the item delegate should be able to align the text as specified (e.g. in a QTreeWidget). Additionally I also implemented a way to elide rich text in order to get a consistent feeling with plaintext delegates (in ItemViews).
So without further ado, here is my code for a RichTextDelegate:
void RichTextItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &inOption,
const QModelIndex &index) const {
QStyleOptionViewItem option = inOption;
initStyleOption(&option, index);
if (option.text.isEmpty()) {
// This is nothing this function is supposed to handle
QStyledItemDelegate::paint(painter, inOption, index);
return;
}
QStyle *style = option.widget ? option.widget->style() : QApplication::style();
QTextOption textOption;
textOption.setWrapMode(option.features & QStyleOptionViewItem::WrapText ? QTextOption::WordWrap
: QTextOption::ManualWrap);
textOption.setTextDirection(option.direction);
QTextDocument doc;
doc.setDefaultTextOption(textOption);
doc.setHtml(option.text);
doc.setDefaultFont(option.font);
doc.setDocumentMargin(0);
doc.setTextWidth(option.rect.width());
doc.adjustSize();
if (doc.size().width() > option.rect.width()) {
// Elide text
QTextCursor cursor(&doc);
cursor.movePosition(QTextCursor::End);
const QString elidedPostfix = "...";
QFontMetrics metric(option.font);
#if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)
int postfixWidth = metric.horizontalAdvance(elidedPostfix);
#else
int postfixWidth = metric.width(elidedPostfix);
#endif
while (doc.size().width() > option.rect.width() - postfixWidth) {
cursor.deletePreviousChar();
doc.adjustSize();
}
cursor.insertText(elidedPostfix);
}
// Painting item without text (this takes care of painting e.g. the highlighted for selected
// or hovered over items in an ItemView)
option.text = QString();
style->drawControl(QStyle::CE_ItemViewItem, &option, painter, inOption.widget);
// Figure out where to render the text in order to follow the requested alignment
QRect textRect = style->subElementRect(QStyle::SE_ItemViewItemText, &option);
QSize documentSize(doc.size().width(), doc.size().height()); // Convert QSizeF to QSize
QRect layoutRect = QStyle::alignedRect(Qt::LayoutDirectionAuto, option.displayAlignment, documentSize, textRect);
painter->save();
// Translate the painter to the origin of the layout rectangle in order for the text to be
// rendered at the correct position
painter->translate(layoutRect.topLeft());
doc.drawContents(painter, textRect.translated(-textRect.topLeft()));
painter->restore();
}
QSize RichTextItemDelegate::sizeHint(const QStyleOptionViewItem &inOption, const QModelIndex &index) const {
QStyleOptionViewItem option = inOption;
initStyleOption(&option, index);
if (option.text.isEmpty()) {
// This is nothing this function is supposed to handle
return QStyledItemDelegate::sizeHint(inOption, index);
}
QTextDocument doc;
doc.setHtml(option.text);
doc.setTextWidth(option.rect.width());
doc.setDefaultFont(option.font);
doc.setDocumentMargin(0);
return QSize(doc.idealWidth(), doc.size().height());
}
Just a slight update from jbmohler's answer, for PyQt5: some classes have apparently been shifted to QtWidgets.
This is way beyond my paygrade (i.e. knowledge of the nuts and bolts behind PyQt5).
I echo the sentiment expressed in Cecil Curry's comment to the question. It is now 2021, and we appear still to have to struggle with this sort of hack. Ridiculous. I've been impressed by Qt5 to date, as compared to JavaFX for example. This deficiency is a let-down.
class HTMLDelegate( QtWidgets.QStyledItemDelegate ):
def __init__( self ):
super().__init__()
# probably better not to create new QTextDocuments every ms
self.doc = QtGui.QTextDocument()
def paint(self, painter, option, index):
options = QtWidgets.QStyleOptionViewItem(option)
self.initStyleOption(options, index)
painter.save()
self.doc.setTextWidth(options.rect.width())
self.doc.setHtml(options.text)
self.doc.setDefaultFont(options.font)
options.text = ''
options.widget.style().drawControl(QtWidgets.QStyle.CE_ItemViewItem, options, painter)
painter.translate(options.rect.left(), options.rect.top())
clip = QtCore.QRectF(0, 0, options.rect.width(), options.rect.height())
painter.setClipRect(clip)
ctx = QtGui.QAbstractTextDocumentLayout.PaintContext()
ctx.clip = clip
self.doc.documentLayout().draw(painter, ctx)
painter.restore()
def sizeHint( self, option, index ):
options = QtWidgets.QStyleOptionViewItem(option)
self.initStyleOption(option, index)
self.doc.setHtml(option.text)
self.doc.setTextWidth(option.rect.width())
return QtCore.QSize(self.doc.idealWidth(), self.doc.size().height())

Resources