Make the interface better

This commit is contained in:
Christopher T. Johnson
2023-12-08 11:25:06 -05:00
parent 6135c5d278
commit 6752249680
8 changed files with 330 additions and 182 deletions

View File

@@ -12,6 +12,7 @@ from PyQt6.QtCore import (
QResource,
Qt,
QTimer,
pyqtSignal,
pyqtSlot,
)
from PyQt6.QtGui import (
@@ -39,8 +40,10 @@ from ui.EditDialog import Ui_Dialog
class EditDialog(QDialog, Ui_Dialog):
block: int
paragraphs = True
displayedWord = pyqtSignal(int)
def __init__(self, person_id: int) -> None:
def __init__(self, session, person_id: int) -> None:
self.session = session
super(EditDialog, self).__init__()
self.person_id = person_id
if not QResource.registerResource(
@@ -65,12 +68,20 @@ class EditDialog(QDialog, Ui_Dialog):
self.block = blockNumber
self.savePosition()
self.stackedWidget.setCurrentIndex(0)
#
# Connect widgets
#
self.defineBtn.clicked.connect(self.defineAction)
self.printBtn.clicked.connect(self.printAction)
self.scrollBtn.clicked.connect(self.scrollAction)
self.nextBtn.clicked.connect(self.nextAction)
self.prevBtn.clicked.connect(self.prevAction)
self.sessionBtn.clicked.connect(self.session.timerAction)
self.paraEdit.verticalScrollBar().valueChanged.connect(self.scrollSlot)
#
# Connect signals
#
self.displayedWord.connect(self.session.addWord)
return
#
@@ -148,7 +159,6 @@ class EditDialog(QDialog, Ui_Dialog):
if msPerTick < 3:
msPerTick = 3
self.target = value + delta
print(f"delta: {delta}, pixels: {self.pxPerTick}, ms: {msPerTick}")
timer = QTimer(self)
timer.timeout.connect(self.softTick)
timer.start(msPerTick)
@@ -200,7 +210,6 @@ class EditDialog(QDialog, Ui_Dialog):
@pyqtSlot()
def defineAction(self) -> None:
print("defineAction")
if self.paragraphs:
self.showDefinition()
else:
@@ -512,6 +521,7 @@ class EditDialog(QDialog, Ui_Dialog):
cursor.insertHtml(self.defToHtml(word, definition))
cursor.setPosition(0)
self.defEdit.setTextCursor(cursor)
self.displayedWord.emit(query.value("word_id"))
return
def showDefinition(self) -> None:

255
main.py
View File

@@ -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

View File

@@ -62,6 +62,14 @@ class Ui_Dialog(object):
self.prevBtn = QtWidgets.QPushButton(parent=self.widget)
self.prevBtn.setObjectName("prevBtn")
self.verticalLayout.addWidget(self.prevBtn)
self.line = QtWidgets.QFrame(parent=self.widget)
self.line.setFrameShape(QtWidgets.QFrame.Shape.HLine)
self.line.setFrameShadow(QtWidgets.QFrame.Shadow.Sunken)
self.line.setObjectName("line")
self.verticalLayout.addWidget(self.line)
self.sessionBtn = QtWidgets.QPushButton(parent=self.widget)
self.sessionBtn.setObjectName("sessionBtn")
self.verticalLayout.addWidget(self.sessionBtn)
self.horizontalLayout.addWidget(self.widget)
self.retranslateUi(Dialog)
@@ -76,3 +84,4 @@ class Ui_Dialog(object):
self.scrollBtn.setText(_translate("Dialog", "Scroll"))
self.nextBtn.setText(_translate("Dialog", "Next Para"))
self.prevBtn.setText(_translate("Dialog", "Prev Para"))
self.sessionBtn.setText(_translate("Dialog", "Start"))

View File

@@ -99,6 +99,20 @@
</property>
</widget>
</item>
<item>
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="sessionBtn">
<property name="text">
<string>Start</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>

View File

@@ -24,18 +24,25 @@ class Ui_MainWindow(object):
self.widget.setObjectName("widget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.widget)
self.verticalLayout.setObjectName("verticalLayout")
self.WordButton = QtWidgets.QPushButton(parent=self.widget)
self.WordButton.setEnabled(False)
self.WordButton.setObjectName("WordButton")
self.verticalLayout.addWidget(self.WordButton)
self.toggleBtn = QtWidgets.QPushButton(parent=self.widget)
self.toggleBtn.setObjectName("toggleBtn")
self.verticalLayout.addWidget(self.toggleBtn)
self.readBtn = QtWidgets.QPushButton(parent=self.widget)
self.readBtn.setObjectName("readBtn")
self.verticalLayout.addWidget(self.readBtn)
self.editBtn = QtWidgets.QPushButton(parent=self.widget)
self.editBtn.setObjectName("editBtn")
self.verticalLayout.addWidget(self.editBtn)
self.line = QtWidgets.QFrame(parent=self.widget)
self.line.setFrameShape(QtWidgets.QFrame.Shape.HLine)
self.line.setFrameShadow(QtWidgets.QFrame.Shadow.Sunken)
self.line.setObjectName("line")
self.verticalLayout.addWidget(self.line)
spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Expanding)
self.verticalLayout.addItem(spacerItem)
self.bookBtn = QtWidgets.QPushButton(parent=self.widget)
self.bookBtn.setObjectName("bookBtn")
self.verticalLayout.addWidget(self.bookBtn)
self.addBtn = QtWidgets.QPushButton(parent=self.widget)
self.addBtn.setObjectName("addBtn")
self.verticalLayout.addWidget(self.addBtn)
self.horizontalLayout.addWidget(self.widget)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(parent=MainWindow)
@@ -45,25 +52,62 @@ class Ui_MainWindow(object):
self.menuFile.setObjectName("menuFile")
self.menuBooks = QtWidgets.QMenu(parent=self.menubar)
self.menuBooks.setObjectName("menuBooks")
self.menuBooks_2 = QtWidgets.QMenu(parent=self.menuBooks)
self.menuBooks_2.setObjectName("menuBooks_2")
self.menuPeople = QtWidgets.QMenu(parent=self.menuBooks)
self.menuPeople.setObjectName("menuPeople")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(parent=MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.actionQuit = QtGui.QAction(parent=MainWindow)
self.actionQuit.setObjectName("actionQuit")
self.actionAddBook = QtGui.QAction(parent=MainWindow)
self.actionAddBook.setObjectName("actionAddBook")
self.actionEditBook = QtGui.QAction(parent=MainWindow)
self.actionEditBook.setObjectName("actionEditBook")
self.actionAddPerson = QtGui.QAction(parent=MainWindow)
self.actionAddPerson.setObjectName("actionAddPerson")
self.actionEditPerson = QtGui.QAction(parent=MainWindow)
self.actionEditPerson.setObjectName("actionEditPerson")
self.actionRead = QtGui.QAction(parent=MainWindow)
self.actionRead.setObjectName("actionRead")
self.menuFile.addAction(self.actionQuit)
self.menuBooks_2.addAction(self.actionAddBook)
self.menuBooks_2.addAction(self.actionEditBook)
self.menuPeople.addAction(self.actionAddPerson)
self.menuPeople.addAction(self.actionEditPerson)
self.menuBooks.addAction(self.menuBooks_2.menuAction())
self.menuBooks.addAction(self.menuPeople.menuAction())
self.menubar.addAction(self.menuFile.menuAction())
self.menubar.addAction(self.menuBooks.menuAction())
self.retranslateUi(MainWindow)
self.editBtn.clicked.connect(self.actionEditPerson.trigger) # type: ignore
self.addBtn.clicked.connect(self.actionAddPerson.trigger) # type: ignore
self.bookBtn.clicked.connect(self.actionAddBook.trigger) # type: ignore
self.readBtn.clicked.connect(self.actionRead.trigger) # type: ignore
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "Reading Helper"))
self.WordButton.setText(_translate("MainWindow", "Words"))
self.toggleBtn.setText(_translate("MainWindow", "Enable"))
self.readBtn.setText(_translate("MainWindow", "Read"))
self.editBtn.setText(_translate("MainWindow", "Edit"))
self.bookBtn.setText(_translate("MainWindow", "Add Book"))
self.addBtn.setText(_translate("MainWindow", "Add Person"))
self.menuFile.setTitle(_translate("MainWindow", "File"))
self.menuBooks.setTitle(_translate("MainWindow", "Books"))
self.menuBooks.setTitle(_translate("MainWindow", "Edit"))
self.menuBooks_2.setTitle(_translate("MainWindow", "Books"))
self.menuPeople.setTitle(_translate("MainWindow", "People"))
self.actionQuit.setText(_translate("MainWindow", "Quit"))
self.actionAddBook.setText(_translate("MainWindow", "Add"))
self.actionAddBook.setToolTip(_translate("MainWindow", "Add Book"))
self.actionEditBook.setText(_translate("MainWindow", "Edit"))
self.actionEditBook.setToolTip(_translate("MainWindow", "Edit Book"))
self.actionAddPerson.setText(_translate("MainWindow", "Add"))
self.actionAddPerson.setToolTip(_translate("MainWindow", "Add A Person"))
self.actionEditPerson.setText(_translate("MainWindow", "Edit"))
self.actionEditPerson.setToolTip(_translate("MainWindow", "Edit A Person"))
self.actionRead.setText(_translate("MainWindow", "Read"))
self.actionRead.setToolTip(_translate("MainWindow", "Read Book"))

View File

@@ -22,19 +22,23 @@
<widget class="QWidget" name="widget" native="true">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QPushButton" name="WordButton">
<property name="enabled">
<bool>false</bool>
</property>
<widget class="QPushButton" name="readBtn">
<property name="text">
<string>Words</string>
<string>Read</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="toggleBtn">
<widget class="QPushButton" name="editBtn">
<property name="text">
<string>Enable</string>
<string>Edit</string>
</property>
</widget>
</item>
<item>
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
@@ -58,6 +62,13 @@
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="addBtn">
<property name="text">
<string>Add Person</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
@@ -80,8 +91,24 @@
</widget>
<widget class="QMenu" name="menuBooks">
<property name="title">
<string>Books</string>
<string>Edit</string>
</property>
<widget class="QMenu" name="menuBooks_2">
<property name="title">
<string>Books</string>
</property>
<addaction name="actionAddBook"/>
<addaction name="actionEditBook"/>
</widget>
<widget class="QMenu" name="menuPeople">
<property name="title">
<string>People</string>
</property>
<addaction name="actionAddPerson"/>
<addaction name="actionEditPerson"/>
</widget>
<addaction name="menuBooks_2"/>
<addaction name="menuPeople"/>
</widget>
<addaction name="menuFile"/>
<addaction name="menuBooks"/>
@@ -92,7 +119,112 @@
<string>Quit</string>
</property>
</action>
<action name="actionAddBook">
<property name="text">
<string>Add</string>
</property>
<property name="toolTip">
<string>Add Book</string>
</property>
</action>
<action name="actionEditBook">
<property name="text">
<string>Edit</string>
</property>
<property name="toolTip">
<string>Edit Book</string>
</property>
</action>
<action name="actionAddPerson">
<property name="text">
<string>Add</string>
</property>
<property name="toolTip">
<string>Add A Person</string>
</property>
</action>
<action name="actionEditPerson">
<property name="text">
<string>Edit</string>
</property>
<property name="toolTip">
<string>Edit A Person</string>
</property>
</action>
<action name="actionRead">
<property name="text">
<string>Read</string>
</property>
<property name="toolTip">
<string>Read Book</string>
</property>
</action>
</widget>
<resources/>
<connections/>
<connections>
<connection>
<sender>editBtn</sender>
<signal>clicked()</signal>
<receiver>actionEditPerson</receiver>
<slot>trigger()</slot>
<hints>
<hint type="sourcelabel">
<x>722</x>
<y>117</y>
</hint>
<hint type="destinationlabel">
<x>-1</x>
<y>-1</y>
</hint>
</hints>
</connection>
<connection>
<sender>addBtn</sender>
<signal>clicked()</signal>
<receiver>actionAddPerson</receiver>
<slot>trigger()</slot>
<hints>
<hint type="sourcelabel">
<x>722</x>
<y>532</y>
</hint>
<hint type="destinationlabel">
<x>-1</x>
<y>-1</y>
</hint>
</hints>
</connection>
<connection>
<sender>bookBtn</sender>
<signal>clicked()</signal>
<receiver>actionAddBook</receiver>
<slot>trigger()</slot>
<hints>
<hint type="sourcelabel">
<x>722</x>
<y>491</y>
</hint>
<hint type="destinationlabel">
<x>-1</x>
<y>-1</y>
</hint>
</hints>
</connection>
<connection>
<sender>readBtn</sender>
<signal>clicked()</signal>
<receiver>actionRead</receiver>
<slot>trigger()</slot>
<hints>
<hint type="sourcelabel">
<x>722</x>
<y>67</y>
</hint>
<hint type="destinationlabel">
<x>-1</x>
<y>-1</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -18,6 +18,6 @@ p, li {
font-size: 24px;
}
p.phonetic {
font-family: "Tex Gyre Heros", sans-serif;
font-size: 32px;
font-family: "Gentium", sans-serif;
font-size: 40px;
}

Binary file not shown.