Word wrap and links in QTreeView
Moved
Unsolved
Qt for Python
-
I need to display clickable hyperlinks inside quite long text in tree view items. So I subclassed
QStyledItemDelegate
to draw HTML there and in this subclass added a method to find out which link was clicked usinganchorAt()
method.However, I was not able to achieve desired results: while word wrap works, only first link in the text can be clicked. Also, there are some visual glitches when resizing treeview widget as shown in screenshots below.
Vertical scroolbar is not shown when part of the text is outside of visible tree view area
and items overlap when widget it resized
Here is my code
from PyQt.QtCore import * from PyQt.QtGui import * from PyQt.QtWidgets import * class MyDelegate(QStyledItemDelegate): def __init__(self, parent=None): super(MyDelegate, self).__init__(parent) self.document = QTextDocument() def paint(self, painter, option, index): text = index.model().data(index) self.document.setHtml(text) self.document.setTextWidth(option.rect.width()) painter.save() painter.translate(option.rect.x(), option.rect.y()) self.document.drawContents(painter) painter.restore() def sizeHint(self, option, index): text = index.model().data(index) self.document.setHtml(text) self.document.setTextWidth(option.rect.width()) return QSize(int(self.document.idealWidth()), int(self.document.size().height())) def anchorAt(self, html, pos): self.document.setHtml(html) layout = self.document.documentLayout() return layout.anchorAt(pos) class MyView(QTreeView): linkHovered = pyqtSignal(str) linkUnhovered = pyqtSignal() linkActivated = pyqtSignal(str) def __init__(self, parent=None): super(MyView, self).__init__(parent) self.setMouseTracking(True) self.mousePressAnchor = None self.hoveredAnchor = None def mousePressEvent(self, event): super().mousePressEvent(event) anchor = self.anchorAt(event.pos()) self.mousePressAnchor = anchor def mouseMoveEvent(self, event): anchor = self.anchorAt(event.pos()) if self.mousePressAnchor != anchor: self.mousePressAnchor = None if self.hoveredAnchor != anchor: self.hoveredAnchor = anchor if self.hoveredAnchor: QApplication.setOverrideCursor(QCursor(Qt.PointingHandCursor)) self.linkHovered.emit(self.hoveredAnchor) else: QApplication.restoreOverrideCursor() self.linkUnhovered.emit() def mouseReleaseEvent(self, event): if self.mousePressAnchor: anchor = self.anchorAt(event.pos()) if anchor == self.mousePressAnchor: self.linkActivated.emit(self.mousePressAnchor) self.mousePressAnchor = None super().mouseReleaseEvent(event) def anchorAt(self, pos): index = self.indexAt(pos) if index.isValid(): delegate = self.itemDelegate(index) if delegate: itemRect = self.visualRect(index) relativeClickPosition = pos - itemRect.topLeft() html = self.model().data(index, Qt.DisplayRole) return delegate.anchorAt(html, relativeClickPosition) return '' model = QStandardItemModel() model.setHorizontalHeaderLabels(["Results"]) tree = MyView() tree.setEditTriggers(QAbstractItemView.NoEditTriggers) tree.setModel(model) tree.setItemDelegate(MyDelegate()) item = QStandardItem("Short text item") model.appendRow(item) item = QStandardItem("Test") sub_item = QStandardItem('Lorem ipsum dolor sit <a href="https://https://forum.qt.io">amet</a>, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia <a href="https://google.com">deserunt mollit</a> anim id est laborum.') item.appendRow(sub_item) model.appendRow(item) tree.expandAll() tree.show()
I would be grateful for any help with these issues.