feat: enhance user interface with new edition checking functionality and sound notifications

This commit is contained in:
2025-09-01 14:32:33 +02:00
parent af53b0310f
commit 5a4156ba04

View File

@@ -12,11 +12,18 @@ from typing import Any, Union
import loguru import loguru
from natsort import natsorted from natsort import natsorted
from PySide6 import QtCore, QtGui, QtWidgets from PySide6 import QtCore, QtGui, QtWidgets
from PySide6.QtCore import QThread, Qt from PySide6.QtMultimedia import QAudioOutput, QMediaPlayer
from PySide6.QtCore import QThread
from PySide6.QtGui import QRegularExpressionValidator from PySide6.QtGui import QRegularExpressionValidator
from src import LOG_DIR, Icon from src import LOG_DIR, Icon
from src.backend import AvailChecker, BookGrabber, Database, DocumentationThread from src.backend import (
AvailChecker,
BookGrabber,
Database,
DocumentationThread,
NewEditionCheckerThread,
)
from src.backend.create_file import recreateFile from src.backend.create_file import recreateFile
from src.backend.delete_temp_contents import delete_temp_contents as tempdelete from src.backend.delete_temp_contents import delete_temp_contents as tempdelete
from src.backend.semester import Semester from src.backend.semester import Semester
@@ -51,6 +58,7 @@ from src.ui.widgets import (
ElsaDialog, ElsaDialog,
FilePicker, FilePicker,
MessageCalendar, MessageCalendar,
NewEditionChecker,
SearchStatisticPage, SearchStatisticPage,
UserCreate, UserCreate,
) )
@@ -65,9 +73,16 @@ log.add(
rotation="1 day", rotation="1 day",
retention="1 month", retention="1 month",
) )
log.critical("UI started") log.success("UI started")
valid_input = (0, 0, 0, 0, 0, 0) valid_input = (0, 0, 0, 0, 0, 0)
def play_sound(sound_file:str):
player = QMediaPlayer()
audio_output = QAudioOutput()
player.setAudioOutput(audio_output)
player.setSource(f"sounds/{sound_file}")
player.play()
class Ui(Ui_Semesterapparat): class Ui(Ui_Semesterapparat):
# use the Ui_MainWindow class from mainwindow.py # use the Ui_MainWindow class from mainwindow.py
@@ -189,6 +204,9 @@ class Ui(Ui_Semesterapparat):
self.btn_reserve.hide() self.btn_reserve.hide()
self.label_20.hide() self.label_20.hide()
self.line_3.hide() self.line_3.hide()
self.progressBar.setValue(0)
self.progressBar.hide()
self.progressBar.setMinimum(0)
self.avail_status.hide() self.avail_status.hide()
self.chkbx_show_del_media.hide() self.chkbx_show_del_media.hide()
self.automation_add_selected_books.hide() self.automation_add_selected_books.hide()
@@ -889,10 +907,15 @@ class Ui(Ui_Semesterapparat):
3, 3,
QtWidgets.QTableWidgetItem(book_data.author), QtWidgets.QTableWidgetItem(book_data.author),
) )
self.tableWidget_apparat_media.setItem( label = QtWidgets.QLabel(f'<a href="{book_data.link}">Katalog</a>')
self.tableWidget_apparat_media.rowCount() - 1, label.setOpenExternalLinks(True)
6, label.setTextFormat(QtCore.Qt.TextFormat.RichText)
QtWidgets.QTableWidgetItem(book_data.link), label.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
label.setTextInteractionFlags(
QtCore.Qt.TextInteractionFlag.TextBrowserInteraction
)
self.tableWidget_apparat_media.setCellWidget(
self.tableWidget_apparat_media.rowCount() - 1, 6, label
) )
if availability == 1: if availability == 1:
# display green checkmark at column 4 in the row # display green checkmark at column 4 in the row
@@ -1099,7 +1122,9 @@ class Ui(Ui_Semesterapparat):
log.info("File selected: {}, {}", file_name, file_location) log.info("File selected: {}, {}", file_name, file_location)
if file_location == "Database": if file_location == "Database":
# create warning, then return # create warning, then return
self.db.recreateFile(file_name, self.active_apparat, filetype=file_type) file = self.db.recreateFile(
file_name, self.active_apparat, filetype=file_type
)
if file_type == "pdf": if file_type == "pdf":
# Todo: implement parser here # Todo: implement parser here
self.confirm_popup("PDF Dateien werden nicht unterstützt!", title="Fehler") self.confirm_popup("PDF Dateien werden nicht unterstützt!", title="Fehler")
@@ -1434,10 +1459,14 @@ class Ui(Ui_Semesterapparat):
contact_action = menu.addAction("Kontaktieren") contact_action = menu.addAction("Kontaktieren")
delete_action = menu.addAction("Löschen") delete_action = menu.addAction("Löschen")
remind_action = menu.addAction("Erinnerung") remind_action = menu.addAction("Erinnerung")
new_edition_check = menu.addAction("Auf Neuauflagen prüfen")
menu.addAction(extend_action) menu.addAction(extend_action)
menu.addActions([contact_action, delete_action, remind_action]) menu.addActions(
[contact_action, delete_action, remind_action, new_edition_check]
)
extend_action.triggered.connect(self.extend_apparat) extend_action.triggered.connect(self.extend_apparat)
remind_action.triggered.connect(self.reminder) remind_action.triggered.connect(self.reminder)
new_edition_check.triggered.connect(self.check_new_editions)
# convert point to row and column # convert point to row and column
row = self.tableWidget_apparate.rowAt(position.y()) row = self.tableWidget_apparate.rowAt(position.y())
column = self.tableWidget_apparate.columnAt(position.x()) column = self.tableWidget_apparate.columnAt(position.x())
@@ -1454,6 +1483,62 @@ class Ui(Ui_Semesterapparat):
) )
menu.exec(self.tableWidget_apparate.mapToGlobal(position)) menu.exec(self.tableWidget_apparate.mapToGlobal(position))
def update_status(self, curr, total):
self.avail_status.show()
self.label_20.show()
self.progressBar.show()
self.avail_status.setText(f"{curr}/{total}")
self.progressBar.setValue(curr)
if curr == total:
self.avail_status.hide()
self.label_20.hide()
self.progressBar.hide()
self.progressBar.setValue(0)
self.avail_status.setText("0/0")
def check_new_editions(self):
app_id = self.tableWidget_apparate.item(
self.tableWidget_apparate.currentRow(), 0
).text()
app_name = self.tableWidget_apparate.item(
self.tableWidget_apparate.currentRow(), 1
).text()
subject = self.tableWidget_apparate.item(
self.tableWidget_apparate.currentRow(), 4
).text()
prof_id: int = self.db.getProfIDByApparat(app_id)
books = self.db.getBooks(app_id, prof_id, deleted=0)
books = [book["bookdata"] for book in books]
log.info(f"Checking {len(books)} for new editions")
self.newEditionChecker = NewEditionCheckerThread(books)
self.newEditionChecker.finished.connect(self.newEditionChecker.deleteLater)
self.progressBar.setMaximum(len(books))
self.newEditionChecker.updateSignal.connect(self.update_status)
self.newEditionChecker.start()
while self.newEditionChecker.isRunning():
QtWidgets.QApplication.processEvents()
play_sound("ding.mp3")
results = self.newEditionChecker.results
newEditionChecker = NewEditionChecker(results=results)
newEditionChecker.exec()
accepted_books = newEditionChecker.accepted_books
# print(accepted_books)
self.mail_thread = Mail_Dialog(
prof_name=self.db.getSpecificProfData(prof_id, ["fullname"]),
prof_mail=self.db.getProfMailById(prof_id),
app_id=app_id,
app_name=app_name,
app_subject=subject,
accepted_books=accepted_books,
default_mail="Neuauflagen für Semesterapparat"
)
self.mail_thread.show()
def reminder(self): def reminder(self):
log.info("Opening reminder dialog") log.info("Opening reminder dialog")
reminder = ReminderDialog() reminder = ReminderDialog()
@@ -1732,10 +1817,18 @@ class Ui(Ui_Semesterapparat):
else: else:
return return
def __contact_dialog(self, apparat, location: tuple | str, mail=None, pid=""): def __contact_dialog(
self,
apparat,
location: tuple | str,
mail=None,
pid="",
accepted_books=None,
app_id="",
):
log.debug( log.debug(
"Got these values apparat: {}, location: {}, mail: {}, pid: {}".format( "Got these values apparat: {}, location: {}, mail: {}, pid: {}, accepted_books: {}, app_id: {}".format(
apparat, location, mail, pid apparat, location, mail, pid, accepted_books, app_id
) )
) )
@@ -1801,7 +1894,7 @@ class Ui(Ui_Semesterapparat):
self.db.deleteApparat(selected_apparat_id, Semester().value) self.db.deleteApparat(selected_apparat_id, Semester().value)
# delete the corresponding entry from self.apparats # delete the corresponding entry from self.apparats
for apparat in self.apparats: for apparat in self.apparats:
if apparat[4] == int(selected_apparat_id): if apparat.appnr == int(selected_apparat_id):
self.apparats.remove(apparat) self.apparats.remove(apparat)
break break
self.old_apparats = self.apparats self.old_apparats = self.apparats