Files
scotus-watch/dockettableview.py
Christopher T. Johnson 6129258f1b Create names for columns
Addresses #17 but it feels like we should have these definitions
in the dbConfig.  Which leads to the question of moving from
QtSql to Pony ORM
2025-02-26 16:47:33 -05:00

152 lines
4.3 KiB
Python

from typing import cast
from PySide6.QtCore import (
QAbstractItemModel,
QDir,
QFile,
QModelIndex,
QObject,
QPersistentModelIndex,
QPoint,
QSize,
Qt,
QUrl,
Signal,
Slot,
)
from PySide6.QtGui import (
QMouseEvent,
QPalette,
QTextDocument,
)
from PySide6.QtNetwork import (
QNetworkAccessManager,
QNetworkReply,
QNetworkRequest,
)
from PySide6.QtWidgets import (
QAbstractItemView,
QSizePolicy,
QStyledItemDelegate,
QStyleOptionViewItem,
QTableView,
QTextEdit,
QWidget,
)
from docketModel import docketModel
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,
_: QStyleOptionViewItem,
index: QModelIndex | QPersistentModelIndex,
) -> QSize:
widget = self.view.indexWidget(index)
return widget.sizeHint()
class docketEntry(QTextEdit):
def __init__(self, parent: QWidget | None = None) -> None:
super(docketEntry, self).__init__(parent)
self.setSizePolicy(
QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Fixed
)
return
def mousePressEvent(self, e: QMouseEvent) -> None:
super().mousePressEvent(e)
anchor = self.anchorAt(e.pos())
if anchor:
obj = cast(QObject, self)
while not isinstance(obj, docketTableView) and obj is not None:
obj = obj.parent()
assert obj is not None
index = obj.indexAt(obj.mapFromGlobal(self.mapToGlobal(e.pos())))
obj.anchorSignal.emit(index, anchor)
return
def sizeHint(self) -> QSize:
size = self.size()
doc = QTextDocument()
doc.setPlainText(self.document().toPlainText())
doc.setTextWidth(size.width())
docSize = doc.size()
return QSize(size.width(), int(docSize.height()))
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
def setModel(self, model: QAbstractItemModel | None) -> None:
assert model is not None
super().setModel(model)
self.model().modelReset.connect(self.modelReset)
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 modelReset(self) -> None:
model = self.model()
red = QPalette()
red.setColor(QPalette.ColorRole.Base, Qt.GlobalColor.red)
for row in range(0, model.rowCount()):
index = model.index(row, docketModel.ColumnNames.text)
widget = docketEntry()
widget.setHtml(model.data(index, Qt.ItemDataRole.DisplayRole))
widget.setAutoFillBackground(False)
widget.setReadOnly(True)
widget.setPalette(red)
self.setIndexWidget(index, widget)
return