feat: enhance user interface with new edition checking functionality and sound notifications
This commit is contained in:
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user