People edit and improved Session
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
from .books import Book
|
||||
from .person import PersonDialog
|
||||
from .read import EditDialog
|
||||
from .session import SessionDialog
|
||||
from .person import PersonDialog
|
||||
|
||||
220
lib/person.py
220
lib/person.py
@@ -1,12 +1,224 @@
|
||||
from html.parser import HTMLParser
|
||||
from io import StringIO
|
||||
|
||||
from PyQt6.QtCore import QSize, Qt, pyqtSlot
|
||||
from PyQt6.QtGui import QStandardItem, QStandardItemModel
|
||||
from PyQt6.QtSql import QSqlQuery, QSqlQueryModel
|
||||
from PyQt6.QtWidgets import QDialog, QDialogButtonBox, QStyledItemDelegate
|
||||
|
||||
from main import query_error
|
||||
from ui.PeopleDialog import Ui_Dialog
|
||||
from PyQt6.QtCore import Qt, pyqtSlot
|
||||
from PyQt6.QtSql import QSqlQuery
|
||||
from PyQt6.QtWidgets import QDialog
|
||||
|
||||
|
||||
class MLStripper(HTMLParser):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.reset()
|
||||
return
|
||||
|
||||
def reset(self):
|
||||
super().reset()
|
||||
self.strict = False
|
||||
self.convert_charrefs = True
|
||||
self.text = StringIO()
|
||||
self.first = True
|
||||
return
|
||||
|
||||
def handle_data(self, d):
|
||||
if self.first:
|
||||
self.text.write(d)
|
||||
self.first = False
|
||||
return
|
||||
|
||||
def get_data(self):
|
||||
return self.text.getvalue()
|
||||
|
||||
|
||||
class PersonDialog(QDialog, Ui_Dialog):
|
||||
def __init__(self,*args, **kwargs):
|
||||
SectionIdRole = Qt.ItemDataRole.UserRole
|
||||
SectionSequenceRole = Qt.ItemDataRole.UserRole + 1
|
||||
BookIdRole = Qt.ItemDataRole.UserRole + 2
|
||||
person_id = 0
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.person_id = kwargs.pop("person_id", 0)
|
||||
super(PersonDialog, self).__init__(*args, **kwargs)
|
||||
self.setupUi(self)
|
||||
self.show()
|
||||
model = QSqlQueryModel()
|
||||
query = QSqlQuery()
|
||||
query.prepare("SELECT book_id, title " "FROM books " "ORDER BY title")
|
||||
if not query.exec():
|
||||
query_error(query)
|
||||
model.setQuery(query)
|
||||
self.bookCombo.setPlaceholderText("Select A Book")
|
||||
self.bookCombo.setModel(model)
|
||||
self.bookCombo.setModelColumn(1)
|
||||
self.bookCombo.setCurrentIndex(-1)
|
||||
model = QStandardItemModel()
|
||||
self.sectionCombo.setPlaceholderText("Select A Section")
|
||||
self.sectionCombo.setModel(model)
|
||||
self.sectionCombo.setEnabled(False)
|
||||
self.sectionCombo.setCurrentIndex(-1)
|
||||
|
||||
button = self.buttonBox.button(QDialogButtonBox.StandardButton.Ok)
|
||||
button.setEnabled(False)
|
||||
|
||||
#
|
||||
# Connections
|
||||
#
|
||||
self.bookCombo.currentIndexChanged.connect(self.bookSelected)
|
||||
self.sectionCombo.currentIndexChanged.connect(self.sectionSelected)
|
||||
self.nameEdit.editingFinished.connect(self.checkLineEdits)
|
||||
self.orgEdit.editingFinished.connect(self.checkLineEdits)
|
||||
if self.person_id > 0:
|
||||
self.setPerson(self.person_id)
|
||||
return
|
||||
|
||||
def setPerson(self, person_id: int) -> None:
|
||||
query = QSqlQuery()
|
||||
query.prepare(
|
||||
"SELECT p.name, p.organization, p.book_id, s.sequence "
|
||||
"FROM people p "
|
||||
"LEFT JOIN person_book pb "
|
||||
"ON (p.book_id = pb.book_id "
|
||||
"AND p.person_id = pb.person_id) "
|
||||
"LEFT JOIN sections s "
|
||||
"ON (s.section_id = pb.section_id) "
|
||||
"WHERE p.person_id = :person_id"
|
||||
)
|
||||
query.bindValue(":person_id", person_id)
|
||||
if not query.exec():
|
||||
query_error(query)
|
||||
if not query.next():
|
||||
raise Exception(f"No person record for {person_id}")
|
||||
self.person_id = person_id
|
||||
self.nameEdit.setText(query.value("name"))
|
||||
self.orgEdit.setText(query.value("organization"))
|
||||
model = self.bookCombo.model()
|
||||
matches = model.match(
|
||||
model.createIndex(0, 0),
|
||||
Qt.ItemDataRole.DisplayRole,
|
||||
query.value("book_id"),
|
||||
1,
|
||||
Qt.MatchFlag.MatchExactly,
|
||||
)
|
||||
if len(matches) != 1:
|
||||
raise Excpetion(
|
||||
f"Match failed looking for book_id: {query.value('book_id')}"
|
||||
)
|
||||
row = int(matches[0].row())
|
||||
self.bookCombo.setCurrentIndex(row)
|
||||
self.sectionCombo.setCurrentIndex(query.value("sequence"))
|
||||
return
|
||||
|
||||
@pyqtSlot(int)
|
||||
def bookSelected(self, index: int) -> None:
|
||||
book_index = self.bookCombo.model().createIndex(index, 0)
|
||||
book_id = book_index.data()
|
||||
model = self.sectionCombo.model()
|
||||
query = QSqlQuery()
|
||||
query.prepare(
|
||||
"SELECT section_id, sequence, content "
|
||||
"FROM sections "
|
||||
"WHERE book_id = :book_id "
|
||||
"ORDER BY sequence"
|
||||
)
|
||||
query.bindValue(":book_id", book_id)
|
||||
if not query.exec():
|
||||
query_error(query)
|
||||
model.clear()
|
||||
stripper = MLStripper()
|
||||
while query.next():
|
||||
stripper.feed(query.value("content"))
|
||||
content = stripper.get_data()
|
||||
stripper.reset()
|
||||
item = QStandardItem()
|
||||
item.setData(content[:40], Qt.ItemDataRole.DisplayRole)
|
||||
item.setData(
|
||||
query.value("sequence"), PersonDialog.SectionSequenceRole
|
||||
)
|
||||
item.setData(query.value("section_id"), PersonDialog.SectionIdRole)
|
||||
model.appendRow(item)
|
||||
self.sectionCombo.setEnabled(True)
|
||||
return
|
||||
|
||||
@pyqtSlot(int)
|
||||
def sectionSelected(self, row: int) -> None:
|
||||
self.checkLineEdits()
|
||||
return
|
||||
|
||||
@pyqtSlot()
|
||||
def accept(self) -> None:
|
||||
query = QSqlQuery()
|
||||
if self.person_id > 0:
|
||||
query.prepare(
|
||||
"UPDATE people SET "
|
||||
"name = :name, "
|
||||
"organization = :org, "
|
||||
"email = :email, "
|
||||
"book_id = :book_id "
|
||||
"WHERE person_id = :person_id"
|
||||
)
|
||||
query.bindValue(":person_id", self.person_id)
|
||||
else:
|
||||
query.prepare(
|
||||
"INSERT INTO people "
|
||||
"(name, organization, email, book_id) "
|
||||
"VALUES (:name, :org, :email, :book_id)"
|
||||
)
|
||||
query.bindValue(":name", self.nameEdit.text().strip())
|
||||
query.bindValue(":org", self.nameEdit.text().strip())
|
||||
query.bindValue(":email", self.emailEdit.text().strip())
|
||||
row = self.bookCombo.currentIndex()
|
||||
model = self.bookCombo.model()
|
||||
book_id = model.data(model.createIndex(row, 0))
|
||||
query.bindValue(":book_id", book_id)
|
||||
section_id = self.sectionCombo.currentData(PersonDialog.SectionIdRole)
|
||||
print(f"section_id: {section_id}")
|
||||
if not section_id:
|
||||
raise Exception(f"Section id is null")
|
||||
if not query.exec():
|
||||
query_error(query)
|
||||
if self.person_id <= 0:
|
||||
self.person_id = query.lastInsertId()
|
||||
query.prepare(
|
||||
"SELECT * FROM person_book pb "
|
||||
"WHERE pb.person_id = :person_id "
|
||||
"AND pb.book_id = :book_id"
|
||||
)
|
||||
query.bindValue(":person_id", self.person_id)
|
||||
query.bindValue(":book_id", book_id)
|
||||
if not query.exec():
|
||||
query_error(query)
|
||||
if query.next():
|
||||
query.prepare(
|
||||
"UPDATE person_book SET "
|
||||
"section_id = :section_id "
|
||||
"WHERE person_id = :person_id "
|
||||
"AND book_id = :book_id"
|
||||
)
|
||||
else:
|
||||
query.prepare(
|
||||
"INSERT INTO person_book "
|
||||
"(person_id, book_id, section_id, block) "
|
||||
"VALUES (:person_id, :book_id, :section_id, 0 )"
|
||||
)
|
||||
query.bindValue(":person_id", self.person_id)
|
||||
query.bindValue(":book_id", book_id)
|
||||
query.bindValue(":section_id", section_id)
|
||||
if not query.exec():
|
||||
query_error(query)
|
||||
super().accept()
|
||||
return
|
||||
|
||||
@pyqtSlot()
|
||||
def checkLineEdits(self):
|
||||
name = self.nameEdit.text().strip()
|
||||
org = self.orgEdit.text().strip()
|
||||
button = self.buttonBox.button(QDialogButtonBox.StandardButton.Ok)
|
||||
if name and org:
|
||||
button.setEnabled(True)
|
||||
else:
|
||||
button.setEnabled(False)
|
||||
return
|
||||
|
||||
12
lib/read.py
12
lib/read.py
@@ -40,7 +40,9 @@ from ui.EditDialog import Ui_Dialog
|
||||
class EditDialog(QDialog, Ui_Dialog):
|
||||
block: int
|
||||
paragraphs = True
|
||||
sessionSignal = pyqtSignal()
|
||||
displayedWord = pyqtSignal(int)
|
||||
newParagraph = pyqtSignal(int, int)
|
||||
|
||||
def __init__(self, session, person_id: int) -> None:
|
||||
self.session = session
|
||||
@@ -76,17 +78,26 @@ class EditDialog(QDialog, Ui_Dialog):
|
||||
self.scrollBtn.clicked.connect(self.scrollAction)
|
||||
self.nextBtn.clicked.connect(self.nextAction)
|
||||
self.prevBtn.clicked.connect(self.prevAction)
|
||||
#self.sessionSignal.connect(self.session.timerAction)
|
||||
#self.sessionBtn.clicked.connect(self.sessionAction)
|
||||
self.sessionBtn.clicked.connect(self.session.timerAction)
|
||||
self.paraEdit.verticalScrollBar().valueChanged.connect(self.scrollSlot)
|
||||
#
|
||||
# Connect signals
|
||||
#
|
||||
self.displayedWord.connect(self.session.addWord)
|
||||
self.newParagraph.connect(self.session.addBlock)
|
||||
return
|
||||
|
||||
#
|
||||
# slots
|
||||
#
|
||||
@pyqtSlot()
|
||||
def sessionAction(self) -> None:
|
||||
self.sessionSignal.emit()
|
||||
self.session.addParagraph(self.section_id, self.block)
|
||||
return
|
||||
|
||||
@pyqtSlot()
|
||||
def printAction(self) -> None:
|
||||
html = "<!DOCTYPE html>\n<html>\n<head>\n"
|
||||
@@ -378,6 +389,7 @@ class EditDialog(QDialog, Ui_Dialog):
|
||||
self.nextSection()
|
||||
return
|
||||
self.savePosition()
|
||||
self.newParagraph.emit(self.section_id, self.block)
|
||||
return
|
||||
|
||||
def prevParagraph(self) -> None:
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from PyQt6.QtCore import Qt, QTime, QTimer, pyqtSignal, pyqtSlot
|
||||
from PyQt6.QtGui import QStandardItem, QStandardItemModel, QTextCursor
|
||||
from PyQt6.QtGui import (
|
||||
QStandardItem,
|
||||
QStandardItemModel,
|
||||
QTextCursor,
|
||||
QTextDocument,
|
||||
QTextBlockFormat
|
||||
)
|
||||
from PyQt6.QtSql import QSqlQuery
|
||||
from PyQt6.QtWidgets import QDialog
|
||||
|
||||
@@ -10,9 +16,16 @@ 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__()
|
||||
@@ -26,8 +39,18 @@ class SessionDialog(QDialog, Ui_Dialog):
|
||||
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)
|
||||
@@ -37,16 +60,26 @@ class SessionDialog(QDialog, Ui_Dialog):
|
||||
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:
|
||||
print("Accepted")
|
||||
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()
|
||||
@@ -81,22 +114,56 @@ class SessionDialog(QDialog, Ui_Dialog):
|
||||
raise Exception(f"Word_id({word_id}) not found in DB")
|
||||
word = QStandardItem()
|
||||
word.setData(query.value("word"), Qt.ItemDataRole.DisplayRole)
|
||||
word_id = QStandardItem()
|
||||
word_id.setData(
|
||||
query.value("word_id"), Qt.ItemDataRole.UserRole + 1
|
||||
)
|
||||
word.setData(query.value("word_id"), SessionDialog.WordIdRole)
|
||||
model = self.wordView.model()
|
||||
matches = model.match(
|
||||
model.createIndex(0, 1),
|
||||
Qt.ItemDataRole.UserRole + 1,
|
||||
model.createIndex(0, 0),
|
||||
SessionDialog.WordIdRole,
|
||||
query.value("word_id"),
|
||||
1,
|
||||
Qt.MatchFlag.MatchExactly,
|
||||
)
|
||||
if len(matches) > 0:
|
||||
return
|
||||
self.wordView.model().appendRow([word, word_id])
|
||||
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:
|
||||
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()
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user