Make the interface better
This commit is contained in:
255
main.py
255
main.py
@@ -1,10 +1,33 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# TODO:
|
||||
# Start/Stop Session
|
||||
# Record all words examined
|
||||
# Record all words defined after start session
|
||||
# Record paragraph start and stop
|
||||
#
|
||||
# Add definition to definition
|
||||
# Follow definition links
|
||||
# Print subset of words, limit to words from this session's paragraphs
|
||||
# plus defined during session
|
||||
# Add Note per session
|
||||
# Add book import dialog
|
||||
# Add person create/edit dialog
|
||||
# Reading scroll with speed control
|
||||
# Move controls out of reading window.
|
||||
# Ability to edit text with updates to word-section links
|
||||
# Need to be able to place a visible cursor in text.
|
||||
# Scroll to cursor
|
||||
# XXX:
|
||||
# Scrolling is messed up. Need a way of marking current line.
|
||||
#
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
from datetime import datetime, timedelta
|
||||
from typing import cast
|
||||
|
||||
from PyQt6.QtCore import QModelIndex, Qt, pyqtSlot
|
||||
from PyQt6.QtCore import QModelIndex, Qt, QTimer, pyqtSignal, pyqtSlot
|
||||
from PyQt6.QtGui import (
|
||||
QAction,
|
||||
QFont,
|
||||
@@ -37,181 +60,97 @@ def query_error(query: QSqlQuery) -> None:
|
||||
)
|
||||
raise Exception("SQL Error")
|
||||
|
||||
|
||||
class ModelOverride(QSqlQueryModel):
|
||||
enableFlag = False
|
||||
|
||||
def flags(self, index: QModelIndex) -> Qt.ItemFlag:
|
||||
itemFlags = super(ModelOverride, self).flags(index)
|
||||
if self.enableFlag:
|
||||
return itemFlags
|
||||
value = index.siblingAtColumn(3).data()
|
||||
if not value or value < 1:
|
||||
itemFlags &= ~(
|
||||
Qt.ItemFlag.ItemIsSelectable | Qt.ItemFlag.ItemIsEnabled
|
||||
)
|
||||
return itemFlags
|
||||
|
||||
@pyqtSlot()
|
||||
def toggle(self) -> None:
|
||||
self.enableFlag = not self.enableFlag
|
||||
sender = cast(QPushButton, self.sender())
|
||||
if self.enableFlag:
|
||||
sender.setText("Disable")
|
||||
else:
|
||||
sender.setText("Enable")
|
||||
return
|
||||
|
||||
|
||||
class MainWindow(QMainWindow, Ui_MainWindow):
|
||||
def __init__(self) -> None:
|
||||
super(MainWindow, self).__init__()
|
||||
self.setupUi(self)
|
||||
model = ModelOverride()
|
||||
#model = ModelOverride()
|
||||
model = QSqlQueryModel()
|
||||
query = QSqlQuery("SELECT * FROM people ORDER BY name")
|
||||
model.setQuery(query)
|
||||
self.peopleView.setModel(model)
|
||||
self.peopleView.setModelColumn(1)
|
||||
self.toggleBtn.clicked.connect(model.toggle)
|
||||
self.bookBtn.clicked.connect(self.bookAction)
|
||||
self.peopleView.doubleClicked.connect(self.readAction)
|
||||
self.actionQuit.triggered.connect(self.close)
|
||||
self.createActions()
|
||||
self.actionEditPerson.setEnabled(False)
|
||||
#
|
||||
# Connections
|
||||
#
|
||||
# Action Connections
|
||||
#
|
||||
self.actionQuit.triggered.connect(self.close) # Y
|
||||
self.actionAddBook.triggered.connect(self.addBook) # Y
|
||||
self.actionEditBook.triggered.connect(self.editBook) # Y
|
||||
self.actionRead.triggered.connect(self.readBook) # Y
|
||||
self.actionRead.enabledChanged.connect(self.readBtn.setEnabled)
|
||||
self.actionAddPerson.triggered.connect(self.addPerson) # Y
|
||||
self.actionEditPerson.triggered.connect(self.editPerson) # Y
|
||||
self.actionEditPerson.enabledChanged.connect(self.editBtn.setEnabled) # Y
|
||||
self.peopleView.doubleClicked.connect(self.editPerson) # Y
|
||||
self.peopleView.clicked.connect(self.selectedPerson) # Y
|
||||
self.show()
|
||||
return
|
||||
|
||||
def createActions(self) -> None:
|
||||
query = QSqlQuery()
|
||||
query.prepare("SELECT * FROM books ORDER BY title")
|
||||
if not query.exec():
|
||||
query_error(query)
|
||||
while query.next():
|
||||
action = QAction(query.value("title"), self)
|
||||
action.setData(query.value("book_id"))
|
||||
action.triggered.connect(self.setBookAction)
|
||||
self.menuBooks.addAction(action)
|
||||
@pyqtSlot(QModelIndex)
|
||||
def selectedPerson(self, index: QModelIndex) -> None:
|
||||
person_id = index.siblingAtColumn(0).data()
|
||||
self.actionEditPerson.setEnabled(True)
|
||||
book_id = index.siblingAtColumn(3).data()
|
||||
if not book_id or book_id < 0:
|
||||
self.actionRead.setEnabled(False)
|
||||
else:
|
||||
self.actionRead.setEnabled(True)
|
||||
return
|
||||
|
||||
@pyqtSlot(bool)
|
||||
def enablePerson(self, flag: bool) -> None:
|
||||
|
||||
if flag:
|
||||
self.editBtn.setEnabled(False)
|
||||
self.readBtn.setEnabled(False)
|
||||
else:
|
||||
self.editBtn.setEnabled(True)
|
||||
self.readBtn.setEnabled(True)
|
||||
return
|
||||
|
||||
@pyqtSlot()
|
||||
def setBookAction(self) -> None:
|
||||
action = cast(QAction, self.sender())
|
||||
book_id = action.data()
|
||||
indexes = self.peopleView.selectedIndexes()
|
||||
if len(indexes) < 1:
|
||||
return
|
||||
person_id = indexes[0].siblingAtColumn(0).data()
|
||||
query = QSqlQuery()
|
||||
query.prepare(
|
||||
"SELECT * FROM person_book "
|
||||
"WHERE person_id = :person_id "
|
||||
"AND book_id = :book_id"
|
||||
)
|
||||
query.bindValue(":person_id", person_id)
|
||||
query.bindValue(":book_id", book_id)
|
||||
if not query.exec():
|
||||
query_error(query)
|
||||
if not query.next():
|
||||
query.prepare(
|
||||
"SELECT * FROM sections WHERE sequence = 0 "
|
||||
"AND book_id = :book_id"
|
||||
)
|
||||
query.bindValue(":book_id", book_id)
|
||||
if not query.exec():
|
||||
query_error(query)
|
||||
if not query.next():
|
||||
raise Exception(f"book_id: {book_id} has no section 0!")
|
||||
section_id = query.value("section_id")
|
||||
query.prepare(
|
||||
"INSERT INTO person_book "
|
||||
"VALUES (:person_id, :book_id, :section_id, 0)"
|
||||
)
|
||||
query.bindValue(":person_id", person_id)
|
||||
query.bindValue(":book_id", book_id)
|
||||
query.bindValue(":section_id", section_id)
|
||||
if not query.exec():
|
||||
query_error(query)
|
||||
query.prepare(
|
||||
"UPDATE people SET book_id = :book_id "
|
||||
"WHERE person_id = :person_id"
|
||||
)
|
||||
query.bindValue(":book_id", book_id)
|
||||
query.bindValue(":person_id", person_id)
|
||||
if not query.exec():
|
||||
query_error(query)
|
||||
query.prepare(
|
||||
"SELECT p.name,b.title FROM people p "
|
||||
"LEFT JOIN books b "
|
||||
"ON (p.book_id = b.book_id) "
|
||||
"WHERE p.person_id = :person_id"
|
||||
)
|
||||
query.bindValue(":person_id", person_id)
|
||||
if not query.exec():
|
||||
query_error(query)
|
||||
query.next()
|
||||
title = query.value("title")
|
||||
name = query.value("name")
|
||||
QMessageBox.information(
|
||||
self, "Book Assignment", f"{title} was assigned to {name}"
|
||||
)
|
||||
self.resetPeopleModel()
|
||||
return
|
||||
|
||||
def resetPeopleModel(self) -> None:
|
||||
query = QSqlQuery("SELECT * FROM people ORDER BY name")
|
||||
self.peopleView.model().setQuery(query)
|
||||
return
|
||||
|
||||
@pyqtSlot()
|
||||
def bookAction(self) -> None:
|
||||
directory = QFileDialog.getExistingDirectory()
|
||||
self.book = Book(directory)
|
||||
return
|
||||
|
||||
def load_definition(self, word: str, definition: dict) -> None:
|
||||
document = None # self.textEdit.document()
|
||||
myCursor = QTextCursor(document)
|
||||
myCursor.movePosition(QTextCursor.MoveOperation.Start)
|
||||
myCursor.movePosition(
|
||||
QTextCursor.MoveOperation.End, QTextCursor.MoveMode.KeepAnchor
|
||||
)
|
||||
myCursor.removeSelectedText()
|
||||
word_format = QTextCharFormat()
|
||||
# word_format.setFontFamily("Caveat")
|
||||
word_format.setFontPointSize(48)
|
||||
word_format.setFontWeight(QFont.Weight.Bold)
|
||||
myCursor.insertText(word, word_format)
|
||||
# word_format.setFont(document.defaultFont())
|
||||
typeFormat = QTextListFormat()
|
||||
typeFormat.setStyle(QTextListFormat.Style.ListDisc)
|
||||
typeFormat.setIndent(1)
|
||||
defFormat = QTextListFormat()
|
||||
defFormat.setStyle(QTextListFormat.Style.ListCircle)
|
||||
defFormat.setIndent(2)
|
||||
myCursor.setCharFormat(word_format)
|
||||
for key in definition.keys():
|
||||
myCursor.insertList(typeFormat)
|
||||
myCursor.insertText(key)
|
||||
myCursor.insertList(defFormat)
|
||||
first = True
|
||||
for a_def in definition[key]:
|
||||
if not first:
|
||||
myCursor.insertBlock()
|
||||
myCursor.insertText(a_def)
|
||||
first = False
|
||||
def addPerson(self) -> None:
|
||||
dlg = PersonDialog()
|
||||
dlg.exec()
|
||||
return
|
||||
|
||||
@pyqtSlot()
|
||||
@pyqtSlot(QModelIndex)
|
||||
def readAction(self, index: QModelIndex | None = None) -> None:
|
||||
if index:
|
||||
person_id = index.siblingAtColumn(0).data()
|
||||
else:
|
||||
indexes = self.peopleView.selectedIndexes()
|
||||
if len(indexes) < 1:
|
||||
return
|
||||
person_id = indexes[0].siblingAtColumn(0).data()
|
||||
dlg = EditDialog(person_id)
|
||||
dlg.exec()
|
||||
def editPerson(self, index = None ) -> None:
|
||||
print("Edit a person")
|
||||
return
|
||||
|
||||
@pyqtSlot()
|
||||
def addBook(self) -> None:
|
||||
directory = QFileDialog.getExistingDirectory()
|
||||
self.book = Book(directory)
|
||||
return
|
||||
|
||||
@pyqtSlot()
|
||||
def editBook(self) -> None:
|
||||
print("Edit Book")
|
||||
return
|
||||
session = None
|
||||
setPerson = pyqtSignal(int)
|
||||
|
||||
@pyqtSlot()
|
||||
def readBook(self) -> None:
|
||||
indexes = self.peopleView.selectedIndexes()
|
||||
if len(indexes) < 1:
|
||||
return
|
||||
person_id = indexes[0].siblingAtColumn(0).data()
|
||||
if not self.session:
|
||||
self.session = SessionDialog()
|
||||
self.setPerson.connect(self.session.setPerson)
|
||||
self.session.show()
|
||||
self.session.raise_()
|
||||
self.setPerson.emit(person_id)
|
||||
self.dlg = EditDialog(self.session, person_id)
|
||||
self.dlg.show()
|
||||
self.dlg.raise_()
|
||||
return
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user