From 51a7dd1ce595334d26008ac422eb68a98224444e Mon Sep 17 00:00:00 2001 From: "Christopher T. Johnson" Date: Wed, 12 Feb 2025 17:15:02 -0500 Subject: [PATCH] Refactor MainWindow to separate file --- MainWindow.py | 210 ++++++++++++++++++++++++++++++++++++++++++++++ scotus-pull.py | 221 +------------------------------------------------ 2 files changed, 211 insertions(+), 220 deletions(-) create mode 100644 MainWindow.py diff --git a/MainWindow.py b/MainWindow.py new file mode 100644 index 0000000..87159ea --- /dev/null +++ b/MainWindow.py @@ -0,0 +1,210 @@ +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 PySide6.QtSql import QSqlTableModel +from PySide6.QtWidgets import QAbstractItemView, QHeaderView, QMainWindow, QStyle, QStyleOptionViewItem, QStyledItemDelegate, QWidget + +from docketModel import docketModel +from ui.MainWindow import Ui_MainWindow +from workers import loadCases, updateThread + +class QStyleOptionViewItemInit(QStyleOptionViewItem): + backgroundBrush: QColor + rect: QRect + widget: QWidget + text: str + +class dateDelegate(QStyledItemDelegate): + def displayText(self, value: QDate, _: Any) -> str: + return value.toString("MMMM d, yyyy") + + def initStyleOption( + self, + option: QStyleOptionViewItem, + index: QModelIndex | QPersistentModelIndex, + /, + ) -> None: + options = cast(QStyleOptionViewItemInit, option) + super().initStyleOption(options, index) + assert isinstance(index, QModelIndex) + if index.siblingAtColumn(5).data() == 0: + options.backgroundBrush = QColor(0x444444) + return + + +class activeDelegate(QStyledItemDelegate): + def initStyleOption( + self, + option: QStyleOptionViewItem, + index: QModelIndex | QPersistentModelIndex, + /, + ) -> None: + options = cast(QStyleOptionViewItemInit, option) + super().initStyleOption(options, index) + assert isinstance(index, QModelIndex) + if index.siblingAtColumn(5).data() == 0: + options.backgroundBrush = QColor(0x444444) + 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) + + loadThread = None + + def __init__(self) -> None: + super(MainWindow, self).__init__() + self.setupUi(self) + self.loadThread = loadCases() + self.loadThread.finished.connect(self.updateDone) + self.loadThread.start() + + model = QSqlTableModel() + model.setTable("cases") + model.select() + model.setHeaderData(1, Qt.Orientation.Horizontal, "Docket") + model.setHeaderData(2, Qt.Orientation.Horizontal, "Petitioners") + model.setHeaderData(3, Qt.Orientation.Horizontal, "Respondents") + self.casesView.setModel(model) + + self.casesView.setSelectionMode( + QAbstractItemView.SelectionMode.SingleSelection + ) + self.casesView.setSelectionBehavior( + QAbstractItemView.SelectionBehavior.SelectRows + ) + self.casesView.hideColumn(0) + self.casesView.setItemDelegate(activeDelegate()) + self.casesView.setItemDelegateForColumn(4, dateDelegate()) + self.casesView.resizeColumnToContents(1) + self.casesView.resizeColumnToContents(5) + header = self.casesView.horizontalHeader() + header.setSectionResizeMode(2, QHeaderView.ResizeMode.Fixed) + header.setSectionResizeMode(3, QHeaderView.ResizeMode.Fixed) + self.show() + remaining = ( + self.casesView.width() + - header.sectionSize(1) + - header.sectionSize(5) + - 5 + ) + self.casesView.setColumnWidth(2, int(remaining * 0.5)) + self.casesView.setColumnWidth(3, int(remaining * 0.5)) + self.casesView.verticalHeader().hide() + self.casesView.resizeRowsToContents() + self.casesView.doubleClicked.connect(self.rowClicked) + self.casesView.clicked.connect(self.rowClicked) + + self.docketView.setModel(docketModel()) + self.docketView.horizontalHeader().setSectionResizeMode( + 1, QHeaderView.ResizeMode.Stretch + ) + self.docketView.resizeRowsToContents() + self.docketView.setItemDelegateForColumn(1, documentDelegate()) + return + + @Slot(QModelIndex) # type: ignore + def rowClicked(self, index: QModelIndex) -> None: + if not index.isValid(): + raise Exception("Bad index") + 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) + self.docketView.resizeColumnToContents(0) + self.docketView.resizeRowsToContents() + return + + updateThread = None + + @Slot() + def on_updateButton_clicked(self) -> None: + text = self.docketInput.toPlainText() + print(f"on_updateButton_clicked(): {text}") + if not self.updateThread: + self.updateThread = updateThread() + assert isinstance(self.updateThread, updateThread) + self.updateThread.finished.connect(self.updateDone) + self.updateThread.setDocketId(text) + 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()}") + return + + @Slot() + def updateDone(self) -> None: + self.updateThread = None + print("Done updating") + model: QSqlTableModel = cast(QSqlTableModel, self.casesView.model()) + query = model.query() + query.exec() + model.setQuery(query) + return diff --git a/scotus-pull.py b/scotus-pull.py index 6c3c1db..90556f1 100755 --- a/scotus-pull.py +++ b/scotus-pull.py @@ -1,233 +1,14 @@ #!venv/bin/python3 -import datetime import sys -from typing import Any, cast -from PySide6.QtCore import ( - QCoreApplication, - QDate, - QEvent, - QModelIndex, - QObject, - QPersistentModelIndex, - QRect, - QSize, - Qt, - Signal, - Slot, -) -from PySide6.QtGui import QColor, QPainter, QTextDocument from PySide6.QtSql import ( QSqlDatabase, - QSqlTableModel, ) from PySide6.QtWidgets import ( - QAbstractItemView, QApplication, - QHeaderView, - QMainWindow, - QStyle, - QStyledItemDelegate, - QStyleOptionViewItem, - QWidget, ) -from docketModel import docketModel -from ui.MainWindow import Ui_MainWindow -from workers import loadCases, updateThread - -translate = QCoreApplication.translate - - -class dateDelegate(QStyledItemDelegate): - def displayText(self, value: QDate, _: Any) -> str: - return value.toString("MMMM d, yyyy") - - -class QStyleOptionViewItemInit(QStyleOptionViewItem): - backgroundBrush: QColor - rect: QRect - widget: QWidget - text: str - - -class activeDelegate(QStyledItemDelegate): - def initStyleOption( - self, - option: QStyleOptionViewItem, - index: QModelIndex | QPersistentModelIndex, - /, - ) -> None: - options = cast(QStyleOptionViewItemInit, option) - super().initStyleOption(options, index) - assert isinstance(index, QModelIndex) - if index.siblingAtColumn(5).data() == 0: - options.backgroundBrush = QColor(0x444444) - 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) - - loadThread = None - - def __init__(self) -> None: - super(MainWindow, self).__init__() - self.setupUi(self) - self.loadThread = loadCases() - self.loadThread.finished.connect(self.updateDone) - self.loadThread.start() - - model = QSqlTableModel() - model.setTable("cases") - model.select() - model.setHeaderData(1, Qt.Orientation.Horizontal, "Docket") - model.setHeaderData(2, Qt.Orientation.Horizontal, "Petitioners") - model.setHeaderData(3, Qt.Orientation.Horizontal, "Respondents") - self.casesView.setModel(model) - - self.casesView.setSelectionMode( - QAbstractItemView.SelectionMode.SingleSelection - ) - self.casesView.setSelectionBehavior( - QAbstractItemView.SelectionBehavior.SelectRows - ) - self.casesView.hideColumn(0) - self.casesView.setItemDelegate(activeDelegate()) - self.casesView.setItemDelegateForColumn(4, dateDelegate()) - self.casesView.resizeColumnToContents(1) - self.casesView.resizeColumnToContents(5) - header = self.casesView.horizontalHeader() - header.setSectionResizeMode(2, QHeaderView.ResizeMode.Fixed) - header.setSectionResizeMode(3, QHeaderView.ResizeMode.Fixed) - self.show() - remaining = ( - self.casesView.width() - - header.sectionSize(1) - - header.sectionSize(5) - - 5 - ) - self.casesView.setColumnWidth(2, int(remaining * 0.5)) - self.casesView.setColumnWidth(3, int(remaining * 0.5)) - self.casesView.verticalHeader().hide() - self.casesView.resizeRowsToContents() - self.casesView.doubleClicked.connect(self.rowClicked) - self.casesView.clicked.connect(self.rowClicked) - - self.docketView.setModel(docketModel()) - self.docketView.horizontalHeader().setSectionResizeMode( - 1, QHeaderView.ResizeMode.Stretch - ) - self.docketView.resizeRowsToContents() - self.docketView.setItemDelegateForColumn(1, documentDelegate()) - return - - @Slot(QModelIndex) # type: ignore - def rowClicked(self, index: QModelIndex) -> None: - if not index.isValid(): - raise Exception("Bad index") - 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) - self.docketView.resizeColumnToContents(0) - self.docketView.resizeRowsToContents() - return - - updateThread = None - - @Slot() - def on_updateButton_clicked(self) -> None: - text = self.docketInput.toPlainText() - print(f"on_updateButton_clicked(): {text}") - if not self.updateThread: - self.updateThread = updateThread() - assert isinstance(self.updateThread, updateThread) - self.updateThread.finished.connect(self.updateDone) - self.updateThread.setDocketId(text) - 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()}") - return - - @Slot() - def updateDone(self) -> None: - self.updateThread = None - print("Done updating") - model: QSqlTableModel = cast(QSqlTableModel, self.casesView.model()) - query = model.query() - query.exec() - model.setQuery(query) - return - +from MainWindow import MainWindow def main() -> int: #