Files
esl-reader/lib/session.py
2023-12-12 12:26:44 -05:00

216 lines
7.3 KiB
Python

from datetime import datetime, timedelta
from PyQt6.QtCore import Qt, QTime, QTimer, pyqtSignal, pyqtSlot
from PyQt6.QtGui import (
QStandardItem,
QStandardItemModel,
QTextBlockFormat,
QTextCursor,
QTextDocument,
)
from PyQt6.QtSql import QSqlQuery
from PyQt6.QtWidgets import QDialog
from main import query_error
from ui.SessionDialog import Ui_Dialog
class SessionDialog(QDialog, Ui_Dialog):
WordIdRole = Qt.ItemDataRole.UserRole
SectionIdRole = Qt.ItemDataRole.UserRole + 1
BlockRole = Qt.ItemDataRole.UserRole + 2
timer = QTimer()
startTime = datetime.now()
totalTime = 0 # seconds
sessionStart = None
sessionEnd = None
blocks = QStandardItemModel()
def __init__(self) -> None:
super(SessionDialog, self).__init__()
self.setupUi(self)
self.wordView.setModel(QStandardItemModel())
self.wordView.setWrapping(True)
#
# Connections
#
self.timer.timeout.connect(self.tickAction)
self.activeBox.stateChanged.connect(self.activeAction)
return
@pyqtSlot()
def resetForm(self) -> None:
self.nameLbl.setText("")
self.totalTime = timedelta()
self.wordView.model().clear()
self.textBrowser.document().clear()
return
@pyqtSlot(int)
def setPerson(self, person_id) -> None:
self.resetForm()
self.person_id = person_id
query = QSqlQuery()
query.prepare("SELECT * FROM people " "WHERE person_id = :person_id")
query.bindValue(":person_id", person_id)
if not query.exec():
query_error(query)
if not query.next():
raise Exception(f"Bad person_id: {person_id}")
self.nameLbl.setText(query.value("name"))
self.totalTime = timedelta()
self.wordView.model().clear()
return
@pyqtSlot()
def accept(self) -> None:
if not self.sessionStart:
super().accept()
return
if not self.sessionEnd:
self.sessionEnd = datetime.now()
query = QSqlQuery()
query.prepare(
"INSERT INTO sessions "
"(person_id, start, stop, notes) "
"VALUES (:person_id, :start, :stop, :notes)"
)
query.bindValue(":person_id", self.person_id)
query.bindValue(":start", self.sessionStart.isoformat())
query.bindValue(":stop", self.sessionEnd.isoformat())
query.bindValue(":notes", self.textEdit.toPlainText())
if not query.exec():
query_error(query)
session_id = query.lastInsertId()
model = self.wordView.model()
sql = "INSERT INTO session_word (session_id,word_id) VALUES "
parameters = ["(?,?)" for x in range(model.rowCount())]
sql += ", ".join(parameters)
query.prepare(sql)
for row in range(model.rowCount()):
query.addBindValue(session_id)
query.addBindValue(model.item(row).data(SessionDialog.WordIdRole))
if not query.exec():
query_error(query)
sql = (
"INSERT INTO session_block (session_id, section_id, block) VALUES "
)
parameters = ["(?,?,?)" for x in range(self.blocks.rowCount())]
sql += ",".join(parameters)
query.prepare(sql)
for row in range(self.blocks.rowCount()):
query.addBindValue(session_id)
item = self.blocks.item(row)
query.addBindValue(item.data(SessionDialog.SectionIdRole))
query.addBindValue(item.data(SessionDialog.BlockRole))
if not query.exec():
query_error(query)
super().accept()
return
@pyqtSlot(int)
def activeAction(self, state: int) -> None:
if state:
if not self.sessionStart:
self.sessionStart = datetime.now()
self.startTime = datetime.now()
self.timer.start()
else:
self.totalTime = self.totalTime + (datetime.now() - self.startTime)
self.timer.stop()
self.sessionEnd = datetime.now()
return
@pyqtSlot()
def timerAction(self) -> None:
if self.activeBox.isChecked(): # we are stopping
self.activeBox.setChecked(False)
self.sender().setText("Start")
return
self.timer.setInterval(1000)
self.sender().setText("Stop")
self.activeBox.setChecked(True)
return
@pyqtSlot()
def tickAction(self) -> None:
delta = self.totalTime + (datetime.now() - self.startTime)
seconds = delta.seconds % 60
minutes = int(delta.seconds / 60) % 60
hours = int(delta.seconds / 3600)
self.timerLbl.setText(f"{hours:02d}:{minutes:02d}:{seconds:02d}")
return
@pyqtSlot(int)
def addWord(self, word_id: int) -> None:
if self.activeBox.isChecked():
query = QSqlQuery()
query.prepare("SELECT * FROM words " "WHERE word_id = :word_id")
query.bindValue(":word_id", word_id)
if not query.exec():
query_error(query)
if not query.next():
raise Exception(f"Word_id({word_id}) not found in DB")
word = QStandardItem()
word.setData(query.value("word"), Qt.ItemDataRole.DisplayRole)
word.setData(query.value("word_id"), SessionDialog.WordIdRole)
model = self.wordView.model()
matches = model.match(
model.createIndex(0, 0),
SessionDialog.WordIdRole,
query.value("word_id"),
1,
Qt.MatchFlag.MatchExactly,
)
if len(matches) > 0:
return
self.wordView.model().appendRow(word)
self.wordView.model().sort(0)
else:
print(f"Not active: {word_id}")
return
@pyqtSlot(int, int)
def addBlock(self, section_id, block) -> None:
if not self.activeBox.isChecked():
return
new_block = QStandardItem()
new_block.setData(section_id, SessionDialog.SectionIdRole)
new_block.setData(block, SessionDialog.BlockRole)
matches = self.blocks.match(
self.blocks.createIndex(0, 0),
SessionDialog.BlockRole,
block,
1,
Qt.MatchFlag.MatchExactly,
)
if len(matches) > 0:
return
self.blocks.appendRow(new_block)
query = QSqlQuery()
query.prepare(
"SELECT * FROM sections " "WHERE section_id = :section_id"
)
query.bindValue(":section_id", section_id)
if not query.exec():
query_error(query)
if not query.next():
raise Exception(f"Section not found {section_id}")
document = QTextDocument()
cursor = QTextCursor(document)
cursor.setPosition(0)
cursor.insertHtml(query.value("content"))
textBlock = document.findBlockByNumber(block)
blockFormat = QTextBlockFormat()
blockFormat.setTextIndent(25.0)
self.textBrowser.textCursor().setBlockFormat(blockFormat)
self.textBrowser.textCursor().insertHtml(
"<p>" + textBlock.text() + "</p>"
)
self.textBrowser.textCursor().insertBlock()
self.textBrowser.ensureCursorVisible()
return