1767 lines
68 KiB
Python
1767 lines
68 KiB
Python
# encoding: utf-8
|
|
import atexit
|
|
import os
|
|
|
|
import sys
|
|
import tempfile
|
|
import webbrowser
|
|
from pathlib import Path
|
|
|
|
from natsort import natsorted
|
|
from PyQt6 import QtCore, QtGui, QtWidgets
|
|
from PyQt6.QtCore import QThread
|
|
from PyQt6.QtGui import QRegularExpressionValidator
|
|
|
|
from src import Icon, logger, settings
|
|
from src.backend import Database, BookGrabber, AvailChecker, DocumentationThread
|
|
from src.backend.semester import Semester
|
|
from src.backend.create_file import recreateFile
|
|
from src.backend.delete_temp_contents import delete_temp_contents as tempdelete
|
|
from src.ui import Ui_Semesterapparat
|
|
from src.logic import (
|
|
APP_NRS,
|
|
# PROF_TITLES,
|
|
ApparatData,
|
|
BookData,
|
|
csv_to_list,
|
|
word_docx_to_csv,
|
|
Prof,
|
|
Apparat,
|
|
)
|
|
from src.ui.dialogs import (
|
|
popus_confirm,
|
|
medienadder_ui,
|
|
About,
|
|
ApparatExtendDialog,
|
|
Mail_Dialog,
|
|
Settings,
|
|
edit_bookdata_ui,
|
|
login_ui,
|
|
parsed_titles_ui,
|
|
reminder_ui,
|
|
)
|
|
from src.ui.widgets import (
|
|
ElsaDialog,
|
|
MessageCalendar,
|
|
FilePicker,
|
|
CalendarEntry,
|
|
UserCreate,
|
|
SearchStatisticPage,
|
|
EditUser,
|
|
EditProf,
|
|
)
|
|
from src.utils import SemesterDocument
|
|
|
|
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:
|
|
logger.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.create_document.clicked.connect(self.create_doc)
|
|
self.calendarWidget = MessageCalendar(self.calendar_frame)
|
|
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)
|
|
self.saveandcreate.hide()
|
|
|
|
# Actions
|
|
self.actionEinstellungen.triggered.connect(self.open_settings)
|
|
Icon("settings", self.actionEinstellungen)
|
|
self.actionDokumentation_lokal.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())
|
|
self.prof_tel_nr.setValidator(
|
|
QtGui.QRegularExpressionValidator(QtCore.QRegularExpression(r"^\d{3,14}"))
|
|
)
|
|
# #print(self.prof_tel_nr.maxLength())
|
|
self.app_fach.setValidator( # validator to allow typing in the app_fach field
|
|
QtGui.QRegularExpressionValidator(
|
|
QtCore.QRegularExpression(r"[a-zA-Z0-9\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
|
|
)
|
|
self.tableWidget_apparate.doubleClicked.connect(self.load_app_data)
|
|
|
|
# #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.btn_reserve.hide()
|
|
self.label_20.hide()
|
|
self.line_3.hide()
|
|
self.avail_status.hide()
|
|
self.chkbx_show_del_media.hide()
|
|
self.automation_add_selected_books.hide()
|
|
# self.btn_del_select_apparats.setEnabled(False)
|
|
|
|
self.tabWidget.currentChanged.connect(self.tabW1_changed)
|
|
|
|
# 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()
|
|
self.add_medium.setEnabled(False)
|
|
self.docu = DocumentationThread()
|
|
self.docu.start()
|
|
self.actionDokumentation_lokal.triggered.connect(self.open_documentation)
|
|
|
|
# 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
|
|
|
|
# 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
|
|
)
|
|
|
|
# admin buttons
|
|
self.select_action_box.currentTextChanged.connect(self.adminActions)
|
|
self.select_action_box.addItem("")
|
|
self.select_action_box.setCurrentText("")
|
|
self.admin_action.setLayout(QtWidgets.QVBoxLayout())
|
|
self.admin_action.setTitle("")
|
|
|
|
# Create instances to be used by the threads in the application
|
|
self.bookGrabber = []
|
|
self.availChecker = None
|
|
self.mail_thread = None
|
|
self.autoGrabber = None
|
|
|
|
self.elsatab.setLayout(QtWidgets.QVBoxLayout())
|
|
self.search_statistics.setLayout(QtWidgets.QVBoxLayout())
|
|
|
|
# add splitter
|
|
self.splitter = QtWidgets.QSplitter(QtCore.Qt.Orientation.Vertical)
|
|
self.splitter.addWidget(self.calendar_frame)
|
|
self.splitter.addWidget(self.frame_creation_progress)
|
|
self.verticalLayout.removeWidget(self.calendar_frame)
|
|
self.verticalLayout.removeWidget(self.frame_creation_progress)
|
|
self.verticalLayout.addWidget(self.splitter)
|
|
|
|
self.steps.hide()
|
|
|
|
def create_doc(self):
|
|
result = self.confirm_popup(
|
|
"Mit dem Klick auf Okay wird eine Übersicht aller aktiven Semesterapparate erstellt und an den FollowME Drucker gesendet. Es kann bis zu 10 Minuten dauern, bis das document im Drucker angezeigt wird",
|
|
"document erstellen?",
|
|
)
|
|
logger.debug(f"Result: {result}")
|
|
if result == 1:
|
|
# print("Creating document")
|
|
apparats = self.apparats
|
|
apps = []
|
|
for apparat in apparats:
|
|
prof = self.db.getProf(apparat[2])
|
|
data = (apparat[4], f"{prof.lastname} ({apparat[1]})")
|
|
apps.append(data)
|
|
# print(apps)
|
|
logger.info("Using apparats: {}", apps)
|
|
doc = SemesterDocument(
|
|
semester=Semester().value,
|
|
filename="Semesterapparate",
|
|
apparats=apps,
|
|
full=True,
|
|
config=settings,
|
|
)
|
|
# doc.make_document()
|
|
# doc.create_pdf()
|
|
# doc.print_document()
|
|
# doc.cleanup()
|
|
# logger.info("Document created and sent to printer")
|
|
|
|
# kill thread after execution done
|
|
|
|
def checkValidInput(self):
|
|
if valid_input == (1, 1, 1, 1, 1, 1):
|
|
self.check_file.setEnabled(True)
|
|
else:
|
|
self.check_file.setEnabled(False)
|
|
|
|
def setWidget(self, widget):
|
|
# remove all widgets from localwidget
|
|
|
|
self.hideWidget()
|
|
# add widget to localwidget
|
|
self.admin_action.layout().addWidget(widget)
|
|
|
|
def hideWidget(self):
|
|
try:
|
|
widgets = [
|
|
self.admin_action.layout().itemAt(i).widget()
|
|
for i in range(self.admin_action.layout().count())
|
|
]
|
|
except AttributeError:
|
|
return
|
|
for widget in widgets:
|
|
self.admin_action.layout().removeWidget(widget)
|
|
widget.deleteLater()
|
|
|
|
def adminActions(self):
|
|
if self.select_action_box.currentText() == "Nutzer anlegen":
|
|
self.setWidget(UserCreate())
|
|
self.admin_action.setTitle("Nutzer anlegen")
|
|
elif self.select_action_box.currentText() == "Nutzer bearbeiten":
|
|
self.setWidget(EditUser())
|
|
self.admin_action.setTitle("Nutzer bearbeiten")
|
|
elif self.select_action_box.currentText() == "Lehrperson bearbeiten":
|
|
self.setWidget(EditProf())
|
|
self.admin_action.setTitle("Lehrperson bearbeiten")
|
|
else:
|
|
self.hideWidget()
|
|
self.admin_action.setTitle("")
|
|
|
|
def toggleButton(self, button):
|
|
if button.isChecked():
|
|
button.setChecked(False)
|
|
self.validate_semester()
|
|
|
|
def open_about(self):
|
|
About().exec()
|
|
|
|
def quit(self):
|
|
# delete all temporary files
|
|
tempdelete()
|
|
sys.exit()
|
|
|
|
def get_apparats(self):
|
|
alist = self.db.getAllAparats(deleted=0)
|
|
alist = natsorted(alist, key=lambda x: x[4], reverse=True)
|
|
self.tableWidget_apparate.setRowCount(0)
|
|
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):
|
|
logger.info("Opening Documentation")
|
|
webbrowser.open("http://localhost:8000")
|
|
|
|
def update_calendar(self, data):
|
|
self.calendarWidget.setMessages([data])
|
|
self.calendarWidget.updateCells()
|
|
|
|
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
|
|
for widget in [
|
|
stats_layout.itemAt(i).widget() for i in range(stats_layout.count())
|
|
]:
|
|
stats_layout.removeWidget(widget)
|
|
widget.deleteLater()
|
|
statistics = SearchStatisticPage()
|
|
statistics.apparat_open.connect(self.open_apparat)
|
|
statistics.refreshSignal.connect(self.update_apparat_list)
|
|
statistics.updateCalendar.connect(self.update_calendar)
|
|
stats_layout.addWidget(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
|
|
elsa_layout = self.elsatab.layout()
|
|
if elsa_layout is not None:
|
|
# delete tabpage, re-add with same name at same position
|
|
widgets = [
|
|
self.elsatab.layout().itemAt(i).widget()
|
|
for i in range(self.elsatab.layout().count())
|
|
]
|
|
for widget in widgets:
|
|
self.elsatab.layout().removeWidget(widget)
|
|
widget.deleteLater()
|
|
|
|
elsa_layout.addWidget(ElsaDialog())
|
|
# print("added")
|
|
pass
|
|
|
|
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 Semester()
|
|
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.apparat.appnr))
|
|
self.prof_title.setText(appdata.prof.title)
|
|
prof_name = appdata.prof.name(True)
|
|
|
|
self.drpdwn_prof_name.setCurrentText(prof_name)
|
|
self.prof_mail.setText(appdata.prof.mail)
|
|
self.prof_tel_nr.setText(appdata.prof.telnr)
|
|
self.app_name.setText(appdata.apparat.name)
|
|
# #print("changing dropdown app_fach from '' to ", appdata.app_fach)
|
|
self.app_fach.setCurrentText(appdata.apparat.subject)
|
|
# #print("changed dropdown app_fach to ", self.app_fach.currentText())
|
|
self.sem_year.setText(appdata.apparat.get_semester.split(" ")[1])
|
|
match appdata.apparat.get_semester.split(" ")[0]:
|
|
case "SoSe":
|
|
self.sem_sommer.setChecked(True)
|
|
self.sem_winter.setChecked(False)
|
|
case "WiSe":
|
|
self.sem_sommer.setChecked(False)
|
|
self.sem_winter.setChecked(True)
|
|
|
|
self.check_eternal_app.setChecked(appdata.apparat.eternal)
|
|
self.prof_id_adis.setText(str(appdata.apparat.prof_id_adis))
|
|
self.apparat_id_adis.setText(str(appdata.apparat.apparat_id_adis))
|
|
self.app_group_box.setEnabled(True)
|
|
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):
|
|
prof = Prof()
|
|
app = Apparat()
|
|
app.subject = self.app_fach.currentText()
|
|
app.name = self.app_name.text()
|
|
app.appnr = self.active_apparat
|
|
app.eternal = self.check_eternal_app.isChecked()
|
|
prof.mail = self.prof_mail.text()
|
|
prof.telnr = self.prof_tel_nr.text()
|
|
prof.title = self.prof_title.text()
|
|
prof.fullname = self.drpdwn_prof_name.currentText().replace(",", "")
|
|
app.created_semester = (
|
|
self.sem_sommer.text() + " " + self.sem_year.text()
|
|
if self.sem_sommer.isChecked()
|
|
else self.sem_winter.text() + " " + self.sem_year.text()
|
|
)
|
|
app.prof_id_adis = self.prof_id_adis.text()
|
|
prof_id = self.db.getProfByName(prof.fullname).id
|
|
self.add_files(prof_id)
|
|
app.apparat_id_adis = self.apparat_id_adis.text()
|
|
appdata = ApparatData(prof=prof, apparat=app)
|
|
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)
|
|
self.add_medium.setEnabled(False)
|
|
# update apparat table
|
|
self.get_apparats()
|
|
|
|
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, True, color="success")
|
|
mand.setText("")
|
|
self.change_state(index, 1)
|
|
else:
|
|
Icon("valid_false", widget, recolor=True, color="warning")
|
|
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())
|
|
>= 2 # check if the year is at least 2 digits long
|
|
)
|
|
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)
|
|
self.checkValidInput()
|
|
|
|
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):
|
|
self.prof_title.clear()
|
|
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)
|
|
# logger.debug(data)
|
|
prof_title = data.title
|
|
if prof_title == "None":
|
|
prof_title = "Kein Titel"
|
|
self.prof_title.setText(prof_title)
|
|
self.prof_tel_nr.setText(data.telnr)
|
|
self.prof_mail.setText(data.mail)
|
|
self.app_name.setFocus()
|
|
|
|
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)
|
|
self.add_medium.setEnabled(True)
|
|
for child in self.app_group_box.findChildren(QtWidgets.QToolButton):
|
|
child.show()
|
|
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.document_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.drpdwn_app_nr.setDisabled(True)
|
|
self.update_app_media_list()
|
|
self.update_document_list()
|
|
return True
|
|
|
|
def update_document_list(self):
|
|
app_id = self.active_apparat
|
|
prof_id = self.db.getProfByName(
|
|
self.drpdwn_prof_name.currentText().replace(",", "")
|
|
).id
|
|
files = self.db.getFiles(app_id, prof_id)
|
|
for file in files:
|
|
self.document_list.insertRow(0)
|
|
self.document_list.setItem(0, 0, QtWidgets.QTableWidgetItem(file[0]))
|
|
self.document_list.setItem(0, 1, QtWidgets.QTableWidgetItem(file[1]))
|
|
self.document_list.setItem(0, 2, QtWidgets.QTableWidgetItem(""))
|
|
self.document_list.setItem(0, 3, QtWidgets.QTableWidgetItem("Database"))
|
|
self.document_list.item(0, 0).setToolTip(file[0])
|
|
|
|
def btn_create_new_apparat(self):
|
|
global valid_input
|
|
self.steps.show()
|
|
for child in self.app_group_box.findChildren(QtWidgets.QToolButton):
|
|
child.show()
|
|
# *create a new apparat
|
|
self.btn_apparat_save.show() if self.btn_apparat_save.isHidden() else None
|
|
# clear document_list
|
|
self.__clear_fields()
|
|
self.document_list.setRowCount(0)
|
|
self.cancel_active_selection.setEnabled(True)
|
|
self.app_group_box.setEnabled(True)
|
|
self.add_medium.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)
|
|
self.check_send_mail.show()
|
|
self.check_file.setEnabled(False)
|
|
self.drpdwn_app_nr.setFocus()
|
|
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
|
|
taken_app_nrs = self.db.getUnavailableApparatNumbers()
|
|
self.drpdwn_app_nr.addItems([str(i) for i in APP_NRS if i not in taken_app_nrs])
|
|
|
|
valid_input = (0, 0, 0, 0, 0, 0)
|
|
self.populate_prof_dropdown()
|
|
|
|
def update_progress_label(self, curr, total):
|
|
text = f"Medium {curr}/{total}"
|
|
logger.info(text)
|
|
self.progress_label.setText(text)
|
|
# update tableWidget_apparat_media
|
|
self.update_app_media_list()
|
|
|
|
def hide_progress_label(self):
|
|
logger.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):
|
|
media = medienadder_ui()
|
|
media.exec()
|
|
mode = media.mode
|
|
data = media.data
|
|
use_any = media.use_any
|
|
use_exact = media.use_exact
|
|
result = media.result()
|
|
|
|
if result == 1:
|
|
self.progress_label.show()
|
|
self.line_2.show()
|
|
self.label_info.show()
|
|
self.progress_label.setText("Bitte warten...")
|
|
if data == []:
|
|
self.confirm_popup(
|
|
"Bitte mindestens ein Medium hinzufügen!", title="Fehler"
|
|
)
|
|
|
|
app_id = self.active_apparat
|
|
prof_id = self.db.getProfId(self.profdata)
|
|
logger.debug(prof_id)
|
|
# check if app_id is in database
|
|
if self.db.checkApparatExistsById(app_id) is False:
|
|
# create apparat
|
|
self.btn_save_apparat(False)
|
|
# create a thread that updates the progress label after each medium
|
|
|
|
# self.bookGrabber = None
|
|
bookGrabber = BookGrabber(self.active_apparat)
|
|
bookGrabber.add_values(
|
|
mode=mode,
|
|
prof_id=prof_id,
|
|
app_id=app_id,
|
|
data=data,
|
|
any_book=use_any,
|
|
exact=use_exact,
|
|
)
|
|
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 bookGrabber.isRunning():
|
|
# #print("waiting for thread to finish")
|
|
QtWidgets.QApplication.processEvents()
|
|
|
|
# self.__clear_fields()
|
|
|
|
else:
|
|
return
|
|
|
|
def check_availability(self):
|
|
|
|
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.profdata),
|
|
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.grabbers.append(availcheck)
|
|
|
|
def btn_cancel_active_selection(self):
|
|
self.steps.hide()
|
|
# clear the rows of the table
|
|
self.tableWidget_apparat_media.setRowCount(0)
|
|
self.document_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.check_eternal_app.setEnabled(False)
|
|
# set all radio buttons to unchecked
|
|
self.sem_sommer.setChecked(False)
|
|
self.sem_winter.setChecked(False)
|
|
self.check_eternal_app.setChecked(False)
|
|
self.add_medium.setEnabled(False)
|
|
|
|
for child in self.app_group_box.findChildren(QtWidgets.QLineEdit):
|
|
child.clear()
|
|
for child in self.app_group_box.findChildren(QtWidgets.QToolButton):
|
|
child.hide()
|
|
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.profdata)
|
|
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)
|
|
# self.tableWidget_apparat_media.
|
|
|
|
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)
|
|
#os.system("start " + 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")
|
|
profs = [f"{prof.lastname}, {prof.firstname}" for prof in profs]
|
|
profs.sort()
|
|
for prof in profs:
|
|
self.drpdwn_prof_name.addItem(prof)
|
|
|
|
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.document_list.insertRow(0)
|
|
self.document_list.setItem(0, 0, QtWidgets.QTableWidgetItem(filename))
|
|
self.document_list.setItem(0, 1, QtWidgets.QTableWidgetItem(filetype))
|
|
self.document_list.setItem(0, 2, QtWidgets.QTableWidgetItem("*"))
|
|
self.document_list.setItem(0, 3, QtWidgets.QTableWidgetItem(file))
|
|
# set tooltip of row 3 to the file path for each row
|
|
self.document_list.item(0, 3).setToolTip(file)
|
|
self.document_list.item(0, 0).setToolTip(filename)
|
|
|
|
def open_document(self):
|
|
_selected_doc_name = ""
|
|
_selected_doc_filetype = ""
|
|
try:
|
|
_selected_doc_name = self.document_list.item(
|
|
self.document_list.currentRow(), 0
|
|
).text()
|
|
_selected_doc_location = self.document_list.item(
|
|
self.document_list.currentRow(), 3
|
|
).text()
|
|
_selected_doc_filetype = self.document_list.item(
|
|
self.document_list.currentRow(), 1
|
|
).text()
|
|
except AttributeError:
|
|
self.confirm_popup("Bitte erst ein document auswählen!", title="Fehler")
|
|
return
|
|
if not _selected_doc_location == "Database":
|
|
path = Path(_selected_doc_location + "/" + _selected_doc_name)
|
|
# path: Path = path.resolve()
|
|
# 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
|
|
)
|
|
|
|
def add_media_from_file(self):
|
|
app_id = self.active_apparat
|
|
prof_id = self.db.getProfId(self.profdata)
|
|
|
|
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()
|
|
# 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.document_list.rowCount() == 0:
|
|
return
|
|
else:
|
|
# if file is selected, check for books in the file
|
|
if self.document_list.currentRow() != -1:
|
|
# #print("File selected")
|
|
file = self.document_list.item(
|
|
self.document_list.currentRow(), 3
|
|
).text()
|
|
|
|
file_type = self.document_list.item(
|
|
self.document_list.currentRow(), 1
|
|
).text()
|
|
file_location = self.document_list.item(
|
|
self.document_list.currentRow(), 3
|
|
).text()
|
|
file_name = self.document_list.item(
|
|
self.document_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
|
|
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)
|
|
data = __open_dialog(signatures)
|
|
# add the data to the database
|
|
for book in data:
|
|
if not isinstance(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
|
|
for book in data:
|
|
if not isinstance(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
|
|
logger.debug(self.profdata)
|
|
prof_id = self.db.getProfId(self.profdata)
|
|
|
|
logger.debug(prof_id)
|
|
# 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")
|
|
if not self.btn_save_apparat(False):
|
|
return
|
|
created = True
|
|
if self.document_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.document_list.item(self.document_list.currentRow(), 3).text()
|
|
|
|
file_type = self.document_list.item(
|
|
self.document_list.currentRow(), 1
|
|
).text()
|
|
file_location = self.document_list.item(
|
|
self.document_list.currentRow(), 3
|
|
).text()
|
|
file_name = self.document_list.item(
|
|
self.document_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(prof_id)
|
|
if file_type == "pdf":
|
|
# Todo: implement parser here
|
|
self.confirm_popup(
|
|
"PDF Dateien werden 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 != ""]
|
|
# logger.debug(signatures)
|
|
# #print("starting thread")
|
|
if prof_id is None:
|
|
prof_id = self.db.getProfId(self.profdata)
|
|
|
|
# print("Prof ID is None", prof_id)
|
|
autoGrabber = BookGrabber(self.active_apparat)
|
|
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.document_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.check_send_mail.setChecked(False)
|
|
self.cancel_active_selection.setEnabled(False)
|
|
# check if sem_sommer, sem_winter and check_eternal_app are checked. if yes, set them to unchecked
|
|
|
|
def btn_save_apparat(self, clear_fields=True):
|
|
self.steps.hide()
|
|
if not self.validate_fields():
|
|
self.confirm_popup("Bitte alle Pflichtfelder ausfüllen!", title="Fehler")
|
|
return False
|
|
prof = Prof(
|
|
fullname=self.drpdwn_prof_name.currentText(),
|
|
telnr=self.prof_tel_nr.text(),
|
|
mail=self.prof_mail.text(),
|
|
)
|
|
prof.title = self.prof_title.text()
|
|
apparat = Apparat(
|
|
appnr=self.active_apparat,
|
|
name=self.app_name.text(),
|
|
created_semester=self.generateSemester(),
|
|
eternal=1 if self.check_eternal_app.isChecked() else 0,
|
|
subject=self.app_fach.currentText(),
|
|
deleted=0,
|
|
prof_id_adis=self.prof_id_adis.text(),
|
|
apparat_id_adis=self.apparat_id_adis.text(),
|
|
)
|
|
|
|
appd = ApparatData(prof=prof, apparat=apparat)
|
|
|
|
error = self.db.createApparat(appd)
|
|
if error:
|
|
self.confirm_popup(error.__str__(), title="Fehler")
|
|
return False
|
|
if self.document_list.rowCount() > 0:
|
|
self.add_files()
|
|
if error is not None:
|
|
self.confirm_popup(error.__str__(), title="Fehler")
|
|
return
|
|
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.apparat.appnr,
|
|
mail="Information zum Semesterapparat",
|
|
location="",
|
|
pid=appd.prof.fullname,
|
|
)
|
|
if clear_fields:
|
|
# #print("clearing fields")
|
|
self.__clear_fields()
|
|
return True
|
|
|
|
def send_mail_preview(self):
|
|
pass
|
|
|
|
@property
|
|
def active_apparat(self):
|
|
return self.drpdwn_app_nr.currentText()
|
|
|
|
@property
|
|
def profdata(self):
|
|
return {
|
|
"title": self.prof_title.text(),
|
|
"profname": self.drpdwn_prof_name.currentText(),
|
|
"prof_mail": self.prof_mail.text(),
|
|
"prof_tel": self.prof_tel_nr.text(),
|
|
}
|
|
|
|
def add_files(self, prof_id=None):
|
|
files = []
|
|
for i in range(self.document_list.rowCount()):
|
|
files.append(
|
|
{
|
|
"name": self.document_list.item(i, 0).text(),
|
|
"type": self.document_list.item(i, 1).text(),
|
|
"date": self.document_list.item(i, 2).text(),
|
|
"path": self.document_list.item(i, 3).text(),
|
|
}
|
|
)
|
|
self.document_list.item(i, 2).setText("")
|
|
|
|
self.db.insertFile(
|
|
files,
|
|
self.active_apparat,
|
|
self.db.getProfId(
|
|
{
|
|
"title": self.prof_title.text(),
|
|
"profname": self.drpdwn_prof_name.currentText(),
|
|
"prof_mail": self.prof_mail.text(),
|
|
"prof_tel": self.prof_tel_nr.text(),
|
|
}
|
|
),
|
|
)
|
|
|
|
def update_apparat_list(self):
|
|
self.tableWidget_apparate.setRowCount(0)
|
|
|
|
for apparat in self.apparats:
|
|
self.insert_apparat_into_table(apparat)
|
|
logger.info("Inserted {} apparats into table".format(len(self.apparats)))
|
|
|
|
def insert_apparat_into_table(self, apparat):
|
|
# logger.debug(apparat)
|
|
def __dauer_check(apparat):
|
|
return "Ja" if apparat[7] == 1 else "Nein"
|
|
|
|
semester = apparat[8] if apparat[8] is not None else apparat[5]
|
|
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(semester)),
|
|
)
|
|
self.tableWidget_apparate.setItem(
|
|
0, 4, QtWidgets.QTableWidgetItem(__dauer_check(apparat))
|
|
)
|
|
self.tableWidget_apparate.setItem(
|
|
0, 5, QtWidgets.QTableWidgetItem(str(apparat[13]))
|
|
)
|
|
|
|
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)
|
|
remind_action.triggered.connect(self.reminder)
|
|
# 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))
|
|
if len(self.tableWidget_apparate.selectedItems()) == 0:
|
|
return
|
|
app_id = self.tableWidget_apparate.item(row, 0).text()
|
|
pid = self.db.getProfIDByApparat(app_id)
|
|
logger.debug(app_id, pid)
|
|
delete_action.triggered.connect(lambda: self.delete_apparat(pos))
|
|
# pass pos to contact_prof
|
|
contact_action.triggered.connect(
|
|
lambda: self.contact_prof(pid=pid, apparat=app_id)
|
|
)
|
|
menu.exec(self.tableWidget_apparate.mapToGlobal(position))
|
|
|
|
def reminder(self):
|
|
logger.info("Opening reminder dialog")
|
|
reminder = reminder_ui()
|
|
reminder.exec()
|
|
tableposition = self.tableWidget_apparate.currentRow()
|
|
appnr = self.tableWidget_apparate.item(tableposition, 0).text()
|
|
if reminder.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 appnr,
|
|
)
|
|
self.update_calendar(data)
|
|
# self.db.update_bookdata(data, book_id)
|
|
# self.db.update_bookdata(data)
|
|
logger.info("committed message to database")
|
|
# self.update_app_media_list()
|
|
|
|
def get_reminders(self):
|
|
messages = self.db.getAllMessages()
|
|
logger.info(f"Got {len(messages)} messages from database")
|
|
self.calendarWidget.setMessages(messages)
|
|
self.calendarWidget.updateCells()
|
|
|
|
def open_reminder(self):
|
|
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):
|
|
# print(settings.dict())
|
|
settingsUI = Settings(self.active_user)
|
|
settingsUI.exec()
|
|
|
|
if settingsUI.result() == QtWidgets.QDialog.DialogCode.Accepted:
|
|
settingsUI.save()
|
|
# print(settings.dict())
|
|
|
|
# self.reload()
|
|
|
|
def reload(self):
|
|
state = self.confirm_popup(
|
|
"Bitte das Programm neustarten, um Änderungen zu übernehemen",
|
|
"Einstellungen geändert",
|
|
)
|
|
if state == 1:
|
|
exit()
|
|
else:
|
|
pass
|
|
|
|
def media_context_menu(self, position):
|
|
menu = QtWidgets.QMenu()
|
|
|
|
delete_action = QtGui.QAction("Löschen")
|
|
edit_action = QtGui.QAction("Bearbeiten")
|
|
apparat_add_action = QtGui.QAction("Zum Apparat hinzufügen")
|
|
apparat_move_action = QtGui.QAction("In Apparat verschieben")
|
|
apparat_copy_action = QtGui.QAction("In Apparat kopieren")
|
|
|
|
apparatmenu = menu.addMenu("Apparate")
|
|
generalmenu = menu.addMenu("Allgemeines")
|
|
apparatmenu.addActions(
|
|
[apparat_add_action, apparat_copy_action, apparat_move_action]
|
|
)
|
|
generalmenu.addActions([edit_action, delete_action])
|
|
# disable apparat_add_action
|
|
apparat_add_action.setEnabled(False)
|
|
delete_action.triggered.connect(self.delete_medium)
|
|
edit_action.triggered.connect(self.edit_medium)
|
|
apparat_add_action.triggered.connect(self.add_to_apparat)
|
|
apparat_copy_action.triggered.connect(self.copy_to_apparat)
|
|
apparat_move_action.triggered.connect(self.move_to_apparat)
|
|
menu.exec(self.tableWidget_apparat_media.mapToGlobal(position))
|
|
|
|
def copy_to_apparat(self):
|
|
selected_rows = self.tableWidget_apparat_media.selectionModel().selectedRows()
|
|
signatures = []
|
|
for row in selected_rows:
|
|
signature = self.tableWidget_apparat_media.item(row.row(), 1).text()
|
|
book_id = self.db.getBookIdBasedOnSignature(
|
|
self.active_apparat,
|
|
self.db.getProfId(self.profdata),
|
|
signature,
|
|
)
|
|
signatures.append(book_id)
|
|
result, apparat = self.confirm_action_dialog(
|
|
"In welchen Apparat sollen die Medien kopiert werden?"
|
|
)
|
|
if result == 1:
|
|
for book_id in signatures:
|
|
self.db.copyBookToApparat(book_id, apparat)
|
|
else:
|
|
return
|
|
|
|
def move_to_apparat(self):
|
|
selected_rows = self.tableWidget_apparat_media.selectionModel().selectedRows()
|
|
signatures = []
|
|
for row in selected_rows:
|
|
signature = self.tableWidget_apparat_media.item(row.row(), 1).text()
|
|
book_id = self.db.getBookIdBasedOnSignature(
|
|
self.active_apparat,
|
|
self.db.getProfId(self.profdata),
|
|
signature,
|
|
)
|
|
signatures.append(book_id)
|
|
result, apparat = self.confirm_action_dialog(
|
|
"In welchen Apparat sollen die Medien verschoben werden?"
|
|
)
|
|
if result == 1:
|
|
for book_id in signatures:
|
|
self.db.moveBookToApparat(book_id, apparat)
|
|
self.update_app_media_list()
|
|
else:
|
|
return
|
|
|
|
def confirm_action_dialog(self, message, title="Bestätigung"):
|
|
appnrs = self.db.getUnavailableApparatNumbers()
|
|
appnrs = [str(i) for i in appnrs]
|
|
appnrs.remove(self.active_apparat)
|
|
if len(appnrs) == 0:
|
|
# create a warning dialog, saying no apparats present
|
|
self.confirm_popup("Keine weiteren Apparate vorhanden", title="Fehler")
|
|
return (None, None)
|
|
dialog = QtWidgets.QDialog()
|
|
dialog.setWindowTitle(title)
|
|
# add a label to the dialog
|
|
label = QtWidgets.QLabel()
|
|
label.setText(message)
|
|
# add a combobox to the dialog
|
|
drpdwn = QtWidgets.QComboBox()
|
|
drpdwn.addItems(appnrs)
|
|
drpdwn.addItem("")
|
|
|
|
# set layout of dialog
|
|
layout = QtWidgets.QVBoxLayout()
|
|
layout.addWidget(label)
|
|
layout.addWidget(drpdwn)
|
|
|
|
# add buttons
|
|
okay_button = QtWidgets.QPushButton("Okay")
|
|
cancel_button = QtWidgets.QPushButton("Abbrechen")
|
|
layout.addWidget(okay_button)
|
|
layout.addWidget(cancel_button)
|
|
okay_button.clicked.connect(dialog.accept)
|
|
cancel_button.clicked.connect(dialog.reject)
|
|
|
|
dialog.setLayout(layout)
|
|
|
|
return dialog.exec(), self.db.getApparatId(
|
|
self.db.getApparatNameByAppNr(drpdwn.currentText())
|
|
)
|
|
|
|
def add_to_apparat(self):
|
|
"""use playwright in background to add medium to apparat"""
|
|
signature = self.tableWidget_apparat_media.item(
|
|
self.tableWidget_apparat_media.currentRow(), 1
|
|
).text()
|
|
self.db.getBookBasedOnSignature(
|
|
self.drpdwn_app_nr.currentText(),
|
|
signature=signature,
|
|
prof_id=self.db.getProfId(self.profdata),
|
|
)
|
|
# print(medium.adis_idn, medium.signature)
|
|
|
|
def edit_medium(self):
|
|
book = self.tableWidget_apparat_media.item(
|
|
self.tableWidget_apparat_media.currentRow(), 1
|
|
).text()
|
|
prof_id = self.db.getProfId(self.profdata)
|
|
data = self.db.getBookBasedOnSignature(
|
|
app_id=self.active_apparat,
|
|
signature=book,
|
|
prof_id=prof_id,
|
|
)
|
|
book_id = self.db.getBookIdBasedOnSignature(
|
|
self.active_apparat,
|
|
prof_id,
|
|
book,
|
|
)
|
|
widget = QtWidgets.QDialog()
|
|
bookedit = edit_bookdata_ui()
|
|
bookedit.setupUi(widget)
|
|
widget.setWindowIcon(Icon("settings").icon)
|
|
# 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(bookdata=data, book_id=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()
|
|
prof_id = self.db.getProfId(self.profdata)
|
|
# 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=prof_id,
|
|
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()
|
|
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(
|
|
app_id=selected_apparat_id,
|
|
prof_id=prof_id,
|
|
signature=signature,
|
|
)
|
|
self.db.deleteBook(book_id)
|
|
self.update_app_media_list()
|
|
|
|
def extend_apparat(self):
|
|
framework = ApparatExtendDialog()
|
|
framework.exec()
|
|
# return data from dialog if ok is pressed
|
|
if framework.result() == QtWidgets.QDialog.DialogCode.Accepted:
|
|
data = framework.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"]
|
|
)
|
|
# update the table
|
|
self.get_apparats()
|
|
else:
|
|
return
|
|
|
|
def __contact_dialog(self, apparat, location: tuple | str, mail=None, pid=""):
|
|
logger.debug(
|
|
"Got these values apparat: {}, location: {}, mail: {}, pid: {}".format(
|
|
apparat, location, mail, pid
|
|
)
|
|
)
|
|
|
|
active_apparat_id = (
|
|
self.drpdwn_app_nr.currentText() if apparat is None else apparat
|
|
)
|
|
if not active_apparat_id:
|
|
# get column 0 of the selected row
|
|
pass
|
|
if isinstance(pid, str):
|
|
prof_id = self.db.getProfByName(pid).id
|
|
else:
|
|
prof_id = pid
|
|
# if profname == "Name Kein":
|
|
# profname = pid
|
|
if self.app_name.text() != "":
|
|
app_name = self.app_name.text()
|
|
else:
|
|
app_name = self.db.getApparatName(active_apparat_id, prof_id)
|
|
if self.app_fach.currentText() != "":
|
|
app_subject = self.app_fach.currentText()
|
|
else:
|
|
app_subject = self.db.getApparatData(active_apparat_id, app_name)
|
|
app_subject = app_subject.apparat.subject
|
|
if prof_id:
|
|
pmail = self.db.getSpecificProfData(prof_id, ["mail"])
|
|
prof_name = self.db.getSpecificProfData(prof_id, ["fullname"])
|
|
else:
|
|
pmail = self.prof_mail.text()
|
|
self.mail_thread = Mail_Dialog(
|
|
app_id=active_apparat_id,
|
|
prof_name=prof_name,
|
|
prof_mail=pmail,
|
|
app_name=app_name,
|
|
app_subject=app_subject,
|
|
default_mail=mail if mail != "" else "Information zum Semesterapparat",
|
|
)
|
|
self.mail_thread.show()
|
|
|
|
def contact_prof(self, apparat="", location="", mail="", pid=""):
|
|
logger.debug(apparat)
|
|
logger.debug(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)
|
|
logger.info("Result state: {}", state)
|
|
if state == 1:
|
|
logger.debug("Deleting apparat {}", selected_apparat_id)
|
|
pid = self.db.getProfIDByApparat(selected_apparat_id)
|
|
self.db.deleteApparat(selected_apparat_id, Semester().value)
|
|
# 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")
|
|
|
|
logger.info("Starting login dialog")
|
|
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()
|
|
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()
|