2126 lines
82 KiB
Python
2126 lines
82 KiB
Python
# encoding: utf-8
|
|
import atexit
|
|
import os
|
|
|
|
import sys
|
|
import tempfile
|
|
import webbrowser
|
|
from pathlib import Path
|
|
|
|
from icecream import ic
|
|
from natsort import natsorted
|
|
from omegaconf import OmegaConf
|
|
from PyQt6 import QtCore, QtGui, QtWidgets
|
|
from PyQt6.QtCore import QDate, QThread
|
|
from PyQt6.QtGui import QRegularExpressionValidator
|
|
from src.transformers.transformers import DictToTable
|
|
|
|
from src import Icon
|
|
from src.backend import (
|
|
AdminCommands,
|
|
Database,
|
|
generateSemesterByDate,
|
|
recreateElsaFile,
|
|
recreateFile,
|
|
tempdelete,
|
|
)
|
|
from src.logic import (
|
|
APP_NRS,
|
|
PROF_TITLES,
|
|
ApparatData,
|
|
AvailChecker,
|
|
BookData,
|
|
BookGrabber,
|
|
MyLogger,
|
|
csv_to_list,
|
|
elsa_word_to_csv,
|
|
word_docx_to_csv,
|
|
ZoteroController,
|
|
)
|
|
from src.ui import (
|
|
About,
|
|
App_Ext_Dialog,
|
|
CalendarEntry,
|
|
DataGraph,
|
|
FilePicker,
|
|
Mail_Dialog,
|
|
MessageCalendar,
|
|
Settings,
|
|
Ui_Semesterapparat,
|
|
edit_bookdata_ui,
|
|
login_ui,
|
|
medienadder_ui,
|
|
parsed_titles_ui,
|
|
popus_confirm,
|
|
reminder_ui,
|
|
SearchStatisticPage,
|
|
)
|
|
from src.ui.dialogs.elsa_add_entry import ElsaAddEntry
|
|
|
|
config = OmegaConf.load("config.yaml")
|
|
|
|
|
|
valid_input = (0, 0, 0, 0, 0, 0)
|
|
|
|
|
|
class Ui(Ui_Semesterapparat):
|
|
# use the Ui_MainWindow class from mainwindow.py
|
|
def __init__(self, MainWindow, username: str) -> None:
|
|
self.logger = MyLogger("Ui")
|
|
self.logger.log_info("Starting Semesterapparatsmanagement")
|
|
super().__init__()
|
|
self.active_user = username
|
|
self.setupUi(MainWindow)
|
|
self.MainWindow = MainWindow
|
|
# set the window title
|
|
MainWindow.setWindowTitle("Semesterapparatsmanagement")
|
|
MainWindow.setWindowIcon(Icon("logo").icon)
|
|
|
|
self.db = Database()
|
|
self.btn_add_document.clicked.connect(self.add_document)
|
|
self.check_file.clicked.connect(
|
|
self.btn_check_file_threaded
|
|
) # default: self.add_media_from_file
|
|
self.create_new_app.clicked.connect(self.btn_create_new_apparat)
|
|
self.btn_apparat_save.clicked.connect(lambda: self.btn_save_apparat(True))
|
|
self.btn_apparat_apply.clicked.connect(self.update_apparat)
|
|
self.btn_open_document.clicked.connect(self.open_document)
|
|
self.add_medium.clicked.connect(self.btn_add_medium)
|
|
self.btn_copy_adis_command.clicked.connect(self.text_to_clipboard)
|
|
self.btn_reserve.clicked.connect(self.check_availability)
|
|
self.calendarWidget = MessageCalendar(self.frame_2)
|
|
self.calendarWidget.setGridVisible(True)
|
|
self.calendarWidget.setVerticalHeaderFormat(
|
|
QtWidgets.QCalendarWidget.VerticalHeaderFormat.NoVerticalHeader
|
|
)
|
|
self.calendarWidget.setObjectName("MessageCalendar")
|
|
self.calendarWidget.clicked.connect(self.open_reminder)
|
|
# assign a context menu to the calendar
|
|
self.calendarlayout.addWidget(self.calendarWidget)
|
|
self.tableWidget_apparat_media.horizontalHeader().setSectionResizeMode(
|
|
QtWidgets.QHeaderView.ResizeMode.Stretch
|
|
)
|
|
self.tableWidget_apparate.horizontalHeader().setSectionResizeMode(
|
|
QtWidgets.QHeaderView.ResizeMode.Stretch
|
|
)
|
|
self.tableWidget_apparate.setSortingEnabled(True)
|
|
|
|
# Actions
|
|
self.actionEinstellungen.triggered.connect(self.open_settings)
|
|
Icon("settings", self.actionEinstellungen)
|
|
self.actionDokumentation.triggered.connect(self.open_documentation)
|
|
Icon("offAction", self.actionBeenden)
|
|
self.actionBeenden.triggered.connect(self.quit)
|
|
self.actionAbout.triggered.connect(self.open_about)
|
|
|
|
# set validators
|
|
self.sem_sommer.clicked.connect(lambda: self.toggleButton(self.sem_winter))
|
|
self.sem_winter.clicked.connect(lambda: self.toggleButton(self.sem_sommer))
|
|
self.sem_year.setText(str(QtCore.QDate.currentDate().year()))
|
|
self.prof_mail.setValidator(
|
|
QRegularExpressionValidator(
|
|
QtCore.QRegularExpression(
|
|
r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}"
|
|
)
|
|
)
|
|
)
|
|
self.prof_tel_nr.setValidator(QtGui.QIntValidator())
|
|
|
|
# set app_fach validator to allow only entries from the present items in self.app_fach and allow manual text entry
|
|
# self.app_fach.setValidator(
|
|
# QtGui.QRegularExpressionValidator(
|
|
# QtCore.QRegularExpression(
|
|
# "|".join([f"{subject[1]}" for subject in self.db.getSubjects()])
|
|
# )
|
|
# )
|
|
# )
|
|
self.app_fach.setValidator( # validator to allow typing in the app_fach field
|
|
QtGui.QRegularExpressionValidator(
|
|
QtCore.QRegularExpression(r"[a-zA-Z0-9\s\W]+")
|
|
)
|
|
)
|
|
self.prof_tel_nr.setValidator(
|
|
QtGui.QRegularExpressionValidator(
|
|
QtCore.QRegularExpression(r"^\d{3}|^\d{4}-\d{2}|^\+\d{8,}")
|
|
)
|
|
)
|
|
# allow only letters, numbers, whitespaces, symbols for the apparat name
|
|
self.app_name.setValidator(
|
|
QtGui.QRegularExpressionValidator(
|
|
QtCore.QRegularExpression(r"[a-zA-Z0-9\s\W]+")
|
|
)
|
|
)
|
|
|
|
self.tableWidget_apparate.addScrollBarWidget(
|
|
QtWidgets.QScrollBar(), QtCore.Qt.AlignmentFlag.AlignRight
|
|
)
|
|
self.tableWidget_apparate.doubleClicked.connect(self.load_app_data)
|
|
self.load_app.hide()
|
|
print(f"user:{self.active_user}")
|
|
userrole = self.db.getRole(self.active_user)
|
|
# hide admin interface when non-admin is logged in
|
|
if userrole == "admin":
|
|
self.tabWidget.setTabVisible(3, True)
|
|
else:
|
|
self.tabWidget.setTabVisible(3, False)
|
|
# self.update_app_media_list()
|
|
self.populate_prof_dropdown()
|
|
self.populate_appfach_dropdown()
|
|
# if the focus is changed from the prof name dropdown, set the prof data if the prof exists in the database, otherwise show a message
|
|
self.drpdwn_prof_name.currentIndexChanged.connect(self.set_prof_data)
|
|
self.cancel_active_selection.clicked.connect(self.btn_cancel_active_selection)
|
|
self.check_eternal_app.stateChanged.connect(self.set_state)
|
|
# validate inputs
|
|
self.prof_mail.textChanged.connect(self.validate_prof_mail)
|
|
self.drpdwn_prof_name.editTextChanged.connect(self.validate_prof_name)
|
|
self.prof_tel_nr.textChanged.connect(self.validate_prof_tel)
|
|
self.app_name.textChanged.connect(self.validate_app_name)
|
|
self.app_fach.currentTextChanged.connect(self.validate_app_fach)
|
|
self.sem_year.textChanged.connect(self.validate_semester)
|
|
self.check_eternal_app.stateChanged.connect(self.validate_semester)
|
|
self.chkbx_show_del_media.stateChanged.connect(self.update_app_media_list)
|
|
|
|
self.progress_label.setText("Bitte warten...")
|
|
|
|
# Set visibility/enabled state of certain entries
|
|
self.chkbx_show_del_media.setEnabled(False)
|
|
self.label_info.hide()
|
|
self.app_group_box.setEnabled(False)
|
|
self.line_2.hide()
|
|
self.progress_label.hide()
|
|
# self.message_frame.hide()
|
|
self.btn_reserve.hide()
|
|
self.label_20.hide()
|
|
self.line_3.hide()
|
|
self.avail_status.hide()
|
|
self.chkbx_show_del_media.hide()
|
|
self.groupBox_2.hide()
|
|
self.groupBox.hide()
|
|
# self.btn_del_select_apparats.setEnabled(False)
|
|
|
|
self.tabWidget.currentChanged.connect(self.tabW1_changed)
|
|
|
|
self.statistics = SearchStatisticPage()
|
|
self.statistics.apparat_open.connect(self.open_apparat)
|
|
self.statistics.reloadSignal.connect(self.reload)
|
|
|
|
# create a thread, that continually checks the validity of the inputs
|
|
self.validate_thread = QThread()
|
|
self.validate_thread.started.connect(self.thread_check)
|
|
self.validate_thread.start()
|
|
|
|
# get all current apparats and cache them in a list
|
|
self.apparats = self.get_apparats()
|
|
|
|
self.old_apparats = self.apparats # create a clone to compare against later
|
|
# if length of apparats changes, update box_apparats
|
|
# if tab is changed, gather data needed
|
|
|
|
### Admin interface ###
|
|
self.select_action_box.addItem("")
|
|
self.select_action_box.setCurrentText("")
|
|
self.hide_all()
|
|
self.select_action_box.currentTextChanged.connect(self.admin_action_changed)
|
|
self.edit_faculty_member_select_member.currentTextChanged.connect(
|
|
self.edit_faculty_member_set_data
|
|
)
|
|
|
|
# Context Menus
|
|
self.tableWidget_apparate.setContextMenuPolicy(
|
|
QtCore.Qt.ContextMenuPolicy.CustomContextMenu
|
|
)
|
|
self.tableWidget_apparat_media.setContextMenuPolicy(
|
|
QtCore.Qt.ContextMenuPolicy.CustomContextMenu
|
|
)
|
|
self.tableWidget_apparate.customContextMenuRequested.connect(
|
|
self.open_context_menu
|
|
)
|
|
self.tableWidget_apparat_media.customContextMenuRequested.connect(
|
|
self.media_context_menu
|
|
)
|
|
self.table_elsa_list.setContextMenuPolicy(
|
|
QtCore.Qt.ContextMenuPolicy.CustomContextMenu
|
|
)
|
|
|
|
self.table_elsa_list.customContextMenuRequested.connect(self.elsa_context_menu)
|
|
# elsa buttons
|
|
Icon("semester", self.active_semester)
|
|
Icon("today", self.elsa_date_today)
|
|
self.create_frame_elsa.setEnabled(False)
|
|
self.elsa_add_new.clicked.connect(self.add_new_elsa)
|
|
self.elsa_cancel_create.clicked.connect(self.cancel_elsa_creation)
|
|
self.elsa_save.clicked.connect(self.save_elsa)
|
|
self.elsa_date_today.clicked.connect(self.generateTodayDateElsa)
|
|
self.active_semester.clicked.connect(self.addSemester)
|
|
self.elsa_update.clicked.connect(self.update_elsa)
|
|
self.elsa_table.doubleClicked.connect(self.open_elsa)
|
|
self.btn_add_document_elsa.clicked.connect(self.addDokumentElsa)
|
|
self.check_file_elsa.clicked.connect(self.parseDokumentElsa)
|
|
self.btn_open_document_elsa.clicked.connect(self.openDocumentElsa)
|
|
self.quote_entry.clicked.connect(self.elsa_table_entry)
|
|
|
|
# admin buttons
|
|
self.user_frame_addUser.clicked.connect(self.add_user)
|
|
self.btn_delete_user.clicked.connect(self.delete_user)
|
|
self.update_user.clicked.connect(self.update_user_data)
|
|
self.update_faculty_member.clicked.connect(self.edit_faculty_member_action)
|
|
|
|
# Create instances to be used by the threads in the application
|
|
self.bookGrabber = []
|
|
self.availChecker = None
|
|
self.mail_thread = None
|
|
self.autoGrabber = None
|
|
|
|
def elsa_context_menu(self, position):
|
|
menu = QtWidgets.QMenu()
|
|
# TODO: add functions
|
|
pass
|
|
|
|
def toggleButton(self, button):
|
|
if button.isChecked():
|
|
button.setChecked(False)
|
|
|
|
def open_about(self):
|
|
About().exec()
|
|
|
|
def quit(self):
|
|
# delete all temporary files
|
|
tempdelete()
|
|
sys.exit()
|
|
|
|
def elsa_table_entry(self):
|
|
dtt = DictToTable()
|
|
zot = ZoteroController()
|
|
data = ElsaAddEntry()
|
|
selected_row = self.elsa_table.currentRow()
|
|
# print all rows in the table
|
|
for i in range(self.elsa_table.rowCount()):
|
|
print(self.elsa_table.item(i, 0).text())
|
|
mediatype = self.table_elsa_list.item(selected_row, 11).text()
|
|
signature = self.table_elsa_list.item(selected_row, 10).text()
|
|
data.searchIdent.setText(signature)
|
|
if mediatype == "Zeitschriftenaufsätze":
|
|
data.btn_zs.click()
|
|
elif mediatype == "Herausgeberwerke":
|
|
data.btn_hg.click()
|
|
elif mediatype == "Monographie":
|
|
data.btn_mono.click()
|
|
|
|
data.exec()
|
|
|
|
def add_new_elsa(self):
|
|
self.create_frame_elsa.setEnabled(True)
|
|
self.elsa_cancel_create.setEnabled(True)
|
|
self.dokument_list_elsa.setRowCount(0)
|
|
profs = self.db.getProfs()
|
|
for prof in profs:
|
|
self.elsa_prof.addItem(f"{prof[3]}, {prof[2]}")
|
|
self.elsa_prof.setCurrentText("")
|
|
self.elsa_date.setText("")
|
|
self.elsa_semester.setText("")
|
|
|
|
def cancel_elsa_creation(self):
|
|
self.create_frame_elsa.setEnabled(False)
|
|
self.elsa_cancel_create.setEnabled(False)
|
|
self.elsa_prof.setCurrentText("")
|
|
self.elsa_date.setText("")
|
|
self.elsa_semester.setText("")
|
|
self.dokument_list_elsa.setRowCount(0)
|
|
self.table_elsa_list.setRowCount(0)
|
|
|
|
def generateTodayDateElsa(self):
|
|
self.elsa_date.setText(QDate.currentDate().toString("dd.MM.yyyy"))
|
|
|
|
def addSemester(self):
|
|
self.elsa_semester.setText(self.generateSemester(today=True))
|
|
|
|
def update_elsa(self):
|
|
prof = self.elsa_prof.currentText()
|
|
date = self.elsa_date.text()
|
|
semester = self.elsa_semester.text()
|
|
elsa_id = self.db.getElsaId(prof, semester, date)
|
|
if elsa_id is None:
|
|
return
|
|
self.db.updateElsaApparat(elsa_id, prof, semester, date)
|
|
self.elsa_update.setEnabled(False)
|
|
|
|
def save_elsa(self):
|
|
if (
|
|
self.elsa_prof.currentText() == ""
|
|
or self.elsa_semester.text() == ""
|
|
or self.elsa_date.text() == ""
|
|
):
|
|
# warning message
|
|
self.confirm_popup("Bitte füllen Sie alle Felder aus", title="Fehler")
|
|
|
|
return
|
|
prof = self.elsa_prof.currentText()
|
|
semester = self.elsa_semester.text()
|
|
date = self.elsa_date.text()
|
|
|
|
self.db.createElsaApparat(date, prof, semester)
|
|
self.cancel_elsa_creation()
|
|
self.refresh_elsa_table()
|
|
self.elsa_prof.clear()
|
|
self.elsa_prof.addItem(prof)
|
|
|
|
def refresh_elsa_table(self):
|
|
self.elsa_table.setRowCount(0)
|
|
elsa_apparats = self.db.getElsaApparats()
|
|
for apparat in elsa_apparats:
|
|
self.insert_elsa_into_table(apparat)
|
|
|
|
def insert_elsa_into_table(self, apparat):
|
|
self.elsa_table.insertRow(0)
|
|
date = apparat[1]
|
|
semester = apparat[2]
|
|
prof = apparat[3]
|
|
self.elsa_table.setItem(0, 0, QtWidgets.QTableWidgetItem(prof))
|
|
self.elsa_table.setItem(0, 1, QtWidgets.QTableWidgetItem(date))
|
|
self.elsa_table.setItem(0, 2, QtWidgets.QTableWidgetItem(semester))
|
|
return (semester, 1)
|
|
|
|
def open_elsa(self):
|
|
prof = self.elsa_table.item(self.elsa_table.currentRow(), 0).text()
|
|
date = self.elsa_table.item(self.elsa_table.currentRow(), 1).text()
|
|
semester = self.elsa_table.item(self.elsa_table.currentRow(), 2).text()
|
|
self.elsa_update.setEnabled(True)
|
|
self.elsa_save.setEnabled(False)
|
|
if self.elsa_prof.currentText() == prof:
|
|
self.logger.log_info("Same prof, stopping")
|
|
return
|
|
|
|
self.dokument_list_elsa.setRowCount(0)
|
|
self.table_elsa_list.setRowCount(0)
|
|
self.elsa_cancel_create.setEnabled(True)
|
|
# get elsa apparats, iterate over them and find the one where all matches
|
|
elsa_apparats = self.db.getElsaApparats()
|
|
elsa_id = None
|
|
for apparat in elsa_apparats:
|
|
if apparat[1] == date and apparat[2] == semester and apparat[3] == prof:
|
|
elsa_id = apparat[0]
|
|
print(elsa_id)
|
|
break
|
|
if elsa_id is None:
|
|
return
|
|
self.elsa_date.setText(date)
|
|
self.elsa_semester.setText(semester)
|
|
self.elsa_prof.setCurrentText(prof)
|
|
documents = self.db.getElsaFiles(elsa_id)
|
|
for document in documents:
|
|
print(document)
|
|
self.dokument_list_elsa.insertRow(0)
|
|
self.dokument_list_elsa.setItem(
|
|
0, 0, QtWidgets.QTableWidgetItem(document[0])
|
|
)
|
|
self.dokument_list_elsa.setItem(
|
|
0, 1, QtWidgets.QTableWidgetItem(document[1])
|
|
)
|
|
self.dokument_list_elsa.setItem(0, 2, QtWidgets.QTableWidgetItem("❌"))
|
|
self.dokument_list_elsa.setItem(
|
|
0, 3, QtWidgets.QTableWidgetItem("Database")
|
|
)
|
|
scans = self.db.getElsaMedia(elsa_id)
|
|
ic(scans)
|
|
if scans == []:
|
|
self.create_frame_elsa.setEnabled(True)
|
|
else:
|
|
pass
|
|
for scan in scans:
|
|
self.table_elsa_list.insertRow(0)
|
|
self.table_elsa_list.setItem(
|
|
0, 0, QtWidgets.QTableWidgetItem(scan["work_author"])
|
|
)
|
|
self.table_elsa_list.setItem(
|
|
0, 1, QtWidgets.QTableWidgetItem(scan["section_author"])
|
|
)
|
|
self.table_elsa_list.setItem(
|
|
0, 2, QtWidgets.QTableWidgetItem(scan["year"])
|
|
)
|
|
self.table_elsa_list.setItem(
|
|
0, 3, QtWidgets.QTableWidgetItem(scan["issue"])
|
|
)
|
|
self.table_elsa_list.setItem(
|
|
0, 4, QtWidgets.QTableWidgetItem(scan["edition"])
|
|
)
|
|
self.table_elsa_list.setItem(
|
|
0, 5, QtWidgets.QTableWidgetItem(scan["work_title"])
|
|
)
|
|
self.table_elsa_list.setItem(
|
|
0, 6, QtWidgets.QTableWidgetItem(scan["chapter_title"])
|
|
)
|
|
self.table_elsa_list.setItem(
|
|
0, 7, QtWidgets.QTableWidgetItem(scan["pages"])
|
|
)
|
|
self.table_elsa_list.setItem(
|
|
0, 8, QtWidgets.QTableWidgetItem(scan["location"])
|
|
)
|
|
self.table_elsa_list.setItem(
|
|
0, 9, QtWidgets.QTableWidgetItem(scan["publisher"])
|
|
)
|
|
self.table_elsa_list.setItem(
|
|
0, 10, QtWidgets.QTableWidgetItem(scan["signature"])
|
|
)
|
|
self.table_elsa_list.setItem(
|
|
0, 11, QtWidgets.QTableWidgetItem(scan["type"])
|
|
)
|
|
self.create_frame_elsa.setEnabled(True)
|
|
|
|
def addDokumentElsa(self):
|
|
print("Add document")
|
|
picker = FilePicker()
|
|
files = picker.pick_files()
|
|
datalist = []
|
|
for file in files:
|
|
data = {}
|
|
print(file)
|
|
filename = file.split("/")[-1]
|
|
filetype = filename.split(".")[-1]
|
|
self.dokument_list_elsa.insertRow(0)
|
|
self.dokument_list_elsa.setItem(0, 0, QtWidgets.QTableWidgetItem(filename))
|
|
self.dokument_list_elsa.setItem(0, 1, QtWidgets.QTableWidgetItem(filetype))
|
|
self.dokument_list_elsa.setItem(0, 2, QtWidgets.QTableWidgetItem("*"))
|
|
self.dokument_list_elsa.setItem(0, 3, QtWidgets.QTableWidgetItem(file))
|
|
# set tooltip of row 3 to the file path for each row
|
|
self.dokument_list_elsa.item(0, 3).setToolTip(file)
|
|
data["name"] = filename
|
|
data["path"] = file
|
|
data["type"] = filetype
|
|
datalist.append(data)
|
|
elsa_id = self.db.getElsaId(
|
|
self.elsa_prof.currentText(),
|
|
self.elsa_semester.text(),
|
|
self.elsa_date.text(),
|
|
)
|
|
print(elsa_id)
|
|
if elsa_id is None:
|
|
# create elsa
|
|
self.db.createElsaApparat(
|
|
self.elsa_date.text(),
|
|
self.elsa_prof.currentText(),
|
|
self.elsa_semester.text(),
|
|
)
|
|
elsa_id = self.db.getElsaId(
|
|
self.elsa_prof.currentText(),
|
|
self.elsa_semester.text(),
|
|
self.elsa_date.text(),
|
|
)
|
|
self.db.insertElsaFile(datalist, elsa_id)
|
|
self.elsa_save.setEnabled(False)
|
|
self.refresh_elsa_table()
|
|
|
|
def parseDokumentElsa(self):
|
|
if self.dokument_list_elsa.rowCount() == 0:
|
|
return
|
|
else:
|
|
# get the file path of the selected file based on it's row
|
|
row = self.dokument_list_elsa.currentRow()
|
|
file = self.dokument_list_elsa.item(row, 3).text()
|
|
print(file)
|
|
if file == "Database":
|
|
filename = self.dokument_list_elsa.item(row, 0).text()
|
|
filetype = self.dokument_list_elsa.item(row, 1).text()
|
|
|
|
file = recreateElsaFile(
|
|
filename=filename, filetype=filetype, open=False
|
|
)
|
|
print(file)
|
|
data, doctype = elsa_word_to_csv(file)
|
|
elsa_id = self.db.getElsaId(
|
|
self.elsa_prof.currentText(),
|
|
self.elsa_semester.text(),
|
|
self.elsa_date.text(),
|
|
)
|
|
for row in data:
|
|
self.table_elsa_list.insertRow(0)
|
|
ic(row)
|
|
self.table_elsa_list.setItem(
|
|
0, 0, QtWidgets.QTableWidgetItem(row["work_author"])
|
|
)
|
|
self.table_elsa_list.setItem(
|
|
0, 1, QtWidgets.QTableWidgetItem(row["section_author"])
|
|
)
|
|
self.table_elsa_list.setItem(
|
|
0, 2, QtWidgets.QTableWidgetItem(row["year"])
|
|
)
|
|
self.table_elsa_list.setItem(
|
|
0, 3, QtWidgets.QTableWidgetItem(row["issue"])
|
|
)
|
|
self.table_elsa_list.setItem(
|
|
0, 4, QtWidgets.QTableWidgetItem(row["edition"])
|
|
)
|
|
self.table_elsa_list.setItem(
|
|
0, 5, QtWidgets.QTableWidgetItem(row["chapter_title"])
|
|
)
|
|
self.table_elsa_list.setItem(
|
|
0, 6, QtWidgets.QTableWidgetItem(row["work_title"])
|
|
)
|
|
self.table_elsa_list.setItem(
|
|
0, 7, QtWidgets.QTableWidgetItem(row["pages"])
|
|
)
|
|
self.table_elsa_list.setItem(
|
|
0, 8, QtWidgets.QTableWidgetItem(row["location"])
|
|
)
|
|
self.table_elsa_list.setItem(
|
|
0, 9, QtWidgets.QTableWidgetItem(row["publisher"])
|
|
)
|
|
self.table_elsa_list.setItem(
|
|
0, 10, QtWidgets.QTableWidgetItem(row["signature"])
|
|
)
|
|
self.table_elsa_list.setItem(
|
|
0, 11, QtWidgets.QTableWidgetItem(row["type"])
|
|
)
|
|
|
|
self.db.addElsaMedia(row, elsa_id)
|
|
|
|
def openDocumentElsa(self):
|
|
# open the selected document
|
|
row = self.dokument_list_elsa.currentRow()
|
|
location = self.dokument_list_elsa.item(row, 3).text()
|
|
filetype = self.dokument_list_elsa.item(row, 1).text()
|
|
filename = self.dokument_list_elsa.item(row, 0).text()
|
|
if location == "Database":
|
|
recreateElsaFile(filename, filetype, open=True)
|
|
else:
|
|
os.system(f"{filename}")
|
|
|
|
def get_apparats(self):
|
|
alist = self.db.getAllAparats(deleted=0)
|
|
alist = natsorted(alist, key=lambda x: x[4], reverse=True)
|
|
for apparat in alist:
|
|
self.insert_apparat_into_table(apparat)
|
|
return alist
|
|
|
|
def populate_appfach_dropdown(self):
|
|
self.app_fach.clear()
|
|
self.app_fach.addItem("")
|
|
self.app_fach.setCurrentText("")
|
|
self.app_fach.addItems([subject[1] for subject in self.db.getSubjects()])
|
|
|
|
def open_documentation(self):
|
|
# open the documentation in the default browser
|
|
webbrowser.open("file:///" + os.path.abspath("docs/index.html"))
|
|
# documentation = documentationview.DocumentationViewer()
|
|
# documentation.show()
|
|
|
|
def tabW1_changed(self):
|
|
if self.tabWidget.currentIndex() == 1: # Statistics
|
|
stats_layout = self.search_statistics.layout()
|
|
if stats_layout is not None:
|
|
# delete tabpage, re-add with same name at same position
|
|
return
|
|
layout = QtWidgets.QVBoxLayout(self.search_statistics)
|
|
layout.addWidget(self.statistics)
|
|
|
|
print("searchpage")
|
|
if self.tabWidget.currentIndex() == 0: # Apparate
|
|
# clear all entries from the table
|
|
self.tableWidget_apparate.setRowCount(0)
|
|
self.get_apparats()
|
|
if self.tabWidget.currentIndex() == 2: # Elsa
|
|
self.elsa_cancel_create.click()
|
|
try:
|
|
self.elsa_statistics.removeTab(1)
|
|
except:
|
|
self.logger.log_debug("No tab to remove")
|
|
self.elsa_table.setRowCount(0)
|
|
elsa_apparats = self.db.getElsaApparats()
|
|
elsa_apparats = natsorted(elsa_apparats, key=lambda x: x[2], reverse=True)
|
|
graph_data = {"x": [], "y": []} # x = semester, y = number of apparats
|
|
|
|
for apparat in elsa_apparats:
|
|
print(apparat)
|
|
data = self.insert_elsa_into_table(apparat)
|
|
semester = data[0]
|
|
number = data[1]
|
|
if semester not in graph_data["x"]:
|
|
graph_data["x"].append(semester)
|
|
graph_data["y"].append(number)
|
|
else:
|
|
index = graph_data["x"].index(semester)
|
|
graph_data["y"][index] += number
|
|
|
|
generateMissing = True if len(graph_data["x"]) > 1 else False
|
|
graph = DataGraph(
|
|
"ELSA Apparate pro Semester",
|
|
graph_data,
|
|
generateMissing,
|
|
"Anzahl der Apparate",
|
|
)
|
|
ic(graph_data)
|
|
self.elsa_statistics_table.setRowCount(0)
|
|
for i in range(len(graph_data["x"])):
|
|
self.elsa_statistics_table.insertRow(0)
|
|
self.elsa_statistics_table.setItem(
|
|
0, 0, QtWidgets.QTableWidgetItem(graph_data["x"][i])
|
|
)
|
|
self.elsa_statistics_table.setItem(
|
|
0, 1, QtWidgets.QTableWidgetItem(str(graph_data["y"][i]))
|
|
)
|
|
self.elsa_statistics.addTab(graph, "Graph")
|
|
|
|
def edit_faculty_member_set_data(self):
|
|
# get the selected member
|
|
name = self.edit_faculty_member_select_member.currentText()
|
|
fullname = name.replace(",", "")
|
|
print(fullname, name)
|
|
# get the data for the selected member
|
|
data = self.db.getProfByName(fullname)
|
|
# set the data
|
|
print(data)
|
|
if data is None:
|
|
self.edit_faculty_member_title.setText("")
|
|
self.faculty_member_old_telnr.setText("")
|
|
self.faculty_member_oldmail.setText("")
|
|
self.edit_faculty_member_title.setText("")
|
|
else:
|
|
self.edit_faculty_member_title.setText(data[1])
|
|
self.faculty_member_old_telnr.setText(data[6])
|
|
self.faculty_member_oldmail.setText(data[5])
|
|
(
|
|
self.edit_faculty_member_title.setText(data[1])
|
|
if data[1] is not None
|
|
else self.edit_faculty_member_title.setText("")
|
|
)
|
|
|
|
def add_user(self):
|
|
username = self.user_create_frame_username.text()
|
|
password = self.user_create_frame_password.text()
|
|
role = self.user_frame_userrole.currentText()
|
|
if self.db.checkUsername(username):
|
|
return
|
|
userdata = AdminCommands().create_password(password)
|
|
self.db.createUser(
|
|
user=username,
|
|
password=f"{userdata[1]}{userdata[0]}",
|
|
salt=userdata[1],
|
|
role=role,
|
|
)
|
|
self.user_create_frame_username.clear()
|
|
self.user_create_frame_password.clear()
|
|
self.user_frame_userrole.setCurrentText("")
|
|
self.admin_action_changed()
|
|
|
|
def delete_user(self):
|
|
if self.user_delete_confirm.isChecked():
|
|
username = self.user_delete_frame_user_select.currentText()
|
|
self.db.deleteUser(username)
|
|
self.user_delete_frame_user_select.removeItem(
|
|
self.user_delete_frame_user_select.currentIndex()
|
|
)
|
|
self.user_delete_confirm.setChecked(False)
|
|
else:
|
|
self.user_delete_err_message.setText(
|
|
"Bitte bestätigen Sie die Löschung des Nutzers"
|
|
) # TODO: implement error message
|
|
|
|
def update_user_data(self):
|
|
username = self.user_edit_frame_user_select.currentText()
|
|
password = (
|
|
self.user_edit_frame_new_password.text()
|
|
if self.user_edit_frame_new_password.text() != ""
|
|
else None
|
|
)
|
|
role = (
|
|
self.user_edit_frame_role_select.currentText()
|
|
if self.user_edit_frame_role_select.currentText() != ""
|
|
else None
|
|
)
|
|
|
|
userdata = AdminCommands().create_password(password)
|
|
data = {
|
|
"password": f"{userdata[1]}{userdata[0]}",
|
|
"salt": userdata[1],
|
|
"role": role,
|
|
}
|
|
data = {key: value for key, value in data.items() if value is not None}
|
|
print(data)
|
|
self.db.updateUser(username=username, data=data)
|
|
self.user_edit_frame_user_select.setCurrentText("")
|
|
self.user_edit_frame_new_password.clear()
|
|
self.user_edit_frame_role_select.setCurrentText("")
|
|
|
|
def edit_faculty_member_action(self):
|
|
def __gen_fullname(fname, lname, data):
|
|
if fname == "" and lname == "":
|
|
return data[3]
|
|
if fname == "" and lname != "":
|
|
return f"{lname} {data[1]}"
|
|
if fname != "" and lname == "":
|
|
return f"{data[2]} {fname}"
|
|
if fname != "" and lname != "":
|
|
return f"{lname} {fname}"
|
|
|
|
# get the data and use new value if it is not none and does not mach the old value
|
|
if self.edit_faculty_member_select_member.currentText() == "":
|
|
return
|
|
olddata = self.db.getFacultyMember(
|
|
self.edit_faculty_member_select_member.currentText()
|
|
)
|
|
ic(olddata)
|
|
data = olddata
|
|
oldlname = data[2]
|
|
oldfname = data[1]
|
|
# take data except first and last entry
|
|
|
|
titel = (
|
|
self.edit_faculty_member_new_title.currentText()
|
|
if self.edit_faculty_member_new_title.currentText() != "Kein Titel"
|
|
else None
|
|
)
|
|
fname = (
|
|
self.edit_faculty_member_new_surname.text()
|
|
if self.edit_faculty_member_new_surname.text() != ""
|
|
else self.edit_faculty_member_select_member.currentText()
|
|
.split(" ")[1]
|
|
.strip()
|
|
)
|
|
lname = (
|
|
self.user_faculty_member_new_name.text()
|
|
if self.user_faculty_member_new_name.text() != ""
|
|
else self.edit_faculty_member_select_member.currentText()
|
|
.split(" ")[0]
|
|
.strip()
|
|
)
|
|
fullname = __gen_fullname(fname, lname, data)
|
|
telnr = self.user_faculty_member_new_telnr.text()
|
|
mail = self.user_faculty_member_new_mail.text()
|
|
new_data = {
|
|
"titel": titel,
|
|
"fname": fname,
|
|
"lname": lname,
|
|
"fullname": fullname,
|
|
"mail": mail,
|
|
"telnr": telnr,
|
|
}
|
|
new_data = {key: value for key, value in new_data.items() if value != ""}
|
|
self.db.updateFacultyMember(data=new_data, oldlname=oldlname, oldfname=oldfname)
|
|
self.add_faculty_member_data()
|
|
self.edit_faculty_member_new_title.setCurrentText("")
|
|
self.edit_faculty_member_new_surname.clear()
|
|
self.user_faculty_member_new_name.clear()
|
|
self.user_faculty_member_new_telnr.clear()
|
|
self.user_faculty_member_new_mail.clear()
|
|
|
|
def hide_all(self):
|
|
self.userCreateBox.hide()
|
|
self.userChangeDataBox.hide()
|
|
self.deleteUserBox.hide()
|
|
self.profChangeDataBox.hide()
|
|
|
|
def admin_action_changed(self):
|
|
action = self.select_action_box.currentText()
|
|
roles = self.db.getRoles()
|
|
roles = [role[0] for role in roles]
|
|
# remove duplicates
|
|
roles = list(dict.fromkeys(roles))
|
|
users = self.db.getUsers()
|
|
users = [user[2] for user in users]
|
|
users.remove(self.active_user)
|
|
if "admin" in users:
|
|
users.remove("admin")
|
|
if action == "Nutzer anlegen":
|
|
self.hide_all()
|
|
self.userCreateBox.show()
|
|
self.user_frame_userrole.clear()
|
|
self.user_frame_userrole.addItems(roles)
|
|
elif action == "Nutzer aktualisieren":
|
|
self.hide_all()
|
|
self.userChangeDataBox.show()
|
|
self.user_edit_frame_role_select.addItems(roles)
|
|
self.user_edit_frame_user_select.addItems(users)
|
|
elif action == "Nutzer löschen":
|
|
self.hide_all()
|
|
self.deleteUserBox.show()
|
|
self.user_delete_frame_user_select.addItems(users)
|
|
self.user_delete_frame_user_select.setCurrentText("")
|
|
self.user_delete_frame_user_select.addItems(users)
|
|
|
|
elif action == "Lehrperson bearbeiten":
|
|
self.hide_all()
|
|
self.profChangeDataBox.show()
|
|
self.add_faculty_member_data()
|
|
self.edit_faculty_member_new_title.addItems(PROF_TITLES)
|
|
|
|
else:
|
|
self.hide_all()
|
|
return
|
|
|
|
def add_faculty_member_data(self):
|
|
faculty_members = self.db.getFacultyMembers()
|
|
names = [f"{member[5]}" for member in faculty_members]
|
|
self.edit_faculty_member_select_member.clear()
|
|
self.edit_faculty_member_select_member.addItems(names)
|
|
self.edit_faculty_member_select_member.addItem("")
|
|
self.edit_faculty_member_select_member.setCurrentText("")
|
|
|
|
def generateSemester(self, today=False):
|
|
"""Generates the current semester.
|
|
|
|
Args:
|
|
-----
|
|
today (bool, optional): If True, the current semester is generated. Defaults to False.
|
|
Returns:
|
|
--------
|
|
str: The current semester
|
|
"""
|
|
if today:
|
|
return generateSemesterByDate()
|
|
currentYear = self.sem_year.text()
|
|
currentYear = int(currentYear[-2:])
|
|
|
|
semester = "SoSe" if self.sem_sommer.isChecked() else "WiSe"
|
|
if semester == "SoSe":
|
|
return "SoSe " + str(currentYear)
|
|
else:
|
|
return f"WiSe {currentYear}/{currentYear+1}"
|
|
|
|
def open_apparat(self, apparat):
|
|
if self.load_app_data(apparat):
|
|
# change tab focus to tab 0
|
|
self.tabWidget.setCurrentIndex(0)
|
|
|
|
def populate_dropdown(self, box, data):
|
|
box.clear()
|
|
box.addItem("")
|
|
box.setCurrentText("")
|
|
box.addItems(data)
|
|
|
|
def populate_frame(self, appdata: ApparatData):
|
|
# populate the frame with the data from the database
|
|
self.drpdwn_app_nr.setCurrentText(str(appdata.appnr))
|
|
self.prof_title.setText(appdata.prof_title)
|
|
prof_name = appdata.profname.split(" ")
|
|
if len(prof_name) > 2:
|
|
fname = " ".join(prof_name[1:])
|
|
lname = prof_name[0]
|
|
prof_name = f"{lname}, {fname}"
|
|
else:
|
|
prof_name = ", ".join(prof_name)
|
|
self.drpdwn_prof_name.setCurrentText(prof_name)
|
|
self.prof_mail.setText(appdata.prof_mail)
|
|
self.prof_tel_nr.setText(appdata.prof_tel)
|
|
self.app_name.setText(appdata.appname)
|
|
print("changing dropdown app_fach from '' to ", appdata.app_fach)
|
|
self.app_fach.setCurrentText(appdata.app_fach)
|
|
print("changed dropdown app_fach to ", self.app_fach.currentText())
|
|
if appdata.semester is not None:
|
|
self.sem_sommer.setChecked(
|
|
True if appdata.semester.split(" ")[0] == "SoSe" else False
|
|
)
|
|
self.sem_winter.setChecked(
|
|
True if appdata.semester.split(" ")[0] == "WiSe" else False
|
|
)
|
|
self.sem_year.setText(appdata.semester.split(" ")[1])
|
|
else:
|
|
self.sem_sommer.setChecked(
|
|
True if appdata.erstellsemester.split(" ")[0] == "SoSe" else False
|
|
)
|
|
self.sem_winter.setChecked(
|
|
True if appdata.erstellsemester.split(" ")[0] == "WiSe" else False
|
|
)
|
|
self.sem_year.setText(appdata.erstellsemester.split(" ")[1])
|
|
self.check_eternal_app.setChecked(appdata.dauerapp)
|
|
self.prof_id_adis.setText(str(appdata.prof_adis_id))
|
|
self.apparat_id_adis.setText(str(appdata.apparat_adis_id))
|
|
self.app_group_box.setEnabled(True)
|
|
self.groupBox_2.hide()
|
|
self.groupBox.hide()
|
|
self.validateLoadedData()
|
|
|
|
def validateLoadedData(self):
|
|
self.validate_prof_mail()
|
|
self.validate_prof_name()
|
|
self.validate_prof_tel()
|
|
self.validate_app_name()
|
|
self.validate_app_fach()
|
|
self.validate_semester()
|
|
|
|
def update_apparat(self):
|
|
appdata = ApparatData()
|
|
appdata.app_fach = self.app_fach.currentText()
|
|
appdata.appname = self.app_name.text()
|
|
appdata.appnr = self.active_apparat
|
|
appdata.dauerapp = self.check_eternal_app.isChecked()
|
|
appdata.prof_mail = self.prof_mail.text()
|
|
appdata.prof_tel = self.prof_tel_nr.text()
|
|
appdata.prof_title = self.prof_title.text()
|
|
appdata.profname = self.drpdwn_prof_name.currentText()
|
|
appdata.semester = (
|
|
self.sem_sommer.text() + " " + self.sem_year.text()
|
|
if self.sem_sommer.isChecked()
|
|
else self.sem_winter.text() + " " + self.sem_year.text()
|
|
)
|
|
appdata.prof_adis_id = self.prof_id_adis.text()
|
|
self.add_files()
|
|
appdata.apparat_adis_id = self.apparat_id_adis.text()
|
|
|
|
self.db.updateApparat(appdata)
|
|
|
|
self.update_app_media_list()
|
|
self.cancel_active_selection.click()
|
|
self.check_send_mail.show()
|
|
self.chkbx_show_del_media.show()
|
|
self.cancel_active_selection.setEnabled(False)
|
|
|
|
def confirm_popup(self, message: str, title: str):
|
|
popup = popus_confirm(title=title)
|
|
popup.textEdit.setReadOnly(True)
|
|
popup.textEdit.setText(message)
|
|
|
|
popup.exec()
|
|
return popup.result()
|
|
|
|
def thread_check(self):
|
|
print("Thread started")
|
|
self.prof_mail.textChanged.connect(self.validate_prof_mail)
|
|
self.drpdwn_prof_name.editTextChanged.connect(self.validate_prof_name)
|
|
self.prof_tel_nr.textChanged.connect(self.validate_prof_tel)
|
|
self.app_name.textChanged.connect(self.validate_app_name)
|
|
self.app_fach.currentTextChanged.connect(self.validate_app_fach)
|
|
self.sem_year.textChanged.connect(self.validate_semester)
|
|
self.check_eternal_app.stateChanged.connect(self.validate_semester)
|
|
|
|
# else:
|
|
# pass
|
|
# # self.drpdwn_prof_name.setStyleSheet("border: 1px solid black;")
|
|
|
|
# Validators
|
|
def __setValidState(self, widget, state, mand, index):
|
|
if state:
|
|
Icon("valid_true", widget)
|
|
mand.setText("")
|
|
self.change_state(index, 1)
|
|
else:
|
|
Icon("valid_false", widget)
|
|
mand.setText("*")
|
|
self.change_state(index, 0)
|
|
|
|
def validate_prof_name(self):
|
|
if (
|
|
self.app_group_box.isEnabled()
|
|
and "," in self.drpdwn_prof_name.currentText()
|
|
):
|
|
self.__setValidState(self.valid_check_profname, 1, self.profname_mand, 0)
|
|
else:
|
|
self.__setValidState(self.valid_check_profname, 0, self.profname_mand, 0)
|
|
|
|
def validate_prof_mail(self):
|
|
if self.app_group_box.isEnabled():
|
|
if self.prof_mail.hasAcceptableInput():
|
|
self.__setValidState(self.valid_check_mail, 1, self.mail_mand, 1)
|
|
else:
|
|
self.__setValidState(self.valid_check_mail, 0, self.mail_mand, 1)
|
|
else:
|
|
self.__setValidState(self.valid_check_mail, 0, self.mail_mand, 1)
|
|
|
|
def validate_prof_tel(self):
|
|
if self.app_group_box.isEnabled():
|
|
if self.prof_tel_nr.text() != "" and self.prof_tel_nr.hasAcceptableInput():
|
|
self.__setValidState(self.valid_check_telnr, 1, self.telnr_mand, 2)
|
|
else:
|
|
self.__setValidState(self.valid_check_telnr, 0, self.telnr_mand, 2)
|
|
else:
|
|
self.__setValidState(self.valid_check_telnr, 0, self.telnr_mand, 2)
|
|
|
|
def validate_app_name(self):
|
|
if self.app_group_box.isEnabled() and self.app_name.hasAcceptableInput():
|
|
self.__setValidState(self.valid_check_appname, 1, self.appname_mand, 3)
|
|
else:
|
|
self.__setValidState(self.valid_check_appname, 0, self.appname_mand, 3)
|
|
|
|
def validate_app_fach(self):
|
|
if self.app_group_box.isEnabled() and self.app_fach.currentText() != "":
|
|
self.__setValidState(self.valid_check_app_fach, 1, self.fach_mand, 4)
|
|
else:
|
|
self.__setValidState(self.valid_check_app_fach, 0, self.fach_mand, 4)
|
|
|
|
def validate_semester(self):
|
|
if (
|
|
self.app_group_box.isEnabled()
|
|
and (
|
|
(self.sem_sommer.isChecked() or self.sem_winter.isChecked())
|
|
and self.sem_year.text() != ""
|
|
and len(self.sem_year.text()) == 4
|
|
)
|
|
or self.check_eternal_app.isChecked()
|
|
):
|
|
self.__setValidState(self.valid_check_semester, 1, self._mand, 5)
|
|
self.check_eternal_app.setEnabled(True)
|
|
else:
|
|
self.__setValidState(self.valid_check_semester, 0, self._mand, 5)
|
|
self.check_eternal_app.setEnabled(False)
|
|
|
|
def change_state(self, index, state):
|
|
global valid_input
|
|
valid_input = list(valid_input)
|
|
valid_input[index] = state
|
|
valid_input = tuple(valid_input)
|
|
|
|
def set_state(self):
|
|
# set state of semester and year
|
|
if self.check_eternal_app.isChecked():
|
|
self.sem_winter.setEnabled(False)
|
|
self.sem_sommer.setEnabled(False)
|
|
self.sem_year.setEnabled(False)
|
|
else:
|
|
self.sem_winter.setEnabled(True)
|
|
self.sem_sommer.setEnabled(True)
|
|
self.sem_year.setEnabled(True)
|
|
|
|
def validate_fields(self):
|
|
return all(valid_input)
|
|
|
|
def set_prof_data(self):
|
|
if "," not in self.drpdwn_prof_name.currentText():
|
|
self.prof_mail.clear()
|
|
self.prof_tel_nr.clear()
|
|
return
|
|
selected_prof = self.drpdwn_prof_name.currentText()
|
|
data = self.db.getProfData(selected_prof)
|
|
# ic(data)
|
|
prof_title = data[2]
|
|
if prof_title == "None":
|
|
prof_title = "Kein Titel"
|
|
self.prof_title.setText(prof_title)
|
|
self.prof_tel_nr.setText(data[1])
|
|
self.prof_mail.setText(data[0])
|
|
|
|
def get_index_of_value(self, table_widget, value):
|
|
for i in range(table_widget.rowCount()):
|
|
for j in range(table_widget.columnCount()):
|
|
if (
|
|
table_widget.item(i, j) is not None
|
|
and table_widget.item(i, j).text() == value
|
|
):
|
|
return i, j
|
|
return (None, None)
|
|
|
|
def load_app_data(self, app_id=None):
|
|
self.cancel_active_selection.setEnabled(True)
|
|
if isinstance(app_id, str):
|
|
# double click the tableWidget_apparate row with the given app_id
|
|
row, column = self.get_index_of_value(self.tableWidget_apparate, app_id)
|
|
if row is None and column is None:
|
|
return False
|
|
# set the current index to the row
|
|
self.tableWidget_apparate.setCurrentCell(row, 0)
|
|
self.check_send_mail.hide()
|
|
app_pos = self.tableWidget_apparate.currentIndex()
|
|
appnr = self.tableWidget_apparate.item(app_pos.row(), 0).text()
|
|
appname = self.tableWidget_apparate.item(app_pos.row(), 1).text()
|
|
self.sem_sommer.setEnabled(False)
|
|
self.sem_winter.setEnabled(False)
|
|
self.sem_year.setEnabled(False)
|
|
self.dokument_list.setRowCount(0)
|
|
self.chkbx_show_del_media.setEnabled(True)
|
|
appdata = self.db.getApparatData(appnr, appname)
|
|
self.populate_frame(appdata)
|
|
self.btn_apparat_save.hide()
|
|
self.btn_reserve.show()
|
|
self.chkbx_show_del_media.show()
|
|
self.groupBox_2.show()
|
|
self.groupBox.show()
|
|
|
|
self.drpdwn_app_nr.setDisabled(True)
|
|
self.update_app_media_list()
|
|
self.update_documemt_list()
|
|
return True
|
|
|
|
def update_documemt_list(self):
|
|
app_id = self.active_apparat
|
|
prof_id = self.db.getProfId(
|
|
self.drpdwn_prof_name.currentText().replace(", ", " ")
|
|
)
|
|
files = self.db.getFiles(app_id, prof_id)
|
|
for file in files:
|
|
self.dokument_list.insertRow(0)
|
|
self.dokument_list.setItem(0, 0, QtWidgets.QTableWidgetItem(file[0]))
|
|
self.dokument_list.setItem(0, 1, QtWidgets.QTableWidgetItem(file[1]))
|
|
self.dokument_list.setItem(0, 2, QtWidgets.QTableWidgetItem(""))
|
|
self.dokument_list.setItem(0, 3, QtWidgets.QTableWidgetItem("Database"))
|
|
|
|
def btn_create_new_apparat(self):
|
|
self.groupBox.show()
|
|
self.groupBox_2.show()
|
|
global valid_input
|
|
# *create a new apparat
|
|
self.btn_apparat_save.show() if self.btn_apparat_save.isHidden() else None
|
|
# clear dokumemt_list
|
|
self.dokument_list.setRowCount(0)
|
|
self.cancel_active_selection.setEnabled(True)
|
|
self.app_group_box.setEnabled(True)
|
|
|
|
self.sem_year.setEnabled(True)
|
|
self.sem_sommer.setEnabled(True)
|
|
self.sem_winter.setEnabled(True)
|
|
self.chkbx_show_del_media.setEnabled(True)
|
|
self.drpdwn_app_nr.setEnabled(True)
|
|
self.app_fach.setEnabled(True)
|
|
|
|
if self.tableWidget_apparat_media.rowCount() > 0:
|
|
self.tableWidget_apparat_media.setRowCount(0)
|
|
# clear all fields
|
|
for item in self.app_group_box.findChildren(QtWidgets.QLineEdit):
|
|
item.clear()
|
|
self.drpdwn_app_nr.clear()
|
|
self.prof_title.clear()
|
|
self.drpdwn_prof_name.clear()
|
|
# set drop down menu for apparat numbers to only available numbers
|
|
self.drpdwn_app_nr.addItems(
|
|
[str(i) for i in APP_NRS if i not in self.db.getUnavailableApparatNumbers()]
|
|
)
|
|
|
|
valid_input = (0, 0, 0, 0, 0, 0)
|
|
self.populate_prof_dropdown()
|
|
|
|
def update_progress_label(self, curr, total):
|
|
text = f"Medium {curr}/{total}"
|
|
self.logger.log_info(text)
|
|
self.progress_label.setText(text)
|
|
# update tableWidget_apparat_media
|
|
self.update_app_media_list()
|
|
|
|
def hide_progress_label(self):
|
|
self.logger.log_info("Finished adding media, hiding progress label")
|
|
self.progress_label.hide()
|
|
self.progress_label.setText("Bitte warten...")
|
|
self.line_2.hide()
|
|
self.label_info.hide()
|
|
|
|
def btn_add_medium(self):
|
|
if not self.app_group_box.isEnabled():
|
|
self.confirm_popup("Bitte erst einen Apparat auswählen!", title="Fehler")
|
|
return
|
|
|
|
media = medienadder_ui()
|
|
media.exec()
|
|
mode = media.mode
|
|
data = media.data
|
|
result = media.result()
|
|
|
|
self.progress_label.show()
|
|
self.line_2.show()
|
|
self.label_info.show()
|
|
self.progress_label.setText("Bitte warten...")
|
|
if result == 1:
|
|
if data == []:
|
|
self.confirm_popup(
|
|
"Bitte mindestens ein Medium hinzufügen!", title="Fehler"
|
|
)
|
|
|
|
app_id = self.active_apparat
|
|
prof_id = self.db.getProfId(self.drpdwn_prof_name.currentText())
|
|
# check if app_id is in database
|
|
if not self.db.checkApparatExists(app_id):
|
|
# create apparat
|
|
self.btn_save_apparat(False)
|
|
# create a thread that updates the progress label after each medium
|
|
|
|
# self.bookGrabber = None
|
|
bookGrabber = BookGrabber()
|
|
bookGrabber.add_values(mode=mode, prof_id=prof_id, app_id=app_id, data=data)
|
|
bookGrabber.finished.connect(self.hide_progress_label)
|
|
bookGrabber.finished.connect(self.update_app_media_list)
|
|
bookGrabber.updateSignal.connect(self.update_progress_label)
|
|
|
|
bookGrabber.start()
|
|
# while self.bookGrabber[-1].isRunning():
|
|
# print("waiting for thread to finish")
|
|
# QtWidgets.QApplication.processEvents()
|
|
|
|
self.__clear_fields()
|
|
|
|
else:
|
|
return
|
|
|
|
def check_availability(self):
|
|
# self.threadeds.clear()
|
|
|
|
def _update_progress(current, all_titles):
|
|
self.avail_status.setText("{}/{}".format(current, all_titles))
|
|
|
|
def _hide_progress_label():
|
|
self.label_20.hide()
|
|
self.avail_status.hide()
|
|
self.avail_status.setText("0/0")
|
|
|
|
# get all links from the table
|
|
# if no index in tableWidget_apparat_media is selected, check all
|
|
if self.tableWidget_apparat_media.currentRow() == -1:
|
|
links = [
|
|
self.tableWidget_apparat_media.item(i, 1).text()
|
|
for i in range(self.tableWidget_apparat_media.rowCount())
|
|
if self.tableWidget_apparat_media.item(i, 4).text() == "❌"
|
|
or self.tableWidget_apparat_media.item(i, 4).text() == ""
|
|
]
|
|
else:
|
|
links = [
|
|
self.tableWidget_apparat_media.item(
|
|
self.tableWidget_apparat_media.currentRow(), 1
|
|
).text()
|
|
]
|
|
items = len(links)
|
|
self.label_20.setText("Verfügbarkeit wird geprüft, bitte warten...")
|
|
self.label_20.show()
|
|
self.avail_status.setText(f"0/{items}")
|
|
self.avail_status.show()
|
|
books = self.db.getBooks(
|
|
self.active_apparat,
|
|
self.db.getProfId(self.drpdwn_prof_name.currentText()),
|
|
deleted=0,
|
|
)
|
|
|
|
# thread = QThread()
|
|
appnumber = self.active_apparat
|
|
print(links)
|
|
self.availChecker = AvailChecker(links, appnumber, books=books)
|
|
# availcheck.moveToThread(thread)
|
|
# availcheck.finished.connect(thread.quit)
|
|
self.availChecker.finished.connect(self.availChecker.deleteLater)
|
|
self.availChecker.finished.connect(self.update_app_media_list)
|
|
self.availChecker.updateProgress.connect(_update_progress)
|
|
self.availChecker.finished.connect(_hide_progress_label)
|
|
self.availChecker.start()
|
|
# kill availcheck after completion
|
|
|
|
# self.threadeds.append(thread)
|
|
# self.grabbers.append(availcheck)
|
|
|
|
def btn_cancel_active_selection(self):
|
|
# clear the rows of the table
|
|
self.tableWidget_apparat_media.setRowCount(0)
|
|
self.dokument_list.setRowCount(0)
|
|
self.app_group_box.setEnabled(False)
|
|
self.app_fach.setCurrentText("")
|
|
self.chkbx_show_del_media.hide()
|
|
self.check_send_mail.hide()
|
|
self.btn_reserve.hide()
|
|
self.groupBox_2.hide()
|
|
self.groupBox.hide()
|
|
self.check_eternal_app.setEnabled(False)
|
|
# set all radio buttons to unchecked
|
|
self.sem_sommer.setChecked(False)
|
|
self.sem_winter.setChecked(False)
|
|
|
|
for child in self.app_group_box.findChildren(QtWidgets.QLineEdit):
|
|
child.clear()
|
|
self.validate_app_fach()
|
|
self.validate_app_name()
|
|
self.validate_prof_mail()
|
|
self.validate_prof_name()
|
|
self.validate_prof_tel()
|
|
self.validate_semester()
|
|
|
|
def update_app_media_list(self):
|
|
deleted = 0 if not self.chkbx_show_del_media.isChecked() else 1
|
|
app_id = self.active_apparat
|
|
prof_id = self.db.getProfId(self.drpdwn_prof_name.currentText())
|
|
books: list[dict[int, BookData, int]] = self.db.getBooks(
|
|
app_id, prof_id, deleted
|
|
)
|
|
|
|
# print(books)
|
|
# take the dataclass from the tuple
|
|
# booklist:list[BookData]=[book[0] for book in books]
|
|
self.tableWidget_apparat_media.setRowCount(0)
|
|
for book in books:
|
|
book["id"]
|
|
book_data = book["bookdata"]
|
|
availability = book["available"]
|
|
# bd = BookData().from_string(book)
|
|
# print(bd, type(bd))
|
|
# create a new row below the last one
|
|
self.tableWidget_apparat_media.insertRow(
|
|
self.tableWidget_apparat_media.rowCount()
|
|
)
|
|
# #set the data
|
|
self.tableWidget_apparat_media.setItem(
|
|
self.tableWidget_apparat_media.rowCount() - 1,
|
|
0,
|
|
QtWidgets.QTableWidgetItem(book_data.title),
|
|
)
|
|
self.tableWidget_apparat_media.setItem(
|
|
self.tableWidget_apparat_media.rowCount() - 1,
|
|
1,
|
|
QtWidgets.QTableWidgetItem(book_data.signature),
|
|
)
|
|
self.tableWidget_apparat_media.setItem(
|
|
self.tableWidget_apparat_media.rowCount() - 1,
|
|
2,
|
|
QtWidgets.QTableWidgetItem(book_data.edition),
|
|
)
|
|
self.tableWidget_apparat_media.setItem(
|
|
self.tableWidget_apparat_media.rowCount() - 1,
|
|
3,
|
|
QtWidgets.QTableWidgetItem(book_data.author),
|
|
)
|
|
self.tableWidget_apparat_media.setItem(
|
|
self.tableWidget_apparat_media.rowCount() - 1,
|
|
6,
|
|
QtWidgets.QTableWidgetItem(book_data.link),
|
|
)
|
|
if availability == 1:
|
|
# display green checkmark at column 4 in the row
|
|
self.tableWidget_apparat_media.setItem(
|
|
self.tableWidget_apparat_media.rowCount() - 1,
|
|
4,
|
|
QtWidgets.QTableWidgetItem("✅"),
|
|
)
|
|
# set tooltip
|
|
self.tableWidget_apparat_media.item(
|
|
self.tableWidget_apparat_media.rowCount() - 1, 4
|
|
).setToolTip("Das Medium wurde im Apparat gefunden")
|
|
else:
|
|
self.tableWidget_apparat_media.setItem(
|
|
self.tableWidget_apparat_media.rowCount() - 1,
|
|
4,
|
|
QtWidgets.QTableWidgetItem("❌"),
|
|
)
|
|
self.tableWidget_apparat_media.item(
|
|
self.tableWidget_apparat_media.rowCount() - 1, 4
|
|
).setToolTip("Das Medium wurde nicht im Apparat gefunden")
|
|
|
|
# make table link clickable
|
|
self.tableWidget_apparat_media.itemClicked.connect(self.open_link)
|
|
|
|
def open_link(self, item):
|
|
def __openLink(link):
|
|
if link == "":
|
|
return
|
|
if "http" not in link:
|
|
link = "https://" + link
|
|
return link
|
|
#
|
|
|
|
# get the name of the column
|
|
columnname = self.tableWidget_apparat_media.horizontalHeaderItem(
|
|
item.column()
|
|
).text()
|
|
if columnname == "Link":
|
|
link = __openLink(item.text())
|
|
if link is not None:
|
|
webbrowser.open(link)
|
|
return
|
|
else:
|
|
pass
|
|
|
|
def text_to_clipboard(self):
|
|
app_id = self.active_apparat
|
|
text = f"SQ=select distinct akkey from aupr01 where aufst='{app_id}' union select pr_isn from aks4pd where akruf ='{app_id}'"
|
|
clipboard = QtWidgets.QApplication.clipboard()
|
|
clipboard.setText(text)
|
|
|
|
def populate_prof_dropdown(self):
|
|
profs = self.db.getProfs()
|
|
# add empty entry to dropdown and set it as current
|
|
self.drpdwn_prof_name.addItem("Kein Name")
|
|
for prof in profs:
|
|
self.drpdwn_prof_name.addItem(f"{prof[3]}, {prof[2]}")
|
|
|
|
def add_document(self):
|
|
print("Add document")
|
|
picker = FilePicker()
|
|
files = picker.pick_files()
|
|
for file in files:
|
|
print(file)
|
|
filename = file.split("/")[-1]
|
|
filetype = filename.split(".")[-1]
|
|
self.dokument_list.insertRow(0)
|
|
self.dokument_list.setItem(0, 0, QtWidgets.QTableWidgetItem(filename))
|
|
self.dokument_list.setItem(0, 1, QtWidgets.QTableWidgetItem(filetype))
|
|
self.dokument_list.setItem(0, 2, QtWidgets.QTableWidgetItem("*"))
|
|
self.dokument_list.setItem(0, 3, QtWidgets.QTableWidgetItem(file))
|
|
# set tooltip of row 3 to the file path for each row
|
|
self.dokument_list.item(0, 3).setToolTip(file)
|
|
|
|
# self.add_files()
|
|
|
|
def open_document(self):
|
|
_selected_doc_name = ""
|
|
_selected_doc_filetype = ""
|
|
try:
|
|
_selected_doc_name = self.dokument_list.item(
|
|
self.dokument_list.currentRow(), 0
|
|
).text()
|
|
_selected_doc_location = self.dokument_list.item(
|
|
self.dokument_list.currentRow(), 3
|
|
).text()
|
|
_selected_doc_filetype = self.dokument_list.item(
|
|
self.dokument_list.currentRow(), 1
|
|
).text()
|
|
except AttributeError:
|
|
self.confirm_popup("Bitte erst ein Dokument auswählen!", title="Fehler")
|
|
return
|
|
if not _selected_doc_location == "Database":
|
|
path = Path(_selected_doc_location)
|
|
path: Path = path.resolve()
|
|
path = path + "/" + _selected_doc_name
|
|
if os.getenv("OS") == "Windows_NT":
|
|
path = path.resolve()
|
|
os.startfile(path)
|
|
else:
|
|
path = path.resolve()
|
|
os.system(f"open {path}")
|
|
else:
|
|
recreateFile(
|
|
_selected_doc_name, self.active_apparat, filetype=_selected_doc_filetype
|
|
)
|
|
# # if ~ in path, replace it with the home directory
|
|
# if "~" in path:
|
|
# path = path.replace("~", str(Path.home()))
|
|
# path = Path(path)
|
|
|
|
def add_media_from_file(self):
|
|
def __open_dialog(signatures):
|
|
dialog = QtWidgets.QDialog()
|
|
frame = parsed_titles_ui()
|
|
frame.setupUi(dialog)
|
|
dialog.show()
|
|
frame.signatures = signatures
|
|
frame.populate_table()
|
|
frame.progressBar.setMaximum(len(signatures))
|
|
frame.progressBar.setValue(0)
|
|
frame.progressBar.show()
|
|
frame.count.setText(str(len(signatures)))
|
|
frame.toolButton.click()
|
|
data = frame.return_data()
|
|
print(data)
|
|
# if no data was returned, return
|
|
|
|
return data
|
|
# get
|
|
|
|
# if files are in the table, and are selected, check for books in the file
|
|
if self.dokument_list.rowCount() == 0:
|
|
return
|
|
else:
|
|
# if file is selected, check for books in the file
|
|
if self.dokument_list.currentRow() != -1:
|
|
print("File selected")
|
|
file = self.dokument_list.item(
|
|
self.dokument_list.currentRow(), 3
|
|
).text()
|
|
|
|
file_type = self.dokument_list.item(
|
|
self.dokument_list.currentRow(), 1
|
|
).text()
|
|
file_location = self.dokument_list.item(
|
|
self.dokument_list.currentRow(), 3
|
|
).text()
|
|
file_name = self.dokument_list.item(
|
|
self.dokument_list.currentRow(), 0
|
|
).text()
|
|
if file_location == "Database":
|
|
# create a temporaty file to use, delete it after use
|
|
temp_file = tempfile.NamedTemporaryFile(
|
|
delete=False, suffix="." + file_type
|
|
)
|
|
temp_file.write(
|
|
self.db.getBlob(file_name, int(self.active_apparat))
|
|
)
|
|
temp_file.close()
|
|
file = temp_file.name
|
|
print(file)
|
|
if file_type == "pdf":
|
|
# Todo: implement parser here
|
|
self.confirm_popup(
|
|
"PDF Dateien werden nochnicht unterstützt!", title="Fehler"
|
|
)
|
|
return
|
|
if file_type == "csv":
|
|
signatures = csv_to_list(file)
|
|
data = __open_dialog(signatures)
|
|
# get the app_id and prof_id
|
|
app_id = self.active_apparat
|
|
prof_id = self.db.getProfId(self.drpdwn_prof_name.currentText())
|
|
# add the data to the database
|
|
for book in data:
|
|
if type(book) != BookData:
|
|
continue
|
|
self.db.addBookToDatabase(
|
|
bookdata=book, app_id=app_id, prof_id=prof_id
|
|
)
|
|
if file_type == "docx":
|
|
data = word_docx_to_csv(file)
|
|
signatures = [
|
|
i
|
|
for i in data["Standnummer"].values
|
|
if i != "\u2002\u2002\u2002\u2002\u2002"
|
|
]
|
|
data = __open_dialog(signatures)
|
|
# if no data was returned, return
|
|
if data == []:
|
|
return
|
|
# get the app_id and prof_id
|
|
app_id = self.active_apparat
|
|
prof_id = self.db.getProfId(self.drpdwn_prof_name.currentText())
|
|
# add the data to the database
|
|
for book in data:
|
|
if type(book) != BookData:
|
|
continue
|
|
self.db.addBookToDatabase(
|
|
bookdata=book, app_id=app_id, prof_id=prof_id
|
|
)
|
|
self.update_app_media_list()
|
|
print(len(signatures))
|
|
|
|
def btn_check_file_threaded(self):
|
|
print("Checking file")
|
|
# get active app_id and prof_id
|
|
self.tableWidget_apparate.setEnabled(False)
|
|
self.tableWidget_apparate.setToolTip(
|
|
"Bitte warten, bis alle Medien hinzugefügt wurden"
|
|
)
|
|
app_id = self.active_apparat
|
|
prof_id = self.db.getProfId(self.drpdwn_prof_name.currentText())
|
|
# check if apparat in database
|
|
|
|
# if app_id not in database, create apparat
|
|
created = False
|
|
if not self.db.checkApparatExistsById(app_id):
|
|
# create apparat
|
|
print("Creating apparat")
|
|
self.btn_save_apparat(False)
|
|
created = True
|
|
prof_id = self.db.getProfId(self.drpdwn_prof_name.currentText())
|
|
if self.dokument_list.rowCount() == 0:
|
|
print("No file selected")
|
|
self.tableWidget_apparate.setEnabled(True)
|
|
self.tableWidget_apparate.setToolTip("")
|
|
return
|
|
else:
|
|
# if file is selected, check for books in the file
|
|
print("File selected")
|
|
file = self.dokument_list.item(self.dokument_list.currentRow(), 3).text()
|
|
|
|
file_type = self.dokument_list.item(
|
|
self.dokument_list.currentRow(), 1
|
|
).text()
|
|
file_location = self.dokument_list.item(
|
|
self.dokument_list.currentRow(), 3
|
|
).text()
|
|
file_name = self.dokument_list.item(
|
|
self.dokument_list.currentRow(), 0
|
|
).text()
|
|
if file_location == "Database":
|
|
file = recreateFile(file_name, app_id, file_type, open=False)
|
|
else:
|
|
if not created:
|
|
self.add_files()
|
|
if file_type == "pdf":
|
|
# Todo: implement parser here
|
|
self.confirm_popup(
|
|
"PDF Dateien werden noch nicht unterstützt!", title="Fehler"
|
|
)
|
|
return
|
|
if file_type == "csv":
|
|
signatures = csv_to_list(file)
|
|
# add the data to the database
|
|
if file_type == "docx":
|
|
data = word_docx_to_csv(file)
|
|
signatures = [
|
|
i
|
|
for i in data["Standnummer"].values
|
|
if i != "\u2002\u2002\u2002\u2002\u2002"
|
|
]
|
|
|
|
signatures = [i for i in signatures if i != ""]
|
|
# ic(signatures)
|
|
print("starting thread")
|
|
|
|
autoGrabber = BookGrabber()
|
|
autoGrabber.add_values(
|
|
mode="ARRAY", app_id=app_id, prof_id=prof_id, data=signatures
|
|
)
|
|
self.label_info.show()
|
|
self.progress_label.show()
|
|
self.line_2.show()
|
|
# grabber.finished.connect(thread.quit)
|
|
# self.autoGrabber.finished.connect(self.autoGrabber.deleteLater)
|
|
autoGrabber.finished.connect(self.hide_progress_label)
|
|
autoGrabber.finished.connect(self.unlock_apparate)
|
|
|
|
autoGrabber.updateSignal.connect(self.update_progress_label)
|
|
# worker.finished.connect(worker.deleteLater)
|
|
|
|
autoGrabber.start()
|
|
while autoGrabber.isRunning():
|
|
QtWidgets.QApplication.processEvents()
|
|
# end of thread
|
|
# self.autoGrabber.exit()
|
|
# self.__clear_fields()
|
|
# self.btn_cancel_active_selection()
|
|
|
|
def unlock_apparate(self):
|
|
self.tableWidget_apparate.setEnabled(True)
|
|
self.tableWidget_apparate.setToolTip("")
|
|
|
|
def __clear_fields(self):
|
|
self.drpdwn_app_nr.setCurrentText("")
|
|
self.prof_title.clear()
|
|
self.drpdwn_prof_name.clearMask()
|
|
self.drpdwn_prof_name.setCurrentText("")
|
|
self.app_name.clear()
|
|
self.prof_mail.clear()
|
|
self.prof_tel_nr.clear()
|
|
self.app_fach.setCurrentText("")
|
|
self.app_name.clear()
|
|
self.sem_year.clear()
|
|
self.dokument_list.setRowCount(0)
|
|
self.sem_winter.setChecked(False)
|
|
self.sem_sommer.setChecked(False)
|
|
self.check_eternal_app.setChecked(False)
|
|
self.prof_id_adis.clear()
|
|
self.prof_id_adis.clear()
|
|
self.apparat_id_adis.clear()
|
|
self.drpdwn_prof_name.clear()
|
|
self.tableWidget_apparat_media.setRowCount(0)
|
|
self.app_group_box.setEnabled(False)
|
|
self.groupBox_2.hide()
|
|
self.groupBox.hide()
|
|
self.check_send_mail.setChecked(False)
|
|
self.cancel_active_selection.setEnabled(False)
|
|
|
|
def btn_save_apparat(self, clear_fields=True):
|
|
if not self.validate_fields():
|
|
self.confirm_popup("Bitte alle Pflichtfelder ausfüllen!", title="Fehler")
|
|
return
|
|
appd = ApparatData()
|
|
appd.appnr = self.active_apparat
|
|
appd.prof_title = (
|
|
None if self.prof_title.text() == "" else self.prof_title.text()
|
|
)
|
|
appd.profname = self.drpdwn_prof_name.currentText()
|
|
appd.appname = self.app_name.text()
|
|
appd.semester = self.generateSemester()
|
|
appd.dauerapp = 1 if self.check_eternal_app.isChecked() else 0
|
|
appd.prof_tel = self.prof_tel_nr.text()
|
|
appd.prof_mail = self.prof_mail.text()
|
|
appd.app_fach = self.app_fach.currentText()
|
|
appd.erstellsemester = self.generateSemester()
|
|
appd.deleted = 0
|
|
appd.prof_adis_id = self.prof_id_adis.text()
|
|
appd.apparat_adis_id = self.apparat_id_adis.text()
|
|
if self.dokument_list.rowCount() > 0:
|
|
self.add_files()
|
|
if not self.validate_fields():
|
|
pass
|
|
self.db.createApparat(appd)
|
|
# if self.dokument_list.rowCount() > 0:
|
|
# self.add_files()
|
|
appdata = self.db.getAllAparats()
|
|
# merge self.appdata and appdata, remove duplicates
|
|
self.apparats = list(set(self.apparats + appdata))
|
|
self.apparats = natsorted(self.apparats, key=lambda x: x[4], reverse=True)
|
|
self.update_apparat_list()
|
|
|
|
# self.btn_load_apparat()
|
|
|
|
if self.check_send_mail.isChecked():
|
|
self.contact_prof(
|
|
apparat=appd.appnr, mail="Information zum Semesterapparat", location=""
|
|
)
|
|
if clear_fields:
|
|
print("clearing fields")
|
|
self.__clear_fields()
|
|
|
|
def send_mail_preview(self):
|
|
pass
|
|
|
|
@property
|
|
def active_apparat(self):
|
|
return self.drpdwn_app_nr.currentText()
|
|
|
|
def add_files(self):
|
|
files = []
|
|
for i in range(self.dokument_list.rowCount()):
|
|
files.append(
|
|
{
|
|
"name": self.dokument_list.item(i, 0).text(),
|
|
"type": self.dokument_list.item(i, 1).text(),
|
|
"date": self.dokument_list.item(i, 2).text(),
|
|
"path": self.dokument_list.item(i, 3).text(),
|
|
}
|
|
)
|
|
self.dokument_list.item(i, 2).setText("")
|
|
|
|
self.db.insertFile(
|
|
files,
|
|
self.active_apparat,
|
|
self.db.getProfId(self.drpdwn_prof_name.currentText()),
|
|
)
|
|
|
|
def update_apparat_list(self):
|
|
# get a list of new apparats based on self.apparats and self.old_apparats
|
|
new_apparats = [
|
|
apparat for apparat in self.apparats if apparat not in self.old_apparats
|
|
]
|
|
print(new_apparats)
|
|
# insert the new apparats into the table
|
|
for apparat in new_apparats:
|
|
self.insert_apparat_into_table(apparat)
|
|
# sort the table by apparat number using natural sorting
|
|
self.tableWidget_apparate.sortItems(0, QtCore.Qt.SortOrder.AscendingOrder)
|
|
self.old_apparats = self.apparats
|
|
|
|
def insert_apparat_into_table(self, apparat):
|
|
# ic(apparat)
|
|
def __dauer_check(apparat):
|
|
return "Ja" if apparat[7] == 1 else "Nein"
|
|
|
|
self.tableWidget_apparate.insertRow(0)
|
|
self.tableWidget_apparate.setItem(
|
|
0, 0, QtWidgets.QTableWidgetItem(str(apparat[4]))
|
|
)
|
|
self.tableWidget_apparate.setItem(
|
|
0, 1, QtWidgets.QTableWidgetItem(str(apparat[1]))
|
|
)
|
|
self.tableWidget_apparate.setItem(
|
|
0,
|
|
2,
|
|
QtWidgets.QTableWidgetItem(
|
|
self.db.getProfNameById(apparat[2], add_title=False)
|
|
),
|
|
)
|
|
self.tableWidget_apparate.setItem(
|
|
0,
|
|
3,
|
|
QtWidgets.QTableWidgetItem(
|
|
str(apparat[8]) if apparat[8] is not None else apparat[5]
|
|
),
|
|
)
|
|
self.tableWidget_apparate.setItem(
|
|
0, 4, QtWidgets.QTableWidgetItem(__dauer_check(apparat))
|
|
)
|
|
self.tableWidget_apparate.setItem(
|
|
0, 5, QtWidgets.QTableWidgetItem(str(apparat[13]))
|
|
)
|
|
self.logger.log_info(f"Inserted apparat {apparat[4]}")
|
|
|
|
def open_context_menu(self, position):
|
|
menu = QtWidgets.QMenu()
|
|
extend_action = menu.addAction("Verlängern")
|
|
contact_action = menu.addAction("Kontaktieren")
|
|
delete_action = menu.addAction("Löschen")
|
|
remind_action = menu.addAction("Erinnerung")
|
|
menu.addAction(extend_action)
|
|
menu.addActions([contact_action, delete_action, remind_action])
|
|
# convert point to row and column
|
|
row = self.tableWidget_apparate.rowAt(position.y())
|
|
column = self.tableWidget_apparate.columnAt(position.x())
|
|
pos = (str(row), str(column))
|
|
pid = self.__get_table_data_field(self.tableWidget_apparate, pos[0], 2)
|
|
|
|
ic(pos, pid)
|
|
extend_action.triggered.connect(self.extend_apparat)
|
|
delete_action.triggered.connect(lambda: self.delete_apparat(pos))
|
|
# pass pos to contact_prof
|
|
contact_action.triggered.connect(lambda: self.contact_prof(pid=pid))
|
|
remind_action.triggered.connect(self.reminder)
|
|
menu.exec(self.tableWidget_apparate.mapToGlobal(position))
|
|
|
|
def reminder(self):
|
|
self.logger.log_info("Opening reminder dialog")
|
|
dialog = QtWidgets.QDialog()
|
|
reminder = reminder_ui()
|
|
reminder.setupUi(dialog)
|
|
dialog.exec()
|
|
if dialog.result() == QtWidgets.QDialog.DialogCode.Accepted:
|
|
data = reminder.return_message()
|
|
print(data)
|
|
self.db.addMessage(
|
|
data,
|
|
self.active_user,
|
|
self.active_apparat if self.active_apparat != "" else None,
|
|
)
|
|
self.calendarWidget.setMessages([data])
|
|
self.calendarWidget.updateCells()
|
|
# self.db.update_bookdata(data, book_id)
|
|
# self.db.update_bookdata(data)
|
|
self.logger.log_info("Commited message to database")
|
|
# self.update_app_media_list()
|
|
|
|
def get_reminders(self):
|
|
messages = self.db.getAllMessages()
|
|
self.logger.log_info(f"Got {len(messages)} messages from database")
|
|
self.calendarWidget.setMessages(messages)
|
|
self.calendarWidget.updateCells()
|
|
|
|
def open_reminder(self):
|
|
# def __update_message():
|
|
# message_select = self.spin_select_message.value()
|
|
# try:
|
|
# message = messages[message_select - 1]
|
|
# except IndexError:
|
|
# self.message_frame.hide()
|
|
# return
|
|
# self.message_box.setText(message["message"])
|
|
# appnr = message["appnr"]
|
|
# appnr = "/" if appnr is None else str(appnr)
|
|
# self.line_app_info.setText(appnr)
|
|
|
|
def __delete_message(id):
|
|
print("trying to delete message", id)
|
|
self.db.deleteMessage(id)
|
|
#
|
|
|
|
selected_date = self.calendarWidget.selectedDate().toString("yyyy-MM-dd")
|
|
# print(selected_date)
|
|
messages = self.db.getMessages(selected_date)
|
|
if messages == []:
|
|
return
|
|
|
|
dialog = CalendarEntry(messages=messages, date=selected_date)
|
|
# append dialog to self.frame_2
|
|
self.calendarlayout.addWidget(dialog)
|
|
dialog.repaintSignal.connect(lambda: self.calendarWidget.reload(selected_date))
|
|
|
|
def open_settings(self):
|
|
settings = Settings(self.active_user)
|
|
settings.exec()
|
|
if settings.result() == QtWidgets.QDialog.DialogCode.Accepted:
|
|
data = settings.return_data()
|
|
print(data)
|
|
OmegaConf.save(data, "config.yaml")
|
|
# re-load the config
|
|
OmegaConf.load("config.yaml")
|
|
self.logger.log_info("Saved settings to config.yaml")
|
|
self.reload()
|
|
|
|
def reload(self):
|
|
# create a new connection to the database, refresh table data and replace the old connection
|
|
self.db = Database()
|
|
self.apparats = self.db.getAllAparats(deleted=0)
|
|
self.apparats = natsorted(self.apparats, key=lambda x: x[4], reverse=True)
|
|
self.tableWidget_apparate.setRowCount(0)
|
|
for apparat in self.apparats:
|
|
self.insert_apparat_into_table(apparat)
|
|
|
|
def media_context_menu(self, position):
|
|
menu = QtWidgets.QMenu()
|
|
delete_action = menu.addAction("Löschen")
|
|
edit_action = menu.addAction("Bearbeiten")
|
|
menu.addAction(delete_action)
|
|
menu.addAction(edit_action)
|
|
delete_action.triggered.connect(self.delete_medium)
|
|
edit_action.triggered.connect(self.edit_medium)
|
|
menu.exec(self.tableWidget_apparat_media.mapToGlobal(position))
|
|
|
|
def edit_medium(self):
|
|
book = self.tableWidget_apparat_media.item(
|
|
self.tableWidget_apparat_media.currentRow(), 1
|
|
).text()
|
|
data = self.db.getBookBasedOnSignature(
|
|
app_id=self.active_apparat,
|
|
signature=book,
|
|
prof_id=self.db.getProfId(self.drpdwn_prof_name.currentText()),
|
|
)
|
|
book_id = self.db.getBookIdBasedOnSignature(
|
|
self.active_apparat,
|
|
self.db.getProfId(self.drpdwn_prof_name.currentText()),
|
|
book,
|
|
)
|
|
widget = QtWidgets.QDialog()
|
|
bookedit = edit_bookdata_ui()
|
|
bookedit.setupUi(widget)
|
|
# change title of dialog
|
|
widget.setWindowTitle("Metadaten")
|
|
bookedit.populate_fields(data)
|
|
widget.exec()
|
|
if widget.result() == QtWidgets.QDialog.DialogCode.Accepted:
|
|
data = bookedit.get_data()
|
|
print(data)
|
|
self.db.updateBookdata(data, book_id)
|
|
# self.db.update_bookdata(data)
|
|
print("accepted")
|
|
self.update_app_media_list()
|
|
else:
|
|
return
|
|
pass
|
|
|
|
def delete_medium(self):
|
|
selected_apparat_id = self.tableWidget_apparate.item(
|
|
self.tableWidget_apparate.currentRow(), 0
|
|
).text()
|
|
# check how many rows are selected
|
|
selected_rows = self.tableWidget_apparat_media.selectionModel().selectedRows()
|
|
if len(selected_rows) == 1:
|
|
signature = self.tableWidget_apparat_media.item(
|
|
self.tableWidget_apparat_media.currentRow(), 1
|
|
).text()
|
|
book_id = self.db.getBookIdBasedOnSignature(
|
|
selected_apparat_id,
|
|
prof_id=self.db.getProfId(self.drpdwn_prof_name.currentText()),
|
|
signature=signature,
|
|
)
|
|
message = f'Soll das Medium "{self.tableWidget_apparat_media.item(self.tableWidget_apparat_media.currentRow(),0).text()}" wirklich gelöscht werden?'
|
|
state = self.confirm_popup(message, title="Löschen?")
|
|
print(state)
|
|
if state == 1:
|
|
self.db.deleteBook(book_id)
|
|
self.update_app_media_list()
|
|
self.contact_prof(mail="deleted", location="")
|
|
pass
|
|
else:
|
|
# get all selected rows
|
|
ranges = self.tableWidget_apparat_media.selectedRanges()
|
|
rows = []
|
|
for r in ranges:
|
|
for row in range(r.topRow(), r.bottomRow() + 1):
|
|
rows.append(row)
|
|
print(rows)
|
|
message = f"Sollen die {len(rows)} Medien wirklich gelöscht werden?"
|
|
state = self.confirm_popup(message, title="Löschen?")
|
|
if state == 1:
|
|
for _ in rows:
|
|
signature = self.tableWidget_apparat_media.item(_, 1).text()
|
|
book_id = self.db.getBookIdBasedOnSignature(
|
|
selected_apparat_id,
|
|
prof_id=self.db.getProfId(self.drpdwn_prof_name.currentText()),
|
|
signature=signature,
|
|
)
|
|
self.db.deleteBook(book_id)
|
|
self.update_app_media_list()
|
|
|
|
def extend_apparat(self):
|
|
framework = QtWidgets.QDialog()
|
|
frame = App_Ext_Dialog()
|
|
frame.setupUi(framework)
|
|
frame.sem_year.setText(str(QtCore.QDate.currentDate().year()))
|
|
framework.exec()
|
|
# return data from dialog if ok is pressed
|
|
if framework.result() == QtWidgets.QDialog.DialogCode.Accepted:
|
|
data = frame.get_data()
|
|
print(data)
|
|
# return data
|
|
selected_apparat_id = self.tableWidget_apparate.item(
|
|
self.tableWidget_apparate.currentRow(), 0
|
|
).text()
|
|
print(selected_apparat_id)
|
|
|
|
self.db.setNewSemesterDate(
|
|
selected_apparat_id, data["semester"], dauerapp=data["dauerapp"]
|
|
)
|
|
else:
|
|
return
|
|
|
|
def __get_table_data_field(self, table, row, column):
|
|
ic(row, column)
|
|
row = int(row)
|
|
return table.item(row, column).text()
|
|
|
|
def __contact_dialog(self, apparat, location: tuple | str, mail=None, pid=""):
|
|
ic(location, pid)
|
|
|
|
active_apparat_id = (
|
|
self.drpdwn_app_nr.currentText() if apparat is None else apparat
|
|
)
|
|
print(active_apparat_id)
|
|
|
|
profname = self.drpdwn_prof_name.currentText().replace(",", "").split(" ")
|
|
profname = f"{profname[1]} {profname[0]}"
|
|
# get the row of the clicked cell
|
|
prof_id = self.db.getProfId(pid)
|
|
if profname == "Name Kein":
|
|
profname = pid
|
|
|
|
profname = f"{profname.split(" ")[1]} {profname.split(" ")[0]}"
|
|
print(profname, pid)
|
|
if prof_id:
|
|
pmail = self.db.getSpecificProfData(prof_id, ["mail"])
|
|
else:
|
|
pmail = self.prof_mail.text()
|
|
# create a new thread to show the mail interface and send the mail
|
|
print("showing mail dialog")
|
|
self.mail_thread = Mail_Dialog(
|
|
app_id=active_apparat_id,
|
|
prof_name=pid,
|
|
prof_mail=pmail,
|
|
app_name=self.app_name.text(),
|
|
app_subject=self.app_fach.currentText(),
|
|
default_mail=mail if mail != "" else "Information zum Semesterapparat",
|
|
)
|
|
self.mail_thread.show()
|
|
|
|
def contact_prof(self, location="", apparat=None, mail="", pid=""):
|
|
print(apparat)
|
|
print("location", location)
|
|
if self.active_apparat == "":
|
|
if apparat is False:
|
|
self.confirm_popup(
|
|
"Bitte erst einen Apparat auswählen!", title="Apparat auswählen"
|
|
)
|
|
return
|
|
self.__contact_dialog(apparat, mail=mail, pid=pid, location=location)
|
|
|
|
def delete_apparat(self, position):
|
|
selected_apparat_id = self.tableWidget_apparate.item(
|
|
self.tableWidget_apparate.currentRow(), 0
|
|
).text()
|
|
message = f"Soll der Apparat {selected_apparat_id} wirklich gelöscht werden?"
|
|
state = self.confirm_popup(message, title="Löschen?")
|
|
print(state)
|
|
pid = self.__get_table_data_field(self.tableWidget_apparate, position[0], 2)
|
|
if state == 1:
|
|
self.db.deleteApparat(selected_apparat_id, generateSemesterByDate())
|
|
# delete the corresponding entry from self.apparats
|
|
for apparat in self.apparats:
|
|
if apparat[4] == int(selected_apparat_id):
|
|
self.apparats.remove(apparat)
|
|
break
|
|
self.old_apparats = self.apparats
|
|
print(self.apparats)
|
|
# remove the row from the table
|
|
self.tableWidget_apparate.removeRow(self.tableWidget_apparate.currentRow())
|
|
# send mail to prof
|
|
self.contact_prof(mail="deleted", apparat=selected_apparat_id, pid=pid)
|
|
|
|
|
|
def launch_gui():
|
|
print("trying to login")
|
|
print("checking if database available")
|
|
|
|
app = QtWidgets.QApplication(sys.argv)
|
|
login_dialog = QtWidgets.QDialog()
|
|
ui = login_ui()
|
|
ui.setupUi(login_dialog)
|
|
login_dialog.exec() # This will block until the dialog is closed
|
|
|
|
if ui.lresult == 1:
|
|
# if login is successful, open main window
|
|
# show login dialog
|
|
print(ui.lusername)
|
|
MainWindow = QtWidgets.QMainWindow()
|
|
aui = Ui(MainWindow, username=ui.lusername)
|
|
|
|
print(aui.active_user)
|
|
MainWindow.show()
|
|
# atexit.register()
|
|
atexit.register(tempdelete)
|
|
atexit.register(aui.validate_thread.quit)
|
|
sys.exit(app.exec())
|
|
|
|
elif ui.lresult == 0:
|
|
warning_dialog = QtWidgets.QMessageBox()
|
|
warning_dialog.setIcon(QtWidgets.QMessageBox.Icon.Warning)
|
|
warning_dialog.setText("Invalid username or password. Please try again.")
|
|
warning_dialog.setWindowTitle("Login Failed")
|
|
warning_dialog.exec()
|
|
elif ui.lresult == 2:
|
|
# TODO: implement admin functionality here
|
|
"""change passwords for apparats, change passwords for users, list users, create and delete users etc"""
|
|
# open a console window
|
|
# console = ""
|
|
print("admin")
|
|
atexit.register(tempdelete)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
print("This is the main window")
|
|
# app = QtWidgets.QApplication(sys.argv)
|
|
# window = MainWindow()
|
|
# app.exec()
|
|
# open login screen
|
|
launch_gui()
|