UI: refactor mail template dialog for plaintext handling, improve logging, and update UI elements
This commit is contained in:
@@ -1,23 +1,18 @@
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
from PySide6 import QtGui, QtWidgets, QtCore
|
||||
from loguru import logger as log
|
||||
from PySide6 import QtCore, QtWidgets
|
||||
|
||||
from src import Icon
|
||||
|
||||
from .dialog_sources import NewMailTemplateDesignerDialog
|
||||
|
||||
import sys
|
||||
from loguru import logger as log
|
||||
|
||||
logger = log
|
||||
logger.remove()
|
||||
logger.add("logs/application.log", rotation="1 week", retention="1 month", enqueue=True)
|
||||
log.add(
|
||||
f"logs/mail.log",
|
||||
enqueue=True,
|
||||
)
|
||||
|
||||
# logger.add(sys.stderr, format="{time} {level} {message}", level="INFO")
|
||||
log.add("logs/mail.log", enqueue=True)
|
||||
logger.add(sys.stdout)
|
||||
|
||||
|
||||
@@ -28,35 +23,34 @@ class MailTemplateDialog(QtWidgets.QDialog, NewMailTemplateDesignerDialog):
|
||||
super().__init__(parent)
|
||||
self.setupUi(self)
|
||||
self.setWindowIcon(Icon("edit_note").icon)
|
||||
self.setWindowTitle("Mailvorlage erstellen")
|
||||
self.setWindowTitle("Mailvorlage erstellen (Text)")
|
||||
|
||||
# placeholders UI
|
||||
self.placeholder_list.addItem("")
|
||||
self.placeholder_list.setCurrentText("")
|
||||
self.insertPlaceholder.clicked.connect(self.insert_placeholder)
|
||||
self.placeholder_list.currentTextChanged.connect(self.updateDescription)
|
||||
self.bold.clicked.connect(self.setFontBold)
|
||||
self.italic.clicked.connect(self.setTextFontItalic)
|
||||
self.underlined.clicked.connect(self.setTextFontUnderline)
|
||||
self.testTemplate.clicked.connect(self.test_template)
|
||||
self.fontBox.currentFontChanged.connect(self.setCurrentFont)
|
||||
self.fontSize.currentTextChanged.connect(self.setFontSize)
|
||||
# buttonbox
|
||||
# save button
|
||||
|
||||
# formatting buttons (kept enabled for UX, but saving uses plain text)
|
||||
|
||||
# buttons
|
||||
self.buttonBox.button(
|
||||
QtWidgets.QDialogButtonBox.StandardButton.Save
|
||||
).clicked.connect(self.save_template)
|
||||
# discard button
|
||||
self.buttonBox.button(
|
||||
QtWidgets.QDialogButtonBox.StandardButton.Discard
|
||||
).clicked.connect(self.discard_changes)
|
||||
# cancel button
|
||||
self.buttonBox.button(
|
||||
QtWidgets.QDialogButtonBox.StandardButton.Cancel
|
||||
).clicked.connect(self.closeNow)
|
||||
log.info("Mail template dialog setup complete")
|
||||
log.info("Mail template dialog (plaintext) setup complete")
|
||||
|
||||
def _normalize_newlines(self, s: str) -> str:
|
||||
# Convert any CRLF/CR to LF then back to CRLF for .eml
|
||||
s = s.replace("\\r\\n", "\\n").replace("\\r", "\\n")
|
||||
return s
|
||||
|
||||
def save_template(self):
|
||||
# print("save triggered")
|
||||
# create a dialog to ask for the name of the template
|
||||
dialog = QtWidgets.QInputDialog()
|
||||
dialog.setInputMode(QtWidgets.QInputDialog.InputMode.TextInput)
|
||||
dialog.setLabelText("Bitte geben Sie den Namen des Templates ein:")
|
||||
@@ -66,12 +60,11 @@ class MailTemplateDialog(QtWidgets.QDialog, NewMailTemplateDesignerDialog):
|
||||
dialog.setWindowIcon(Icon("save").icon)
|
||||
save = dialog.exec()
|
||||
template_name = dialog.textValue()
|
||||
log.info("Saving template")
|
||||
log.info("Saving plaintext template")
|
||||
if template_name != "" and save == 1:
|
||||
template = template_name + ".eml"
|
||||
if template in os.listdir("mail_vorlagen"):
|
||||
log.error("Template already exists")
|
||||
# warning dialog
|
||||
dialog = QtWidgets.QMessageBox()
|
||||
dialog.setIcon(QtWidgets.QMessageBox.Icon.Warning)
|
||||
Icon("warning", dialog)
|
||||
@@ -87,36 +80,34 @@ class MailTemplateDialog(QtWidgets.QDialog, NewMailTemplateDesignerDialog):
|
||||
ret = dialog.exec()
|
||||
if ret == QtWidgets.QMessageBox.StandardButton.No:
|
||||
return
|
||||
mail = f"""Subject: {self.subject.text()}
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/html; charset="UTF-8"
|
||||
Content-Transfer-Encoding: 8bit
|
||||
{self.templateEdit.toHtml()}"""
|
||||
html_head = """<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||
</head>
|
||||
"""
|
||||
mail_base = mail.split("<html>")[0]
|
||||
mail_body = mail.split("</head>")[1]
|
||||
mail = mail_base + html_head + mail_body
|
||||
mail = (
|
||||
mail.replace("<", "<")
|
||||
.replace(">", ">")
|
||||
.replace(""", '"')
|
||||
.replace("&", "&")
|
||||
)
|
||||
with open(f"mail_vorlagen/{template}", "w", encoding="utf-8") as f:
|
||||
f.write(mail)
|
||||
|
||||
# Build plaintext from editor
|
||||
body_text = self.templateEdit.toPlainText()
|
||||
body_text = self._normalize_newlines(body_text)
|
||||
|
||||
# Build EML headers and payload (headers, then one blank line, then body)
|
||||
mail_headers = f"""
|
||||
Subject: {self.subject.text()}
|
||||
"""
|
||||
mail_body = body_text
|
||||
|
||||
eml = mail_headers + "\n\n" + mail_body
|
||||
eml = re.sub(r" +", " ", eml) # remove multiple spaces
|
||||
eml = re.sub(r"\n +", "\n", eml) #
|
||||
print(eml)
|
||||
|
||||
with open(
|
||||
f"mail_vorlagen/{template}", "w", encoding="utf-8", newline=""
|
||||
) as f:
|
||||
f.write(eml)
|
||||
|
||||
self.updateSignal.emit()
|
||||
self.close()
|
||||
log.success(f"Template {template} saved successfully")
|
||||
# log.success(f"Template {template} saved successfully (plaintext)")
|
||||
else:
|
||||
# warning dialog
|
||||
dialog = QtWidgets.QMessageBox()
|
||||
dialog.setIcon(QtWidgets.QMessageBox.Icon.Warning)
|
||||
dialog.setWindowIcon(Icon("warning").icon)
|
||||
|
||||
dialog.setText("Bitte geben Sie einen Namen für das Template ein.")
|
||||
dialog.setWindowTitle("Fehler beim Speichern")
|
||||
dialog.exec()
|
||||
@@ -145,52 +136,20 @@ Content-Transfer-Encoding: 8bit
|
||||
self.close()
|
||||
|
||||
def updateDescription(self):
|
||||
# print("update triggered")
|
||||
# print(self.placeholder_list.currentText())
|
||||
placeholders = {
|
||||
"anrede": "Die Anrede beinhaltet sowohl Person als auch Sehr geehrte/r; dargestellt als: {greeting}",
|
||||
"anrede": "Die Anrede inkl. 'Sehr geehrte/r' oder neutral; dargestellt als: {greeting}",
|
||||
"apparatsfach": "Das Fach, in welchem der Apparat angelegt wurde; dargestellt als: {AppSubject}",
|
||||
"apparatsname": "Der Name des Apparats; dargestellt als: {Appname}",
|
||||
"apparatsnummer": "Die Nummer des Apparats; dargestellt als: {AppNr}",
|
||||
"dozentname": "Der Name des Dozenten / der Dozentin; dargestellt als: {Profname}",
|
||||
"signatur": "Die persönliche / allgemeine Signatur am ende der Mail; dargestellt als: {signature}",
|
||||
"signatur": "Ihre Signatur; dargestellt als: {signature}",
|
||||
"": " ",
|
||||
}
|
||||
for (
|
||||
key,
|
||||
item,
|
||||
) in placeholders.items():
|
||||
for key, item in placeholders.items():
|
||||
if key in self.placeholder_list.currentText().lower():
|
||||
self.lineEdit.setText(item)
|
||||
break
|
||||
|
||||
def setCurrentFont(self):
|
||||
font = self.fontBox.currentFont()
|
||||
font.setPointSize(int(self.fontSize.currentText()))
|
||||
self.templateEdit.setFont(font)
|
||||
|
||||
def setFontSize(self):
|
||||
size = self.fontSize.currentText()
|
||||
self.templateEdit.setFontPointSize(int(size))
|
||||
|
||||
def setFontBold(self):
|
||||
if self.bold.isChecked():
|
||||
self.templateEdit.setFontWeight(QtGui.QFont.Weight.Bold)
|
||||
else:
|
||||
self.templateEdit.setFontWeight(QtGui.QFont.Weight.Normal)
|
||||
|
||||
def setTextFontItalic(self):
|
||||
if self.italic.isChecked():
|
||||
self.templateEdit.setFontItalic(True)
|
||||
else:
|
||||
self.templateEdit.setFontItalic(False)
|
||||
|
||||
def setTextFontUnderline(self):
|
||||
if self.underlined.isChecked():
|
||||
self.templateEdit.setFontUnderline(True)
|
||||
else:
|
||||
self.templateEdit.setFontUnderline(False)
|
||||
|
||||
def test_template(self):
|
||||
placeholders = [
|
||||
"{greeting}",
|
||||
@@ -201,35 +160,29 @@ Content-Transfer-Encoding: 8bit
|
||||
"{signature}",
|
||||
]
|
||||
mail_subject = self.subject.text()
|
||||
mail_body = self.templateEdit.toHtml()
|
||||
mail_body = self.templateEdit.toPlainText()
|
||||
missing_body = []
|
||||
missing_subject = []
|
||||
try:
|
||||
assert placeholders[2] in mail_subject
|
||||
assert "{Appname}" in mail_subject or "{AppName}" in mail_subject
|
||||
except AssertionError:
|
||||
missing_subject.append(placeholders[2])
|
||||
# check if all placeholders are in the mail body
|
||||
missing_subject.append("{Appname}")
|
||||
for placeholder in placeholders:
|
||||
try:
|
||||
assert placeholder in mail_body
|
||||
except AssertionError:
|
||||
missing_body.append(placeholder)
|
||||
if missing_body != []:
|
||||
# warning dialog
|
||||
Icon("template_fail", self.testTemplate)
|
||||
if missing_body:
|
||||
dialog = QtWidgets.QMessageBox()
|
||||
dialog.setWindowIcon(Icon("warning").icon)
|
||||
|
||||
dialog.setText("Folgende Platzhalter fehlen im Template:")
|
||||
|
||||
missing = (
|
||||
"Betreff:\n"
|
||||
+ "\n".join(missing_subject)
|
||||
+ "\n\n"
|
||||
+ "\\n".join(missing_subject)
|
||||
+ "\\n\\n"
|
||||
+ "Mailtext:\n"
|
||||
+ "\n".join(missing_body)
|
||||
+ "\\n".join(missing_body)
|
||||
)
|
||||
|
||||
dialog.setInformativeText(f"{missing}")
|
||||
dialog.setWindowTitle("Fehlende Platzhalter")
|
||||
dialog.exec()
|
||||
@@ -238,21 +191,16 @@ Content-Transfer-Encoding: 8bit
|
||||
self.testTemplate.setText("✔")
|
||||
|
||||
def insert_placeholder(self):
|
||||
placeholder = {
|
||||
placeholder_map = {
|
||||
"anrede": "{greeting}",
|
||||
"apparatsfach": "{AppSubject}",
|
||||
"apparatsname": "{Appname}",
|
||||
"apparatsnummer": "{AppNr}",
|
||||
"dozentname": "{Profname}",
|
||||
"signatur": """<pre class="moz-signature" cols="72">--
|
||||
{signature}
|
||||
</pre>""",
|
||||
"signatur": "{signature}",
|
||||
}
|
||||
cursor = self.templateEdit.textCursor()
|
||||
for (
|
||||
key,
|
||||
item,
|
||||
) in placeholder.items():
|
||||
for key, item in placeholder_map.items():
|
||||
if key in self.placeholder_list.currentText().lower():
|
||||
cursor.insertText(item)
|
||||
break
|
||||
|
||||
113
src/ui/dialogs/newEdition.py
Normal file
113
src/ui/dialogs/newEdition.py
Normal file
@@ -0,0 +1,113 @@
|
||||
import sys
|
||||
|
||||
import loguru
|
||||
from PySide6 import QtCore, QtWidgets
|
||||
|
||||
from src import LOG_DIR
|
||||
from src.backend.database import Database
|
||||
from src.backend.catalogue import Catalogue
|
||||
|
||||
from src.ui.dialogs.mail import Mail_Dialog
|
||||
|
||||
from .dialog_sources.order_neweditions_ui import Ui_Dialog
|
||||
|
||||
log = loguru.logger
|
||||
log.remove()
|
||||
log.add(sys.stdout, level="INFO")
|
||||
log.add(f"{LOG_DIR}/application.log", rotation="1 MB", retention="10 days")
|
||||
|
||||
|
||||
class NewEditionDialog(QtWidgets.QDialog, Ui_Dialog):
|
||||
def __init__(self, app_id, mail_data):
|
||||
super().__init__()
|
||||
self.setupUi(self)
|
||||
self.setWindowTitle("Neuauflagen bestellen")
|
||||
self.db = Database()
|
||||
self.catalogue = Catalogue()
|
||||
self.app_id = app_id
|
||||
self.mail_data = mail_data
|
||||
self.books = self.db.getNewEditionsByApparat(app_id)
|
||||
self.pushButton.clicked.connect(self.orderBooks)
|
||||
self.populateTable()
|
||||
|
||||
def populateTable(self):
|
||||
for book in self.books:
|
||||
signature = book.signature
|
||||
if signature is None or signature == "None":
|
||||
signature = self.catalogue.get_signature(book.ppn)
|
||||
link_label = QtWidgets.QLabel()
|
||||
link = (
|
||||
book.link
|
||||
if book.link != "SWB"
|
||||
else f"https://www.lehmanns.de/search/quick?mediatype_id=&q={book.isbn[0]}"
|
||||
)
|
||||
|
||||
link_label.setText(f'<a href="{link}">Lehmanns.de</a>')
|
||||
link_label.setOpenExternalLinks(True)
|
||||
link_label.setTextFormat(QtCore.Qt.TextFormat.RichText)
|
||||
link_label.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
|
||||
link_label.setTextInteractionFlags(
|
||||
QtCore.Qt.TextInteractionFlag.TextBrowserInteraction
|
||||
)
|
||||
self.tableWidget.insertRow(0)
|
||||
# first column is checkbox for ordering
|
||||
checkbox = QtWidgets.QCheckBox()
|
||||
|
||||
checkbox.setChecked(False)
|
||||
self.tableWidget.setCellWidget(0, 0, checkbox)
|
||||
self.tableWidget.setItem(
|
||||
0,
|
||||
1,
|
||||
QtWidgets.QTableWidgetItem(
|
||||
str(book.signature if book.signature else "")
|
||||
),
|
||||
)
|
||||
self.tableWidget.setItem(0, 2, QtWidgets.QTableWidgetItem(book.title))
|
||||
self.tableWidget.setItem(
|
||||
0, 3, QtWidgets.QTableWidgetItem(",".join(book.isbn))
|
||||
)
|
||||
self.tableWidget.setItem(0, 4, QtWidgets.QTableWidgetItem(book.author))
|
||||
self.tableWidget.setItem(0, 5, QtWidgets.QTableWidgetItem(book.edition))
|
||||
self.tableWidget.setItem(0, 6, QtWidgets.QTableWidgetItem(book.library_location))
|
||||
self.tableWidget.setCellWidget(0, 7, link_label)
|
||||
|
||||
def orderBooks(self):
|
||||
ordered_books = []
|
||||
for row in range(self.tableWidget.rowCount()):
|
||||
checkbox = self.tableWidget.cellWidget(row, 0)
|
||||
if checkbox.isChecked():
|
||||
book = self.books[row]
|
||||
book.link = (
|
||||
book.link
|
||||
if book.link != "SWB"
|
||||
else f"https://www.lehmanns.de/search/quick?mediatype_id=&q={book.isbn[0]}"
|
||||
)
|
||||
print(f"Bestelle Neuauflage für {book.title} ({book.edition})")
|
||||
ordered_books.append(book)
|
||||
# Process ordered_books as needed
|
||||
# editionId = self.db.getNewEditionId(book)
|
||||
# self.db.setOrdered(editionId)
|
||||
|
||||
self.mail = Mail_Dialog(
|
||||
app_id=self.mail_data.get("app_nr"),
|
||||
prof_name=self.mail_data.get("prof_name"),
|
||||
prof_mail=self.mail_data.get("prof_mail"),
|
||||
app_name=self.mail_data.get("app_name"),
|
||||
default_mail="Bitte um Bestellung",
|
||||
ordered_books=ordered_books,
|
||||
)
|
||||
self.mail.exec()
|
||||
|
||||
|
||||
def launch():
|
||||
app = QtWidgets.QApplication.instance()
|
||||
if app is None:
|
||||
app = QtWidgets.QApplication([])
|
||||
mail_data = {
|
||||
"prof_name": "Erwerbung",
|
||||
"prof_mail": "carola.wiestler@ph-freiburg.de",
|
||||
"app_nr": 131,
|
||||
"app_name": "Beratung und Teamarbeit",
|
||||
}
|
||||
dialog = NewEditionDialog(app_id=18, mail_data=mail_data)
|
||||
dialog.exec()
|
||||
@@ -3,6 +3,8 @@ from typing import List
|
||||
from PySide6 import QtWidgets
|
||||
from PySide6.QtCore import Qt
|
||||
|
||||
from src import Icon
|
||||
from src.backend.catalogue import Catalogue
|
||||
from src.logic import BookData
|
||||
|
||||
from .widget_sources.new_edition_check_book_ui import (
|
||||
@@ -11,14 +13,20 @@ from .widget_sources.new_edition_check_book_ui import (
|
||||
from .widget_sources.new_edition_check_found_result_ui import (
|
||||
Ui_Dialog as Ui_NewEditionCheckFoundResult,
|
||||
)
|
||||
from .widget_sources.new_edition_check_selector_ui import (
|
||||
Ui_Dialog as Ui_NewEditionCheckSelector,
|
||||
)
|
||||
from .widget_sources.new_edition_check_ui import Ui_Dialog as Ui_NewEditionCheck
|
||||
from .widget_sources.new_edition_check_selector_ui import Ui_Dialog as Ui_NewEditionCheckSelector
|
||||
|
||||
cat = Catalogue()
|
||||
|
||||
|
||||
class NewEditionCheckSelector(QtWidgets.QDialog, Ui_NewEditionCheckSelector):
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self.setupUi(self)
|
||||
self.setWindowTitle("Neuauflagen prüfen")
|
||||
self.setWindowIcon(Icon("confirm_type").icon)
|
||||
self.btn_apparat.clicked.connect(self.select_apparat)
|
||||
self.btn_prof.clicked.connect(self.select_professor)
|
||||
self.selection = None
|
||||
@@ -31,6 +39,7 @@ class NewEditionCheckSelector(QtWidgets.QDialog, Ui_NewEditionCheckSelector):
|
||||
self.selection = "professor"
|
||||
self.accept()
|
||||
|
||||
|
||||
class NewEditionCheckFoundResult(QtWidgets.QDialog, Ui_NewEditionCheckFoundResult):
|
||||
def __init__(self, book: BookData, parent=None):
|
||||
assert isinstance(book, BookData)
|
||||
@@ -44,6 +53,7 @@ class NewEditionCheckFoundResult(QtWidgets.QDialog, Ui_NewEditionCheckFoundResul
|
||||
self.line_publisher.setText(self.book.publisher if self.book.publisher else "")
|
||||
self.line_year.setText(self.book.year if self.book.year else "")
|
||||
self.line_pages.setText(self.book.pages if self.book.pages else "")
|
||||
self.line_author.setText(self.book.author if self.book.author else "")
|
||||
link = self.book.link if self.book.link else ""
|
||||
if self.book.link != "SWB":
|
||||
link = f"<a href='{link}'>Lehmanns</a>"
|
||||
@@ -66,7 +76,17 @@ class NewEditionCheckFoundResult(QtWidgets.QDialog, Ui_NewEditionCheckFoundResul
|
||||
self.in_library.setText(
|
||||
"Diese Neuauflage ist bereits in der Bibliothek vorhanden."
|
||||
)
|
||||
self.book.library_location = 1
|
||||
self.book.link == f"https://www.lehmanns.de/search/quick?mediatype_id=&q={self.book.isbn[0]}"
|
||||
if (
|
||||
self.book.link == "SWB"
|
||||
and self.book.signature is not None
|
||||
and self.book.signature != ""
|
||||
and self.book.library_location not in (0, "0", None)
|
||||
):
|
||||
self.in_library.setText(
|
||||
f"Diese Neuauflage ist bereits in der Bibliothek vorhanden, und an diesem Standort: {self.book.library_location}."
|
||||
)
|
||||
f"https://www.lehmanns.de/search/quick?mediatype_id=&q={self.book.isbn[0]}"
|
||||
|
||||
pass
|
||||
|
||||
@@ -78,7 +98,10 @@ class NewEditionCheckBook(QtWidgets.QDialog, Ui_NewEditionCheckBook):
|
||||
self.book = book
|
||||
self.accepted_books = []
|
||||
self.responses = responses
|
||||
self.line_author.setText(self.book.author)
|
||||
author = self.book.author if self.book.author else cat.get_author(self.book.ppn)
|
||||
if self.book.author is None and author is not None:
|
||||
self.book.author = author
|
||||
self.line_author.setText(author if author else "")
|
||||
self.line_title.setText(self.book.title)
|
||||
self.line_ppn.setText(self.book.ppn if self.book.ppn else "")
|
||||
self.line_signature.setText(self.book.signature if self.book.signature else "")
|
||||
@@ -103,6 +126,9 @@ class NewEditionCheckBook(QtWidgets.QDialog, Ui_NewEditionCheckBook):
|
||||
self.label_book_index.setText(f"1 / {self.stackedWidget.count()}")
|
||||
self.btn_next.clicked.connect(self.next)
|
||||
self.btn_prev.clicked.connect(self.previous)
|
||||
if self.stackedWidget.count() <= 1:
|
||||
self.btn_next.hide()
|
||||
self.btn_prev.hide()
|
||||
|
||||
def next(self):
|
||||
index = self.stackedWidget.currentIndex()
|
||||
@@ -110,6 +136,7 @@ class NewEditionCheckBook(QtWidgets.QDialog, Ui_NewEditionCheckBook):
|
||||
index += 1
|
||||
self.stackedWidget.setCurrentIndex(index)
|
||||
self.label_book_index.setText(f"{index + 1} / {self.stackedWidget.count()}")
|
||||
self.btn_prev.show()
|
||||
if index == self.stackedWidget.count() - 1:
|
||||
self.btn_next.hide()
|
||||
|
||||
@@ -119,6 +146,9 @@ class NewEditionCheckBook(QtWidgets.QDialog, Ui_NewEditionCheckBook):
|
||||
index -= 1
|
||||
self.stackedWidget.setCurrentIndex(index)
|
||||
self.label_book_index.setText(f"{index + 1} / {self.stackedWidget.count()}")
|
||||
self.btn_next.show()
|
||||
if index == 0:
|
||||
self.btn_prev.hide()
|
||||
if index < self.stackedWidget.count() - 1:
|
||||
self.btn_next.show()
|
||||
|
||||
@@ -130,7 +160,8 @@ class NewEditionChecker(QtWidgets.QDialog, Ui_NewEditionCheck):
|
||||
super().__init__(parent)
|
||||
self.setupUi(self)
|
||||
self.results = results
|
||||
self.setWindowTitle("Prüfung auf Neuauflagen")
|
||||
self.setWindowIcon(Icon("results").icon)
|
||||
self.setWindowTitle(f"Neuauflagen prüfen ({len(self.results)})")
|
||||
# remove pages from stacked widget
|
||||
for _ in range(self.stackedWidget.count()):
|
||||
widget = self.stackedWidget.widget(0)
|
||||
@@ -138,6 +169,7 @@ class NewEditionChecker(QtWidgets.QDialog, Ui_NewEditionCheck):
|
||||
widget.deleteLater()
|
||||
for resultset in self.results:
|
||||
book, responses = resultset
|
||||
# print(book, responses)
|
||||
self.stackedWidget.addWidget(
|
||||
NewEditionCheckBook(parent=self, book=book, responses=responses)
|
||||
)
|
||||
@@ -170,7 +202,7 @@ class NewEditionChecker(QtWidgets.QDialog, Ui_NewEditionCheck):
|
||||
self.progressBar.setValue(index + 1)
|
||||
|
||||
def accept(self) -> None:
|
||||
print("finished checking for new editions")
|
||||
# print("finished checking for new editions")
|
||||
accepted_books = []
|
||||
for i in range(self.stackedWidget.count()):
|
||||
book_widget = self.stackedWidget.widget(i)
|
||||
@@ -179,7 +211,8 @@ class NewEditionChecker(QtWidgets.QDialog, Ui_NewEditionCheck):
|
||||
found_widget = book_widget.stackedWidget.widget(j)
|
||||
if isinstance(found_widget, NewEditionCheckFoundResult):
|
||||
if found_widget.checkBox.isChecked():
|
||||
found_widget.book.old_book = book_widget.book
|
||||
accepted_books.append(found_widget.book)
|
||||
super().accept()
|
||||
print("accepted", len(accepted_books), "new editions")
|
||||
# print("accepted", len(accepted_books), "new editions")
|
||||
self.accepted_books = accepted_books
|
||||
|
||||
@@ -194,7 +194,7 @@ class SearchStatisticPage(QtWidgets.QDialog, Ui_Dialog):
|
||||
appnr = self.tableWidget.item(tableposition, 2).text()
|
||||
if reminder.result() == QtWidgets.QDialog.DialogCode.Accepted:
|
||||
data = reminder.return_message()
|
||||
# #print(data)
|
||||
# ##print(data)
|
||||
self.db.addMessage(
|
||||
data,
|
||||
"admin",
|
||||
@@ -222,7 +222,6 @@ class SearchStatisticPage(QtWidgets.QDialog, Ui_Dialog):
|
||||
params = {key: value for key, value in params.items() if value is not None}
|
||||
log.info(params)
|
||||
retdata = self.db.searchBook(params)
|
||||
log.info(retdata)
|
||||
if retdata == [] or retdata is None:
|
||||
self.no_result.setText("Keine Ergebnisse gefunden")
|
||||
return
|
||||
@@ -235,7 +234,7 @@ class SearchStatisticPage(QtWidgets.QDialog, Ui_Dialog):
|
||||
self.book_search_result.setItem(
|
||||
0, 1, QtWidgets.QTableWidgetItem(book[0].signature)
|
||||
)
|
||||
# #print(book[1])
|
||||
# ##print(book[1])
|
||||
self.book_search_result.setItem(
|
||||
0,
|
||||
2,
|
||||
@@ -281,7 +280,7 @@ class SearchStatisticPage(QtWidgets.QDialog, Ui_Dialog):
|
||||
self.btn_notify_for_deletion.setEnabled(False)
|
||||
|
||||
def setStatisticTableSize(self):
|
||||
# # #print(self.statistics_table.size(), self.statistics_table.rowCount())
|
||||
# # ##print(self.statistics_table.size(), self.statistics_table.rowCount())
|
||||
size = self.statistics_table.size()
|
||||
h = size.height()
|
||||
w = size.width()
|
||||
@@ -402,7 +401,7 @@ class SearchStatisticPage(QtWidgets.QDialog, Ui_Dialog):
|
||||
selected_apparats.append(self.tableWidget.item(i, 2).text())
|
||||
selected_apparat_rows.append(i)
|
||||
# delete all selected apparats
|
||||
# # #print(selected_apparats)
|
||||
# # ##print(selected_apparats)
|
||||
log.info(f"Deleting apparats: {selected_apparats}")
|
||||
for apparat in selected_apparats:
|
||||
self.db.deleteApparat(apparat, self.semester)
|
||||
@@ -594,13 +593,13 @@ class SearchStatisticPage(QtWidgets.QDialog, Ui_Dialog):
|
||||
"Dieser Semesterapparat kann nicht gelöscht werden, da er bereits gelöscht wurde"
|
||||
)
|
||||
elif parent_depth == 2:
|
||||
# #print("depth", parent_depth)
|
||||
# ##print("depth", parent_depth)
|
||||
# apparat selected case - open the apparat in the frame
|
||||
self.apparat_open.emit(apparat)
|
||||
return
|
||||
|
||||
def emit_signal(self, *args):
|
||||
# #print("emit_signal", *args)
|
||||
# ##print("emit_signal", *args)
|
||||
self.apparat_open.emit(args[1])
|
||||
|
||||
|
||||
|
||||
@@ -1,10 +1,28 @@
|
||||
from PySide6 import QtCore, QtWidgets
|
||||
import sys
|
||||
from datetime import datetime
|
||||
|
||||
import loguru
|
||||
from PySide6 import QtCore, QtWidgets
|
||||
from PySide6.QtMultimedia import QAudioOutput, QMediaPlayer
|
||||
|
||||
from src import LOG_DIR
|
||||
from src.backend.catalogue import Catalogue
|
||||
from src.backend.database import Database
|
||||
from src.logic.swb import SWB
|
||||
|
||||
from .widget_sources.admin_update_signatures_ui import Ui_Dialog
|
||||
|
||||
log = loguru.logger
|
||||
log.remove()
|
||||
log.add(sys.stdout, level="INFO")
|
||||
log.add(f"{LOG_DIR}/application.log", rotation="1 MB", retention="10 days")
|
||||
|
||||
log.add(
|
||||
f"{LOG_DIR}/{datetime.now().strftime('%Y-%m-%d')}.log",
|
||||
rotation="1 day",
|
||||
retention="1 month",
|
||||
)
|
||||
|
||||
|
||||
class UpdaterThread(QtCore.QThread):
|
||||
progress = QtCore.Signal(int)
|
||||
@@ -19,17 +37,66 @@ class UpdaterThread(QtCore.QThread):
|
||||
def run(self):
|
||||
total_books = len(self.books)
|
||||
for index, book in enumerate(self.books):
|
||||
id = book["id"]
|
||||
bookdata = book["bookdata"]
|
||||
ppn = bookdata.link.split("kid=")[-1]
|
||||
result = self.catalogue.get_book(ppn)
|
||||
if result:
|
||||
bookdata.signature = result.signature
|
||||
print(bookdata)
|
||||
self.db.updateBookdata(id, bookdata)
|
||||
else:
|
||||
print(f"No result for {ppn}")
|
||||
self.db.deleteBook(id)
|
||||
try:
|
||||
id = book["id"]
|
||||
bookdata = book["bookdata"]
|
||||
ppn = bookdata.ppn
|
||||
result = self.catalogue.get_book(ppn)
|
||||
if result:
|
||||
log.debug(f"Updating book {id} with ppn {ppn}")
|
||||
bookdata.signature = result.signature
|
||||
# #print(bookdata)
|
||||
self.db.updateBookdata(id, bookdata)
|
||||
else:
|
||||
log.debug(f"No result for {ppn}")
|
||||
# #print(f"No result for {ppn}")
|
||||
# self.db.deleteBook(id)
|
||||
except Exception as e:
|
||||
log.error(f"Error updating book {book}: {e}")
|
||||
self.progress.emit(index + 1)
|
||||
self.currtot.emit(index + 1, total_books)
|
||||
|
||||
|
||||
class CompleterThread(QtCore.QThread):
|
||||
progress = QtCore.Signal(int)
|
||||
currtot = QtCore.Signal(int, int)
|
||||
|
||||
def __init__(self, books=None):
|
||||
super().__init__()
|
||||
self.books = books
|
||||
self.db = Database()
|
||||
self.catalogue = Catalogue()
|
||||
self.swb = SWB()
|
||||
|
||||
def run(self):
|
||||
total_books = len(self.books)
|
||||
for index, book in enumerate(self.books):
|
||||
try:
|
||||
id = book["id"]
|
||||
bookdata = book["bookdata"]
|
||||
|
||||
ppn = bookdata.ppn
|
||||
cat_book = self.catalogue.get_book(f"kid:{ppn}")
|
||||
|
||||
swb_version = self.swb.getBooks(["pica.bib=20735", f"pica.ppn={ppn}"])[
|
||||
0
|
||||
]
|
||||
if cat_book:
|
||||
merged = cat_book.merge(swb_version)
|
||||
else:
|
||||
merged = swb_version
|
||||
|
||||
# compare original_book with merged, if different, update db
|
||||
if bookdata != merged:
|
||||
# #print(f"Updating book {id} with ppn {ppn}")
|
||||
# #print("Original book:", bookdata)
|
||||
# #print("Merged book:", merged)
|
||||
self.db.updateBookdata(id, merged)
|
||||
except Exception as e:
|
||||
log.error(f"Error updating book {book}: {e}")
|
||||
# else:
|
||||
# #print(f"No result for {ppn}")
|
||||
# self.db.deleteBook(id)
|
||||
self.progress.emit(index + 1)
|
||||
self.currtot.emit(index + 1, total_books)
|
||||
|
||||
@@ -40,20 +107,49 @@ class UpdateSignatures(QtWidgets.QDialog, Ui_Dialog):
|
||||
self.setupUi(self)
|
||||
self.setWindowTitle("Updating signatures...")
|
||||
self.progressBar.setValue(0)
|
||||
self.pushButton.clicked.connect(self.start)
|
||||
self.btn_update_signatures.clicked.connect(self.update_signatures)
|
||||
self.btn_add_missing_data.clicked.connect(self.add_missing)
|
||||
self.db = Database()
|
||||
self.catalogue = Catalogue()
|
||||
self.player = QMediaPlayer()
|
||||
self.audio_output = QAudioOutput()
|
||||
|
||||
def start(self):
|
||||
def play_sound(self, sound_file: str):
|
||||
self.player.setAudioOutput(self.audio_output)
|
||||
self.audio_output.setVolume(50)
|
||||
self.player.setSource(QtCore.QUrl.fromLocalFile(f"src/sounds/{sound_file}"))
|
||||
self.player.play()
|
||||
|
||||
def update_signatures(self):
|
||||
books = self.db.getAllBooks()
|
||||
total_books = len(books)
|
||||
self.progressBar.setMaximum(total_books)
|
||||
self.updater = UpdaterThread(books)
|
||||
self.updater.progress.connect(self.update_progress)
|
||||
self.updater.finished.connect(self.updater.deleteLater)
|
||||
self.updater.start()
|
||||
|
||||
def add_missing(self):
|
||||
books = self.db.getAllBooks()
|
||||
total_books = len(books)
|
||||
self.progressBar.setMaximum(total_books)
|
||||
incomplete_books = [
|
||||
book
|
||||
for book in books
|
||||
if any(
|
||||
value in (None, "", "None")
|
||||
for value in book["bookdata"].__dict__.values()
|
||||
)
|
||||
]
|
||||
self.completionist = CompleterThread(incomplete_books)
|
||||
self.completionist.progress.connect(self.update_progress)
|
||||
self.completionist.finished.connect(self.completionist.deleteLater)
|
||||
self.completionist.start()
|
||||
|
||||
def update_progress(self, value):
|
||||
self.progressBar.setValue(value)
|
||||
if value >= self.progressBar.maximum():
|
||||
self.pushButton.setText("Done")
|
||||
self.pushButton.setEnabled(False)
|
||||
if value <= self.progressBar.maximum():
|
||||
self.btn_update_signatures.setEnabled(False)
|
||||
if value == self.progressBar.maximum():
|
||||
self.btn_update_signatures.setEnabled(True)
|
||||
self.play_sound("ding.mp3")
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
from typing import Any
|
||||
from .widget_sources.welcome_wizard_ui import Ui_Wizard
|
||||
from PySide6 import QtWidgets, QtCore, QtGui
|
||||
from src import settings, LOG_DIR
|
||||
from src.backend import Database
|
||||
import sys
|
||||
from appdirs import AppDirs
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
import loguru
|
||||
from appdirs import AppDirs
|
||||
from PySide6 import QtCore, QtWidgets
|
||||
|
||||
from src import LOG_DIR, settings
|
||||
from src.backend import Database
|
||||
|
||||
from .widget_sources.welcome_wizard_ui import Ui_Wizard
|
||||
|
||||
appdirs = AppDirs("SemesterApparatsManager", "SAM")
|
||||
|
||||
@@ -193,15 +196,17 @@ class WelcomeWizard(QtWidgets.QWizard, Ui_Wizard):
|
||||
settings.set_openai_attr("api_key", openai_api_key)
|
||||
settings.set_openai_attr("model", openai_model)
|
||||
# save settings to file
|
||||
print("Saving settings...")
|
||||
# print("Saving settings...")
|
||||
settings.save()
|
||||
|
||||
def open_database_settings(self):
|
||||
#open filepicker dialog to select database file folder
|
||||
# open filepicker dialog to select database file folder
|
||||
file_dialog = QtWidgets.QFileDialog(self, "Select Database File")
|
||||
file_dialog.setFileMode(QtWidgets.QFileDialog.FileMode.Directory)
|
||||
file_dialog.setViewMode(QtWidgets.QFileDialog.ViewMode.List)
|
||||
file_dialog.setWindowFlags(file_dialog.windowFlags() | QtCore.Qt.WindowType.WindowStaysOnTopHint)
|
||||
file_dialog.setWindowFlags(
|
||||
file_dialog.windowFlags() | QtCore.Qt.WindowType.WindowStaysOnTopHint
|
||||
)
|
||||
# set start dir to appdir.user_data_dir
|
||||
file_dialog.setDirectory(str(appdirs.user_data_dir))
|
||||
if file_dialog.exec():
|
||||
@@ -212,7 +217,7 @@ class WelcomeWizard(QtWidgets.QWizard, Ui_Wizard):
|
||||
self.settings_database.setText(db_path)
|
||||
|
||||
def open_temp_settings(self):
|
||||
#open filepicker dialog to select temporary directory
|
||||
# open filepicker dialog to select temporary directory
|
||||
dir_dialog = QtWidgets.QFileDialog(self, "Select Temporary Directory")
|
||||
dir_dialog.setFileMode(QtWidgets.QFileDialog.FileMode.Directory)
|
||||
dir_dialog.setViewMode(QtWidgets.QFileDialog.ViewMode.List)
|
||||
@@ -224,6 +229,7 @@ class WelcomeWizard(QtWidgets.QWizard, Ui_Wizard):
|
||||
temp_path = selected_dirs[0]
|
||||
self.settings_temp.setText(temp_path)
|
||||
|
||||
|
||||
def launch_wizard():
|
||||
"""Launch the welcome wizard."""
|
||||
app = QtWidgets.QApplication.instance()
|
||||
@@ -235,4 +241,4 @@ def launch_wizard():
|
||||
wizard.setWizardStyle(QtWidgets.QWizard.WizardStyle.ModernStyle)
|
||||
wizard.setStartId(0)
|
||||
wizard.show()
|
||||
return wizard.exec()
|
||||
return wizard.exec()
|
||||
|
||||
Reference in New Issue
Block a user