Allow for printing session results.
This commit is contained in:
207
lib/person.py
207
lib/person.py
@@ -1,7 +1,14 @@
|
||||
import json
|
||||
import os
|
||||
import secrets
|
||||
import smtplib
|
||||
from datetime import datetime, timedelta
|
||||
from email import policy
|
||||
from email.message import EmailMessage
|
||||
from html.parser import HTMLParser
|
||||
from io import StringIO
|
||||
|
||||
from PyQt6.QtCore import QSize, Qt, pyqtSlot
|
||||
from PyQt6.QtCore import QResource, QSize, Qt, pyqtSlot
|
||||
from PyQt6.QtGui import QStandardItem, QStandardItemModel
|
||||
from PyQt6.QtSql import QSqlQuery, QSqlQueryModel
|
||||
from PyQt6.QtWidgets import QDialog, QDialogButtonBox, QStyledItemDelegate
|
||||
@@ -10,6 +17,66 @@ from main import query_error
|
||||
from ui.PeopleDialog import Ui_Dialog
|
||||
|
||||
|
||||
class blockHandler(HTMLParser):
|
||||
text = ""
|
||||
blocks = []
|
||||
active = 0
|
||||
tags = [
|
||||
"h1",
|
||||
"h2",
|
||||
"h3",
|
||||
"h4",
|
||||
"h5",
|
||||
"h6",
|
||||
"p",
|
||||
"b",
|
||||
"i",
|
||||
"em",
|
||||
"st",
|
||||
"span",
|
||||
]
|
||||
space = ["b", "i", "em", "st", "span"]
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.reset()
|
||||
self.strict = False
|
||||
self.convert_charrefs = True
|
||||
self.text = ""
|
||||
self.blocks = []
|
||||
self.active = 0
|
||||
return
|
||||
|
||||
def handle_starttag(self, tag, attrs):
|
||||
if not tag in self.tags:
|
||||
return
|
||||
self.active += 1
|
||||
if tag in self.space:
|
||||
self.text += " "
|
||||
self.text += f"<{tag}>"
|
||||
return
|
||||
|
||||
def handle_endtag(self, tag):
|
||||
if not tag in self.tags:
|
||||
return
|
||||
self.active -= 1
|
||||
self.text += f"</{tag}>"
|
||||
if tag in self.space:
|
||||
self.text += " "
|
||||
if self.active <= 0:
|
||||
self.blocks.append(self.text)
|
||||
self.text = ""
|
||||
self.active = 0
|
||||
return
|
||||
|
||||
def handle_data(self, data):
|
||||
self.text += data
|
||||
return
|
||||
|
||||
def get_block(self, block):
|
||||
return self.blocks[block]
|
||||
|
||||
|
||||
class MLStripper(HTMLParser):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
@@ -45,6 +112,9 @@ class PersonDialog(QDialog, Ui_Dialog):
|
||||
super(PersonDialog, self).__init__(*args, **kwargs)
|
||||
self.setupUi(self)
|
||||
self.show()
|
||||
QResource.registerResource(
|
||||
os.path.join(os.path.dirname(__file__), "../ui/resources.rcc"), "/"
|
||||
)
|
||||
model = QSqlQueryModel()
|
||||
query = QSqlQuery()
|
||||
query.prepare("SELECT book_id, title " "FROM books " "ORDER BY title")
|
||||
@@ -60,7 +130,8 @@ class PersonDialog(QDialog, Ui_Dialog):
|
||||
self.sectionCombo.setModel(model)
|
||||
self.sectionCombo.setEnabled(False)
|
||||
self.sectionCombo.setCurrentIndex(-1)
|
||||
|
||||
self.printBtn.setEnabled(False)
|
||||
self.emailBtn.setEnabled(False)
|
||||
button = self.buttonBox.button(QDialogButtonBox.StandardButton.Ok)
|
||||
button.setEnabled(False)
|
||||
|
||||
@@ -71,6 +142,8 @@ class PersonDialog(QDialog, Ui_Dialog):
|
||||
self.sectionCombo.currentIndexChanged.connect(self.sectionSelected)
|
||||
self.nameEdit.editingFinished.connect(self.checkLineEdits)
|
||||
self.orgEdit.editingFinished.connect(self.checkLineEdits)
|
||||
self.printBtn.clicked.connect(self.senditAction)
|
||||
self.emailBtn.clicked.connect(self.senditAction)
|
||||
if self.person_id > 0:
|
||||
self.setPerson(self.person_id)
|
||||
return
|
||||
@@ -78,7 +151,7 @@ class PersonDialog(QDialog, Ui_Dialog):
|
||||
def setPerson(self, person_id: int) -> None:
|
||||
query = QSqlQuery()
|
||||
query.prepare(
|
||||
"SELECT p.name, p.organization, p.book_id, s.sequence "
|
||||
"SELECT p.name, p.organization, p.book_id, p.email, s.sequence "
|
||||
"FROM people p "
|
||||
"LEFT JOIN person_book pb "
|
||||
"ON (p.book_id = pb.book_id "
|
||||
@@ -95,6 +168,7 @@ class PersonDialog(QDialog, Ui_Dialog):
|
||||
self.person_id = person_id
|
||||
self.nameEdit.setText(query.value("name"))
|
||||
self.orgEdit.setText(query.value("organization"))
|
||||
self.emailEdit.setText(query.value("email"))
|
||||
model = self.bookCombo.model()
|
||||
matches = model.match(
|
||||
model.createIndex(0, 0),
|
||||
@@ -104,12 +178,58 @@ class PersonDialog(QDialog, Ui_Dialog):
|
||||
Qt.MatchFlag.MatchExactly,
|
||||
)
|
||||
if len(matches) != 1:
|
||||
raise Excpetion(
|
||||
raise Exception(
|
||||
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"))
|
||||
query.prepare(
|
||||
"SELECT * FROM sessions "
|
||||
"WHERE person_id = :person_id "
|
||||
"ORDER BY start DESC"
|
||||
)
|
||||
query.bindValue(":person_id", person_id)
|
||||
if not query.exec():
|
||||
query_error(query)
|
||||
model = QSqlQueryModel()
|
||||
model.setQuery(query)
|
||||
self.sessionCombo.setModel(model)
|
||||
self.sessionCombo.setModelColumn(2)
|
||||
self.printBtn.setEnabled(True)
|
||||
self.emailBtn.setEnabled(True)
|
||||
return
|
||||
|
||||
@pyqtSlot()
|
||||
def senditAction(self) -> None:
|
||||
html = "<!DOCTYPE html>\n<html><head><title>Hello</title>\n"
|
||||
html += (
|
||||
'<style type="text/css">\n'
|
||||
+ QResource(":email.css").data().decode("utf-8")
|
||||
+ "</style>\n"
|
||||
)
|
||||
html += "</head><body>\n"
|
||||
html += self.makeDefinitions()
|
||||
html += self.makeText()
|
||||
html += "</body>\n</html>\n"
|
||||
|
||||
if self.sender() == self.printBtn:
|
||||
print(html)
|
||||
return
|
||||
msg = EmailMessage(policy=policy.default)
|
||||
start = datetime.fromisoformat(self.sessionCombo.currentText())
|
||||
msg["Subject"] = f"TT English, Session: {start.date().isoformat()}"
|
||||
msg["From"] = "Christopher T. Johnson <cjohnson@troglodite.com>"
|
||||
msg["To"] = self.emailEdit.text().strip()
|
||||
msg.set_content("There is a html message you should read")
|
||||
msg.add_alternative(html, subtype="html")
|
||||
server = smtplib.SMTP(secrets.SMTP_HOST, secrets.SMTP_PORT)
|
||||
server.set_debuglevel(1)
|
||||
if secrets.SMTP_STARTTLS:
|
||||
server.starttls()
|
||||
server.login(secrets.SMTP_USER, secrets.SMTP_PASSWORD)
|
||||
server.send_message(msg)
|
||||
server.quit()
|
||||
return
|
||||
|
||||
@pyqtSlot(int)
|
||||
@@ -222,3 +342,82 @@ class PersonDialog(QDialog, Ui_Dialog):
|
||||
else:
|
||||
button.setEnabled(False)
|
||||
return
|
||||
|
||||
def makeDefinitions(self) -> str:
|
||||
query = QSqlQuery()
|
||||
query.prepare(
|
||||
"SELECT w.word, w.definition FROM sessions s "
|
||||
"LEFT JOIN session_word sw "
|
||||
"ON (s.session_id = s.session_id) "
|
||||
"LEFT JOIN words w "
|
||||
"ON (sw.word_id = w.word_id) "
|
||||
"WHERE s.session_id = :session_id "
|
||||
"ORDER BY w.word"
|
||||
)
|
||||
|
||||
row = self.sessionCombo.currentIndex()
|
||||
model = self.sessionCombo.model()
|
||||
index = model.index(row, 0)
|
||||
session_id = index.data()
|
||||
query.bindValue(":session_id", session_id)
|
||||
if not query.exec():
|
||||
query_error(query)
|
||||
html = '<div class="words">\n<dl>\n'
|
||||
while query.next():
|
||||
html += "<dt>" + query.value("word") + "</dt>\n<dd>\n"
|
||||
data = json.loads(query.value("definition"))
|
||||
if "phonetics" in data:
|
||||
for p in data["phonetics"]:
|
||||
if "text" in p:
|
||||
html += '<p class="phonetic">' + p["text"] + "</p>\n"
|
||||
html += '<dl class="meanings">\n'
|
||||
for meaning in data["meanings"]:
|
||||
html += "<dt>" + meaning["partOfSpeech"] + "</dt>\n<dd><ul>\n"
|
||||
for definition in meaning["definitions"]:
|
||||
html += "<li>" + definition["definition"] + "</li>\n"
|
||||
html += "</ul>\n"
|
||||
html += "</dl>\n</dd>\n"
|
||||
html += "</dl>\n</div>\n"
|
||||
return html
|
||||
|
||||
def makeText(self) -> str:
|
||||
query = QSqlQuery()
|
||||
section_query = QSqlQuery()
|
||||
html = '<div class="text">'
|
||||
|
||||
session_id = (
|
||||
self.sessionCombo.model()
|
||||
.index(self.sessionCombo.currentIndex(), 0)
|
||||
.data()
|
||||
)
|
||||
query.prepare(
|
||||
"SELECT * FROM session_block sb "
|
||||
"WHERE sb.session_id = :session_id "
|
||||
"ORDER BY sb.section_id, sb.block"
|
||||
)
|
||||
query.bindValue(":session_id", session_id)
|
||||
if not query.exec():
|
||||
query_error(query)
|
||||
|
||||
section_query.prepare(
|
||||
"SELECT * FROM sections " "WHERE section_id = :section_id"
|
||||
)
|
||||
section_id = 0
|
||||
while query.next():
|
||||
if section_id != query.value("section_id"):
|
||||
section_id = query.value("section_id")
|
||||
section_query.bindValue(":section_id", section_id)
|
||||
if not section_query.exec():
|
||||
query_error(section_query)
|
||||
if not section_query.next():
|
||||
raise Exception(f"Missing section {section_id}")
|
||||
section = blockHandler()
|
||||
section.feed(section_query.value("content"))
|
||||
html += section.get_block(query.value("block")) + "\n"
|
||||
html += "</div>\n"
|
||||
return html
|
||||
|
||||
def makeStats(self) -> str:
|
||||
html = '<div class="stats">'
|
||||
html += "</div>\n"
|
||||
return html
|
||||
|
||||
1
main.py
1
main.py
@@ -198,6 +198,7 @@ SQL_CMDS = [
|
||||
"person_id INTEGER REFERENCES people ON DELETE CASCADE, "
|
||||
"start TEXT DEFAULT '', "
|
||||
"stop TEXT DEFAULT '', "
|
||||
"total TEXT DEFAULT '', "
|
||||
"notes TEXT DEFAULT '')",
|
||||
#
|
||||
"CREATE TABLE IF NOT EXISTS session_word "
|
||||
|
||||
@@ -12,7 +12,12 @@ from PyQt6 import QtCore, QtGui, QtWidgets
|
||||
class Ui_Dialog(object):
|
||||
def setupUi(self, Dialog):
|
||||
Dialog.setObjectName("Dialog")
|
||||
Dialog.resize(542, 219)
|
||||
Dialog.resize(542, 300)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Preferred, QtWidgets.QSizePolicy.Policy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(Dialog.sizePolicy().hasHeightForWidth())
|
||||
Dialog.setSizePolicy(sizePolicy)
|
||||
self.formLayout = QtWidgets.QFormLayout(Dialog)
|
||||
self.formLayout.setObjectName("formLayout")
|
||||
self.label = QtWidgets.QLabel(parent=Dialog)
|
||||
@@ -21,6 +26,12 @@ class Ui_Dialog(object):
|
||||
self.nameEdit = QtWidgets.QLineEdit(parent=Dialog)
|
||||
self.nameEdit.setObjectName("nameEdit")
|
||||
self.formLayout.setWidget(0, QtWidgets.QFormLayout.ItemRole.FieldRole, self.nameEdit)
|
||||
self.label_5 = QtWidgets.QLabel(parent=Dialog)
|
||||
self.label_5.setObjectName("label_5")
|
||||
self.formLayout.setWidget(1, QtWidgets.QFormLayout.ItemRole.LabelRole, self.label_5)
|
||||
self.emailEdit = QtWidgets.QLineEdit(parent=Dialog)
|
||||
self.emailEdit.setObjectName("emailEdit")
|
||||
self.formLayout.setWidget(1, QtWidgets.QFormLayout.ItemRole.FieldRole, self.emailEdit)
|
||||
self.label_2 = QtWidgets.QLabel(parent=Dialog)
|
||||
self.label_2.setObjectName("label_2")
|
||||
self.formLayout.setWidget(2, QtWidgets.QFormLayout.ItemRole.LabelRole, self.label_2)
|
||||
@@ -39,17 +50,45 @@ class Ui_Dialog(object):
|
||||
self.sectionCombo = QtWidgets.QComboBox(parent=Dialog)
|
||||
self.sectionCombo.setObjectName("sectionCombo")
|
||||
self.formLayout.setWidget(4, QtWidgets.QFormLayout.ItemRole.FieldRole, self.sectionCombo)
|
||||
self.widget = QtWidgets.QWidget(parent=Dialog)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Preferred, QtWidgets.QSizePolicy.Policy.Expanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.widget.sizePolicy().hasHeightForWidth())
|
||||
self.widget.setSizePolicy(sizePolicy)
|
||||
self.widget.setObjectName("widget")
|
||||
self.horizontalLayout = QtWidgets.QHBoxLayout(self.widget)
|
||||
self.horizontalLayout.setObjectName("horizontalLayout")
|
||||
self.printBtn = QtWidgets.QPushButton(parent=self.widget)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Expanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.printBtn.sizePolicy().hasHeightForWidth())
|
||||
self.printBtn.setSizePolicy(sizePolicy)
|
||||
self.printBtn.setObjectName("printBtn")
|
||||
self.horizontalLayout.addWidget(self.printBtn)
|
||||
self.emailBtn = QtWidgets.QPushButton(parent=self.widget)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Expanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.emailBtn.sizePolicy().hasHeightForWidth())
|
||||
self.emailBtn.setSizePolicy(sizePolicy)
|
||||
self.emailBtn.setObjectName("emailBtn")
|
||||
self.horizontalLayout.addWidget(self.emailBtn)
|
||||
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
|
||||
self.horizontalLayout.addItem(spacerItem)
|
||||
self.formLayout.setWidget(7, QtWidgets.QFormLayout.ItemRole.FieldRole, self.widget)
|
||||
self.buttonBox = QtWidgets.QDialogButtonBox(parent=Dialog)
|
||||
self.buttonBox.setOrientation(QtCore.Qt.Orientation.Horizontal)
|
||||
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.StandardButton.Cancel|QtWidgets.QDialogButtonBox.StandardButton.Ok)
|
||||
self.buttonBox.setObjectName("buttonBox")
|
||||
self.formLayout.setWidget(5, QtWidgets.QFormLayout.ItemRole.SpanningRole, self.buttonBox)
|
||||
self.label_5 = QtWidgets.QLabel(parent=Dialog)
|
||||
self.label_5.setObjectName("label_5")
|
||||
self.formLayout.setWidget(1, QtWidgets.QFormLayout.ItemRole.LabelRole, self.label_5)
|
||||
self.emailEdit = QtWidgets.QLineEdit(parent=Dialog)
|
||||
self.emailEdit.setObjectName("emailEdit")
|
||||
self.formLayout.setWidget(1, QtWidgets.QFormLayout.ItemRole.FieldRole, self.emailEdit)
|
||||
self.formLayout.setWidget(8, QtWidgets.QFormLayout.ItemRole.SpanningRole, self.buttonBox)
|
||||
self.label_6 = QtWidgets.QLabel(parent=Dialog)
|
||||
self.label_6.setObjectName("label_6")
|
||||
self.formLayout.setWidget(6, QtWidgets.QFormLayout.ItemRole.LabelRole, self.label_6)
|
||||
self.sessionCombo = QtWidgets.QComboBox(parent=Dialog)
|
||||
self.sessionCombo.setObjectName("sessionCombo")
|
||||
self.formLayout.setWidget(6, QtWidgets.QFormLayout.ItemRole.FieldRole, self.sessionCombo)
|
||||
|
||||
self.retranslateUi(Dialog)
|
||||
self.buttonBox.accepted.connect(Dialog.accept) # type: ignore
|
||||
@@ -64,7 +103,10 @@ class Ui_Dialog(object):
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
Dialog.setWindowTitle(_translate("Dialog", "People"))
|
||||
self.label.setText(_translate("Dialog", "Name"))
|
||||
self.label_5.setText(_translate("Dialog", "Email"))
|
||||
self.label_2.setText(_translate("Dialog", "Organization"))
|
||||
self.label_3.setText(_translate("Dialog", "Book"))
|
||||
self.label_4.setText(_translate("Dialog", "Section"))
|
||||
self.label_5.setText(_translate("Dialog", "Email"))
|
||||
self.printBtn.setText(_translate("Dialog", "Print"))
|
||||
self.emailBtn.setText(_translate("Dialog", "EMail"))
|
||||
self.label_6.setText(_translate("Dialog", "Session"))
|
||||
|
||||
@@ -7,9 +7,15 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>542</width>
|
||||
<height>219</height>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>People</string>
|
||||
</property>
|
||||
@@ -24,6 +30,16 @@
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="nameEdit"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Email</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="emailEdit"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
@@ -54,7 +70,58 @@
|
||||
<item row="4" column="1">
|
||||
<widget class="QComboBox" name="sectionCombo"/>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="2">
|
||||
<item row="7" column="1">
|
||||
<widget class="QWidget" name="widget" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="printBtn">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Print</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="emailBtn">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>EMail</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0" colspan="2">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
@@ -64,15 +131,15 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Email</string>
|
||||
<string>Session</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="emailEdit"/>
|
||||
<item row="6" column="1">
|
||||
<widget class="QComboBox" name="sessionCombo"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
|
||||
31
ui/email.css
Normal file
31
ui/email.css
Normal file
@@ -0,0 +1,31 @@
|
||||
@import url('https://fonts.cdnfonts.com/css/gentium-plus');
|
||||
@import url('https://fonts.cdnfonts.com/css/opendyslexic');
|
||||
body {
|
||||
font-family: "OpenDyslexic3", sans-serif;
|
||||
font-size: 20px;
|
||||
}
|
||||
div.words dt {
|
||||
font-family: "opendyslexic", sans-serif;
|
||||
font-size: 48px;
|
||||
font-weight: Bold;
|
||||
}
|
||||
dl.meanings dt {
|
||||
font-family: "opendyslexic", sans-serif;
|
||||
font-size: 24px;
|
||||
font-weight: Bold;
|
||||
}
|
||||
dl.meanings li {
|
||||
font-family: "opendyslexic", sans-serif;
|
||||
max-width: 66ch;
|
||||
}
|
||||
p.phonetic {
|
||||
font-family: "Gentium Plus", sans-serif;
|
||||
font-size: 40px;
|
||||
margin-top: 0px;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
div.text {
|
||||
font-size: 20px;
|
||||
font-family: "opendyslexic", sans-serif;
|
||||
max-width: 66ch;
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
<qresource prefix="/">
|
||||
<file>print.css</file>
|
||||
<file>display.css</file>
|
||||
<file>email.css</file>
|
||||
<file>opendyslexic/OpenDyslexic-Regular.otf</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
BIN
ui/resources.rcc
BIN
ui/resources.rcc
Binary file not shown.
Reference in New Issue
Block a user