Files
SemesterapparatsManager/src/logic/userInterface.py
2024-05-24 16:30:31 +02:00

2415 lines
98 KiB
Python

# encoding: utf-8
import atexit
import os
# import re
import sys
import tempfile
import time
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 QColor, QRegularExpressionValidator
from src.backend.admin_console import AdminCommands
from src.backend.create_file import recreateElsaFile, recreateFile
from src.backend.database import Database
from src.backend.delete_temp_contents import delete_temp_contents
from src.backend.semester import generateSemesterByDate
from src.logic import AvailChecker, BookGrabber, c_sort
from src.logic.constants import APP_NRS, PROF_TITLES
from src.logic.csvparser import csv_to_list
from src.logic.dataclass import ApparatData, BookData
from src.logic.log import MyLogger
from src.logic.wordparser import elsa_word_to_csv, word_docx_to_csv
from src.ui import (
App_Ext_Dialog,
DataGraph,
FilePicker,
Mail_Dialog,
StatusWidget,
Ui_Semesterapparat,
edit_bookdata_ui,
login_ui,
medienadder_ui,
parsed_titles_ui,
popus_confirm,
reminder_ui,
settings_ui,
)
config = OmegaConf.load("config.yaml")
class Medien(medienadder_ui):
def __init__(self) -> None:
self.logger = MyLogger("Medien")
super().__init__()
self.mode = ""
self.data = []
def get_list_data(self) -> list:
signatures = self.listWidget.findItems("*", QtCore.Qt.MatchFlag.MatchWildcard)
return [signature.text() for signature in signatures]
def get_mode(self) -> str:
return self.comboBox.currentText()
class MyComboBox(QtWidgets.QComboBox):
def __init__(self, parent=None):
super().__init__(parent)
valid_input = (0, 0, 0, 0, 0, 0)
class MessageCalendar(QtWidgets.QCalendarWidget):
# Widget for MessageCalendar
def __init__(self, parent=None):
super().__init__(parent)
self.messages = {} # Dictionary to store dates with messages
def setMessages(self, messages):
for message in messages:
print(message)
# Convert the date string to a QDate object
date = QDate.fromString(message["remind_at"], "yyyy-MM-dd")
# Store the message for the date
self.messages[date] = message["message"]
self.updateCells()
def updateCells(self):
self.repaint()
def paintCell(self, painter, rect, date):
super().paintCell(painter, rect, date)
# Check if there is a message for the current date
if date in self.messages:
# If there is a message, color the cell background
painter.fillRect(rect, QColor("#a7e681"))
def change_stylesheet_cell(self, date: QDate, color: str):
# change the stylesheet of a cell
self.setStyleSheet(
f"QCalendarWidget QTableView QTableCornerButton::section {{background-color: {color};}}"
)
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")
icon = QtGui.QIcon()
icon.addPixmap(
QtGui.QPixmap("icons/logo.ico"),
QtGui.QIcon.Mode.Normal,
QtGui.QIcon.State.Off,
)
MainWindow.setWindowIcon(icon)
self.db = Database()
# self.show()
# self.setWindowTitle("Semesterapparatsmanagement")
# self.setWindowIcon(QIcon("ui\icon.png"))
# self.sem_sommer.clicked.connect(self.buttonClicked)
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.load_app.clicked.connect(self.btn_load_apparat)
self.btn_apparat_save.clicked.connect(self.btn_save_apparat)
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.setGeometry(QtCore.QRect(0, 0, 291, 191))
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.tableWidget_apparat_media.horizontalHeader().setSectionResizeMode(
QtWidgets.QHeaderView.ResizeMode.Stretch
)
self.tableWidget_apparate.horizontalHeader().setSectionResizeMode(
QtWidgets.QHeaderView.ResizeMode.Stretch
)
self.tableWidget_apparate.setSortingEnabled(True)
# self.tableWidget_apparate.text
self.actionEinstellungen.triggered.connect(self.open_settings)
# if help>documentation is clicked, open the documentation or shortcut is pressed
self.actionDokumentation.triggered.connect(self.open_documentation)
# set validators
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 the validator for the app name, allow all letters and umlauts
self.app_fach.setValidator(
QtGui.QRegularExpressionValidator(
QtCore.QRegularExpression(r"[a-zA-Z\s\W]+")
)
)
# 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
)
# connect contextmenuevent to tablewidget
# enable automatic resizing of columns for book_search_result
self.book_search_result.horizontalHeader().setSectionResizeMode(
QtWidgets.QHeaderView.ResizeMode.Stretch
)
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.frame.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.check_deletable.stateChanged.connect(self.gridchange)
self.tableWidget.horizontalHeader().setSectionResizeMode(
QtWidgets.QHeaderView.ResizeMode.Stretch
)
self.btn_del_select_apparats.clicked.connect(self.delete_selected_apparats)
self.statistics_table.doubleClicked.connect(self.display_detailed_data)
self.tabWidget_2.currentChanged.connect(self.tabW2_changed)
self.tabWidget.currentChanged.connect(self.tabW1_changed)
self.tableWidget.resizeColumnsToContents()
self.tableWidget.resizeRowsToContents()
# 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
self.tabWidget.currentChanged.connect(self.tab_changed)
self.btn_search.clicked.connect(self.statistics)
# self.thread_check()
### 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
)
self.book_search.clicked.connect(self.search_book)
# 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.tableWidget.customContextMenuRequested.connect(
self.statistics_table_context_menu
)
# statistic side buttons
self.btn_notify_for_deletion.clicked.connect(self.notify_for_deletion)
self.btn_notify_for_deletion.setEnabled(False)
# elsa buttons
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_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)
# admin buttons
self.user_frame_addUser.clicked.connect(self.add_user)
self.pushButton.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 = None
self.availChecker = None
self.mail_thread = None
self.autoGrabber = None
def add_new_elsa(self):
self.create_frame_elsa.setEnabled(True)
self.elsa_cancel_create.setEnabled(True)
self.active_semester.setEnabled(True)
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 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")
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()
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()
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)
if scans == []:
self.MainWindow.setStatusTip("ELSA-Apparat hat noch keine Daten")
self.create_frame_elsa.setEnabled(True)
else:
self.MainWindow.setStatusTip(
"ELSA-Apparat hat bereits alle benötigten Daten"
)
for scan in scans:
self.table_elsa_list.insertRow(0)
self.table_elsa_list.setItem(0, 0, QtWidgets.QTableWidgetItem(scan[1]))
self.table_elsa_list.setItem(0, 1, QtWidgets.QTableWidgetItem(scan[2]))
self.table_elsa_list.setItem(0, 2, QtWidgets.QTableWidgetItem(scan[3]))
self.table_elsa_list.setItem(0, 3, QtWidgets.QTableWidgetItem(scan[4]))
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:
# get length of elsa table
rows = self.elsa_table.rowCount()
elsa_id = rows + 1
self.db.insertElsaFile(datalist, elsa_id)
self.elsa_save.click()
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 = elsa_word_to_csv(file)
for row in data:
self.table_elsa_list.insertRow(0)
ic(row)
chapter_title = row[2]
book_title = row[4]
signature = row[7]
pages = row[6]
data = {
"chapter": chapter_title,
"title": book_title,
"signature": signature,
"pages": pages,
}
self.table_elsa_list.setItem(
0, 0, QtWidgets.QTableWidgetItem(chapter_title)
)
self.table_elsa_list.setItem(
0, 1, QtWidgets.QTableWidgetItem(book_title)
)
self.table_elsa_list.setItem(
0, 2, QtWidgets.QTableWidgetItem(signature)
)
self.table_elsa_list.setItem(0, 3, QtWidgets.QTableWidgetItem(pages))
self.db.addElsaMedia(
data,
self.db.getElsaId(
self.elsa_prof.currentText(),
self.elsa_semester.text(),
self.elsa_date.text(),
),
)
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 notify_for_deletion(self):
# get all selected apparats
selected_apparats: list[dict] = []
for i in range(self.tableWidget.rowCount()):
data = {}
if self.tableWidget.cellWidget(i, 0).isChecked():
data["app_id"] = self.tableWidget.item(i, 2).text()
data["app_name"] = self.tableWidget.item(i, 1).text()
data["prof_name"] = self.tableWidget.item(i, 3).text()
selected_apparats.append(data)
# delete all selected apparats
ic(selected_apparats)
dialogs = []
for i in selected_apparats:
app_id = i["app_id"]
app_name = i["app_name"]
prof_name = i["prof_name"]
prof_mail = self.db.getProfData(prof_name)[0]
self.mail_thread = Mail_Dialog(
app_id=app_id,
app_name=app_name,
prof_name=prof_name,
prof_mail=prof_mail,
app_subject="",
default_mail="Information bezüglich der Auflösung des Semesterapparates",
)
dialogs.append(self.mail_thread)
for dialog in dialogs:
dialog.exec()
self.btn_notify_for_deletion.setEnabled(False)
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)
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: # Statistic
# self.tabWidget.setCurrentIndex(1)
self.tabWidget_2.setCurrentIndex(1)
self.tabWidget_2.setCurrentIndex(0)
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:
pass
self.elsa_table.setRowCount(0)
elsa_apparats = self.db.getElsaApparats()
elsa_apparats = natsorted(elsa_apparats, key=lambda x: x[2], reverse=True)
graph_data = {}
for apparat in elsa_apparats:
print(apparat)
data = self.insert_elsa_into_table(apparat)
if data[0] in graph_data.keys():
graph_data["x"].append(data[0])
graph_data["y"].append(data[1])
else:
graph_data["x"] = [data[0]]
graph_data["y"] = [data[1]]
generateMissing = True if len(graph_data["x"]) > 1 else False
graph = DataGraph(
"ELSA Apparate pro Semester",
graph_data,
generateMissing,
"Anzahl der Apparate",
)
self.elsa_statistics.addTab(graph, "Graph")
def search_book(self):
self.book_search_result.setRowCount(0)
signature = self.seach_by_signature.text()
title = self.search_by_title.text()
params = {
"signature": signature if signature != "" else None,
"title": title if title != "" else None,
}
params = {key: value for key, value in params.items() if value is not None}
# ic(params)
retdata = self.db.searchBook(params)
if retdata is None:
return
for book in retdata:
self.book_search_result.insertRow(0)
self.book_search_result.setItem(
0, 0, QtWidgets.QTableWidgetItem(book[0].title)
)
self.book_search_result.setItem(
0, 1, QtWidgets.QTableWidgetItem(book[0].signature)
)
print(book[1])
self.book_search_result.setItem(
0,
2,
QtWidgets.QTableWidgetItem(self.db.getApparatName(book[1], book[2])),
)
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("")
)
# self.edit_faculty_member_name.setText(f"{data[3]} {data[2]}")
# self.edit_faculty_member_title.setCurrentText(data[1])
# self.edit_faculty_member_mail.setText(data[4])
# self.edit_faculty_member_tel.setText(data[5])
# self.edit_faculty_member_adis_id.setText(str(data[0]))
# self.edit_faculty_member_id.setText(str(data[6]))
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):
# ic("username already exists")
# self.user_create_frame_error.setText("Der Nutzername ist bereits vergeben")#TODO: implement error message
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
# ic("please confirm the deletion of the user")
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.user_create_frame.hide()
self.user_edit_frame.hide()
self.user_delete_frame.hide()
self.edit_faculty_member.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.user_create_frame.show()
self.user_frame_userrole.addItems(roles)
elif action == "Nutzer aktualisieren":
self.hide_all()
self.user_edit_frame.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.user_delete_frame.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.edit_faculty_member.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 tabW2_changed(self):
if self.tabWidget_2.currentIndex() == 0:
self.stackedWidget_4.setCurrentIndex(0)
else:
self.stackedWidget_4.setCurrentIndex(1)
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 = (
self.sem_sommer.text()
if self.sem_sommer.isChecked()
else self.sem_winter.text()
)
if semester == "Sommer":
return "SoSe " + str(currentYear)
else:
return f"WiSe {currentYear}/{currentYear+1}"
def display_detailed_data(self):
selected_semester = self.statistics_table.item(
self.statistics_table.currentRow(), 0
).text()
# get all apparats from the selected semester
data = self.db.getApparatsBySemester(selected_semester)
# replace keys for german names
# split to two lists
created = {"Erstellt": data["created"]}
deleted = {"Gelöscht": data["deleted"]}
created_status = StatusWidget(created, selected_semester)
deleted_status = StatusWidget(deleted, selected_semester)
created_status.setSizePolicy(
QtWidgets.QSizePolicy.Policy.Expanding,
QtWidgets.QSizePolicy.Policy.Expanding,
)
deleted_status.setSizePolicy(
QtWidgets.QSizePolicy.Policy.Expanding,
QtWidgets.QSizePolicy.Policy.Expanding,
)
# add them to the gridLayout_4
self.gridLayout_4.addWidget(created_status, 1, 0)
self.gridLayout_4.addWidget(deleted_status, 1, 1)
created_status.person_double_clicked.connect(self.open_apparat)
deleted_status.person_double_clicked.connect(self.open_apparat)
def open_apparat(self, header: str, apparat: str, parent_depth: int):
print(header)
if header == "deleted" and parent_depth == 2:
# TODO: warn message here
print("warning")
if parent_depth == 1:
print(apparat)
# person selected case - open all apparats from this person in the tableWidget
self.tableWidget.setRowCount(0)
prof_id = self.db.getProfId(apparat.split("(")[0].strip())
apparats = self.db.getApparatsByProf(prof_id)
for app in apparats:
print(app)
# set the items 0 = clickable checkbox, 1 = appname, 2 = profname, 3 = fach
# insert new row
self.tableWidget.insertRow(0)
self.tableWidget.setItem(0, 0, QtWidgets.QTableWidgetItem(""))
self.tableWidget.setItem(0, 1, QtWidgets.QTableWidgetItem(app[1]))
self.tableWidget.setItem(0, 2, QtWidgets.QTableWidgetItem(str(app[4])))
self.tableWidget.setItem(0, 3, QtWidgets.QTableWidgetItem(app[2]))
self.tableWidget.setItem(0, 4, QtWidgets.QTableWidgetItem(app[3]))
# replace the 0 with a checkbox
checkbox = QtWidgets.QCheckBox()
checkbox.setChecked(False)
self.tableWidget.setCellWidget(0, 0, checkbox)
# if i[9] is 1, set the background of the row to red
if int(app[9]) == 1:
for j in range(5):
self.tableWidget.item(0, j).setBackground(
QtGui.QColor(235, 74, 71)
)
# disable the checkbox
self.tableWidget.cellWidget(0, 0).setEnabled(False)
# set the tooltip
self.tableWidget.cellWidget(0, 0).setToolTip(
"Dieser Semesterapparat kann nicht gelöscht werden, da er bereits gelöscht wurde"
)
elif parent_depth == 2:
# apparat selected case - open the apparat in the frame
self.load_app_data(apparat)
# change tab focus to tab 0
self.tabWidget.setCurrentIndex(0)
return
def gridchange(self):
if self.check_deletable.isChecked():
self.box_semester.setEnabled(False)
self.box_semester.clear()
self.box_appnrs.setEnabled(False)
self.box_appnrs.clear()
self.box_person.setEnabled(False)
self.box_person.clear()
self.box_fach.setEnabled(False)
self.box_fach.clear()
self.box_erstellsemester.setEnabled(False)
self.box_erstellsemester.clear()
self.box_dauerapp.setEnabled(False)
self.box_dauerapp.clear()
else:
self.box_semester.setEnabled(True)
self.box_appnrs.setEnabled(True)
self.box_person.setEnabled(True)
self.box_fach.setEnabled(True)
self.box_erstellsemester.setEnabled(True)
self.box_dauerapp.setEnabled(True)
self.tab_changed()
def populate_tab(self):
# add default values to the dropdowns
self.box_appnrs.clear()
self.box_appnrs.addItem("")
self.box_appnrs.setCurrentText("")
self.box_person.clear()
self.box_person.addItem("")
self.box_person.setCurrentText("")
self.box_fach.clear()
self.box_fach.addItem("")
self.box_fach.setCurrentText("")
self.box_erstellsemester.clear()
self.box_erstellsemester.addItem("")
self.box_erstellsemester.setCurrentText("")
self.box_semester.clear()
self.box_semester.addItem("")
self.box_semester.setCurrentText("")
self.box_dauerapp.clear()
self.box_dauerapp.addItems(["Ja", "Nein", ""])
self.box_dauerapp.setCurrentText("")
# add custom vaules
appnrs = self.db.getUnavailableApparatNumbers()
apparats = natsorted(appnrs)
apparats = [str(apparat) for apparat in apparats]
self.box_appnrs.addItems(apparats)
persons = self.db.getProfs()
self.box_person.addItems([f"{person[3]}, {person[2]}" for person in persons])
self.box_fach.addItems(subject[1] for subject in self.db.getSubjects())
semester = self.db.getSemersters()
self.box_erstellsemester.addItems(semester)
self.statistics_table.setRowCount(0)
# set data for table and graph in tab 2 tableWidget_3
data = self.db.getApparatCountBySemester()
data = c_sort.custom_sort(data)
# self.tabWidget_3.clear()
self.tabWidget_3.removeTab(1)
self.statistics_table.setRowCount(len(data))
for i in range(len(data)):
self.statistics_table.setItem(i, 0, QtWidgets.QTableWidgetItem(data[i][0]))
self.statistics_table.setItem(
i, 1, QtWidgets.QTableWidgetItem(str(data[i][1]))
)
self.statistics_table.setItem(
i, 2, QtWidgets.QTableWidgetItem(str(data[i][2]))
)
self.statistics_table.resizeColumnsToContents()
self.statistics_table.resizeRowsToContents()
# create graph
graph_data = {
"x": [i[0] for i in data],
"y": {"Erstellt": [i[1] for i in data], "Gelöscht": [i[2] for i in data]},
}
graph = DataGraph(title="Erstellte und gelöschte Apparate", data=graph_data)
# place the graph into tabWidget_3
self.tabWidget_3.addTab(graph, "Graph")
self.tabWidget_3.setCurrentIndex(0)
def tab_changed(self):
curr_tab = self.tabWidget.currentIndex()
if curr_tab == 0: # create tab
return
elif curr_tab == 1: # statistics tab
self.populate_tab()
def populate_dropdown(self, box, data):
box.clear()
box.addItem("")
box.setCurrentText("")
box.addItems(data)
def delete_selected_apparats(self):
# get all selected apparats
selected_apparats = []
selected_apparat_rows = []
for i in range(self.tableWidget.rowCount()):
if self.tableWidget.cellWidget(i, 0).isChecked():
selected_apparats.append(self.tableWidget.item(i, 2).text())
selected_apparat_rows.append(i)
# delete all selected apparats
print(selected_apparats)
for apparat in selected_apparats:
self.db.deleteApparat(apparat, self.generateSemester(today=True))
for row in selected_apparat_rows:
# set the background of the row to red
for j in range(5):
self.tableWidget.item(row, j).setBackground(QtGui.QColor(235, 74, 71))
# refresh the table
self.populate_tab()
self.btn_del_select_apparats.setEnabled(False)
def statistics(self):
"""Generate the statistics based on the selected filters."""
self.db_err_message.setText("")
self.btn_del_select_apparats.setEnabled(True)
self.btn_notify_for_deletion.setEnabled(True)
params = {
"appnr": (
self.box_appnrs.currentText()
if self.box_appnrs.currentText() != ""
else None
),
"prof_id": (
self.db.getProfId(self.box_person.currentText())
if self.box_person.currentText() != ""
else None
),
"fach": (
self.box_fach.currentText()
if self.box_fach.currentText() != ""
else None
),
"erstellsemester": (
self.box_erstellsemester.currentText()
if self.box_erstellsemester.currentText() != ""
else None
),
"dauer": (
"1"
if self.box_dauerapp.currentText() == "Ja"
else "0" if self.box_dauerapp.currentText() == "Nein" else None
),
"endsemester": (
self.box_semester.currentText()
if self.box_semester.currentText() != ""
else None
),
"deletable": "True" if self.check_deletable.isChecked() else None,
"deletesemester": self.generateSemester(today=True),
}
params = {
key: value for key, value in params.items() if value is not None
} # remove empty lines to prevent errors
print(params)
params = {
key: value for key, value in params.items() if value != "Alle"
} # remove empty lines to prevent errors
print(params)
result = self.db.statistic_request(**params)
# add QTableWidgetItems to the table
self.tableWidget.setRowCount(len(result))
if len(result) == 0:
self.db_err_message.setText("Keine Ergebnisse gefunden")
return
for i in range(len(result)):
print(result[i])
# set the items 0 = clickable checkbox, 1 = appname, 2 = profname, 3 = fach
self.tableWidget.setItem(i, 0, QtWidgets.QTableWidgetItem(""))
self.tableWidget.setItem(i, 1, QtWidgets.QTableWidgetItem(result[i][1]))
self.tableWidget.setItem(
i, 2, QtWidgets.QTableWidgetItem(str(result[i][4]))
)
self.tableWidget.setItem(i, 3, QtWidgets.QTableWidgetItem(result[i][2]))
self.tableWidget.setItem(i, 4, QtWidgets.QTableWidgetItem(result[i][3]))
# replace the 0 with a checkbox
checkbox = QtWidgets.QCheckBox()
checkbox.setChecked(False)
self.tableWidget.setCellWidget(i, 0, checkbox)
# if i[9] is 1, set the background of the row to red
if int(result[i][9]) == 1:
for j in range(5):
self.tableWidget.item(i, j).setBackground(QtGui.QColor(235, 74, 71))
# disable the checkbox
self.tableWidget.cellWidget(i, 0).setEnabled(False)
# set the tooltip
self.tableWidget.cellWidget(i, 0).setToolTip(
"Dieser Semesterapparat kann nicht gelöscht werden, da er bereits gelöscht wurde"
)
def populate_frame(self, appdata: ApparatData):
# populate the frame with the data from the database
# ic(appdata)
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.frame.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):
dial = QtWidgets.QDialog()
popup = popus_confirm()
popup.setupUi(dial)
popup.textEdit.setReadOnly(True)
popup.textEdit.setText(message)
dial.exec()
return dial.result()
def threads(self):
while True:
self.validate_prof_mail()
self.validate_prof_name()
self.validate_prof_tel()
self.validate_app_name()
self.validate_app_fach()
self.validate_semester()
def thread_check(self):
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)
def validate_prof_name(self):
if self.frame.isEnabled():
if "," in self.drpdwn_prof_name.currentText():
self.drpdwn_prof_name.setStyleSheet("border: 1px solid green;")
self.profname_mand.setText("")
self.change_state(0, 1)
else:
self.drpdwn_prof_name.setStyleSheet("border: 1px solid red;")
self.profname_mand.setText("*")
self.change_state(0, 0)
else:
self.drpdwn_prof_name.setStyleSheet("border: 1px solid black;")
def validate_prof_mail(self):
if self.frame.isEnabled():
if self.prof_mail.hasAcceptableInput():
self.prof_mail.setStyleSheet("border: 1px solid green;")
self.mail_mand.setText("")
self.change_state(1, 1)
else:
self.prof_mail.setStyleSheet("border: 1px solid red;")
self.mail_mand.setText("*")
self.change_state(1, 0)
else:
self.prof_mail.setStyleSheet("border: 1px solid black;")
def validate_prof_tel(self):
if self.frame.isEnabled():
if self.prof_tel_nr.text() != "":
self.prof_tel_nr.setStyleSheet("border: 1px solid green;")
self.telnr_mand.setText("")
self.change_state(2, 1)
else:
self.prof_tel_nr.setStyleSheet("border: 1px solid red;")
self.telnr_mand.setText("*")
self.change_state(2, 0)
def validate_app_name(self):
if self.frame.isEnabled():
if self.app_name.hasAcceptableInput():
self.app_name.setStyleSheet("border: 1px solid green;")
self.appname_mand.setText("")
self.change_state(3, 1)
else:
self.app_name.setStyleSheet("border: 1px solid red;")
self.appname_mand.setText("*")
self.change_state(3, 0)
def validate_app_fach(self):
if self.frame.isEnabled():
if self.app_fach.currentText() != "":
self.app_fach.setStyleSheet("border: 1px solid green;")
self.fach_mand.setText("")
self.change_state(4, 1)
else:
self.app_fach.setStyleSheet("border: 1px solid red;")
self.fach_mand.setText("*")
self.change_state(4, 0)
def validate_semester(self):
if self.frame.isEnabled():
if (
(self.sem_sommer.isChecked() or self.sem_winter.isChecked())
and self.sem_year.hasAcceptableInput()
) or self.check_eternal_app.isChecked():
self._mand.setText("")
self.change_state(5, 1)
else:
self._mand.setText("*")
self.change_state(5, 0)
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 req_fields_filled(self):
# # check if all required fields are filled
# values = []
# for item in self.frame.findChildren(QtWidgets.QLabel):
# # if label name contains "req" and the text is empty, return false
# if "mand" in item.objectName() and item.text() == "":
# values.append(True)
# elif "mand" in item.objectName() and item.text() != "":
# values.append(False)
# return all(values)
#
def buttonClicked(self):
print("Button clicked")
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
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)
# 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()
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_load_apparat(self):
# # remove all rows from table
# #get all
# self.tableWidget_apparate.sortItems(0, QtCore.Qt.SortOrder.AscendingOrder)
# self.frame.setDisabled(True)
# for child in self.frame.findChildren(QtWidgets.QLineEdit):
# child.clear()
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.frame.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.frame.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()
# self.horizontalLayout_6.show()
# increase size by 300px
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.frame.isEnabled():
self.confirm_popup("Bitte erst einen Apparat auswählen!")
return
def __new_ui():
dialog = QtWidgets.QDialog()
frame = Medien()
frame.setupUi(dialog)
dialog.exec()
mode = frame.get_mode()
data = frame.get_list_data()
return mode, data, dialog.result()
self.progress_label.show()
self.line_2.show()
self.label_info.show()
self.progress_label.setText("Bitte warten...")
mode, data, result = __new_ui()
if result == 1:
if data == []:
self.confirm_popup("Bitte mindestens ein Medium hinzufügen!")
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()
# create a thread that updates the progress label after each medium
self.bookGrabber = BookGrabber(
mode=mode, app_id=app_id, prof_id=prof_id, data=data
)
# grabber.mode = mode
# grabber.data = data
# grabber.app_id = app_id
# grabber.prof_id = prof_id
self.bookGrabber.finished.connect(self.bookGrabber.deleteLater)
self.bookGrabber.finished.connect(self.hide_progress_label)
self.bookGrabber.finished.connect(self.update_app_media_list)
self.bookGrabber.updateSignal.connect(self.update_progress_label)
self.bookGrabber.start()
# run grabber.deletelater
# for book in data:
# # self.progress_label.setText(f"Medium {ct}/{len(data)}")
# # update the progress label
# self.logger.log_info(f"trying to add BookData for Signature {book}")
# webdata = WebRequest().get_ppn(book).get_data()
# bd: BookData = BibTextTransformer(mode).get_data(webdata).return_data()
# bd.signature = book
# self.db.addBookToDatabase(bookdata=bd, app_id=app_id, prof_id=prof_id)
# get all media list books
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.frame.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()
for child in self.frame.findChildren(QtWidgets.QLineEdit):
child.clear()
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
webbrowser.open(link)
# get the name of the column
columnname = self.tableWidget_apparat_media.horizontalHeaderItem(
item.column()
).text()
if columnname == "Link":
__openLink(item.text())
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.db.insert_file(files, self.active_apparat, self.db.get_prof_id(self.drpdwn_prof_name.currentText()))
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!")
return
if not _selected_doc_location == "Database":
path = Path(_selected_doc_location)
path: 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!")
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
if not self.db.checkApparatExistsById(app_id):
# create apparat
print("Creating apparat")
self.btn_save_apparat()
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:
self.add_files()
if file_type == "pdf":
# Todo: implement parser here
self.confirm_popup("PDF Dateien werden noch nicht unterstützt!")
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")
self.autoGrabber = BookGrabber(
mode="ARRAY", app_id=app_id, prof_id=prof_id, data=signatures
)
# grabber.mode = "ARRAY"
# grabber.data = signatures
# grabber.app_id = app_id
# grabber.prof_id = prof_id
# grabber.moveToThread(thread)
self.label_info.show()
self.progress_label.show()
self.line_2.show()
# grabber.finished.connect(thread.quit)
self.autoGrabber.finished.connect(self.autoGrabber.deleteLater)
self.autoGrabber.finished.connect(self.hide_progress_label)
self.autoGrabber.finished.connect(self.update_app_media_list)
self.autoGrabber.finished.connect(self.unlock_apparate)
self.autoGrabber.updateSignal.connect(self.update_progress_label)
# worker.finished.connect(worker.deleteLater)
self.autoGrabber.start()
# self.thread = thread
# kill grabber after completion
# self.grabbers.append(grabber)
def unlock_apparate(self):
self.tableWidget_apparate.setEnabled(True)
self.tableWidget_apparate.setToolTip("")
def btn_save_apparat(self):
def __clear_fields():
self.drpdwn_app_nr.clear()
self.prof_title.clear()
self.drpdwn_prof_name.clearMask()
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.frame.setEnabled(False)
self.groupBox_2.hide()
self.groupBox.hide()
self.check_send_mail.setChecked(False)
self.cancel_active_selection.setEnabled(False)
if not self.validate_fields():
self.confirm_popup("Bitte alle Pflichtfelder ausfüllen!")
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"
)
__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])
extend_action.triggered.connect(self.extend_apparat)
delete_action.triggered.connect(self.delete_apparat)
contact_action.triggered.connect(self.contact_prof)
remind_action.triggered.connect(self.reminder)
menu.exec(self.tableWidget_apparate.mapToGlobal(position))
def statistics_table_context_menu(self, position):
menu = QtWidgets.QMenu()
restore_action = menu.addAction("Wiederherstellen")
menu.addAction(restore_action)
restore_action.triggered.connect(self.restore_apparat)
menu.exec(self.tableWidget.mapToGlobal(position))
def restore_apparat(self):
row = self.tableWidget.currentRow()
apparat = self.tableWidget.item(row, 1).text()
ic(apparat)
apparat_id = self.db.getApparatId(apparat)
# restore the apparat
self.db.restoreApparat(apparat_id)
# update the table
self.reload()
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.getMessages()
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():
message = messages[self.spin_select_message.value() - 1]
self.db.deleteMessage(message["id"])
# remove message from list
messages.remove(message)
self.spin_select_message.setMaximum(len(messages))
self.spin_select_message.setValue(1)
self.label_total_day_messages.setText("/ " + str(len(messages)))
#
selected_date = self.calendarWidget.selectedDate().toString("yyyy-MM-dd")
print(selected_date)
messages = self.db.getMessages(selected_date)
if messages == []:
self.message_frame.hide() if self.message_frame.isVisible() else None
return
print(messages)
message_count = len(messages)
self.spin_select_message.setMaximum(message_count)
self.message_frame.show()
self.label_total_day_messages.setText("/ " + str(message_count))
# if there is only one message, disable the spinbox
(
self.spin_select_message.setEnabled(False)
if message_count == 1
else self.spin_select_message.setEnabled(True)
)
self.spin_select_message.setValue(1)
# load the first message
__update_message()
# on valuechanged, update the message
self.spin_select_message.valueChanged.connect(__update_message)
self.btn_delete_message.clicked.connect(__delete_message)
def open_settings(self):
dialog = QtWidgets.QDialog()
settings = settings_ui()
settings.setupUi(dialog)
dialog.exec()
if dialog.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)
print(state)
if state == 1:
self.db.deleteBook(book_id)
self.update_app_media_list()
self.contact_prof(mail="deleted")
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)
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)
# update self.apparats with the new data
# find matching apparat
# for apparat in self.apparats:
# if apparat[4] == int(selected_apparat_id):
# apparat[5]=data["semester"]
# apparat[7]=data["dauerapp"]
# break
# self.old_apparats = self.apparats
self.db.setNewSemesterDate(
selected_apparat_id, data["semester"], dauerapp=data["dauerapp"]
)
else:
return
def contact_prof(self, apparat=None, mail=""):
if self.active_apparat == "":
if apparat is None:
self.confirm_popup("Bitte erst einen Apparat auswählen!")
return
active_apparat_id = (
self.tableWidget_apparate.item(
self.tableWidget_apparate.currentRow(), 0
).text()
if apparat is None
else apparat
)
profname = self.drpdwn_prof_name.currentText().replace(",", "").split(" ")
profname = f"{profname[1]} {profname[0]}"
prof_id = self.db.getProfId(self.drpdwn_prof_name.currentText())
pmail = self.db.getSpecificProfData(prof_id, ["mail"])
# create a new thread to show the mail interface and send the mail
self.mail_thread = Mail_Dialog(
app_id=active_apparat_id,
prof_name=profname,
prof_mail=pmail,
app_name=self.app_name.text(),
app_subject=self.app_fach.currentText(),
)
self.mail_thread.show()
def delete_apparat(self):
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)
print(state)
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)
# if state==QtWidgets.QDialog.DialogCode.Accepted:
# self.db.delete_apparat(selected_apparat_id)
# pass
def launch_gui():
print("trying to login")
print("checking if database available")
# database = config.database.path + config.database.name
# print(database)
# if not os.path.exists(database):
# print("Database not found, creating new database")
# db = Database()
# db.create_database()
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(delete_temp_contents)
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(delete_temp_contents)
if __name__ == "__main__":
print("This is the main window")
# app = QtWidgets.QApplication(sys.argv)
# window = MainWindow()
# app.exec()
# open login screen
launch_gui()