From 760cd726126946c2b31ac1b8abeadeb23baa3474 Mon Sep 17 00:00:00 2001 From: "Christopher T. Johnson" Date: Fri, 14 Feb 2025 12:11:34 -0500 Subject: [PATCH] Refactor tableview out of MainWindow --- MainWindow.py | 100 +++++++----------------------- dockettableview.py | 151 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 172 insertions(+), 79 deletions(-) create mode 100644 dockettableview.py diff --git a/MainWindow.py b/MainWindow.py index 87159ea..a647976 100644 --- a/MainWindow.py +++ b/MainWindow.py @@ -1,10 +1,11 @@ -from typing import Any, cast -from PySide6.QtCore import QDate, QEvent, QModelIndex, QObject, QPersistentModelIndex, QRect, QSize, Signal, Qt, Slot -from PySide6.QtGui import QColor, QPainter, QTextDocument +from typing import Any, Self, cast +from PySide6.QtCore import QDate, QEvent, QModelIndex, QObject, QPersistentModelIndex, QPoint, QRect, QSize, Signal, Qt, Slot +from PySide6.QtGui import QColor, QFont, QPainter, QTextDocument, QTextDocumentFragment from PySide6.QtSql import QSqlTableModel -from PySide6.QtWidgets import QAbstractItemView, QHeaderView, QMainWindow, QStyle, QStyleOptionViewItem, QStyledItemDelegate, QWidget +from PySide6.QtWidgets import QAbstractItemView, QHeaderView, QMainWindow, QStyle, QStyleOptionViewItem, QStyledItemDelegate, QTableView, QWidget from docketModel import docketModel +from dockettableview import documentDelegate from ui.MainWindow import Ui_MainWindow from workers import loadCases, updateThread @@ -12,6 +13,7 @@ class QStyleOptionViewItemInit(QStyleOptionViewItem): backgroundBrush: QColor rect: QRect widget: QWidget + font: QFont text: str class dateDelegate(QStyledItemDelegate): @@ -47,69 +49,6 @@ class activeDelegate(QStyledItemDelegate): return -class documentDelegate(QStyledItemDelegate): - def initStyleOption( - self, - option: QStyleOptionViewItem, - index: QModelIndex | QPersistentModelIndex, - /, - ) -> None: - options = cast(QStyleOptionViewItemInit, option) - super().initStyleOption(options, index) - assert index.isValid() and isinstance(index, QModelIndex) - if index.siblingAtColumn(6).data() == 0: - options.backgroundBrush = QColor(0x444444) - return - - def eventFilter(self, object: QObject, event: QEvent) -> bool: - if event.type() in [ - QEvent.Type.MouseButtonPress, - QEvent.Type.MouseButtonRelease, - ]: - return False - return super().eventFilter(object, event) - - def event(self, ev: QEvent) -> bool: - print(ev) - return super(documentDelegate, self).event(ev) - - def paint( - self, - painter: QPainter, - option: QStyleOptionViewItem, - index: QModelIndex | QPersistentModelIndex, - ) -> None: - options = cast(QStyleOptionViewItemInit, option) - self.initStyleOption(options, index) - painter.save() - doc = QTextDocument() - doc.setTextWidth(options.rect.width()) - doc.setHtml(options.text) - 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 - - def sizeHint( - self, - option: QStyleOptionViewItem, - index: QModelIndex | QPersistentModelIndex, - ) -> QSize: - options = cast(QStyleOptionViewItemInit, option) - self.initStyleOption(options, index) - doc = QTextDocument() - doc.setTextWidth(options.rect.width()) - doc.setHtml(options.text) - doc.setTextWidth(options.rect.width()) - return QSize(int(doc.idealWidth()), int(doc.size().height())) - class MainWindow(QMainWindow, Ui_MainWindow): show_entries = Signal(int) @@ -119,12 +58,13 @@ class MainWindow(QMainWindow, Ui_MainWindow): def __init__(self) -> None: super(MainWindow, self).__init__() self.setupUi(self) - self.loadThread = loadCases() - self.loadThread.finished.connect(self.updateDone) - self.loadThread.start() + #self.loadThread = loadCases() + #self.loadThread.finished.connect(self.updateDone) + #self.loadThread.start() model = QSqlTableModel() model.setTable("cases") + model.sort(1, Qt.SortOrder.AscendingOrder) model.select() model.setHeaderData(1, Qt.Orientation.Horizontal, "Docket") model.setHeaderData(2, Qt.Orientation.Horizontal, "Petitioners") @@ -141,7 +81,7 @@ class MainWindow(QMainWindow, Ui_MainWindow): self.casesView.setItemDelegate(activeDelegate()) self.casesView.setItemDelegateForColumn(4, dateDelegate()) self.casesView.resizeColumnToContents(1) - self.casesView.resizeColumnToContents(5) + self.casesView.resizeColumnToContents(4) header = self.casesView.horizontalHeader() header.setSectionResizeMode(2, QHeaderView.ResizeMode.Fixed) header.setSectionResizeMode(3, QHeaderView.ResizeMode.Fixed) @@ -149,7 +89,7 @@ class MainWindow(QMainWindow, Ui_MainWindow): remaining = ( self.casesView.width() - header.sectionSize(1) - - header.sectionSize(5) + - header.sectionSize(4) - 5 ) self.casesView.setColumnWidth(2, int(remaining * 0.5)) @@ -159,12 +99,13 @@ class MainWindow(QMainWindow, Ui_MainWindow): self.casesView.doubleClicked.connect(self.rowClicked) self.casesView.clicked.connect(self.rowClicked) + self.docketView.clickedEvent.connect(self.clickedEvent) self.docketView.setModel(docketModel()) self.docketView.horizontalHeader().setSectionResizeMode( 1, QHeaderView.ResizeMode.Stretch ) self.docketView.resizeRowsToContents() - self.docketView.setItemDelegateForColumn(1, documentDelegate()) + #self.docketView.setItemDelegateForColumn(1, documentDelegate()) return @Slot(QModelIndex) # type: ignore @@ -174,8 +115,8 @@ class MainWindow(QMainWindow, Ui_MainWindow): docket = index.siblingAtColumn(1).data() self.docketLabel.setText(docket) self.show_entries.emit(index.siblingAtColumn(0).data()) - model = docketModel(index.siblingAtColumn(0).data()) - self.docketView.setModel(model) + model = cast(docketModel, self.docketView.model()) + model.newCase(index.siblingAtColumn(0).data()) self.docketView.resizeColumnToContents(0) self.docketView.resizeRowsToContents() return @@ -194,11 +135,12 @@ class MainWindow(QMainWindow, Ui_MainWindow): self.updateThread.start() return - @Slot(QModelIndex) # type: ignore - def on_docketView_clicked(self, index: QModelIndex) -> None: - print(f"view clicked, cell: {index.column()}, {index.row()}") + @Slot() + def clickedEvent(self, pos:QPoint) -> None: + print(pos) + viewport = self.docketView.viewport() + print(viewport,viewport.children()) return - @Slot() def updateDone(self) -> None: self.updateThread = None diff --git a/dockettableview.py b/dockettableview.py new file mode 100644 index 0000000..baa2244 --- /dev/null +++ b/dockettableview.py @@ -0,0 +1,151 @@ +from typing import cast +from PySide6.QtCore import QAbstractItemModel, QDir, QEvent, QFile, QModelIndex, QObject, QPersistentModelIndex, QPoint, QRect, QSize, QUrl, Signal, Qt, Slot +from PySide6.QtGui import QColor, QFont, QMouseEvent, QPainter, QPalette, QShowEvent, QTextDocument +from PySide6.QtWidgets import QApplication, QSizePolicy, QStyle, QStyleOptionViewItem, QStyledItemDelegate, QTableView, QTextEdit, QWidget +from PySide6.QtNetwork import QNetworkAccessManager, QNetworkReply, QNetworkRequest + +from pdfView import PDFViewer +class QStyleOptionViewItemInit(QStyleOptionViewItem): + backgroundBrush: QColor + rect: QRect + widget: QWidget + font: QFont + text: str + +class documentDelegate(QStyledItemDelegate): + def initStyleOption( + self, + option: QStyleOptionViewItem, + index: QModelIndex | QPersistentModelIndex, + /, + ) -> None: + options = cast(QStyleOptionViewItemInit, option) + super().initStyleOption(options, index) + assert index.isValid() and isinstance(index, QModelIndex) + if index.siblingAtColumn(6).data() == 0: + options.backgroundBrush = QColor(0x444444) + return + + def paint( + self, + painter: QPainter, + option: QStyleOptionViewItem, + index: QModelIndex | QPersistentModelIndex, + ) -> None: + options = cast(QStyleOptionViewItemInit, option) + self.initStyleOption(options, index) + painter.save() + doc = QTextDocument() + doc.setTextWidth(options.rect.width()) + doc.setHtml(options.text) + 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 + + def sizeHint( + self, + option: QStyleOptionViewItem, + index: QModelIndex | QPersistentModelIndex, + ) -> QSize: + options = cast(QStyleOptionViewItemInit, option) + self.initStyleOption(options, index) + doc = QTextDocument() + doc.setTextWidth(options.rect.width()) + doc.setHtml(options.text) + doc.setTextWidth(options.rect.width()) + return QSize(int(doc.idealWidth()), int(doc.size().height())) + + +class docketEntry(QTextEdit): + def mousePressEvent(self, e: QMouseEvent) -> None: + super().mousePressEvent(e) + anchor = self.anchorAt(e.pos()) + print(f"self.size(): {self.size()}") + if anchor: + print(f"Anchors away: {anchor}") + obj = 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() + print(f"size: {size}, docSize: {docSize}") + return QSize(size.width(), int(docSize.height())) + + +class docketTableView(QTableView): + manager = QNetworkAccessManager() + clickedEvent = Signal(QPoint) + anchorSignal = Signal(QModelIndex, str) + + def __init__(self, parent: QWidget|None = None) -> None: + super(docketTableView,self).__init__(parent) + self.anchorSignal.connect(self.doAnchor) + 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) + print("Setting Model") + 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 = PDFViewer(self) + self.pdf.load_pdf(dest) + self.pdf.show() + return + + @Slot(QModelIndex, str) # type: ignore + def doAnchor(self, index: QModelIndex, anchor: str) -> None: + url = QUrl(anchor) + print(f"{index.row()}, {index.column()} -> {url.path()}") + dirs = url.path().split('/') + dirs.pop() + dirs.pop(0) + currentDir = QDir() + path = '/'.join(dirs) + currentDir.mkpath(path) + if QDir('.'+url.path()).exists(): + file = QFile('.'+url.path()) + self.pdf = PDFViewer(self) + self.pdf.load_pdf(file) + self.pdf.show() + else: + 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,1) + widget = docketEntry() + widget.setHtml(model.data(index,Qt.ItemDataRole.DisplayRole)) + widget.setAutoFillBackground(False) + widget.setReadOnly(True) + widget.setPalette(red) + self.setIndexWidget(index, widget) + return