diff --git a/src/ui/dialogs/mailTemplate.py b/src/ui/dialogs/mailTemplate.py index c8aae04..32c0dd5 100644 --- a/src/ui/dialogs/mailTemplate.py +++ b/src/ui/dialogs/mailTemplate.py @@ -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 = """ -
- - - """ - mail_base = mail.split("")[0] - mail_body = mail.split("")[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": """--
-{signature}
-""",
+ "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
diff --git a/src/ui/dialogs/newEdition.py b/src/ui/dialogs/newEdition.py
new file mode 100644
index 0000000..56acf5e
--- /dev/null
+++ b/src/ui/dialogs/newEdition.py
@@ -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'Lehmanns.de')
+ 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()
diff --git a/src/ui/widgets/new_edition_check.py b/src/ui/widgets/new_edition_check.py
index 4d94e27..787c138 100644
--- a/src/ui/widgets/new_edition_check.py
+++ b/src/ui/widgets/new_edition_check.py
@@ -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"Lehmanns"
@@ -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
diff --git a/src/ui/widgets/searchPage.py b/src/ui/widgets/searchPage.py
index 2948a77..63992a0 100644
--- a/src/ui/widgets/searchPage.py
+++ b/src/ui/widgets/searchPage.py
@@ -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])
diff --git a/src/ui/widgets/signature_update.py b/src/ui/widgets/signature_update.py
index fc3cb5d..135eeae 100644
--- a/src/ui/widgets/signature_update.py
+++ b/src/ui/widgets/signature_update.py
@@ -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")
diff --git a/src/ui/widgets/welcome_wizard.py b/src/ui/widgets/welcome_wizard.py
index 571ce01..a8f47f4 100644
--- a/src/ui/widgets/welcome_wizard.py
+++ b/src/ui/widgets/welcome_wizard.py
@@ -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()
\ No newline at end of file
+ return wizard.exec()