I seem to be closing the solution.
I can get clicks on elements by overriding the delegate .editorEvent(event, model, option, index)
. Then I can find out event.type()
by clicking the line from index.row()
and the actual coordinates from event.x()
and event.y()
(since if the event type is MouseButtonRelease, the event is QMouseEvent).
From this, I think I can match the coordinates with my elements on the screen and act accordingly.
I will update this answer when I have working code.
EDIT
A simple working example using PySide:
class MyModel(QtGui.QStandardItemModel): def __init__(self): super(MyModel, self).__init__() for i in range(10): self.appendRow(QtGui.QStandardItem("Row %d" % i)) class MyDelegate(QtGui.QStyledItemDelegate): def __init__(self, parent=None): super(MyDelegate, self).__init__(parent) self.links = {} def makeLinkFunc(self, row, text): def linkFunc(): print("Clicked on %s in row %d" % (text, row)) return linkFunc def paint(self, painter, option, index): painter.save() textHeight = QtGui.QFontMetrics(painter.font()).height() painter.drawText(option.rect.x()+2, option.rect.y()+2+textHeight, index.data()) rowLinks = {} for i in range(3): text = "Link %d" % (3-i) linkWidth = QtGui.QFontMetrics(font).width(text) x = option.rect.right() - (i+1) * (linkWidth + 10) painter.drawText(x, y, text) rect = QtCore.QRect(x, y - textHeight, linkWidth, textHeight) rowLinks[rect] = self.makeLinkFunc(index.row(), text) self.links[index.row()] = rowLinks painter.restore() def sizeHint(self, option, index): hint = super().sizeHint(option, index) hint.setHeight(30) return hint def editorEvent(self, event, model, option, index): if event.type() == QtCore.QEvent.MouseButtonRelease: for rect, link in self.links[index.row()].items(): if rect.contains(event.pos()): link() return True return False listmodel = MyModel() listview = QtGui.QListView() listview.setModel(listmodel) listview.setItemDelegate(MyDelegate(parent=listview)) listview.setSelectionMode(QtGui.QAbstractItemView.NoSelection)