UI: refactor mail template dialog for plaintext handling, improve logging, and update UI elements

This commit is contained in:
2025-09-22 09:47:18 +02:00
parent 11d5d67538
commit d35b2e816e
6 changed files with 342 additions and 147 deletions

View File

@@ -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>
# 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_base = mail.split("<html>")[0]
mail_body = mail.split("</head>")[1]
mail = mail_base + html_head + mail_body
mail = (
mail.replace("&lt;", "<")
.replace("&gt;", ">")
.replace("&quot;", '"')
.replace("&amp;", "&")
)
with open(f"mail_vorlagen/{template}", "w", encoding="utf-8") as f:
f.write(mail)
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

View 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()

View File

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

View File

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

View File

@@ -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):
try:
id = book["id"]
bookdata = book["bookdata"]
ppn = bookdata.link.split("kid=")[-1]
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)
# #print(bookdata)
self.db.updateBookdata(id, bookdata)
else:
print(f"No result for {ppn}")
self.db.deleteBook(id)
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")

View File

@@ -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,7 +196,7 @@ 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):
@@ -201,7 +204,9 @@ class WelcomeWizard(QtWidgets.QWizard, Ui_Wizard):
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():
@@ -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()