Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Qt for Python
  4. Word wrap and links in QTreeView
QtWS25 Last Chance

Word wrap and links in QTreeView

Scheduled Pinned Locked Moved Unsolved Qt for Python
qtreeviewdelegatewordwraphyperlink
1 Posts 1 Posters 1.1k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • V Offline
    V Offline
    voltron
    wrote on 14 Mar 2022, 14:35 last edited by
    #1

    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 using anchorAt() 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

    76fd02c8-97cc-441c-98d2-91b670deb000-зображення.png

    and items overlap when widget it resized

    a1471c32-f5c0-4935-9b44-e493d7214066-зображення.png

    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.

    1 Reply Last reply
    0

    1/1

    14 Mar 2022, 14:35

    • Login

    • Login or register to search.
    1 out of 1
    • First post
      1/1
      Last post
    0
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Get Qt Extensions
    • Unsolved