tags:

views:

23

answers:

1

I want to render each row with HTML code. The rendering works but -at least for me- items cannot be selected individually.

import sys
from PyQt4.QtCore import * 
from PyQt4.QtGui import * 

#################################################################### 
def main(): 
    app = QApplication(sys.argv) 
    w = MyWindow() 
    w.show() 
    sys.exit(app.exec_()) 


list_data = [1,2,3,4]

#################################################################### 
class MyWindow(QWidget): 
    def __init__(self, *args): 
        QWidget.__init__(self, *args) 

        # create table        
        lm = MyListModel(list_data, self)
        lv = QListView()
        lv.setModel(lm)
        lv.setItemDelegate(HTMLDelegate(self))

        # layout
        layout = QVBoxLayout()
        layout.addWidget(lv) 
        self.setLayout(layout)

#################################################################### 
class MyListModel(QAbstractListModel): 
    def __init__(self, datain, parent=None, *args): 
        """ datain: a list where each item is a row
        """
        QAbstractListModel.__init__(self, parent, *args) 
        self.listdata = datain

    def rowCount(self, parent=QModelIndex()): 
        return len(self.listdata) 

    def data(self, index, role): 
        if index.isValid() and role == Qt.DisplayRole:
            return QVariant(self.listdata[index.row()])
        else: 
            return QVariant()

class HTMLDelegate(QStyledItemDelegate):
    def paint(self, painter, option, index):
        painter.save()

        model = index.model()
        record = model.listdata[index.row()]
        doc = QTextDocument(self)
        doc.setHtml("<b>%s</b>"%record)
        doc.setTextWidth(option.rect.width())
        ctx = QAbstractTextDocumentLayout.PaintContext()

        painter.translate(option.rect.topLeft());
        painter.setClipRect(option.rect.translated(-option.rect.topLeft()))
        dl = doc.documentLayout()
        dl.draw(painter, ctx)
        painter.restore()


    def sizeHint(self, option, index):
        model = index.model()
        record = model.listdata[index.row()]
        doc = QTextDocument(self)
        doc.setHtml("<b>%s</b>"%record)
        doc.setTextWidth(option.rect.width())
        return QSize(doc.idealWidth(), doc.size().height())
    def flags(self, index):
        return Qt.ItemIsEnabled | Qt.ItemIsSelectable 
####################################################################
if __name__ == "__main__": 
    main()
A: 

I believe what you should do is detect selected items in your HTMLDelegate.paint method and fill the background with "highlight" color if such items detected. I've slightly changed your paint method, pls, check if it works for you

def paint(self, painter, option, index):
    painter.save()

    # highlight selected items
    if option.state & QtGui.QStyle.State_Selected:  
        painter.fillRect(option.rect, option.palette.highlight());

    model = index.model()
    record = model.listdata[index.row()]
    doc = QTextDocument(self)
    doc.setHtml("<b>%s</b>"%record)
    doc.setTextWidth(option.rect.width())
    ctx = QAbstractTextDocumentLayout.PaintContext()

    painter.translate(option.rect.topLeft());
    painter.setClipRect(option.rect.translated(-option.rect.topLeft()))
    dl = doc.documentLayout()
    dl.draw(painter, ctx)

    painter.restore()

hope this helps, regards

serge_gubenko