Refactor user interface: enhance sound playback functionality and integrate signature update process,
fix broken database calls by using the app_id instead of the previously used appnr
This commit is contained in:
@@ -7,14 +7,14 @@ import time
|
|||||||
import webbrowser
|
import webbrowser
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, Union
|
from typing import Any, List, Optional, Tuple, 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.QtMultimedia import QAudioOutput, QMediaPlayer
|
|
||||||
from PySide6.QtCore import QThread
|
from PySide6.QtCore import QThread
|
||||||
from PySide6.QtGui import QRegularExpressionValidator
|
from PySide6.QtGui import QRegularExpressionValidator
|
||||||
|
from PySide6.QtMultimedia import QAudioOutput, QMediaPlayer
|
||||||
|
|
||||||
from src import LOG_DIR, Icon
|
from src import LOG_DIR, Icon
|
||||||
from src.backend import (
|
from src.backend import (
|
||||||
@@ -59,7 +59,10 @@ from src.ui.widgets import (
|
|||||||
FilePicker,
|
FilePicker,
|
||||||
MessageCalendar,
|
MessageCalendar,
|
||||||
NewEditionChecker,
|
NewEditionChecker,
|
||||||
|
NewEditionCheckSelector,
|
||||||
SearchStatisticPage,
|
SearchStatisticPage,
|
||||||
|
UpdaterThread,
|
||||||
|
UpdateSignatures,
|
||||||
UserCreate,
|
UserCreate,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -76,13 +79,6 @@ log.add(
|
|||||||
log.success("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
|
||||||
@@ -256,6 +252,7 @@ class Ui(Ui_Semesterapparat):
|
|||||||
self.availChecker = None
|
self.availChecker = None
|
||||||
self.mail_thread = None
|
self.mail_thread = None
|
||||||
self.autoGrabber = None
|
self.autoGrabber = None
|
||||||
|
self.newEditionChecker = NewEditionCheckerThread()
|
||||||
|
|
||||||
self.elsatab.setLayout(QtWidgets.QVBoxLayout())
|
self.elsatab.setLayout(QtWidgets.QVBoxLayout())
|
||||||
self.search_statistics.setLayout(QtWidgets.QVBoxLayout())
|
self.search_statistics.setLayout(QtWidgets.QVBoxLayout())
|
||||||
@@ -270,6 +267,9 @@ class Ui(Ui_Semesterapparat):
|
|||||||
|
|
||||||
self.steps.hide()
|
self.steps.hide()
|
||||||
|
|
||||||
|
self.player = QMediaPlayer()
|
||||||
|
self.audio_output = QAudioOutput()
|
||||||
|
|
||||||
self.valid_check_semester.clicked.connect(self.display_valid_semester) # type:ignore
|
self.valid_check_semester.clicked.connect(self.display_valid_semester) # type:ignore
|
||||||
|
|
||||||
def create_doc(self):
|
def create_doc(self):
|
||||||
@@ -313,6 +313,9 @@ class Ui(Ui_Semesterapparat):
|
|||||||
elif self.select_action_box.currentText() == "Lehrperson bearbeiten":
|
elif self.select_action_box.currentText() == "Lehrperson bearbeiten":
|
||||||
self.setWidget(EditProf())
|
self.setWidget(EditProf())
|
||||||
self.admin_action.setTitle("Lehrperson bearbeiten")
|
self.admin_action.setTitle("Lehrperson bearbeiten")
|
||||||
|
elif self.select_action_box.currentText() == "Signaturen aktualisieren":
|
||||||
|
self.setWidget(UpdateSignatures())
|
||||||
|
self.admin_action.setTitle("Signaturen aktualisieren")
|
||||||
else:
|
else:
|
||||||
self.hideWidget()
|
self.hideWidget()
|
||||||
self.admin_action.setTitle("")
|
self.admin_action.setTitle("")
|
||||||
@@ -330,6 +333,12 @@ class Ui(Ui_Semesterapparat):
|
|||||||
tempdelete()
|
tempdelete()
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
|
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 get_apparats(self):
|
def get_apparats(self):
|
||||||
alist = self.db.getAllAparats(deleted=0)
|
alist = self.db.getAllAparats(deleted=0)
|
||||||
alist = natsorted(alist, key=lambda x: x.appnr, reverse=True)
|
alist = natsorted(alist, key=lambda x: x.appnr, reverse=True)
|
||||||
@@ -417,7 +426,7 @@ class Ui(Ui_Semesterapparat):
|
|||||||
else:
|
else:
|
||||||
return f"WiSe {currentYear}/{currentYear + 1}"
|
return f"WiSe {currentYear}/{currentYear + 1}"
|
||||||
|
|
||||||
def open_apparat(self, apparat):
|
def open_apparat(self, apparat: Union[int, str]):
|
||||||
if self.load_app_data(apparat):
|
if self.load_app_data(apparat):
|
||||||
# change tab focus to tab 0
|
# change tab focus to tab 0
|
||||||
self.tabWidget.setCurrentIndex(0)
|
self.tabWidget.setCurrentIndex(0)
|
||||||
@@ -626,17 +635,17 @@ class Ui(Ui_Semesterapparat):
|
|||||||
self.prof_mail.setText(data.mail)
|
self.prof_mail.setText(data.mail)
|
||||||
self.app_name.setFocus()
|
self.app_name.setFocus()
|
||||||
|
|
||||||
def get_index_of_value(self, table_widget, value):
|
def get_index_of_value(self, table_widget: QtWidgets.QTableWidget, value: str):
|
||||||
for i in range(table_widget.rowCount()):
|
for i in range(table_widget.rowCount()):
|
||||||
for j in range(table_widget.columnCount()):
|
for j in range(table_widget.columnCount()):
|
||||||
if (
|
if (
|
||||||
table_widget.item(i, j) is not None
|
table_widget.item(i, j) is not None
|
||||||
and table_widget.item(i, j).text() == value
|
and table_widget.item(i, j).text() == value # type: ignore
|
||||||
):
|
):
|
||||||
return i, j
|
return i, j
|
||||||
return (None, None)
|
return (None, None)
|
||||||
|
|
||||||
def load_app_data(self, app_id=None):
|
def load_app_data(self, app_id: Optional[Union[int, str]] = None):
|
||||||
self.cancel_active_selection.setEnabled(True)
|
self.cancel_active_selection.setEnabled(True)
|
||||||
self.add_medium.setEnabled(True)
|
self.add_medium.setEnabled(True)
|
||||||
for child in self.app_group_box.findChildren(QtWidgets.QToolButton):
|
for child in self.app_group_box.findChildren(QtWidgets.QToolButton):
|
||||||
@@ -866,8 +875,9 @@ class Ui(Ui_Semesterapparat):
|
|||||||
|
|
||||||
def update_app_media_list(self):
|
def update_app_media_list(self):
|
||||||
deleted = 0 if not self.chkbx_show_del_media.isChecked() else 1
|
deleted = 0 if not self.chkbx_show_del_media.isChecked() else 1
|
||||||
app_id = self.active_apparat
|
app_id = self.db.getId(self.app_name.text())
|
||||||
prof_id = self.db.getProfId(self.profdata)
|
prof_id = self.db.getProfId(self.profdata)
|
||||||
|
print(app_id, prof_id)
|
||||||
books: list[dict[int, BookData, int]] = self.db.getBooks(
|
books: list[dict[int, BookData, int]] = self.db.getBooks(
|
||||||
app_id, prof_id, deleted
|
app_id, prof_id, deleted
|
||||||
)
|
)
|
||||||
@@ -1201,6 +1211,7 @@ class Ui(Ui_Semesterapparat):
|
|||||||
for runner in self.bookGrabber:
|
for runner in self.bookGrabber:
|
||||||
if not runner.isRunning():
|
if not runner.isRunning():
|
||||||
runner.deleteLater()
|
runner.deleteLater()
|
||||||
|
self.bookGrabber.remove(runner)
|
||||||
# #log.debug("Checking file")
|
# #log.debug("Checking file")
|
||||||
# get active app_id and prof_id
|
# get active app_id and prof_id
|
||||||
self.tableWidget_apparate.setEnabled(False)
|
self.tableWidget_apparate.setEnabled(False)
|
||||||
@@ -1497,22 +1508,34 @@ class Ui(Ui_Semesterapparat):
|
|||||||
self.avail_status.setText("0/0")
|
self.avail_status.setText("0/0")
|
||||||
|
|
||||||
def check_new_editions(self):
|
def check_new_editions(self):
|
||||||
|
# create a dialog that asks "Prof oder Apparat" with a button for each. based on that either search through the books of the apparat, or all books associated with the prof
|
||||||
|
selector = NewEditionCheckSelector()
|
||||||
|
selector.exec()
|
||||||
|
pick = selector.selection
|
||||||
|
|
||||||
app_id = self.tableWidget_apparate.item(
|
app_id = self.tableWidget_apparate.item(
|
||||||
self.tableWidget_apparate.currentRow(), 0
|
self.tableWidget_apparate.currentRow(), 0
|
||||||
).text()
|
).text()
|
||||||
|
prof_id: int = self.db.getProfIDByApparat(app_id)
|
||||||
app_name = self.tableWidget_apparate.item(
|
app_name = self.tableWidget_apparate.item(
|
||||||
self.tableWidget_apparate.currentRow(), 1
|
self.tableWidget_apparate.currentRow(), 1
|
||||||
).text()
|
).text()
|
||||||
subject = self.tableWidget_apparate.item(
|
subject = self.tableWidget_apparate.item(
|
||||||
self.tableWidget_apparate.currentRow(), 4
|
self.tableWidget_apparate.currentRow(), 4
|
||||||
).text()
|
).text()
|
||||||
|
if pick == "professor":
|
||||||
prof_id: int = self.db.getProfIDByApparat(app_id)
|
books = self.db.getBooksByProfId(prof_id)
|
||||||
books = self.db.getBooks(app_id, prof_id, deleted=0)
|
app_name = "Sammelmail"
|
||||||
|
app_id = ", ".join(
|
||||||
|
[str(app.appnr) for app in self.db.getApparatsByProf(prof_id)]
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
books = self.db.getBooks(app_id, prof_id, deleted=0)
|
||||||
books = [book["bookdata"] for book in books]
|
books = [book["bookdata"] for book in books]
|
||||||
log.info(f"Checking {len(books)} for new editions")
|
log.info(f"Checking {len(books)} for new editions")
|
||||||
self.newEditionChecker = NewEditionCheckerThread(books)
|
|
||||||
self.newEditionChecker.finished.connect(self.newEditionChecker.deleteLater)
|
self.newEditionChecker.entries = books
|
||||||
|
self.newEditionChecker.finished.connect(self.newEditionChecker.reset)
|
||||||
|
|
||||||
self.progressBar.setMaximum(len(books))
|
self.progressBar.setMaximum(len(books))
|
||||||
self.newEditionChecker.updateSignal.connect(self.update_status)
|
self.newEditionChecker.updateSignal.connect(self.update_status)
|
||||||
@@ -1520,13 +1543,18 @@ class Ui(Ui_Semesterapparat):
|
|||||||
self.newEditionChecker.start()
|
self.newEditionChecker.start()
|
||||||
while self.newEditionChecker.isRunning():
|
while self.newEditionChecker.isRunning():
|
||||||
QtWidgets.QApplication.processEvents()
|
QtWidgets.QApplication.processEvents()
|
||||||
play_sound("ding.mp3")
|
self.play_sound("ding.mp3")
|
||||||
results = self.newEditionChecker.results
|
results = self.newEditionChecker.results
|
||||||
|
if results == []:
|
||||||
|
return
|
||||||
|
log.info(f"Found {len(results)} possible new editions - opening dialog")
|
||||||
newEditionChecker = NewEditionChecker(results=results)
|
newEditionChecker = NewEditionChecker(results=results)
|
||||||
newEditionChecker.exec()
|
newEditionChecker.exec()
|
||||||
|
|
||||||
accepted_books = newEditionChecker.accepted_books
|
accepted_books = newEditionChecker.accepted_books
|
||||||
# print(accepted_books)
|
# print(accepted_books)
|
||||||
|
if accepted_books == []:
|
||||||
|
return
|
||||||
|
|
||||||
self.mail_thread = Mail_Dialog(
|
self.mail_thread = Mail_Dialog(
|
||||||
prof_name=self.db.getSpecificProfData(prof_id, ["fullname"]),
|
prof_name=self.db.getSpecificProfData(prof_id, ["fullname"]),
|
||||||
@@ -1535,7 +1563,7 @@ class Ui(Ui_Semesterapparat):
|
|||||||
app_name=app_name,
|
app_name=app_name,
|
||||||
app_subject=subject,
|
app_subject=subject,
|
||||||
accepted_books=accepted_books,
|
accepted_books=accepted_books,
|
||||||
default_mail="Neuauflagen für Semesterapparat"
|
default_mail="Neuauflagen für Semesterapparat",
|
||||||
)
|
)
|
||||||
self.mail_thread.show()
|
self.mail_thread.show()
|
||||||
|
|
||||||
@@ -1625,8 +1653,45 @@ class Ui(Ui_Semesterapparat):
|
|||||||
menu.exec(self.tableWidget_apparat_media.mapToGlobal(position)) # type: ignore
|
menu.exec(self.tableWidget_apparat_media.mapToGlobal(position)) # type: ignore
|
||||||
|
|
||||||
def update_data(self):
|
def update_data(self):
|
||||||
# TODO: use link in table, parse data and if needed, update location / signature
|
signatures = [
|
||||||
pass
|
self.tableWidget_apparat_media.item(row, 1).text()
|
||||||
|
for row in range(self.tableWidget_apparat_media.rowCount())
|
||||||
|
] # type: ignore
|
||||||
|
prof_id = self.db.getProfId(self.profdata) # type: ignore
|
||||||
|
app_id = self.active_apparat
|
||||||
|
books: List[Tuple[int, BookData]] = []
|
||||||
|
for signature in signatures:
|
||||||
|
book = self.db.getBookBasedOnSignature(
|
||||||
|
app_id=app_id,
|
||||||
|
signature=signature,
|
||||||
|
prof_id=prof_id,
|
||||||
|
)
|
||||||
|
book_id = self.db.getBookIdBasedOnSignature(
|
||||||
|
self.active_apparat,
|
||||||
|
prof_id,
|
||||||
|
signature,
|
||||||
|
)
|
||||||
|
books.append((book_id, book))
|
||||||
|
# self.autoUpdater.entries = books
|
||||||
|
# self.autoUpdater.finished.connect(self.autoUpdater.reset)
|
||||||
|
self.updater = UpdaterThread()
|
||||||
|
u_books = []
|
||||||
|
for book_id, book in books:
|
||||||
|
u_books.append({"id": book_id, "bookdata": book})
|
||||||
|
self.updater.books = u_books
|
||||||
|
self.progressBar.setMaximum(len(books))
|
||||||
|
self.updater.finished.connect(self.updater.deleteLater)
|
||||||
|
self.updater.finished.connect(self.update_app_media_list)
|
||||||
|
self.updater.currtot.connect(self.update_status)
|
||||||
|
self.updater.start()
|
||||||
|
# ppn = book.link.split("kid=")[-1]
|
||||||
|
# result = cat.get_book(ppn)
|
||||||
|
# if result:
|
||||||
|
# book.signature = result.signature
|
||||||
|
# book.in_apparat = True
|
||||||
|
# print(book)
|
||||||
|
# self.db.updateBookdata(book_id, book)
|
||||||
|
# self.update_app_media_list()
|
||||||
|
|
||||||
def copy_to_apparat(self):
|
def copy_to_apparat(self):
|
||||||
selected_rows = self.tableWidget_apparat_media.selectionModel().selectedRows() # type: ignore
|
selected_rows = self.tableWidget_apparat_media.selectionModel().selectedRows() # type: ignore
|
||||||
@@ -1724,12 +1789,12 @@ class Ui(Ui_Semesterapparat):
|
|||||||
).text()
|
).text()
|
||||||
prof_id = self.db.getProfId(self.profdata)
|
prof_id = self.db.getProfId(self.profdata)
|
||||||
data = self.db.getBookBasedOnSignature(
|
data = self.db.getBookBasedOnSignature(
|
||||||
app_id=self.active_apparat,
|
app_id=self.db.getId(self.app_name.text()),
|
||||||
signature=book,
|
signature=book,
|
||||||
prof_id=prof_id,
|
prof_id=prof_id,
|
||||||
)
|
)
|
||||||
book_id = self.db.getBookIdBasedOnSignature(
|
book_id = self.db.getBookIdBasedOnSignature(
|
||||||
self.active_apparat,
|
self.db.getId(self.app_name.text()),
|
||||||
prof_id,
|
prof_id,
|
||||||
book,
|
book,
|
||||||
)
|
)
|
||||||
@@ -1891,7 +1956,13 @@ class Ui(Ui_Semesterapparat):
|
|||||||
if state == 1:
|
if state == 1:
|
||||||
log.debug("Deleting apparat {}", selected_apparat_id)
|
log.debug("Deleting apparat {}", selected_apparat_id)
|
||||||
pid = self.db.getProfIDByApparat(selected_apparat_id)
|
pid = self.db.getProfIDByApparat(selected_apparat_id)
|
||||||
self.db.deleteApparat(selected_apparat_id, Semester().value)
|
apparat = Apparat(
|
||||||
|
appnr=int(selected_apparat_id),
|
||||||
|
name=self.tableWidget_apparate.item(
|
||||||
|
self.tableWidget_apparate.currentRow(), 1
|
||||||
|
).text(),
|
||||||
|
)
|
||||||
|
self.db.deleteApparat(apparat=apparat, semester=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.appnr == int(selected_apparat_id):
|
if apparat.appnr == int(selected_apparat_id):
|
||||||
@@ -1935,6 +2006,7 @@ def launch_gui():
|
|||||||
) # if that thread uses an event loop
|
) # if that thread uses an event loop
|
||||||
app.aboutToQuit.connect(aui.docu.terminate) # our new slot
|
app.aboutToQuit.connect(aui.docu.terminate) # our new slot
|
||||||
app.aboutToQuit.connect(aui.docu.wait)
|
app.aboutToQuit.connect(aui.docu.wait)
|
||||||
|
app.aboutToQuit.connect(aui.newEditionChecker.terminate)
|
||||||
atexit.register(tempdelete)
|
atexit.register(tempdelete)
|
||||||
# atexit.register(aui.validate_thread.quit)
|
# atexit.register(aui.validate_thread.quit)
|
||||||
# atexit.register(aui.docu.quit)
|
# atexit.register(aui.docu.quit)
|
||||||
|
|||||||
Reference in New Issue
Block a user