Files
scotus-watch/dockettableview.py
Christopher T. Johnson 69fa955be1 Switch from DocketEntry widget to ItemDelegate.
We were using a subclassed QTextEdit widget so that we could capture
clicks on anchors.

Moving to a delegate removed the widget per row issue.  Unfortunately,
there was no more click on anchor.

Adding a mouseEvent() to the TableView allowed us to translate raw
mouse presses to anchor triggers.

Fixes: #18
2025-02-27 13:40:28 -05:00

154 lines
4.7 KiB
Python

from typing import cast
from PySide6.QtCore import (
QDir,
QFile,
QModelIndex,
QPersistentModelIndex,
QPoint,
QPointF,
QRect,
QSize,
Qt,
QUrl,
Signal,
Slot,
)
from PySide6.QtGui import (
QMouseEvent,
QPainter,
QTextDocument,
)
from PySide6.QtNetwork import (
QNetworkAccessManager,
QNetworkReply,
QNetworkRequest,
)
from PySide6.QtWidgets import (
QAbstractItemView,
QStyle,
QStyledItemDelegate,
QStyleOptionViewItem,
QTableView,
QTextEdit,
QWidget,
)
from lib.utils import QStyleOptionViewItemInit
from pdfView import PDFViewer
class docketEntryDelegate(QStyledItemDelegate):
def __init__(
self, view: QAbstractItemView, parent: QWidget | None = None
) -> None:
super(docketEntryDelegate, self).__init__(parent)
self.view = view
return
def sizeHint(
self,
option: QStyleOptionViewItem,
index: QModelIndex | QPersistentModelIndex,
) -> QSize:
options = cast(QStyleOptionViewItemInit, option)
self.initStyleOption(options, index)
doc = QTextDocument()
doc.setHtml(options.text)
doc.setTextWidth(options.rect.width())
return QSize(int(doc.idealWidth()), int(doc.size().height()))
def paint(self, painter: QPainter, option: QStyleOptionViewItem, index: QModelIndex | QPersistentModelIndex) -> None:
options = cast(QStyleOptionViewItemInit, option)
self.initStyleOption(options, index)
painter.save()
doc = QTextDocument()
doc.setHtml(options.text)
doc.setTextWidth(options.rect.width())
options.text = ''
options.widget.style().drawControl(QStyle.ControlElement.CE_ItemViewItem, options, painter)
painter.translate(options.rect.left(), options.rect.top())
clip = QRect(0,0, options.rect.width(), options.rect.height())
doc.drawContents(painter, clip)
painter.restore()
return
class docketTableView(QTableView):
manager: QNetworkAccessManager
clickedEvent = Signal(QPoint)
anchorSignal = Signal(QModelIndex, str)
pdf: PDFViewer
def __init__(self, parent: QWidget | None = None) -> None:
super(docketTableView, self).__init__(parent)
self.setItemDelegateForColumn(1, docketEntryDelegate(self))
self.anchorSignal.connect(self.doAnchor)
self.manager = QNetworkAccessManager()
self.manager.finished.connect(self.getDone)
return
@Slot(QNetworkReply) # type: ignore
def getDone(self, reply: QNetworkReply) -> None:
dest = QFile("." + reply.url().path())
dest.open(QFile.OpenModeFlag.WriteOnly)
dest.write(reply.readAll())
dest.close()
reply.deleteLater()
self.pdf.open(dest)
self.pdf.show()
return
@Slot(QModelIndex, str) # type: ignore
def doAnchor(self, _: QModelIndex, anchor: str) -> None:
url = QUrl(anchor)
dirs = url.path().split("/")
dirs.pop()
dirs.pop(0)
currentDir = QDir()
path = "/".join(dirs)
currentDir.mkpath(path)
print(f"Checking for .{url.path()} existance.")
if not hasattr(self, "pdf"):
self.pdf = PDFViewer(self)
if QFile("." + url.path()).exists():
self.pdf.open(QFile("." + url.path()))
self.pdf.show()
else:
print(f"Fetching {url}")
self.manager.get(QNetworkRequest(url))
return
def mousePressEvent(self, event: QMouseEvent) -> None:
#
# The mouse has been pressed somewere in our rect. We need to translate that to a click
# within the cell with the document. This will allow the document to find anchors.
#
index = self.indexAt(event.pos())
if not index.isValid():
return
if index.column() != 1:
return
doc = QTextDocument()
doc.setHtml(index.data(Qt.ItemDataRole.DisplayRole))
doc.setTextWidth(self.columnWidth(index.column()))
#
# We need to map our click position to a position within the cell.
#
pos = event.position()
new_pos = QPointF(pos.x() - self.horizontalScrollBar().value(),
pos.y() - self.verticalScrollBar().value())
rowHeight = 0
for row in range(0, index.row()):
rowHeight += self.rowHeight(row)
cell_pos = QPointF(new_pos.x() - self.columnWidth(0),
new_pos.y() - rowHeight)
te = QTextEdit()
te.setDocument(doc)
anchor = te.anchorAt(cell_pos.toPoint())
if anchor:
self.anchorSignal.emit(index,anchor)
return