fix broken files after faulty update

This commit is contained in:
2025-01-14 08:51:58 +01:00
parent 598da9bfac
commit 997d618ff1
102 changed files with 2499 additions and 548 deletions

39
.bumpversion.toml Normal file
View File

@@ -0,0 +1,39 @@
[tool.bumpversion]
current_version = "0.1.0"
parse = """(?x)
(?P<major>0|[1-9]\\d*)\\.
(?P<minor>0|[1-9]\\d*)\\.
(?P<patch>0|[1-9]\\d*)
(?:
- # dash separator for pre-release section
(?P<pre_l>[a-zA-Z-]+) # pre-release label
(?P<pre_n>0|[1-9]\\d*) # pre-release version number
)? # pre-release section is optional
"""
serialize = [
"{major}.{minor}.{patch}-{pre_l}{pre_n}",
"{major}.{minor}.{patch}",
]
search = "{current_version}"
replace = "{new_version}"
regex = false
ignore_missing_version = false
ignore_missing_files = false
tag = true
sign_tags = false
tag_name = "v{new_version}"
tag_message = "Bump version: {current_version} → {new_version}"
allow_dirty = false
commit = true
message = "Bump version: {current_version} → {new_version}"
commit_args = ""
setup_hooks = []
pre_commit_hooks = []
post_commit_hooks = []
[tool.bumpversion.parts.pre_l]
values = ["dev", "rc", "final"]
optional_value = "final"
[[tool.bumpversion.files]]
filename = ".version"
[[tool.bumpversion.files]]
filename = "__init__.py"

1
.python-version Normal file
View File

@@ -0,0 +1 @@
3.13

0
.version Normal file
View File

0
CHANGELOG.md Normal file
View File

View File

@@ -1,3 +1,3 @@
from src import UI from src.ui.userInterface import launch_gui as UI
if __name__ == "__main__": if __name__ == "__main__":
UI() UI() #:des

View File

@@ -1 +1,2 @@
from .config import Config from .config import Config

View File

@@ -1,3 +1,4 @@
from typing import Optional from typing import Optional
from dataclasses import dataclass from dataclasses import dataclass
from omegaconf import OmegaConf, DictConfig from omegaconf import OmegaConf, DictConfig

View File

@@ -4,6 +4,7 @@
Auf dieser Seite gibt es zwei Hauptfunktionen: die Suche und die Statistik. Standardmäßig wird die Statistik geöffnet. Auf dieser Seite gibt es zwei Hauptfunktionen: die Suche und die Statistik. Standardmäßig wird die Statistik geöffnet.
## Statistikbereich ## Statistikbereich
### Suche ### Suche
@@ -24,6 +25,8 @@ In diesem Bereich kann die Suche nach Semesterapparaten durchgeführt werden. Su
Die Suche kann durch Klicken auf den Button **Suchen** gestartet werden. Die Ergebnisse werden in der Tabelle darunter angezeigt. Die Suche kann durch Klicken auf den Button **Suchen** gestartet werden. Die Ergebnisse werden in der Tabelle darunter angezeigt.
### Suchergebnisse ### Suchergebnisse
!!! Info
Der Ergebnisbereich kann über den Vertikalen Slider verschoben werden, um mehr Platz für Tabelle, oder den Graphen zu schaffen. Hierzu mit der Maus auf den Raum zwischen den beiden Bereichen klicken und ziehen.
![Statistiksuchergebnisse](images/ss_stat_result.png) ![Statistiksuchergebnisse](images/ss_stat_result.png)
In diesem Bereich werden die Suchergebnisse angezeigt. Für jeden gefundenen Treffer wird eine Zeile angelegt: In diesem Bereich werden die Suchergebnisse angezeigt. Für jeden gefundenen Treffer wird eine Zeile angelegt:

View File

@@ -1,3 +1,4 @@
from .config import Icons from .config import Icons
icons = Icons() icons = Icons()

59
icons/config.py Normal file
View File

@@ -0,0 +1,59 @@
from omegaconf import OmegaConf, DictConfig
from typing import Optional
import os
import sys
class Icons:
_config: Optional[DictConfig] = None
def __init__(self):
self._config = OmegaConf.load("icons/icons.yaml")
self.config_path = "icons/config.yaml"
def save(self):
OmegaConf.save(self._config, self.config_path)
@property
def icons(self):
return self._config.icons
def get_icon(self, name: str):
return self.icons[name]
def set_icon(self, name: str, value: str):
self._config.icons[name] = value
@property
def path(self):
return self._config.icon_path
@property
def colors(self):
return self._config.colors
@colors.setter
def colors(self, value):
self._config.colors = value
@property
def dark(self):
return self._config.colors.dark
@property
def light(self):
return self._config.colors.light
@property
def warning(self):
return self._config.colors.warning
@property
def success(self):
return self._config.colors.success
def set_color(self, name: str, value: str):
self._config.colors[name] = value
@icons.setter
def icons(self, value):
self._config.icons = value

View File

@@ -1,28 +0,0 @@
icon_path: icons/
dark_color: '#75FB4Cmail'
light_color: '#EA3323'
icons:
locked: locked.svg
logo: logo.ico
show_password: visibility_off.svg
hide_password: visibility_on.svg
settings: settings.svg
today: calendar_today.svg
save: save.svg
edit_note: edit_note.svg
warning: warning.svg
error: error.svg
mail: mail.svg
semester: semester.svg
template_fail: test_fail.svg
offAction: shutdown.svg
info: info.svg
help: help.svg
close: close.svg
notification: notification.svg
valid_true: check_success.svg
valid_false: check_fail.svg
edit: edit.svg
important_warn : red_warn.svg
person: person_add.svg

View File

@@ -1,3 +1,4 @@
import sys import sys
from PyQt6 import QtWidgets from PyQt6 import QtWidgets

11
mail_vorlagen/test.eml Normal file
View File

@@ -0,0 +1,11 @@
Subject: test new template
MIME-Version: 1.0
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: 8bit
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body style=" font-family:'Segoe UI'; font-size:9pt; font-weight:400; font-style:normal;">
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">dklfdslködfskfd</p></body></html>

View File

@@ -1,6 +1,4 @@
from src.logic import userInterface from src.ui.userInterface import launch_gui as UI
if __name__ == "__main__": if __name__ == "__main__":
userInterface.launch_gui() UI()
# display_graph()

33
pyproject.toml Normal file
View File

@@ -0,0 +1,33 @@
[project]
name = "semesterapparatsmanager"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
"beautifulsoup4>=4.12.3",
"bump-my-version>=0.29.0",
"chardet>=5.2.0",
"darkdetect>=0.8.0",
"docx2pdf>=0.1.8",
"loguru>=0.7.3",
"mkdocs>=1.6.1",
"mkdocs-material>=9.5.49",
"mkdocs-material-extensions>=1.3.1",
"natsort>=8.4.0",
"omegaconf>=2.3.0",
"pandas>=2.2.3",
"pyqt6>=6.8.0",
"pyqtgraph>=0.13.7",
"python-docx>=1.1.2",
"pyzotero>=1.6.4",
"ratelimit>=2.2.1",
"requests>=2.32.3",
]
[dependency-groups]
dev = [
"bump-my-version>=0.29.0",
"icecream>=2.1.4",
"nuitka>=2.5.9",
]

12
pytest.ini Normal file
View File

@@ -0,0 +1,12 @@
[pytest]
# command should be *including --cov to generate coverage report
addopts = --cov
testpaths = tests
python_files = test_*.py
; Configuring pytest
; More info: https://docs.pytest.org/en/6.2.x/customize.html
;Logging
; DATE FORMAT EXAMPLE: %Y-%m-%d %H:%M:%S
; log_cli_format = %(asctime)s %(levelname)-8s %(name)-8s %(message)s
; log_cli_date_format = %H:%M:%S

View File

@@ -1,11 +1,25 @@
__version__ = "1.0.0"
__author__ = "Alexander Kirchner"
import sys
from config import Config from config import Config
import os
from loguru import logger as log
import sys
settings = Config("config/config.yaml") settings = Config("config/config.yaml")
from .utils.icon import Icon from .utils.icon import Icon
from .logic.log import MyLogger __version__ = "0.1.0"
from .ui.userInterface import launch_gui as UI __author__ = "Alexander Kirchner"
if not os.path.exists("logs"):
os.mkdir("logs")
# open and close the file to create it
logger = log
logger.remove()
logger.add("logs/application_info.log", rotation="1 week", level="INFO", enqueue=True)
logger.add("logs/application_error.log", rotation="1 week", level="ERROR", enqueue=True)
logger.add("logs/application_debug.log", rotation="1 week", level="DEBUG", enqueue=True)
logger.add("logs/application.log", rotation="1 week", enqueue=True)
# logger.add(sys.stderr, format="{time} {level} {message}", level="INFO")
logger.add(sys.stdout)

View File

@@ -1,5 +1,6 @@
from .admin_console import AdminCommands from .admin_console import AdminCommands
from .create_file import recreateElsaFile, recreateFile from .create_file import recreateElsaFile, recreateFile
from .database import Database from .database import Database
from .delete_temp_contents import delete_temp_contents as tempdelete from .delete_temp_contents import delete_temp_contents as tempdelete
from .semester import generateSemesterByDate, generateSemesterByOffset from .semester import Semester

View File

@@ -1,3 +1,4 @@
import hashlib import hashlib
import random import random

View File

@@ -1,7 +1,6 @@
import os import os
from pathlib import Path from pathlib import Path
from icecream import ic
from src.backend.database import Database from src.backend.database import Database

View File

@@ -5,9 +5,9 @@ import tempfile
from pathlib import Path from pathlib import Path
from src import settings from src import settings
from typing import Any, Dict, List, Optional, Tuple, Union from typing import Any, Dict, List, Optional, Tuple, Union
# from icecream import ic
from omegaconf import OmegaConf from omegaconf import OmegaConf
import datetime import datetime
from src import logger
from src.backend.db import ( from src.backend.db import (
CREATE_ELSA_FILES_TABLE, CREATE_ELSA_FILES_TABLE,
CREATE_ELSA_MEDIA_TABLE, CREATE_ELSA_MEDIA_TABLE,
@@ -22,15 +22,14 @@ from src.backend.db import (
CREATE_TABLE_USER, CREATE_TABLE_USER,
) )
from src.errors import AppPresentError, NoResultError from src.errors import AppPresentError, NoResultError
from src.logic import ApparatData, BookData, Prof, Apparat, ELSA, logger as log from src.logic import ApparatData, BookData, Prof, Apparat, ELSA
from src.logic.constants import SEMAP_MEDIA_ACCOUNTS from src.logic.constants import SEMAP_MEDIA_ACCOUNTS
from src.utils import create_blob, dump_pickle, load_pickle from src.utils import create_blob, dump_pickle, load_pickle
from .semester import generateSemesterByDate from .semester import Semester
from icecream import ic from string import ascii_lowercase as lower, digits, punctuation
from string import ascii_lowercase as lower, digits
ascii_lowercase = lower + digits ascii_lowercase = lower + digits + punctuation
# get the line that called the function # get the line that called the function
class Database: class Database:
database = settings.database database = settings.database
@@ -62,7 +61,7 @@ class Database:
# print(path) # print(path)
os.makedirs(path) os.makedirs(path)
if self.get_db_contents() == []: if self.get_db_contents() == []:
log.critical("Database does not exist, creating tables") logger.critical("Database does not exist, creating tables")
self.create_tables() self.create_tables()
self.insertSubjects() self.insertSubjects()
@@ -146,12 +145,12 @@ class Database:
""" """
conn = self.connect() conn = self.connect()
cursor = conn.cursor() cursor = conn.cursor()
log.info(f"Inserting {params} into database with query {query}") logger.debug(f"Inserting {params} into database with query {query}")
cursor.execute(query, params) cursor.execute(query, params)
conn.commit() conn.commit()
self.close_connection(conn) self.close_connection(conn)
@log.catch @logger.catch
def query_db( def query_db(
self, query: str, args: Tuple = (), one: bool = False self, query: str, args: Tuple = (), one: bool = False
) -> Union[Tuple, List[Tuple]]: ) -> Union[Tuple, List[Tuple]]:
@@ -181,14 +180,14 @@ class Database:
# if "INSERT" in query: # if "INSERT" in query:
# log_message = f"Querying database with query {query}" # log_message = f"Querying database with query {query}"
log.info(log_message) logger.debug(log_message)
try: try:
cursor.execute(query, args) cursor.execute(query, args)
rv = cursor.fetchall() rv = cursor.fetchall()
conn.commit() conn.commit()
self.close_connection(conn) self.close_connection(conn)
except sql.OperationalError as e: except sql.OperationalError as e:
log.error(f"Error in query: {e}") logger.error(f"Error in query: {e}")
return None return None
return (rv[0] if rv else None) if one else rv return (rv[0] if rv else None) if one else rv
@@ -211,7 +210,7 @@ class Database:
t_query = ( t_query = (
f"SELECT bookdata FROM media WHERE app_id={app_id} AND prof_id={prof_id}" f"SELECT bookdata FROM media WHERE app_id={app_id} AND prof_id={prof_id}"
) )
log.info(t_query) logger.debug(t_query)
# # print(t_query) # # print(t_query)
result = cursor.execute(t_query).fetchall() result = cursor.execute(t_query).fetchall()
result = [load_pickle(i[0]) for i in result] result = [load_pickle(i[0]) for i in result]
@@ -238,7 +237,7 @@ class Database:
params = (converted, app_id, prof_id, 0) params = (converted, app_id, prof_id, 0)
cursor.execute(query, params) cursor.execute(query, params)
logMessage = f"Added book with signature {bookdata.signature} to database, data: {converted}" logMessage = f"Added book with signature {bookdata.signature} to database, data: {converted}"
log.info(logMessage) logger.info(logMessage)
conn.commit() conn.commit()
self.close_connection(conn) self.close_connection(conn)
@@ -307,7 +306,7 @@ class Database:
list[tuple[BookData, int]]: A list of tuples containing the wrapped Metadata and the id of the book list[tuple[BookData, int]]: A list of tuples containing the wrapped Metadata and the id of the book
""" """
rdata = self.query_db("SELECT * FROM media WHERE deleted=0") rdata = self.query_db("SELECT * FROM media WHERE deleted=0")
# ic(rdata, len(rdata)) # logger.debug(rdata, len(rdata))
mode = 0 mode = 0
if len(data) == 1: if len(data) == 1:
if "signature" in data.keys(): if "signature" in data.keys():
@@ -335,7 +334,7 @@ class Database:
and data["title"] in bookdata.title and data["title"] in bookdata.title
): ):
ret.append((bookdata, app_id, prof_id)) ret.append((bookdata, app_id, prof_id))
# ic(ret) # logger.debug(ret)
return ret return ret
def setAvailability(self, book_id: str, available: str): def setAvailability(self, book_id: str, available: str):
@@ -514,7 +513,7 @@ class Database:
(app_id, prof_id), (app_id, prof_id),
) )
def getSemersters(self) -> list[str]: def getSemesters(self) -> list[str]:
"""Return all the unique semesters in the database """Return all the unique semesters in the database
Returns: Returns:
@@ -640,7 +639,7 @@ class Database:
Args: Args:
message_id (str): the id of the message message_id (str): the id of the message
""" """
log.info(f"Deleting message with id {message_id}") logger.debug(f"Deleting message with id {message_id}")
self.query_db("DELETE FROM messages WHERE id=?", (message_id,)) self.query_db("DELETE FROM messages WHERE id=?", (message_id,))
# Prof data # Prof data
@@ -710,7 +709,6 @@ class Database:
(profname.replace(",", ""),), (profname.replace(",", ""),),
one=True, one=True,
) )
print(data)
person = Prof() person = Prof()
return person.from_tuple(data) return person.from_tuple(data)
@@ -770,20 +768,21 @@ class Database:
if result is None: if result is None:
raise NoResultError("No result found") raise NoResultError("No result found")
apparat = ApparatData() apparat = ApparatData()
apparat.appname = result[1] apparat.apparat.id = result[0]
apparat.appnr = result[4] apparat.apparat.name = result[1]
apparat.dauerapp = True if result[7] == 1 else False apparat.apparat.appnr = result[4]
prof_data = self.getProfData(self.getProfNameById(result[2])) apparat.apparat.eternal = True if result[7] == 1 else False
apparat.profname = self.getProfNameById(result[2]) apparat.prof = self.getProfData(self.getProfNameById(result[2]))
apparat.prof_mail = prof_data.mail apparat.prof.fullname = self.getProfNameById(result[2])
apparat.prof_tel = prof_data.telnr apparat.apparat.prof_id = result[2]
apparat.prof_title = prof_data.title
apparat.app_fach = result[3] apparat.apparat.subject = result[3]
apparat.erstellsemester = result[5] apparat.apparat.created_semester = result[5]
apparat.semester = result[8] apparat.apparat.extend_until = result[8]
apparat.deleted = result[9] apparat.apparat.deleted = result[9]
apparat.apparat_adis_id = result[11] apparat.apparat.apparat_id_adis = result[11]
apparat.prof_adis_id = result[12] apparat.apparat.prof_id_adis = result[12]
apparat.apparat.konto = result[13]
return apparat return apparat
def getUnavailableApparatNumbers(self) -> List[int]: def getUnavailableApparatNumbers(self) -> List[int]:
@@ -796,7 +795,7 @@ class Database:
"SELECT appnr FROM semesterapparat WHERE deletion_status=0" "SELECT appnr FROM semesterapparat WHERE deletion_status=0"
) )
numbers = [i[0] for i in numbers] numbers = [i[0] for i in numbers]
log.info(f"Currently used apparat numbers: {numbers}") logger.info(f"Currently used apparat numbers: {numbers}")
return numbers return numbers
def setNewSemesterDate(self, app_id: Union[str, int], newDate, dauerapp=False): def setNewSemesterDate(self, app_id: Union[str, int], newDate, dauerapp=False):
@@ -850,21 +849,22 @@ class Database:
Returns: Returns:
Optional[int]: the id of the apparat Optional[int]: the id of the apparat
""" """
ic(apparat) logger.debug(apparat)
prof = self.getProfByName(apparat.prof_details.fullname) app = apparat.apparat
prof_id = prof.id prof = apparat.prof
ic(prof_id, apparat.profname) present_prof = self.getProfByName(prof.name())
prof_id = present_prof.id
logger.debug(present_prof)
app_id = self.getApparatId(apparat.appname) app_id = self.getApparatId(app.name)
if app_id: if app_id:
return AppPresentError(app_id) return AppPresentError(app_id)
if not prof_id: if not prof_id:
print("prof id not present, creating prof with data", apparat.prof_details) logger.debug("prof id not present, creating prof with data", prof)
prof_id = self.createProf(apparat.prof_details) prof_id = self.createProf(prof)
# self.getProfId(apparat.profname) logger.debug(prof_id)
ic(prof_id) query = f"INSERT OR IGNORE INTO semesterapparat (appnr, name, erstellsemester, dauer, prof_id, fach,deletion_status,konto) VALUES ('{app.appnr}', '{app.name}', '{app.created_semester}', '{app.eternal}', {prof_id}, '{app.subject}', '{0}', '{SEMAP_MEDIA_ACCOUNTS[app.appnr]}')"
query = f"INSERT OR IGNORE INTO semesterapparat (appnr, name, erstellsemester, dauer, prof_id, fach,deletion_status,konto) VALUES ('{apparat.appnr}', '{apparat.appname}', '{apparat.semester}', '{apparat.dauerapp}', {prof_id}, '{apparat.app_fach}', '{0}', '{SEMAP_MEDIA_ACCOUNTS[apparat.appnr]}')" logger.debug(query)
log.info(query)
self.query_db(query) self.query_db(query)
return None return None
def getApparatsByProf(self, prof_id: Union[str, int]) -> list[tuple]: def getApparatsByProf(self, prof_id: Union[str, int]) -> list[tuple]:
@@ -934,7 +934,7 @@ class Database:
""" """
conn = self.connect() conn = self.connect()
cursor = conn.cursor() cursor = conn.cursor()
semesters = self.getSemersters() semesters = self.getSemesters()
created = [] created = []
deleted = [] deleted = []
for semester in semesters: for semester in semesters:
@@ -946,7 +946,6 @@ class Database:
deleted.append(result[0]) deleted.append(result[0])
# store data in a tuple # store data in a tuple
ret = [] ret = []
e_tuple = ()
for sem in semesters: for sem in semesters:
e_tuple = ( e_tuple = (
sem, sem,
@@ -957,17 +956,16 @@ class Database:
self.close_connection(conn) self.close_connection(conn)
return ret return ret
def deleteApparat(self, app_id: Union[str, int]): def deleteApparat(self, app_id: Union[str, int], semester):
"""Delete an apparat from the database """Delete an apparat from the database
Args: Args:
app_id (Union[str, int]): the id of the apparat app_id (Union[str, int]): the id of the apparat
semester (str): the semester the apparat should be deleted from semester (str): the semester the apparat should be deleted from
""" """
today = datetime.datetime.now().strftime("%Y-%m-%d")
self.query_db( self.query_db(
"UPDATE semesterapparat SET deletion_status=1, deleted_date=? WHERE appnr=?", "UPDATE semesterapparat SET deletion_status=1, deleted_date=? WHERE appnr=?",
(today, app_id), (semester, app_id),
) )
def isEternal(self, id): def isEternal(self, id):
@@ -1007,15 +1005,15 @@ class Database:
""" """
query = "UPDATE semesterapparat SET name = ?, fach = ?, dauer = ?, prof_id = ?, prof_id_adis = ?, apparat_id_adis = ? WHERE appnr = ?" query = "UPDATE semesterapparat SET name = ?, fach = ?, dauer = ?, prof_id = ?, prof_id_adis = ?, apparat_id_adis = ? WHERE appnr = ?"
params = ( params = (
apparat_data.appname, apparat_data.apparat.name,
apparat_data.app_fach, apparat_data.apparat.subject,
apparat_data.dauerapp, apparat_data.apparat.eternal,
self.getProfData(apparat_data.prof_details.fullname).id, self.getProfData(apparat_data.prof.fullname).id,
apparat_data.prof_adis_id, apparat_data.apparat.prof_id_adis,
apparat_data.apparat_adis_id, apparat_data.apparat.apparat_id_adis,
apparat_data.appnr, apparat_data.apparat.appnr,
) )
log.info(f"Updating apparat with query {query} and params {params}") logger.debug(f"Updating apparat with query {query} and params {params}")
self.query_db(query, params) self.query_db(query, params)
def checkApparatExists(self, app_name: str): def checkApparatExists(self, app_name: str):
@@ -1067,7 +1065,8 @@ class Database:
Returns: Returns:
list: the result of the query list: the result of the query
""" """
ic(query) logger.debug(query)
logger.debug(f"Query: {query}")
conn = self.connect() conn = self.connect()
cursor = conn.cursor() cursor = conn.cursor()
result = cursor.execute(query).fetchall() result = cursor.execute(query).fetchall()
@@ -1080,15 +1079,15 @@ class Database:
result_a = tuple(result_a) result_a = tuple(result_a)
result[result.index(orig_value)] = result_a result[result.index(orig_value)] = result_a
self.close_connection(conn) self.close_connection(conn)
log.info(f"Query result: {result}") logger.debug(f"Query result: {result}")
return result return result
if "deletable" in kwargs.keys(): if "deletable" in kwargs.keys():
query = f"""SELECT * FROM semesterapparat query = f"""SELECT * FROM semesterapparat
WHERE deletion_status=0 AND dauer=0 AND WHERE deletion_status=0 AND dauer=0 AND
( (
(erstellsemester!='{kwargs['deletesemester']}' AND verlängerung_bis IS NULL) OR (erstellsemester!='{kwargs["deletesemester"]}' AND verlängerung_bis IS NULL) OR
(erstellsemester!='{kwargs['deletesemester']}' AND verlängerung_bis!='{kwargs['deletesemester']}' AND verlängerung_bis!='{generateSemesterByDate(True)}') (erstellsemester!='{kwargs["deletesemester"]}' AND verlängerung_bis!='{kwargs["deletesemester"]}' AND verlängerung_bis!='{Semester()}')
)""" )"""
return __query(query) return __query(query)
if "dauer" in kwargs.keys(): if "dauer" in kwargs.keys():
@@ -1119,8 +1118,10 @@ class Database:
f"(erstellsemester='{kwargs['endsemester']}' OR verlängerung_bis='{kwargs['endsemester']}') AND ", f"(erstellsemester='{kwargs['endsemester']}' OR verlängerung_bis='{kwargs['endsemester']}') AND ",
) )
# remove all x="" parts from the query where x is a key in kwargs # remove all x="" parts from the query where x is a key in kwargs
query = query[:-5] logger.info(f"Query before: {query}")
query = query.strip() query = query.strip()
query = query[:-4]
logger.info(f"Query after: {query}")
# check if query ends with lowercase letter or a '. if not, remove last symbol and try again # check if query ends with lowercase letter or a '. if not, remove last symbol and try again
while query[-1] not in ascii_lowercase and query[-1] != "'": while query[-1] not in ascii_lowercase and query[-1] != "'":
query = query[:-1] query = query[:-1]
@@ -1471,22 +1472,19 @@ class Database:
) )
### ###
def createProf(self, profdata: Prof):
logger.debug(profdata)
def createProf(self, profdata:Prof):
print("createProf")
ic(profdata)
conn = self.connect() conn = self.connect()
cursor = conn.cursor() cursor = conn.cursor()
fname = profdata.firstname#profdata["profname"].split(", ")[1].strip() fname = profdata.firstname
lname = profdata.lastname#profdata["profname"].split(", ")[0].strip() lname = profdata.lastname
fullname = f"{lname} {fname}" fullname = f"{lname} {fname}"
mail = profdata.mail#profdata["prof_mail"] mail = profdata.mail
telnr = profdata.telnr#profdata["prof_tel"] telnr = profdata.telnr
title = profdata.title #profdata["title"] title = profdata.title
query = f"INSERT INTO prof (fname, lname, fullname, mail, telnr,titel) VALUES ('{fname}','{lname}','{fullname}','{mail}','{telnr}','{title}')" query = f"INSERT INTO prof (fname, lname, fullname, mail, telnr,titel) VALUES ('{fname}','{lname}','{fullname}','{mail}','{telnr}','{title}')"
log.info(query) logger.debug(query)
cursor.execute(query) cursor.execute(query)
conn.commit() conn.commit()
@@ -1519,7 +1517,7 @@ class Database:
conn = self.connect() conn = self.connect()
cursor = conn.cursor() cursor = conn.cursor()
if isinstance(profdata, Prof): if isinstance(profdata, Prof):
fullname = profdata.fullname fullname = profdata.name()
else: else:
name = profdata["profname"] name = profdata["profname"]
if ","in name: if ","in name:
@@ -1529,7 +1527,7 @@ class Database:
else: else:
fullname = profdata["profname"] fullname = profdata["profname"]
query = f"SELECT id FROM prof WHERE fullname = '{fullname}'" query = f"SELECT id FROM prof WHERE fullname = '{fullname}'"
log.info(query) logger.debug(query)
cursor.execute(query) cursor.execute(query)
result = cursor.fetchone() result = cursor.fetchone()
@@ -1546,7 +1544,7 @@ class Database:
conn = self.connect() conn = self.connect()
cursor = conn.cursor() cursor = conn.cursor()
query = f"SELECT * FROM prof WHERE fullname = '{fullname}'" query = f"SELECT * FROM prof WHERE fullname = '{fullname}'"
log.info(query) logger.debug(query)
result = cursor.execute(query).fetchone() result = cursor.execute(query).fetchone()
if result: if result:

View File

@@ -1,3 +1,4 @@
CREATE_TABLE_APPARAT = """CREATE TABLE semesterapparat ( CREATE_TABLE_APPARAT = """CREATE TABLE semesterapparat (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
name TEXT, name TEXT,

View File

@@ -1,8 +1,9 @@
import os import os
from pathlib import Path from pathlib import Path
from src import database from src import settings
database = settings.database
def delete_temp_contents(): def delete_temp_contents():
""" """

View File

@@ -1,3 +1,4 @@
import pickle import pickle
from typing import Any, ByteString from typing import Any, ByteString

View File

@@ -1,24 +1,21 @@
import datetime import datetime
from src.logic.log import logger from src import logger
from dataclasses import dataclass from dataclasses import dataclass
@dataclass @dataclass
class Semester: class Semester:
logger.debug("Semester class loaded") logger.debug("Semester class loaded")
_year: int | None = datetime.datetime.now().year _year: int | None = str(datetime.datetime.now().year)[2:]
_semester: str | None = None _semester: str | None = None
_month: int | None = datetime.datetime.now().month _month: int | None = datetime.datetime.now().month
value: str = None value: str = None
logger.debug(f"Got values year:{_year}, semester:{_semester}, month:{_month}")
def __post_init__(self): def __post_init__(self):
logger.debug( if isinstance(self._year, str):
f"Got values post_init year:{self._year}, semester:{self._semester}, month:{self._month}" self._year = int(self._year)
)
if self._year is None: if self._year is None:
self._year = datetime.datetime.now().year self._year = datetime.datetime.now().year[2:]
if self._month is None: if self._month is None:
self._month = datetime.datetime.now().month self._month = datetime.datetime.now().month
if self._semester is None: if self._semester is None:
@@ -37,11 +34,7 @@ class Semester:
@logger.catch @logger.catch
def computeValue(self): def computeValue(self):
# year is only last two digits # year is only last two digits
year = str(self._year)[2:] year = self._year
year = int(year)
logger.debug(
f"Year is {year}, month is {self._month}, semester is {self._semester}"
)
if self._semester == "WiSe": if self._semester == "WiSe":
if self._month < 4: if self._month < 4:
valueyear = str(year - 1) + "/" + str(year) valueyear = str(year - 1) + "/" + str(year)
@@ -60,25 +53,63 @@ class Semester:
str: the new semester value str: the new semester value
""" """
assert isinstance(value, int), "Value must be an integer" assert isinstance(value, int), "Value must be an integer"
logger.debug(f"Offsetting semester by {value}")
if value == 0: if value == 0:
return self return self
if value > 0: if value > 0:
if value % 2 == 0: if value % 2 == 0:
return Semester(self._year + value // 2, self._semester) return Semester(
self._year - value // 2, self._semester - value // 2 + 1
)
else: else:
semester = self._semester semester = self._semester
semester = "SoSe" if semester == "WiSe" else "WiSe" semester = "SoSe" if semester == "WiSe" else "WiSe"
logger.debug(f"Semester is {semester}")
return Semester(self._year + value // 2, semester) return Semester(self._year + value // 2, semester)
else: else:
if value % 2 == 0: if value % 2 == 0:
return Semester(self._year - value // 2, self._semester) return Semester(self.year + value // 2, self._semester)
else: else:
semester = self._semester semester = self._semester
semester = "SoSe" if semester == "WiSe" else "WiSe" semester = "SoSe" if semester == "WiSe" else "WiSe"
return Semester(self._year + value // 2, semester) return Semester(self._year + value // 2, semester)
def isPastSemester(self, semester) -> bool:
"""Checks if the current Semester is a past Semester compared to the given Semester
Args:
semester (str): The semester to compare to
Returns:
bool: True if the current semester is in the past, False otherwise
"""
if self.year < semester.year:
return True
if self.year == semester.year:
if self.semester == "WiSe" and semester.semester == "SoSe":
return True
return False
def isFutureSemester(self, semester: "Semester") -> bool:
"""Checks if the current Semester is a future Semester compared to the given Semester
Args:
semester (str): The semester to compare to
Returns:
bool: True if the current semester is in the future, False otherwise
"""
if self.year > semester.year:
return True
if self.year == semester.year:
if self.semester == "SoSe" and semester.semester == "WiSe":
return True
return False
def from_string(self, val):
self.value = val
self._year = int(val[-2:])
self._semester = val[:4]
return self
@property @property
def next(self): def next(self):
return self.offset(1) return self.offset(1)
@@ -86,3 +117,11 @@ class Semester:
@property @property
def previous(self): def previous(self):
return self.offset(-1) return self.offset(-1)
@property
def year(self):
return self._year
@property
def semester(self):
return self._semester

View File

@@ -1,3 +1,4 @@
from dataclasses import dataclass, field from dataclasses import dataclass, field
import yaml import yaml

View File

@@ -1,3 +1,4 @@
class NoResultError(Exception): class NoResultError(Exception):
def __init__(self, message): def __init__(self, message):
self.message = f"The query: {message} returned no results" self.message = f"The query: {message} returned no results"

View File

@@ -1,2 +1,3 @@
# import basic error classes # import basic error classes
from .DatabaseErrors import * from .DatabaseErrors import *

View File

@@ -1,9 +1,9 @@
from .log import MyLogger, logger
from .dataclass import ApparatData, BookData, Prof, Apparat, ELSA from .dataclass import ApparatData, BookData, Prof, Apparat, ELSA
from .thread_bookgrabber import BookGrabber from .thread_bookgrabber import BookGrabber
from .threads_autoadder import AutoAdder from .threads_autoadder import AutoAdder
from .threads_availchecker import AvailChecker from .threads_availchecker import AvailChecker
from .c_sort import custom_sort from .c_sort import custom_sort, sort_semesters_list
from .constants import APP_NRS, PROF_TITLES, SEMAP_MEDIA_ACCOUNTS from .constants import APP_NRS, PROF_TITLES, SEMAP_MEDIA_ACCOUNTS
from .csvparser import csv_to_list from .csvparser import csv_to_list
from .wordparser import elsa_word_to_csv, word_docx_to_csv from .wordparser import elsa_word_to_csv, word_docx_to_csv

View File

@@ -1,59 +1,86 @@
from typing import List, Tuple def parse_semester(semester: str):
from natsort import natsorted
def custom_sort(unsorted: List[Tuple[str, int, int]]) -> List[Tuple[str, int, int]]:
"""Sort a list of semesters in the format "SoSe n" and "WiSe n/n+1" in the correct order.
Where n == year in 2 digit format
Args:
----
unsorted (list[tuple]): List of semesters in the format "SoSe n" and "WiSe n/n+1"
Returns:
-------
ret (list[tuple]): Sorted list in correct order of WiSe n/n+1 and SoSe n
""" """
summer = natsorted([i for i in unsorted if "SoSe" in i[0]]) Parses the semester string into a sortable format.
winter = natsorted([i for i in unsorted if "WiSe" in i[0]]) Returns a tuple of (year, type), where type is 0 for SoSe and 1 for WiSe.
summer = natsorted(summer, key=lambda x: x[0]) """
winter = natsorted(winter, key=lambda x: x[0]) if semester.startswith("SoSe"):
return int(semester.split()[1]), 0
elif semester.startswith("WiSe"):
year_part = semester.split()[1]
start_year, _ = map(int, year_part.split("/"))
return start_year, 1
else:
raise ValueError(f"Invalid semester format: {semester}")
# Merge the lists
ret = [] def custom_sort(entries):
i = 0 """
j = 0 Sorts the list of tuples based on the custom schema.
while i < len(summer) and j < len(winter):
if summer[i][0][5:] <= winter[j][0][5:]: :param entries: List of tuples in the format (str, int, int).
ret.append(summer[i]) :return: Sorted list of tuples.
i += 1 """
return sorted(
entries,
key=lambda entry: (
parse_semester(entry[0]), # Sort by semester parsed as (year, type)
entry[1], # Then by the second element of the tuple
entry[2], # Finally by the third element of the tuple
),
)
def parse_semester(semester: str):
"""
Parses the semester string into a sortable format.
Returns a tuple of (year, type), where type is 0 for SoSe and 1 for WiSe.
"""
if semester.startswith("SoSe"):
return int(semester.split()[1]), 0
elif semester.startswith("WiSe"):
year_part = semester.split()[1]
if "/" in year_part:
start_year, _ = map(int, year_part.split("/"))
else: else:
ret.append(winter[j]) start_year = int(year_part)
j += 1 return start_year, 1
else:
raise ValueError(f"Invalid semester format: {semester}")
# Append the remaining items
while i < len(summer):
ret.append(summer[i])
i += 1
while j < len(winter):
ret.append(winter[j])
j += 1
return ret def sort_semesters_list(semesters: list) -> list:
"""
Sorts a list of semester strings based on year and type.
# Test the function :param semesters: List of semester strings (e.g., "SoSe 24", "WiSe 22/23").
:return: Sorted list of semester strings.
pass """
return sorted(semesters, key=parse_semester)
if __name__ == "__main__": if __name__ == "__main__":
unsorted = [ unsorted = [
("WiSe 23/24", 7, 5), "SoSe 24",
("SoSe 23", 5, 0), "WiSe 22/23",
("SoSe 22", 1, 0), "WiSe 23/24",
("WiSe 22/23", 1, 0), "WiSe 20/21",
("SoSe 15", 1, 0), "SoSe 23",
"SoSe 20",
"WiSe 7/8",
"WiSe 14/15",
"WiSe 13/14",
"SoSe 8",
"WiSe 19/20",
"WiSe 12/13",
"WiSe 21/22",
"WiSe 18/19",
"WiSe 11/12",
"WiSe 9/10",
"WiSe 6/7",
"SoSe 7",
"WiSe 16/17",
"WiSe 24/25",
"SoSe 25",
] ]
# print(custom_sort(unsorted)) print(sort_semesters_list(unsorted))

View File

@@ -1,3 +1,4 @@
from enum import Enum from enum import Enum
APP_NRS = [i for i in range(1, 181)] APP_NRS = [i for i in range(1, 181)]

View File

@@ -1,3 +1,4 @@
import csv import csv
import chardet import chardet

View File

@@ -1,18 +1,20 @@
import re import re
from dataclasses import dataclass, field from dataclasses import dataclass, field
from enum import Enum from enum import Enum
@dataclass @dataclass
class Prof: class Prof:
id: int = None id: int = None
_title: str = None _title: str = None
firstname: str= None firstname: str = None
lastname: str= None lastname: str = None
fullname: str= None fullname: str = None
mail: str= None mail: str = None
telnr: str= None telnr: str = None
#add function that sets the data based on a dict # add function that sets the data based on a dict
def from_dict(self, data: dict): def from_dict(self, data: dict):
for key, value in data.items(): for key, value in data.items():
if hasattr(self, key): if hasattr(self, key):
@@ -28,7 +30,8 @@ class Prof:
@title.setter @title.setter
def title(self, value): def title(self, value):
self._title = value self._title = value
#add function that sets the data from a tuple
# add function that sets the data from a tuple
def from_tuple(self, data: tuple): def from_tuple(self, data: tuple):
setattr(self, "id", data[0]) setattr(self, "id", data[0])
setattr(self, "_title", data[1]) setattr(self, "_title", data[1])
@@ -40,40 +43,18 @@ class Prof:
return self return self
def name(self, comma=False): def name(self, comma=False):
if self.firstname is None and self.lastname is None:
if "," in self.fullname:
self.firstname = self.fullname.split(",")[1].strip()
self.lastname = self.fullname.split(",")[0].strip()
else:
return self.fullname
if comma: if comma:
return f"{self.lastname}, {self.firstname}" return f"{self.lastname}, {self.firstname}"
return f"{self.lastname} {self.firstname}" return f"{self.lastname} {self.firstname}"
@dataclass
class ApparatData:
prof_title: str | None = None
profname: str | None = None
dauerapp: bool = False
appnr: int | None = None
appname: str | None = None
app_fach: str | None = None
semester: str | None = None
erstellsemester: str | None = None
prof_mail: str | None = None
prof_tel: int | None = None
deleted: int = 0
prof_adis_id: int | None = None
apparat_adis_id: int | None = None
@property
def prof_details(self) -> Prof:
return Prof().from_dict({
"title": self.prof_title,
"firstname": self.profname.split(',')[1].strip(),
"lastname": self.profname.split(',')[0].strip(),
"mail": self.prof_mail,
"telnr": self.prof_tel,
"fullname": f"{self.profname.split(',')[0].strip()} {self.profname.split(',')[1].strip()}",
})
def translateToFullname(self):
return f"{self.profname.split(',')[0].strip()} {self.profname.split(',')[1].strip()}"
@dataclass @dataclass
class BookData: class BookData:
ppn: str | None = None ppn: str | None = None
@@ -132,7 +113,7 @@ class Subjects(Enum):
FRENCH = (6, "Französisch") FRENCH = (6, "Französisch")
GEOGRAPHY = (7, "Geographie") GEOGRAPHY = (7, "Geographie")
HISTORY = (8, "Geschichte") HISTORY = (8, "Geschichte")
HEALT_EDUCATION = (9, "Gesundheitspädagogik") HEALTH_EDUCATION = (9, "Gesundheitspädagogik")
HTW = (10, "Haushalt / Textil") HTW = (10, "Haushalt / Textil")
ART = (11, "Kunst") ART = (11, "Kunst")
MATH_IT = (12, "Mathematik / Informatik") MATH_IT = (12, "Mathematik / Informatik")
@@ -197,6 +178,13 @@ class Apparat:
setattr(self, "konto", data[13]) setattr(self, "konto", data[13])
return self return self
@property
def get_semester(self):
if self.extend_until is not None:
return self.extend_until
else:
return self.created_semester
@dataclass @dataclass
class ELSA: class ELSA:
@@ -211,3 +199,7 @@ class ELSA:
setattr(self, "semester", data[2]) setattr(self, "semester", data[2])
setattr(self, "prof_id", data[3]) setattr(self, "prof_id", data[3])
return self return self
@dataclass
class ApparatData:
prof: Prof = field(default_factory=Prof)
apparat: Apparat = field(default_factory=Apparat)

View File

@@ -1,3 +1,4 @@
import csv import csv
import pandas as pd import pandas as pd

View File

@@ -0,0 +1 @@

View File

@@ -1,3 +1,4 @@
from dataclasses import dataclass, field from dataclasses import dataclass, field
import yaml import yaml

View File

@@ -3,7 +3,7 @@ import sqlite3
from PyQt6.QtCore import QThread from PyQt6.QtCore import QThread
from PyQt6.QtCore import pyqtSignal as Signal from PyQt6.QtCore import pyqtSignal as Signal
from src.backend.database import Database from src.backend.database import Database
from src.logic.log import MyLogger
from src.logic.webrequest import BibTextTransformer, WebRequest from src.logic.webrequest import BibTextTransformer, WebRequest
@@ -16,8 +16,7 @@ class BookGrabber(QThread):
def __init__(self, appnr): def __init__(self, appnr):
super(BookGrabber, self).__init__(parent=None) super(BookGrabber, self).__init__(parent=None)
self.is_Running = True self.is_Running = True
self.logger = MyLogger("Worker") logger.info("Starting worker thread")
self.logger.log_info("Starting worker thread")
self.data = None self.data = None
self.app_id = None self.app_id = None
self.prof_id = None self.prof_id = None
@@ -35,9 +34,9 @@ class BookGrabber(QThread):
self.data = data self.data = data
self.use_any = any_book self.use_any = any_book
self.use_exact = exact self.use_exact = exact
self.logger.log_info(f"Working on {len(self.data)} entries") logger.info(f"Working on {len(self.data)} entries")
self.tstate = (self.app_id, self.prof_id, self.mode, self.data) self.tstate = (self.app_id, self.prof_id, self.mode, self.data)
self.logger.log_debug("State: " + str(self.tstate)) logger.debug("State: " + str(self.tstate))
# print(self.tstate) # print(self.tstate)
def run(self): def run(self):
@@ -50,7 +49,7 @@ class BookGrabber(QThread):
for entry in iterdata: for entry in iterdata:
# print(entry) # print(entry)
signature = str(entry) signature = str(entry)
self.logger.log_info("Processing entry: " + signature) logger.info("Processing entry: " + signature)
webdata = WebRequest().set_apparat(self.appnr).get_ppn(entry) webdata = WebRequest().set_apparat(self.appnr).get_ppn(entry)
if self.use_any: if self.use_any:
@@ -79,7 +78,7 @@ class BookGrabber(QThread):
self.db.addBookToDatabase(bd, self.app_id, self.prof_id) self.db.addBookToDatabase(bd, self.app_id, self.prof_id)
# get latest book id # get latest book id
self.book_id = self.db.getLastBookId() self.book_id = self.db.getLastBookId()
self.logger.log_info("Added book to database") logger.info("Added book to database")
state = 0 state = 0
for result in transformer.RDS_DATA: for result in transformer.RDS_DATA:
# print(result.RDS_LOCATION) # print(result.RDS_LOCATION)
@@ -87,17 +86,17 @@ class BookGrabber(QThread):
state = 1 state = 1
break break
self.logger.log_info(f"State of {signature}: {state}") logger.info(f"State of {signature}: {state}")
# print("updating availability of " + str(self.book_id) + " to " + str(state)) # print("updating availability of " + str(self.book_id) + " to " + str(state))
try: try:
self.db.setAvailability(self.book_id, state) self.db.setAvailability(self.book_id, state)
except sqlite3.OperationalError as e: except sqlite3.OperationalError as e:
self.logger.log_error(f"Failed to update availability: {e}") logger.error(f"Failed to update availability: {e}")
# time.sleep(5) # time.sleep(5)
item += 1 item += 1
self.updateSignal.emit(item, len(self.data)) self.updateSignal.emit(item, len(self.data))
self.logger.log_info("Worker thread finished") logger.info("Worker thread finished")
# self.done.emit() # self.done.emit()
self.quit() self.quit()
@@ -111,17 +110,17 @@ class BookGrabber(QThread):
# def __init__(self, app_id, prof_id, mode, data, parent=None): # def __init__(self, app_id, prof_id, mode, data, parent=None):
# super(BookGrabber, self).__init__(parent=None) # super(BookGrabber, self).__init__(parent=None)
# self.is_Running = True # self.is_Running = True
# self.logger = MyLogger("Worker") # logger = MyLogger("Worker")
# self.logger.log_info("Starting worker thread") # logger.info("Starting worker thread")
# self.data = data # self.data = data
# self.logger.log_info(f"Working on {len(self.data)} entries") # logger.info(f"Working on {len(self.data)} entries")
# self.app_id = app_id # self.app_id = app_id
# self.prof_id = prof_id # self.prof_id = prof_id
# self.mode = mode # self.mode = mode
# self.book_id = None # self.book_id = None
# self.state = (self.app_id, self.prof_id, self.mode, self.data) # self.state = (self.app_id, self.prof_id, self.mode, self.data)
# # print(self.state) # # print(self.state)
# self.logger.log_info("state: " + str(self.state)) # logger.info("state: " + str(self.state))
# # time.sleep(2) # # time.sleep(2)
# def resetValues(self): # def resetValues(self):
@@ -140,7 +139,7 @@ class BookGrabber(QThread):
# for entry in iterdata: # for entry in iterdata:
# # print(entry) # # print(entry)
# signature = str(entry) # signature = str(entry)
# self.logger.log_info("Processing entry: " + signature) # logger.info("Processing entry: " + signature)
# webdata = WebRequest().get_ppn(entry).get_data() # webdata = WebRequest().get_ppn(entry).get_data()
# if webdata == "error": # if webdata == "error":
@@ -153,19 +152,19 @@ class BookGrabber(QThread):
# self.db.addBookToDatabase(bd, self.app_id, self.prof_id) # self.db.addBookToDatabase(bd, self.app_id, self.prof_id)
# # get latest book id # # get latest book id
# self.book_id = self.db.getLastBookId() # self.book_id = self.db.getLastBookId()
# self.logger.log_info("Added book to database") # logger.info("Added book to database")
# state = 0 # state = 0
# # print(len(rds.items)) # # print(len(rds.items))
# for rds_item in rds.items: # for rds_item in rds.items:
# sign = rds_item.superlocation # sign = rds_item.superlocation
# loc = rds_item.location # loc = rds_item.location
# # ic(sign, loc) # # logger.debug(sign, loc)
# # ic(rds_item) # # logger.debug(rds_item)
# if self.app_id in sign or self.app_id in loc: # if self.app_id in sign or self.app_id in loc:
# state = 1 # state = 1
# break # break
# self.logger.log_info(f"State of {signature}: {state}") # logger.info(f"State of {signature}: {state}")
# # print( # # print(
# "updating availability of " # "updating availability of "
# + str(self.book_id) # + str(self.book_id)
@@ -175,12 +174,12 @@ class BookGrabber(QThread):
# try: # try:
# self.db.setAvailability(self.book_id, state) # self.db.setAvailability(self.book_id, state)
# except sqlite3.OperationalError as e: # except sqlite3.OperationalError as e:
# self.logger.log_error(f"Failed to update availability: {e}") # logger.error(f"Failed to update availability: {e}")
# # time.sleep(5) # # time.sleep(5)
# item += 1 # item += 1
# self.updateSignal.emit(item, len(self.data)) # self.updateSignal.emit(item, len(self.data))
# self.logger.log_info("Worker thread finished") # logger.info("Worker thread finished")
# # self.done.emit() # # self.done.emit()
# self.stop() # self.stop()
# if not self.is_Running: # if not self.is_Running:

View File

@@ -5,7 +5,7 @@ from PyQt6.QtCore import QThread
from PyQt6.QtCore import pyqtSignal as Signal from PyQt6.QtCore import pyqtSignal as Signal
from src.backend.database import Database from src.backend.database import Database
from src.logic.log import MyLogger
# from src.transformers import RDS_AVAIL_DATA # from src.transformers import RDS_AVAIL_DATA
@@ -18,7 +18,6 @@ class AutoAdder(QThread):
def __init__(self, data=None, app_id=None, prof_id=None, parent=None): def __init__(self, data=None, app_id=None, prof_id=None, parent=None):
super().__init__(parent) super().__init__(parent)
self.logger = MyLogger("AutoAdder")
self.data = data self.data = data
self.app_id = app_id self.app_id = app_id
self.prof_id = prof_id self.prof_id = prof_id
@@ -29,7 +28,7 @@ class AutoAdder(QThread):
def run(self): def run(self):
self.db = Database() self.db = Database()
# show the dialog, start the thread to gather data and dynamically update progressbar and listwidget # show the dialog, start the thread to gather data and dynamically update progressbar and listwidget
self.logger.log_info("Starting worker thread") logger.info("Starting worker thread")
item = 0 item = 0
for entry in self.data: for entry in self.data:
try: try:
@@ -42,11 +41,11 @@ class AutoAdder(QThread):
except Exception as e: except Exception as e:
# print(e) # print(e)
self.logger.log_exception( logger.exception(
f"The query failed with message {e} for signature {entry}" f"The query failed with message {e} for signature {entry}"
) )
continue continue
if item == len(self.data): if item == len(self.data):
self.logger.log_info("Worker thread finished") logger.info("Worker thread finished")
# teminate thread # teminate thread
self.finished.emit() self.finished.emit()

View File

@@ -5,7 +5,7 @@ from PyQt6.QtCore import QThread
from PyQt6.QtCore import pyqtSignal as Signal from PyQt6.QtCore import pyqtSignal as Signal
from src.backend.database import Database from src.backend.database import Database
from src.logic.log import MyLogger
from src.logic.webrequest import BibTextTransformer, WebRequest from src.logic.webrequest import BibTextTransformer, WebRequest
# from src.transformers import RDS_AVAIL_DATA # from src.transformers import RDS_AVAIL_DATA
@@ -21,9 +21,8 @@ class AvailChecker(QThread):
if links is None: if links is None:
links = [] links = []
super().__init__(parent) super().__init__(parent)
self.logger = MyLogger("AvailChecker") logger.info("Starting worker thread")
self.logger.log_info("Starting worker thread") logger.info(
self.logger.log_info(
"Checking availability for " "Checking availability for "
+ str(links) + str(links)
+ " with appnumber " + " with appnumber "
@@ -33,7 +32,7 @@ class AvailChecker(QThread):
self.links = links self.links = links
self.appnumber = appnumber self.appnumber = appnumber
self.books = books self.books = books
self.logger.log_info( logger.info(
f"Started worker with appnumber: {self.appnumber} and links: {self.links} and {len(self.books)} books..." f"Started worker with appnumber: {self.appnumber} and links: {self.links} and {len(self.books)} books..."
) )
time.sleep(2) time.sleep(2)
@@ -43,7 +42,7 @@ class AvailChecker(QThread):
state = 0 state = 0
count = 0 count = 0
for link in self.links: for link in self.links:
self.logger.log_info("Processing entry: " + str(link)) logger.info("Processing entry: " + str(link))
data = WebRequest().set_apparat(self.appnumber).get_ppn(link).get_data() data = WebRequest().set_apparat(self.appnumber).get_ppn(link).get_data()
transformer = BibTextTransformer("RDS") transformer = BibTextTransformer("RDS")
rds = transformer.get_data(data).return_data("rds_availability") rds = transformer.get_data(data).return_data("rds_availability")
@@ -60,14 +59,14 @@ class AvailChecker(QThread):
if book["bookdata"].signature == link: if book["bookdata"].signature == link:
book_id = book["id"] book_id = book["id"]
break break
self.logger.log_info(f"State of {link}: " + str(state)) logger.info(f"State of {link}: " + str(state))
# print("Updating availability of " + str(book_id) + " to " + str(state)) # print("Updating availability of " + str(book_id) + " to " + str(state))
self.db.setAvailability(book_id, state) self.db.setAvailability(book_id, state)
count += 1 count += 1
self.updateProgress.emit(count, len(self.links)) self.updateProgress.emit(count, len(self.links))
self.updateSignal.emit(item.callnumber, state) self.updateSignal.emit(item.callnumber, state)
self.logger.log_info("Worker thread finished") logger.info("Worker thread finished")
# teminate thread # teminate thread
self.quit() self.quit()

View File

@@ -5,10 +5,9 @@ from bs4 import BeautifulSoup
from ratelimit import limits, sleep_and_retry from ratelimit import limits, sleep_and_retry
from src.logic.dataclass import BookData from src.logic.dataclass import BookData
from src.logic.log import MyLogger
from src.transformers import ARRAYData, BibTeXData, COinSData, RDSData, RISData from src.transformers import ARRAYData, BibTeXData, COinSData, RDSData, RISData
logger = MyLogger(__name__)
API_URL = "https://rds.ibs-bw.de/phfreiburg/opac/RDSIndexrecord/{}/" API_URL = "https://rds.ibs-bw.de/phfreiburg/opac/RDSIndexrecord/{}/"
PPN_URL = "https://rds.ibs-bw.de/phfreiburg/opac/RDSIndex/Search?type0%5B%5D=allfields&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND&type0%5B%5D=au&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND&type0%5B%5D=ti&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND&type0%5B%5D=ct&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND&type0%5B%5D=isn&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND&type0%5B%5D=ta&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND&type0%5B%5D=co&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND&type0%5B%5D=py&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND&type0%5B%5D=pp&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND&type0%5B%5D=pu&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND&type0%5B%5D=si&lookfor0%5B%5D={}&join=AND&bool0%5B%5D=AND&type0%5B%5D=zr&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND&type0%5B%5D=cc&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND" PPN_URL = "https://rds.ibs-bw.de/phfreiburg/opac/RDSIndex/Search?type0%5B%5D=allfields&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND&type0%5B%5D=au&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND&type0%5B%5D=ti&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND&type0%5B%5D=ct&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND&type0%5B%5D=isn&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND&type0%5B%5D=ta&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND&type0%5B%5D=co&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND&type0%5B%5D=py&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND&type0%5B%5D=pp&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND&type0%5B%5D=pu&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND&type0%5B%5D=si&lookfor0%5B%5D={}&join=AND&bool0%5B%5D=AND&type0%5B%5D=zr&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND&type0%5B%5D=cc&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND"
@@ -37,19 +36,19 @@ class WebRequest:
self.ppn = None self.ppn = None
self.data = None self.data = None
self.timeout = 5 self.timeout = 5
logger.log_info("Initialized WebRequest") logger.info("Initialized WebRequest")
@property @property
def use_any_book(self): def use_any_book(self):
"""use any book that matches the search term""" """use any book that matches the search term"""
self.use_any = True self.use_any = True
logger.log_info("Using any book") logger.info("Using any book")
return self return self
def set_apparat(self, apparat): def set_apparat(self, apparat):
self.apparat = apparat self.apparat = apparat
if int(self.apparat) < 10: if int(self.apparat) < 10:
self.apparat = f"0{self.apparat}" self.apparat = f"0{self.apparat}"
logger.log_info(f"Set apparat to {self.apparat}") logger.info(f"Set apparat to {self.apparat}")
return self return self
def get_ppn(self, signature): def get_ppn(self, signature):
@@ -81,7 +80,7 @@ class WebRequest:
response = requests.get(link, timeout=self.timeout) response = requests.get(link, timeout=self.timeout)
return response.text return response.text
except requests.exceptions.RequestException as e: except requests.exceptions.RequestException as e:
logger.log_error(f"Request failed: {e}") logger.error(f"Request failed: {e}")
return None return None
def get_data(self): def get_data(self):
links = self.get_book_links(self.ppn) links = self.get_book_links(self.ppn)
@@ -105,7 +104,7 @@ class WebRequest:
return_data.append(data) return_data.append(data)
return return_data return return_data
else: else:
logger.log_error("No <pre> tag found") logger.error("No <pre> tag found")
raise ValueError("No <pre> tag found") raise ValueError("No <pre> tag found")
if f"Semesterapparat-{self.apparat}" in item_location: if f"Semesterapparat-{self.apparat}" in item_location:
pre_tag = soup.find_all("pre") pre_tag = soup.find_all("pre")
@@ -116,7 +115,7 @@ class WebRequest:
return_data.append(data) return_data.append(data)
return return_data return return_data
else: else:
logger.log_error("No <pre> tag found") logger.error("No <pre> tag found")
return return_data return return_data
def get_data_elsa(self): def get_data_elsa(self):
@@ -137,7 +136,7 @@ class WebRequest:
return_data.append(data) return_data.append(data)
return return_data return return_data
else: else:
logger.log_error("No <pre> tag found") logger.error("No <pre> tag found")
return return_data return return_data
@@ -155,7 +154,7 @@ class BibTextTransformer:
self.field = None self.field = None
self.signature = None self.signature = None
if mode not in self.valid_modes: if mode not in self.valid_modes:
logger.log_error(f"Mode {mode} not valid") logger.error(f"Mode {mode} not valid")
raise ValueError(f"Mode {mode} not valid") raise ValueError(f"Mode {mode} not valid")
self.data = None self.data = None
# self.bookdata = BookData(**self.data) # self.bookdata = BookData(**self.data)

View File

@@ -1,3 +1,4 @@
import pandas as pd import pandas as pd
from docx import Document from docx import Document
import re import re

View File

@@ -1,3 +1,4 @@
from pyzotero import zotero from pyzotero import zotero
from dataclasses import dataclass from dataclasses import dataclass
from src.logic.webrequest import WebRequest, BibTextTransformer from src.logic.webrequest import WebRequest, BibTextTransformer

122
src/transformers/schemas.py Normal file
View File

@@ -0,0 +1,122 @@
from __future__ import annotations
from typing import Optional, Any, List
from dataclasses import dataclass
from dataclasses import field as dataclass_field
import json
@dataclass
class Item:
superlocation: str | None = dataclass_field(default_factory=str)
status: str | None = dataclass_field(default_factory=str)
availability: str | None = dataclass_field(default_factory=str)
notes: str | None = dataclass_field(default_factory=str)
limitation: str | None = dataclass_field(default_factory=str)
duedate: str | None = dataclass_field(default_factory=str)
id: str | None = dataclass_field(default_factory=str)
item_id: str | None = dataclass_field(default_factory=str)
ilslink: str | None = dataclass_field(default_factory=str)
number: int | None = dataclass_field(default_factory=int)
barcode: str | None = dataclass_field(default_factory=str)
reserve: str | None = dataclass_field(default_factory=str)
callnumber: str | None = dataclass_field(default_factory=str)
department: str | None = dataclass_field(default_factory=str)
locationhref: str | None = dataclass_field(default_factory=str)
location: str | None = dataclass_field(default_factory=str)
def from_dict(self, data: dict):
"""Import data from dict"""
data = data["items"]
for entry in data:
for key, value in entry.items():
setattr(self, key, value)
return self
@dataclass
class RDS_AVAIL_DATA:
"""Class to store RDS availability data"""
library_sigil: str = dataclass_field(default_factory=str)
items: List[Item] = dataclass_field(default_factory=list)
def import_from_dict(self, data: str):
"""Import data from dict"""
edata = json.loads(data)
# library sigil is first key
self.library_sigil = str(list(edata.keys())[0])
# get data from first key
edata = edata[self.library_sigil]
for location in edata:
item = Item(superlocation=location).from_dict(edata[location])
self.items.append(item)
return self
@dataclass
class RDS_DATA:
"""Class to store RDS data"""
RDS_SIGNATURE: str = dataclass_field(default_factory=str)
RDS_STATUS: str = dataclass_field(default_factory=str)
RDS_LOCATION: str = dataclass_field(default_factory=str)
RDS_URL: Any = dataclass_field(default_factory=str)
RDS_HINT: Any = dataclass_field(default_factory=str)
RDS_COMMENT: Any = dataclass_field(default_factory=str)
RDS_HOLDING: Any = dataclass_field(default_factory=str)
RDS_HOLDING_LEAK: Any = dataclass_field(default_factory=str)
RDS_INTERN: Any = dataclass_field(default_factory=str)
RDS_PROVENIENCE: Any = dataclass_field(default_factory=str)
RDS_LOCAL_NOTATION: str = dataclass_field(default_factory=str)
RDS_LEA: Any = dataclass_field(default_factory=str)
def import_from_dict(self, data: dict) -> RDS_DATA:
"""Import data from dict"""
for key, value in data.items():
setattr(self, key, value)
return self
@dataclass
class RDS_GENERIC_DATA:
LibrarySigil: str = dataclass_field(default_factory=str)
RDS_DATA: List[RDS_DATA] = dataclass_field(default_factory=list)
def import_from_dict(self, data: str) -> RDS_GENERIC_DATA:
"""Import data from dict"""
edata = json.loads(data)
# library sigil is first key
self.LibrarySigil = str(list(edata.keys())[0])
# get data from first key
edata = edata[self.LibrarySigil]
for entry in edata:
rds_data = RDS_DATA() # Create a new RDS_DATA instance
# Populate the RDS_DATA instance from the entry
# This assumes that the entry is a dictionary that matches the structure of the RDS_DATA class
rds_data.import_from_dict(entry)
self.RDS_DATA.append(rds_data) # Add the RDS_DATA instance to the list
return self
@dataclass
class LoksatzData:
type: Optional[str] = None
adis_idn: Optional[str] = None
t_idn: Optional[str] = None
ktrl_nr: Optional[str] = None
adis_isil: Optional[str] = None
adis_sigel: Optional[str] = None
bib_sigel: Optional[str] = None
standort: Optional[str] = None
signatur: Optional[str] = None
ausleihcode: Optional[str] = None
sig_katalog: Optional[str] = None
erwerb_datum: Optional[str] = None
medientypcode: Optional[str] = None
bestellart: Optional[str] = None
faecherstatistik: Optional[str] = None
exemplar_stat: Optional[str] = None
so_standort: Optional[str] = None

View File

@@ -8,10 +8,8 @@ from typing import Any, List, Optional
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
from src.logic.dataclass import BookData
from src.logic.log import MyLogger
logger = MyLogger("transformers.py") from src.logic.dataclass import BookData
###Pydatnic models ###Pydatnic models
@@ -135,7 +133,7 @@ class ARRAYData:
except Exception: except Exception:
# # print(f"ARRAYData.transform failed, {source}, {search}") # # print(f"ARRAYData.transform failed, {source}, {search}")
logger.log_exception(f"ARRAYData.transform failed, no string {search}") logger.exception(f"ARRAYData.transform failed, no string {search}")
return "" return ""
def _get_list_entry(source: str, search: str, entry: str) -> str: def _get_list_entry(source: str, search: str, entry: str) -> str:

View File

@@ -1,3 +1,4 @@
import pathlib import pathlib
from .Ui_semesterapparat_ui import Ui_MainWindow as Ui_Semesterapparat from .Ui_semesterapparat_ui import Ui_MainWindow as Ui_Semesterapparat

View File

@@ -1,3 +1,4 @@
from .bookdata import BookDataUI as edit_bookdata_ui from .bookdata import BookDataUI as edit_bookdata_ui
from .login import LoginDialog as login_ui from .login import LoginDialog as login_ui
from .mail import Mail_Dialog from .mail import Mail_Dialog

View File

@@ -1,3 +1,4 @@
from .dialog_sources.Ui_about import Ui_about from .dialog_sources.Ui_about import Ui_about
from PyQt6 import QtWidgets from PyQt6 import QtWidgets
from PyQt6.QtCore import PYQT_VERSION_STR from PyQt6.QtCore import PYQT_VERSION_STR

View File

@@ -1,7 +1,8 @@
from PyQt6 import QtWidgets from PyQt6 import QtWidgets
from .dialog_sources.Ui_apparat_extend import Ui_Dialog from .dialog_sources.Ui_apparat_extend import Ui_Dialog
from src import Icon from src import Icon
from src.backend import generateSemesterByDate, generateSemesterByOffset from src.backend import Semester
class ApparatExtendDialog(QtWidgets.QDialog, Ui_Dialog): class ApparatExtendDialog(QtWidgets.QDialog, Ui_Dialog):
def __init__( def __init__(
self, self,

View File

@@ -1,3 +1,4 @@
from PyQt6 import QtCore, QtWidgets from PyQt6 import QtCore, QtWidgets
from src.logic.dataclass import BookData from src.logic.dataclass import BookData

View File

@@ -1,3 +1,4 @@
from .dialog_sources.Ui_confirm_extend import Ui_extend_confirm from .dialog_sources.Ui_confirm_extend import Ui_extend_confirm
from PyQt6 import QtWidgets from PyQt6 import QtWidgets

View File

@@ -1,3 +1,4 @@
# Form implementation generated from reading ui file 'c:\Users\aky547\GitHub\SemesterapparatsManager\src\ui\dialogs\dialog_sources\about.ui' # Form implementation generated from reading ui file 'c:\Users\aky547\GitHub\SemesterapparatsManager\src\ui\dialogs\dialog_sources\about.ui'
# #
# Created by: PyQt6 UI code generator 6.6.1 # Created by: PyQt6 UI code generator 6.6.1

View File

@@ -1,3 +1,4 @@
# Form implementation generated from reading ui file 'c:\Users\aky547\GitHub\SemesterapparatsManager\src\ui\dialogs\dialog_sources\app_status.ui' # Form implementation generated from reading ui file 'c:\Users\aky547\GitHub\SemesterapparatsManager\src\ui\dialogs\dialog_sources\app_status.ui'
# #
# Created by: PyQt6 UI code generator 6.6.1 # Created by: PyQt6 UI code generator 6.6.1

View File

@@ -1,3 +1,4 @@
# Form implementation generated from reading ui file 'c:\Users\aky547\GitHub\SemesterapparatsManager\src\ui\dialogs\dialog_sources\apparat_extend.ui' # Form implementation generated from reading ui file 'c:\Users\aky547\GitHub\SemesterapparatsManager\src\ui\dialogs\dialog_sources\apparat_extend.ui'
# #
# Created by: PyQt6 UI code generator 6.7.1 # Created by: PyQt6 UI code generator 6.7.1

View File

@@ -1,3 +1,4 @@
# Form implementation generated from reading ui file 'c:\Users\aky547\GitHub\SemesterapparatsManager\src\ui\dialogs\dialog_sources\confirm_extend.ui' # Form implementation generated from reading ui file 'c:\Users\aky547\GitHub\SemesterapparatsManager\src\ui\dialogs\dialog_sources\confirm_extend.ui'
# #
# Created by: PyQt6 UI code generator 6.7.1 # Created by: PyQt6 UI code generator 6.7.1

View File

@@ -1,3 +1,4 @@
# Form implementation generated from reading ui file 'c:\Users\aky547\GitHub\SemesterapparatsManager\src\ui\dialogs\dialog_sources\edit_bookdata.ui' # Form implementation generated from reading ui file 'c:\Users\aky547\GitHub\SemesterapparatsManager\src\ui\dialogs\dialog_sources\edit_bookdata.ui'
# #
# Created by: PyQt6 UI code generator 6.6.1 # Created by: PyQt6 UI code generator 6.6.1

View File

@@ -1,3 +1,4 @@
# Form implementation generated from reading ui file 'c:\Users\aky547\GitHub\SemesterapparatsManager\src\ui\dialogs\dialog_sources\elsa_add_table_entry.ui' # Form implementation generated from reading ui file 'c:\Users\aky547\GitHub\SemesterapparatsManager\src\ui\dialogs\dialog_sources\elsa_add_table_entry.ui'
# #
# Created by: PyQt6 UI code generator 6.7.1 # Created by: PyQt6 UI code generator 6.7.1

View File

@@ -1,3 +1,4 @@
# Form implementation generated from reading ui file 'c:\Users\aky547\GitHub\SemesterapparatsManager\src\ui\dialogs\dialog_sources\elsa_generate_citation.ui' # Form implementation generated from reading ui file 'c:\Users\aky547\GitHub\SemesterapparatsManager\src\ui\dialogs\dialog_sources\elsa_generate_citation.ui'
# #
# Created by: PyQt6 UI code generator 6.6.1 # Created by: PyQt6 UI code generator 6.6.1

View File

@@ -1,3 +1,4 @@
# Form implementation generated from reading ui file 'c:\Users\aky547\GitHub\SemesterapparatsManager\src\ui\dialogs\dialog_sources\elsa_generator_confirm.ui' # Form implementation generated from reading ui file 'c:\Users\aky547\GitHub\SemesterapparatsManager\src\ui\dialogs\dialog_sources\elsa_generator_confirm.ui'
# #
# Created by: PyQt6 UI code generator 6.6.1 # Created by: PyQt6 UI code generator 6.6.1

View File

@@ -1,3 +1,4 @@
# Form implementation generated from reading ui file 'c:\Users\aky547\GitHub\SemesterapparatsManager\src\ui\dialogs\dialog_sources\login.ui' # Form implementation generated from reading ui file 'c:\Users\aky547\GitHub\SemesterapparatsManager\src\ui\dialogs\dialog_sources\login.ui'
# #
# Created by: PyQt6 UI code generator 6.6.1 # Created by: PyQt6 UI code generator 6.6.1

View File

@@ -1,3 +1,4 @@
# Form implementation generated from reading ui file 'c:\Users\aky547\GitHub\SemesterapparatsManager\src\ui\dialogs\dialog_sources\mail_preview.ui' # Form implementation generated from reading ui file 'c:\Users\aky547\GitHub\SemesterapparatsManager\src\ui\dialogs\dialog_sources\mail_preview.ui'
# #
# Created by: PyQt6 UI code generator 6.7.1 # Created by: PyQt6 UI code generator 6.7.1

View File

@@ -1,3 +1,4 @@
# Form implementation generated from reading ui file 'c:\Users\aky547\GitHub\SemesterapparatsManager\src\ui\dialogs\dialog_sources\medianadder.ui' # Form implementation generated from reading ui file 'c:\Users\aky547\GitHub\SemesterapparatsManager\src\ui\dialogs\dialog_sources\medianadder.ui'
# #
# Created by: PyQt6 UI code generator 6.7.1 # Created by: PyQt6 UI code generator 6.7.1

View File

@@ -1,3 +1,4 @@
# Form implementation generated from reading ui file 'c:\Users\aky547\GitHub\SemesterapparatsManager\src\ui\dialogs\dialog_sources\newMailTemplateDesigner.ui' # Form implementation generated from reading ui file 'c:\Users\aky547\GitHub\SemesterapparatsManager\src\ui\dialogs\dialog_sources\newMailTemplateDesigner.ui'
# #
# Created by: PyQt6 UI code generator 6.6.1 # Created by: PyQt6 UI code generator 6.6.1

View File

@@ -1,3 +1,4 @@
# Form implementation generated from reading ui file 'c:\Users\aky547\GitHub\SemesterapparatsManager\src\ui\dialogs\dialog_sources\parsed_titles.ui' # Form implementation generated from reading ui file 'c:\Users\aky547\GitHub\SemesterapparatsManager\src\ui\dialogs\dialog_sources\parsed_titles.ui'
# #
# Created by: PyQt6 UI code generator 6.6.1 # Created by: PyQt6 UI code generator 6.6.1

View File

@@ -1,3 +1,4 @@
# Form implementation generated from reading ui file 'c:\Users\aky547\GitHub\SemesterapparatsManager\src\ui\dialogs\dialog_sources\reminder.ui' # Form implementation generated from reading ui file 'c:\Users\aky547\GitHub\SemesterapparatsManager\src\ui\dialogs\dialog_sources\reminder.ui'
# #
# Created by: PyQt6 UI code generator 6.6.1 # Created by: PyQt6 UI code generator 6.6.1

View File

@@ -1,3 +1,4 @@
# Form implementation generated from reading ui file 'c:\Users\aky547\GitHub\SemesterapparatsManager\src\ui\dialogs\dialog_sources\settings.ui' # Form implementation generated from reading ui file 'c:\Users\aky547\GitHub\SemesterapparatsManager\src\ui\dialogs\dialog_sources\settings.ui'
# #
# Created by: PyQt6 UI code generator 6.7.1 # Created by: PyQt6 UI code generator 6.7.1

View File

@@ -1,10 +1,10 @@
from .dialog_sources.Ui_elsa_add_table_entry import Ui_Dialog from .dialog_sources.Ui_elsa_add_table_entry import Ui_Dialog
from src.logic.webrequest import WebRequest, BibTextTransformer from src.logic.webrequest import WebRequest, BibTextTransformer
from src import Icon from src import Icon
from PyQt6 import QtWidgets from PyQt6 import QtWidgets
from src.transformers.transformers import DictToTable from src.transformers.transformers import DictToTable
from src.logic.zotero import ZoteroController from src.logic.zotero import ZoteroController
from icecream import ic
zot = ZoteroController() zot = ZoteroController()
dtt = DictToTable() dtt = DictToTable()
@@ -117,7 +117,7 @@ class ElsaAddEntry(QtWidgets.QDialog, Ui_Dialog):
if table["type"] == "zs": if table["type"] == "zs":
book = zot.createBook(table["isbn"]) book = zot.createBook(table["isbn"])
res_key = zot.createJournalArticle(book, table) res_key = zot.createJournalArticle(book, table)
ic(book) logger.debug(book)
a_lastname = table["section_author"].split(";")[0].strip().split(",")[0] a_lastname = table["section_author"].split(";")[0].strip().split(",")[0]
a_firstname = table["section_author"].split(";")[0].strip().split(",")[1] a_firstname = table["section_author"].split(";")[0].strip().split(",")[1]
author = f"{a_lastname}, {a_firstname[0]}" author = f"{a_lastname}, {a_firstname[0]}"

View File

@@ -1,3 +1,4 @@
from .dialog_sources.Ui_elsa_generate_citation import Ui_Dialog from .dialog_sources.Ui_elsa_generate_citation import Ui_Dialog
from PyQt6 import QtWidgets from PyQt6 import QtWidgets

View File

@@ -1,3 +1,4 @@
from .dialog_sources.Ui_elsa_generator_confirm import Ui_Dialog from .dialog_sources.Ui_elsa_generator_confirm import Ui_Dialog
from PyQt6 import QtCore, QtWidgets, QtGui from PyQt6 import QtCore, QtWidgets, QtGui

View File

@@ -2,16 +2,15 @@ import hashlib
from PyQt6 import QtCore, QtGui, QtWidgets from PyQt6 import QtCore, QtGui, QtWidgets
from src import Icon from src import Icon, logger
from src.backend.admin_console import AdminCommands from src.backend.admin_console import AdminCommands
from src.backend.database import Database from src.backend.database import Database
from .dialog_sources.Ui_login import Ui_Dialog from .dialog_sources.Ui_login import Ui_Dialog
from src import MyLogger
class LoginDialog(Ui_Dialog): class LoginDialog(Ui_Dialog):
def setupUi(self, Dialog): def setupUi(self, Dialog):
self.log = MyLogger("Login")
Dialog.setObjectName("Dialog") Dialog.setObjectName("Dialog")
Dialog.resize(218, 190) Dialog.resize(218, 190)
self.dialog = Dialog self.dialog = Dialog
@@ -76,16 +75,20 @@ class LoginDialog(Ui_Dialog):
if self.db.login(username, hashed_password): if self.db.login(username, hashed_password):
self.lresult = 1 # Indicate successful login self.lresult = 1 # Indicate successful login
self.lusername = username self.lusername = username
logger.success(f"User {username} logged in.")
self.dialog.accept() self.dialog.accept()
else: else:
# Credentials are invalid, display a warning # Credentials are invalid, display a warning
if username == "" or password == "": if username == "" or password == "":
logger.warning("Invalid username or password. Login failed.")
warning_dialog = QtWidgets.QMessageBox() warning_dialog = QtWidgets.QMessageBox()
warning_dialog.setIcon(QtWidgets.QMessageBox.Icon.Warning) warning_dialog.setIcon(QtWidgets.QMessageBox.Icon.Warning)
warning_dialog.setText("Please enter a username and password.") warning_dialog.setText("Please enter a username and password.")
warning_dialog.setWindowTitle("Login Failed") warning_dialog.setWindowTitle("Login Failed")
warning_dialog.exec() warning_dialog.exec()
else: else:
logger.warning("Invalid username or password. Login failed.")
warning_dialog = QtWidgets.QMessageBox() warning_dialog = QtWidgets.QMessageBox()
warning_dialog.setIcon(QtWidgets.QMessageBox.Icon.Warning) warning_dialog.setIcon(QtWidgets.QMessageBox.Icon.Warning)
warning_dialog.setText( warning_dialog.setText(

View File

@@ -4,14 +4,12 @@ import sys
from PyQt6 import QtCore, QtGui, QtWidgets from PyQt6 import QtCore, QtGui, QtWidgets
from src import Icon, settings as config from src import Icon, settings as config
from src.logic.log import MyLogger
from .dialog_sources.Ui_mail_preview import Ui_eMailPreview as MailPreviewDialog from .dialog_sources.Ui_mail_preview import Ui_eMailPreview as MailPreviewDialog
from .mailTemplate import MailTemplateDialog from .mailTemplate import MailTemplateDialog
logger = MyLogger("Mail")
empty_signature = """<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> empty_signature = """<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
<html><head><meta name="qrichtext" content="1" /><meta charset="utf-8" /><style <html><head><meta name="qrichtext" content="1" /><meta charset="utf-8" /><style
@@ -52,7 +50,7 @@ class Mail_Dialog(QtWidgets.QDialog, MailPreviewDialog):
# prof_name, # prof_name,
) )
logger.log_info("Setting up mail dialog") logger.info("Setting up mail dialog")
self.appid = app_id self.appid = app_id
self.appname = app_name self.appname = app_name
self.subject = app_subject self.subject = app_subject
@@ -84,7 +82,7 @@ class Mail_Dialog(QtWidgets.QDialog, MailPreviewDialog):
self.btn_okay.clicked.connect(self.createAndSendMail) self.btn_okay.clicked.connect(self.createAndSendMail)
def open_new_template(self): def open_new_template(self):
logger.log_info("Opening new template dialog") logger.info("Opening new template dialog")
# TODO: implement new mail template dialog # TODO: implement new mail template dialog
dialog = MailTemplateDialog() dialog = MailTemplateDialog()
dialog.exec() dialog.exec()
@@ -101,9 +99,9 @@ Tel.: 0761/682-778 | 07617682-545"""
def load_mail_templates(self): def load_mail_templates(self):
# print("loading mail templates") # print("loading mail templates")
logger.log_info("Loading mail templates") logger.info("Loading mail templates")
mail_templates = os.listdir("mail_vorlagen") mail_templates = os.listdir("mail_vorlagen")
logger.log_info(f"Mail templates: {mail_templates}") logger.info(f"Mail templates: {mail_templates}")
for template in mail_templates: for template in mail_templates:
self.comboBox.addItem(template) self.comboBox.addItem(template)
@@ -121,10 +119,10 @@ Tel.: 0761/682-778 | 07617682-545"""
return f"Guten Tag {name}," return f"Guten Tag {name},"
def set_mail(self): def set_mail(self):
logger.log_info("Setting mail") logger.info("Setting mail")
email_template = self.comboBox.currentText() email_template = self.comboBox.currentText()
if email_template == "": if email_template == "":
logger.log_debug("No mail template selected") logger.debug("No mail template selected")
return return
with open(f"mail_vorlagen/{email_template}", "r", encoding="utf-8") as f: with open(f"mail_vorlagen/{email_template}", "r", encoding="utf-8") as f:
mail_template = f.read() mail_template = f.read()
@@ -147,10 +145,10 @@ Tel.: 0761/682-778 | 07617682-545"""
) )
self.mail_body.setHtml(mail_html) self.mail_body.setHtml(mail_html)
logger.log_info(f"Mail template set to {email_template}") logger.info(f"Mail template set to {email_template}")
def createAndSendMail(self): def createAndSendMail(self):
logger.log_info("Sending mail") logger.info("Sending mail")
import smtplib import smtplib
import ssl import ssl
from email.mime.multipart import MIMEMultipart from email.mime.multipart import MIMEMultipart
@@ -188,7 +186,7 @@ Tel.: 0761/682-778 | 07617682-545"""
# print("Mail sent") # print("Mail sent")
# end active process # end active process
server.quit() server.quit()
logger.log_info("Mail sent, closing connection to server and dialog") logger.info("Mail sent, closing connection to server and dialog")
# close the dialog # close the dialog
self.accept() self.accept()

View File

@@ -1,3 +1,4 @@
import os import os
from PyQt6 import QtCore, QtGui, QtWidgets from PyQt6 import QtCore, QtGui, QtWidgets

View File

@@ -1,3 +1,4 @@
# Form implementation generated from reading ui file 'ui\dialogs\mail_preview.ui' # Form implementation generated from reading ui file 'ui\dialogs\mail_preview.ui'
# #
# Created by: PyQt6 UI code generator 6.3.1 # Created by: PyQt6 UI code generator 6.3.1

View File

@@ -1,5 +1,5 @@
from PyQt6 import QtCore, QtGui, QtWidgets from PyQt6 import QtCore, QtGui, QtWidgets
from src import MyLogger
from .dialog_sources.Ui_medianadder import Ui_Dialog from .dialog_sources.Ui_medianadder import Ui_Dialog
from src import Icon from src import Icon
class MedienAdder(QtWidgets.QDialog, Ui_Dialog): class MedienAdder(QtWidgets.QDialog, Ui_Dialog):

View File

@@ -1,3 +1,4 @@
# Form implementation generated from reading ui file '/home/alexander/GitHub/Semesterapparate/ui/dialogs/new_subject.ui' # Form implementation generated from reading ui file '/home/alexander/GitHub/Semesterapparate/ui/dialogs/new_subject.ui'
# #
# Created by: PyQt6 UI code generator 6.5.3 # Created by: PyQt6 UI code generator 6.5.3

View File

@@ -1,12 +1,10 @@
from PyQt6 import QtCore, QtWidgets from PyQt6 import QtCore, QtWidgets
from src.logic import AutoAdder from src.logic import AutoAdder
from src.logic.log import MyLogger
from .dialog_sources.Ui_parsed_titles import Ui_Form from .dialog_sources.Ui_parsed_titles import Ui_Form
logger = MyLogger("AutoTitleAdder")
class ParsedTitles(QtWidgets.QWidget, Ui_Form): class ParsedTitles(QtWidgets.QWidget, Ui_Form):
def __init__(self, parent=None): def __init__(self, parent=None):
@@ -35,7 +33,7 @@ class ParsedTitles(QtWidgets.QWidget, Ui_Form):
self.worker = None self.worker = None
def start(self): def start(self):
logger.log_info("Starting AutoAdder") logger.info("Starting AutoAdder")
self.worker = AutoAdder( self.worker = AutoAdder(
data=self.signatures, data=self.signatures,
@@ -54,8 +52,8 @@ class ParsedTitles(QtWidgets.QWidget, Ui_Form):
self.worker.start() self.worker.start()
def on_completion(self): def on_completion(self):
logger.log_info("AutoAdder finished") logger.info("AutoAdder finished")
logger.log_info("Returning data") logger.info("Returning data")
# create a function that closes the dialog # create a function that closes the dialog
@@ -64,7 +62,7 @@ class ParsedTitles(QtWidgets.QWidget, Ui_Form):
length = self.listWidget.count() length = self.listWidget.count()
# print(f"Length of listWidget: {length}") # print(f"Length of listWidget: {length}")
if length == 0: if length == 0:
logger.log_info("AutoAdder finished") logger.info("AutoAdder finished")
self.buttonBox.accepted.emit() self.buttonBox.accepted.emit()
def update_lists(self, signal): def update_lists(self, signal):

View File

@@ -1,3 +1,4 @@
# Form implementation generated from reading ui file '/home/alexander/GitHub/Semesterapparate/ui/dialogs/parsed_titles.ui' # Form implementation generated from reading ui file '/home/alexander/GitHub/Semesterapparate/ui/dialogs/parsed_titles.ui'
# #
# Created by: PyQt6 UI code generator 6.5.3 # Created by: PyQt6 UI code generator 6.5.3

View File

@@ -1,3 +1,4 @@
# Form implementation generated from reading ui file 'ui\dialogs\confirm_extend.ui' # Form implementation generated from reading ui file 'ui\dialogs\confirm_extend.ui'
# #
# Created by: PyQt6 UI code generator 6.3.1 # Created by: PyQt6 UI code generator 6.3.1

View File

@@ -1,3 +1,4 @@
from PyQt6 import QtWidgets from PyQt6 import QtWidgets
from .dialog_sources.Ui_reminder import Ui_Erinnerung as Ui_Dialog from .dialog_sources.Ui_reminder import Ui_Erinnerung as Ui_Dialog

View File

@@ -1,3 +1,4 @@
from PyQt6 import QtCore, QtGui, QtWidgets from PyQt6 import QtCore, QtGui, QtWidgets
from src import Icon, settings from src import Icon, settings
from .dialog_sources.Ui_settings import Ui_Dialog as _settings from .dialog_sources.Ui_settings import Ui_Dialog as _settings

View File

@@ -7,16 +7,15 @@ import tempfile
import webbrowser import webbrowser
from pathlib import Path from pathlib import Path
from icecream import ic
from natsort import natsorted from natsort import natsorted
from PyQt6 import QtCore, QtGui, QtWidgets from PyQt6 import QtCore, QtGui, QtWidgets
from PyQt6.QtCore import QThread from PyQt6.QtCore import QThread
from PyQt6.QtGui import QRegularExpressionValidator from PyQt6.QtGui import QRegularExpressionValidator
from src import Icon, settings from src import Icon, settings, logger
from src.backend import ( from src.backend import (
Database, Database,
generateSemesterByDate, Semester,
recreateFile, recreateFile,
tempdelete, tempdelete,
) )
@@ -27,9 +26,10 @@ from src.logic import (
AvailChecker, AvailChecker,
BookData, BookData,
BookGrabber, BookGrabber,
MyLogger,
csv_to_list, csv_to_list,
word_docx_to_csv, word_docx_to_csv,
Prof,
Apparat,
) )
from src.ui import ( from src.ui import (
About, About,
@@ -50,7 +50,7 @@ from src.ui import (
ElsaDialog, ElsaDialog,
UserCreate, UserCreate,
EditUser, EditUser,
EditProf EditProf,
) )
from src.utils import SemesterDocument from src.utils import SemesterDocument
@@ -60,8 +60,7 @@ valid_input = (0, 0, 0, 0, 0, 0)
class Ui(Ui_Semesterapparat): class Ui(Ui_Semesterapparat):
# use the Ui_MainWindow class from mainwindow.py # use the Ui_MainWindow class from mainwindow.py
def __init__(self, MainWindow, username: str) -> None: def __init__(self, MainWindow, username: str) -> None:
self.logger = MyLogger("Ui") logger.info("Starting Semesterapparatsmanagement")
self.logger.log_info("Starting Semesterapparatsmanagement")
super().__init__() super().__init__()
self.active_user = username self.active_user = username
self.setupUi(MainWindow) self.setupUi(MainWindow)
@@ -172,7 +171,6 @@ class Ui(Ui_Semesterapparat):
self.app_group_box.setEnabled(False) self.app_group_box.setEnabled(False)
self.line_2.hide() self.line_2.hide()
self.progress_label.hide() self.progress_label.hide()
# self.message_frame.hide()
self.btn_reserve.hide() self.btn_reserve.hide()
self.label_20.hide() self.label_20.hide()
self.line_3.hide() self.line_3.hide()
@@ -247,7 +245,7 @@ class Ui(Ui_Semesterapparat):
apps.append(data) apps.append(data)
print(apps) print(apps)
doc = SemesterDocument( doc = SemesterDocument(
semester=self.generateSemester(today=True), semester=Semester(),
filename="Semesterapparate", filename="Semesterapparate",
apparats=apps, apparats=apps,
) )
@@ -372,14 +370,12 @@ class Ui(Ui_Semesterapparat):
"""Generates the current semester. """Generates the current semester.
Args: Args:
-----
today (bool, optional): If True, the current semester is generated. Defaults to False. today (bool, optional): If True, the current semester is generated. Defaults to False.
Returns: Returns:
--------
str: The current semester str: The current semester
""" """
if today: if today:
return generateSemesterByDate() return Semester()
currentYear = self.sem_year.text() currentYear = self.sem_year.text()
currentYear = int(currentYear[-2:]) currentYear = int(currentYear[-2:])
@@ -387,7 +383,7 @@ class Ui(Ui_Semesterapparat):
if semester == "SoSe": if semester == "SoSe":
return "SoSe " + str(currentYear) return "SoSe " + str(currentYear)
else: else:
return f"WiSe {currentYear}/{currentYear+1}" return f"WiSe {currentYear}/{currentYear + 1}"
def open_apparat(self, apparat): def open_apparat(self, apparat):
if self.load_app_data(apparat): if self.load_app_data(apparat):
@@ -402,41 +398,29 @@ class Ui(Ui_Semesterapparat):
def populate_frame(self, appdata: ApparatData): def populate_frame(self, appdata: ApparatData):
# populate the frame with the data from the database # populate the frame with the data from the database
self.drpdwn_app_nr.setCurrentText(str(appdata.appnr)) self.drpdwn_app_nr.setCurrentText(str(appdata.apparat.appnr))
self.prof_title.setText(appdata.prof_title) self.prof_title.setText(appdata.prof.title)
prof_name = appdata.profname.split(" ") prof_name = appdata.prof.name(True)
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.drpdwn_prof_name.setCurrentText(prof_name)
self.prof_mail.setText(appdata.prof_mail) self.prof_mail.setText(appdata.prof.mail)
self.prof_tel_nr.setText(appdata.prof_tel) self.prof_tel_nr.setText(appdata.prof.telnr)
self.app_name.setText(appdata.appname) self.app_name.setText(appdata.apparat.name)
# print("changing dropdown app_fach from '' to ", appdata.app_fach) # print("changing dropdown app_fach from '' to ", appdata.app_fach)
self.app_fach.setCurrentText(appdata.app_fach) self.app_fach.setCurrentText(appdata.apparat.subject)
# print("changed dropdown app_fach to ", self.app_fach.currentText()) # print("changed dropdown app_fach to ", self.app_fach.currentText())
if appdata.semester is not None: self.sem_year.setText(appdata.apparat.get_semester.split(" ")[1])
self.sem_sommer.setChecked( match appdata.apparat.get_semester.split(" ")[0]:
True if appdata.semester.split(" ")[0] == "SoSe" else False case "SoSe":
) self.sem_sommer.setChecked(True)
self.sem_winter.setChecked( self.sem_winter.setChecked(False)
True if appdata.semester.split(" ")[0] == "WiSe" else False case "WiSe":
) self.sem_sommer.setChecked(False)
self.sem_year.setText(appdata.semester.split(" ")[1]) self.sem_winter.setChecked(True)
else:
self.sem_sommer.setChecked( self.check_eternal_app.setChecked(appdata.apparat.eternal)
True if appdata.erstellsemester.split(" ")[0] == "SoSe" else False self.prof_id_adis.setText(str(appdata.apparat.prof_id_adis))
) self.apparat_id_adis.setText(str(appdata.apparat.apparat_id_adis))
self.sem_winter.setChecked(
True if appdata.erstellsemester.split(" ")[0] == "WiSe" else False
)
self.sem_year.setText(appdata.erstellsemester.split(" ")[1])
self.check_eternal_app.setChecked(appdata.dauerapp)
self.prof_id_adis.setText(str(appdata.prof_adis_id))
self.apparat_id_adis.setText(str(appdata.apparat_adis_id))
self.app_group_box.setEnabled(True) self.app_group_box.setEnabled(True)
self.validateLoadedData() self.validateLoadedData()
@@ -449,25 +433,26 @@ class Ui(Ui_Semesterapparat):
self.validate_semester() self.validate_semester()
def update_apparat(self): def update_apparat(self):
appdata = ApparatData() prof = Prof()
appdata.app_fach = self.app_fach.currentText() app = Apparat()
appdata.appname = self.app_name.text() app.subject = self.app_fach.currentText()
appdata.appnr = self.active_apparat app.name = self.app_name.text()
appdata.dauerapp = self.check_eternal_app.isChecked() app.appnr = self.active_apparat
appdata.prof_mail = self.prof_mail.text() app.eternal = self.check_eternal_app.isChecked()
appdata.prof_tel = self.prof_tel_nr.text() prof.mail = self.prof_mail.text()
appdata.prof_title = self.prof_title.text() prof.telnr = self.prof_tel_nr.text()
appdata.profname = self.drpdwn_prof_name.currentText() prof.title = self.prof_title.text()
appdata.semester = ( prof.fullname = self.drpdwn_prof_name.currentText().replace(",", "")
app.created_semester = (
self.sem_sommer.text() + " " + self.sem_year.text() self.sem_sommer.text() + " " + self.sem_year.text()
if self.sem_sommer.isChecked() if self.sem_sommer.isChecked()
else self.sem_winter.text() + " " + self.sem_year.text() else self.sem_winter.text() + " " + self.sem_year.text()
) )
appdata.prof_adis_id = self.prof_id_adis.text() app.prof_id_adis = self.prof_id_adis.text()
prof_id = self.db.getProfByName(appdata.prof_details.fullname).id prof_id = self.db.getProfByName(prof.fullname).id
self.add_files(prof_id) self.add_files(prof_id)
appdata.apparat_adis_id = self.apparat_id_adis.text() app.apparat_id_adis = self.apparat_id_adis.text()
appdata = ApparatData(prof=prof, apparat=app)
self.db.updateApparat(appdata) self.db.updateApparat(appdata)
self.update_app_media_list() self.update_app_media_list()
@@ -597,7 +582,7 @@ class Ui(Ui_Semesterapparat):
return return
selected_prof = self.drpdwn_prof_name.currentText() selected_prof = self.drpdwn_prof_name.currentText()
data = self.db.getProfData(selected_prof) data = self.db.getProfData(selected_prof)
# ic(data) # logger.debug(data)
prof_title = data.title prof_title = data.title
if prof_title == "None": if prof_title == "None":
prof_title = "Kein Titel" prof_title = "Kein Titel"
@@ -701,13 +686,13 @@ class Ui(Ui_Semesterapparat):
def update_progress_label(self, curr, total): def update_progress_label(self, curr, total):
text = f"Medium {curr}/{total}" text = f"Medium {curr}/{total}"
self.logger.log_info(text) logger.info(text)
self.progress_label.setText(text) self.progress_label.setText(text)
# update tableWidget_apparat_media # update tableWidget_apparat_media
self.update_app_media_list() self.update_app_media_list()
def hide_progress_label(self): def hide_progress_label(self):
self.logger.log_info("Finished adding media, hiding progress label") logger.info("Finished adding media, hiding progress label")
self.progress_label.hide() self.progress_label.hide()
self.progress_label.setText("Bitte warten...") self.progress_label.setText("Bitte warten...")
self.line_2.hide() self.line_2.hide()
@@ -734,7 +719,7 @@ class Ui(Ui_Semesterapparat):
app_id = self.active_apparat app_id = self.active_apparat
prof_id = self.db.getProfId(self.profdata) prof_id = self.db.getProfId(self.profdata)
ic(prof_id) logger.debug(prof_id)
# check if app_id is in database # check if app_id is in database
if self.db.checkApparatExistsById(app_id) is False: if self.db.checkApparatExistsById(app_id) is False:
# create apparat # create apparat
@@ -1066,7 +1051,7 @@ class Ui(Ui_Semesterapparat):
data = __open_dialog(signatures) data = __open_dialog(signatures)
# add the data to the database # add the data to the database
for book in data: for book in data:
if type(book) != BookData: if not isinstance(book, BookData):
continue continue
self.db.addBookToDatabase( self.db.addBookToDatabase(
bookdata=book, app_id=app_id, prof_id=prof_id bookdata=book, app_id=app_id, prof_id=prof_id
@@ -1083,7 +1068,7 @@ class Ui(Ui_Semesterapparat):
if data == []: if data == []:
return return
for book in data: for book in data:
if type(book) != BookData: if not isinstance(book, BookData):
continue continue
self.db.addBookToDatabase( self.db.addBookToDatabase(
bookdata=book, app_id=app_id, prof_id=prof_id bookdata=book, app_id=app_id, prof_id=prof_id
@@ -1099,10 +1084,10 @@ class Ui(Ui_Semesterapparat):
"Bitte warten, bis alle Medien hinzugefügt wurden" "Bitte warten, bis alle Medien hinzugefügt wurden"
) )
app_id = self.active_apparat app_id = self.active_apparat
ic(self.profdata) logger.debug(self.profdata)
prof_id = self.db.getProfId(self.profdata) prof_id = self.db.getProfId(self.profdata)
ic(prof_id) logger.debug(prof_id)
# check if apparat in database # check if apparat in database
# if app_id not in database, create apparat # if app_id not in database, create apparat
@@ -1110,7 +1095,7 @@ class Ui(Ui_Semesterapparat):
if not self.db.checkApparatExistsById(app_id): if not self.db.checkApparatExistsById(app_id):
# create apparat # create apparat
# print("Creating apparat") # print("Creating apparat")
if self.btn_save_apparat(False) == False: if not self.btn_save_apparat(False):
return return
created = True created = True
if self.dokument_list.rowCount() == 0: if self.dokument_list.rowCount() == 0:
@@ -1155,7 +1140,7 @@ class Ui(Ui_Semesterapparat):
] ]
signatures = [i for i in signatures if i != ""] signatures = [i for i in signatures if i != ""]
# ic(signatures) # logger.debug(signatures)
# print("starting thread") # print("starting thread")
if prof_id is None: if prof_id is None:
prof_id = self.db.getProfId(self.profdata) prof_id = self.db.getProfId(self.profdata)
@@ -1218,23 +1203,29 @@ class Ui(Ui_Semesterapparat):
if not self.validate_fields(): if not self.validate_fields():
self.confirm_popup("Bitte alle Pflichtfelder ausfüllen!", title="Fehler") self.confirm_popup("Bitte alle Pflichtfelder ausfüllen!", title="Fehler")
return False return False
appd = ApparatData() prof = Prof(
appd.appnr = self.active_apparat fullname=self.drpdwn_prof_name.currentText(),
appd.prof_title = self.prof_title.text() telnr=self.prof_tel_nr.text(),
appd.profname = self.drpdwn_prof_name.currentText() mail=self.prof_mail.text(),
appd.appname = self.app_name.text() )
appd.semester = self.generateSemester() prof.title = self.prof_title.text()
appd.dauerapp = 1 if self.check_eternal_app.isChecked() else 0 apparat = Apparat(
appd.prof_tel = self.prof_tel_nr.text() appnr=self.active_apparat,
appd.prof_mail = self.prof_mail.text() name=self.app_name.text(),
appd.app_fach = self.app_fach.currentText() created_semester=self.generateSemester(),
appd.erstellsemester = self.generateSemester() eternal=1 if self.check_eternal_app.isChecked() else 0,
appd.deleted = 0 subject=self.app_fach.currentText(),
appd.prof_adis_id = self.prof_id_adis.text() deleted=0,
appd.apparat_adis_id = self.apparat_id_adis.text() 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) error = self.db.createApparat(appd)
if error:
self.confirm_popup(error.__str__(), title="Fehler")
return False
if self.dokument_list.rowCount() > 0: if self.dokument_list.rowCount() > 0:
self.add_files() self.add_files()
if error is not None: if error is not None:
@@ -1251,15 +1242,16 @@ class Ui(Ui_Semesterapparat):
if self.check_send_mail.isChecked(): if self.check_send_mail.isChecked():
self.contact_prof( self.contact_prof(
apparat=appd.appnr, apparat=appd.apparat.appnr,
mail="Information zum Semesterapparat", mail="Information zum Semesterapparat",
location="", location="",
pid=appd.profname, pid=appd.prof.fullname,
) )
if clear_fields: if clear_fields:
# print("clearing fields") # print("clearing fields")
self.__clear_fields() self.__clear_fields()
return True return True
def send_mail_preview(self): def send_mail_preview(self):
pass pass
@@ -1270,10 +1262,10 @@ class Ui(Ui_Semesterapparat):
@property @property
def profdata(self): def profdata(self):
return { return {
"title":self.prof_title.text(), "title": self.prof_title.text(),
"profname": self.drpdwn_prof_name.currentText(), "profname": self.drpdwn_prof_name.currentText(),
"prof_mail":self.prof_mail.text(), "prof_mail": self.prof_mail.text(),
"prof_tel":self.prof_tel_nr.text() "prof_tel": self.prof_tel_nr.text(),
} }
def add_files(self, prof_id=None): def add_files(self, prof_id=None):
@@ -1307,9 +1299,10 @@ class Ui(Ui_Semesterapparat):
for apparat in self.apparats: for apparat in self.apparats:
self.insert_apparat_into_table(apparat) self.insert_apparat_into_table(apparat)
logger.info("Inserted {} apparats into table".format(len(self.apparats)))
def insert_apparat_into_table(self, apparat): def insert_apparat_into_table(self, apparat):
# ic(apparat) # logger.debug(apparat)
def __dauer_check(apparat): def __dauer_check(apparat):
return "Ja" if apparat[7] == 1 else "Nein" return "Ja" if apparat[7] == 1 else "Nein"
@@ -1339,7 +1332,6 @@ class Ui(Ui_Semesterapparat):
self.tableWidget_apparate.setItem( self.tableWidget_apparate.setItem(
0, 5, QtWidgets.QTableWidgetItem(str(apparat[13])) 0, 5, QtWidgets.QTableWidgetItem(str(apparat[13]))
) )
self.logger.log_info(f"Inserted apparat {apparat[4]}")
def open_context_menu(self, position): def open_context_menu(self, position):
menu = QtWidgets.QMenu() menu = QtWidgets.QMenu()
@@ -1357,7 +1349,7 @@ class Ui(Ui_Semesterapparat):
return return
pid = self.__get_table_data_field(self.tableWidget_apparate, pos[0], 2) pid = self.__get_table_data_field(self.tableWidget_apparate, pos[0], 2)
app_id = self.__get_table_data_field(self.tableWidget_apparate, pos[0], 0) app_id = self.__get_table_data_field(self.tableWidget_apparate, pos[0], 0)
ic(pos, pid) logger.debug(pos, pid)
extend_action.triggered.connect(self.extend_apparat) extend_action.triggered.connect(self.extend_apparat)
delete_action.triggered.connect(lambda: self.delete_apparat(pos)) delete_action.triggered.connect(lambda: self.delete_apparat(pos))
# pass pos to contact_prof # pass pos to contact_prof
@@ -1368,7 +1360,7 @@ class Ui(Ui_Semesterapparat):
menu.exec(self.tableWidget_apparate.mapToGlobal(position)) menu.exec(self.tableWidget_apparate.mapToGlobal(position))
def reminder(self): def reminder(self):
self.logger.log_info("Opening reminder dialog") logger.info("Opening reminder dialog")
reminder = reminder_ui() reminder = reminder_ui()
reminder.exec() reminder.exec()
tableposition = self.tableWidget_apparate.currentRow() tableposition = self.tableWidget_apparate.currentRow()
@@ -1385,17 +1377,17 @@ class Ui(Ui_Semesterapparat):
self.calendarWidget.updateCells() self.calendarWidget.updateCells()
# self.db.update_bookdata(data, book_id) # self.db.update_bookdata(data, book_id)
# self.db.update_bookdata(data) # self.db.update_bookdata(data)
self.logger.log_info("Commited message to database") logger.info("Commited message to database")
# self.update_app_media_list() # self.update_app_media_list()
def get_reminders(self): def get_reminders(self):
messages = self.db.getAllMessages() messages = self.db.getAllMessages()
self.logger.log_info(f"Got {len(messages)} messages from database") logger.info(f"Got {len(messages)} messages from database")
self.calendarWidget.setMessages(messages) self.calendarWidget.setMessages(messages)
self.calendarWidget.updateCells() self.calendarWidget.updateCells()
def open_reminder(self): def open_reminder(self):
if settings.mail.use_user_name == False: if not settings.mail.use_user_name:
print("False") print("False")
selected_date = self.calendarWidget.selectedDate().toString("yyyy-MM-dd") selected_date = self.calendarWidget.selectedDate().toString("yyyy-MM-dd")
# # print(selected_date) # # print(selected_date)
@@ -1542,6 +1534,7 @@ class Ui(Ui_Semesterapparat):
prof_id=self.db.getProfId(self.profdata), prof_id=self.db.getProfId(self.profdata),
) )
print(medium.adis_idn, medium.signature) print(medium.adis_idn, medium.signature)
def edit_medium(self): def edit_medium(self):
book = self.tableWidget_apparat_media.item( book = self.tableWidget_apparat_media.item(
self.tableWidget_apparat_media.currentRow(), 1 self.tableWidget_apparat_media.currentRow(), 1
@@ -1592,7 +1585,7 @@ class Ui(Ui_Semesterapparat):
prof_id=prof_id, prof_id=prof_id,
signature=signature, signature=signature,
) )
message = f'Soll das Medium "{self.tableWidget_apparat_media.item(self.tableWidget_apparat_media.currentRow(),0).text()}" wirklich gelöscht werden?' 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?") state = self.confirm_popup(message, title="Löschen?")
# print(state) # print(state)
if state == 1: if state == 1:
@@ -1642,12 +1635,12 @@ class Ui(Ui_Semesterapparat):
return return
def __get_table_data_field(self, table, row, column): def __get_table_data_field(self, table, row, column):
ic(row, column) logger.debug(row, column)
row = int(row) row = int(row)
return table.item(row, column).text() return table.item(row, column).text()
def __contact_dialog(self, apparat, location: tuple | str, mail=None, pid=""): def __contact_dialog(self, apparat, location: tuple | str, mail=None, pid=""):
ic(location, pid, apparat) logger.debug(location, pid, apparat)
active_apparat_id = ( active_apparat_id = (
self.drpdwn_app_nr.currentText() if apparat is None else apparat self.drpdwn_app_nr.currentText() if apparat is None else apparat
@@ -1674,7 +1667,7 @@ class Ui(Ui_Semesterapparat):
app_subject = self.app_fach.currentText() app_subject = self.app_fach.currentText()
else: else:
app_subject = self.db.getApparatData(active_apparat_id, app_name) app_subject = self.db.getApparatData(active_apparat_id, app_name)
app_subject = app_subject.app_fach app_subject = app_subject.apparat.subject
# profname = f"{profname.split(" ")[1]} {profname.split(" ")[0]}" # profname = f"{profname.split(" ")[1]} {profname.split(" ")[0]}"
# print(pid) # print(pid)
if prof_id: if prof_id:
@@ -1696,8 +1689,8 @@ class Ui(Ui_Semesterapparat):
self.mail_thread.show() self.mail_thread.show()
def contact_prof(self, apparat="", location="", mail="", pid=""): def contact_prof(self, apparat="", location="", mail="", pid=""):
ic(apparat) logger.debug(apparat)
ic(location) logger.debug(location)
if self.active_apparat == "": if self.active_apparat == "":
if apparat is False: if apparat is False:
self.confirm_popup( self.confirm_popup(
@@ -1733,8 +1726,8 @@ class Ui(Ui_Semesterapparat):
def launch_gui(): def launch_gui():
# print("trying to login") # print("trying to login")
# print("checking if database available") # print("checking if database available")
log = MyLogger("login")
log.log_info("Starting login dialog") logger.info("Starting login dialog")
app = QtWidgets.QApplication(sys.argv) app = QtWidgets.QApplication(sys.argv)
login_dialog = QtWidgets.QDialog() login_dialog = QtWidgets.QDialog()
ui = login_ui() ui = login_ui()

View File

@@ -1,9 +1,9 @@
from src import logger
from PyQt6 import QtWidgets, QtCore from PyQt6 import QtWidgets, QtCore
from PyQt6.QtCore import QDate from PyQt6.QtCore import QDate
from PyQt6.QtGui import QColor, QPen from PyQt6.QtGui import QColor, QPen
from src.backend import Database from src.backend import Database
import darkdetect import darkdetect
from icecream import ic
color = "#ddfb00" if darkdetect.isDark() else "#2204ff" color = "#ddfb00" if darkdetect.isDark() else "#2204ff"
pen = QPen(QColor(color)) pen = QPen(QColor(color))
@@ -22,7 +22,7 @@ class MessageCalendar(QtWidgets.QCalendarWidget):
def getMessages(self): def getMessages(self):
# Get the messages from the database # Get the messages from the database
messages = Database().getAllMessages() messages = Database().getAllMessages()
ic(messages) logger.debug(messages)
self.setMessages(messages) self.setMessages(messages)
def deleteMessage(self, id): def deleteMessage(self, id):

View File

@@ -1,3 +1,4 @@
__all__ = ["filepicker"] __all__ = ["filepicker"]
from .collapse import StatusWidget from .collapse import StatusWidget
from .filepicker import FilePicker from .filepicker import FilePicker

View File

@@ -1,3 +1,4 @@
from PyQt6 import QtWidgets, QtCore, QtGui from PyQt6 import QtWidgets, QtCore, QtGui
from PyQt6.QtCore import pyqtSignal from PyQt6.QtCore import pyqtSignal
from .widget_sources.Ui_admin_create_user import Ui_Dialog from .widget_sources.Ui_admin_create_user import Ui_Dialog

View File

@@ -1,9 +1,10 @@
from .widget_sources.Ui_admin_edit_prof import Ui_Dialog# from .widget_sources.Ui_admin_edit_prof import Ui_Dialog#
from PyQt6 import QtWidgets, QtCore from PyQt6 import QtWidgets, QtCore
from PyQt6.QtCore import pyqtSignal from PyQt6.QtCore import pyqtSignal
from icecream import ic from src import logger
from src.backend import Database
from src.logic import Prof from src.logic import Prof
from src.backend import Database
class EditProf(QtWidgets.QDialog, Ui_Dialog): class EditProf(QtWidgets.QDialog, Ui_Dialog):
def __init__(self): def __init__(self):
super(EditProf, self).__init__() super(EditProf, self).__init__()
@@ -59,7 +60,7 @@ class EditProf(QtWidgets.QDialog, Ui_Dialog):
else: else:
self.faculty_member_old_telnr.setText(data.telnr) self.faculty_member_old_telnr.setText(data.telnr)
self.faculty_member_oldmail.setText(data.mail) self.faculty_member_oldmail.setText(data.mail)
ic(data) logger.debug(data)
( (
self.edit_faculty_member_title.setText(data.title) self.edit_faculty_member_title.setText(data.title)
if data.title is not None if data.title is not None
@@ -83,7 +84,7 @@ class EditProf(QtWidgets.QDialog, Ui_Dialog):
olddata = self.db.getProfByName( olddata = self.db.getProfByName(
self.edit_faculty_member_select_member.currentText() self.edit_faculty_member_select_member.currentText()
) )
ic(olddata) logger.debug(olddata)
data = olddata data = olddata
oldlname = data.lastname oldlname = data.lastname
oldfname = data.firstname oldfname = data.firstname

View File

@@ -1,7 +1,7 @@
from .widget_sources.Ui_admin_edit_user import Ui_Dialog from .widget_sources.Ui_admin_edit_user import Ui_Dialog
from PyQt6 import QtWidgets, QtCore from PyQt6 import QtWidgets, QtCore
from PyQt6.QtCore import pyqtSignal from PyQt6.QtCore import pyqtSignal
from icecream import ic
from src.backend import Database from src.backend import Database
from src.backend import AdminCommands from src.backend import AdminCommands
admin = AdminCommands() admin = AdminCommands()

View File

@@ -1,3 +1,4 @@
from .widget_sources.Ui_calendar_entry import Ui_Dialog from .widget_sources.Ui_calendar_entry import Ui_Dialog
from PyQt6 import QtWidgets, QtCore from PyQt6 import QtWidgets, QtCore
from PyQt6.QtCore import pyqtSignal, QDate from PyQt6.QtCore import pyqtSignal, QDate

View File

@@ -1,3 +1,4 @@
# import pysignal pyslot # import pysignal pyslot
from PyQt6.QtCore import pyqtSignal as Signal from PyQt6.QtCore import pyqtSignal as Signal
from PyQt6.QtWidgets import ( from PyQt6.QtWidgets import (

View File

@@ -1,14 +1,12 @@
import os import os
from natsort import natsorted from natsort import natsorted
from icecream import ic
from .widget_sources.Ui_elsa_maindialog import Ui_Dialog from .widget_sources.Ui_elsa_maindialog import Ui_Dialog
from PyQt6 import QtCore, QtWidgets, QtGui from PyQt6 import QtCore, QtWidgets, QtGui
from PyQt6.QtGui import QRegularExpressionValidator from PyQt6.QtGui import QRegularExpressionValidator
from PyQt6.QtCore import QDate from PyQt6.QtCore import QDate
from src import Icon from src import Icon, logger
from src.backend import recreateElsaFile, generateSemesterByDate, Database from src.backend import recreateElsaFile, Semester, Database
from src.logic import elsa_word_to_csv, MyLogger, Prof from src.logic import elsa_word_to_csv, Prof
from src.logic.log import log
from src.ui import popus_confirm from src.ui import popus_confirm
from src.ui.dialogs import ElsaAddEntry from src.ui.dialogs import ElsaAddEntry
from src.ui.widgets import FilePicker from src.ui.widgets import FilePicker
@@ -39,6 +37,23 @@ class ElsaDialog(QtWidgets.QDialog, Ui_Dialog):
self.quote_entry.clicked.connect(self.elsa_table_entry) self.quote_entry.clicked.connect(self.elsa_table_entry)
self.quote_entry.setEnabled(False) self.quote_entry.setEnabled(False)
self.newProf.hide() self.newProf.hide()
self.splitter = QtWidgets.QSplitter(QtCore.Qt.Orientation.Horizontal)
self.splitter.addWidget(self.media_table)
self.splitter.addWidget(self.statistics)
self.results.layout().removeWidget(self.media_table)
self.results.layout().removeWidget(self.statistics)
self.results.layout().addWidget(self.splitter)
self.elsa_statistics_table.setColumnCount(2)
# set header to occupy the whole width and auto scale based on table width
self.elsa_statistics_table.horizontalHeader().setStretchLastSection(True)
self.elsa_statistics_table.horizontalHeader().setSectionResizeMode(
QtWidgets.QHeaderView.ResizeMode.Stretch
)
# if table size gets smaller, set horitzontal headers text to be left aligned
self.elsa_statistics_table.horizontalHeader().setDefaultAlignment(
QtCore.Qt.AlignmentFlag.AlignLeft
)
# self.table_elsa_list.
Icon("person", self.prof_icon) Icon("person", self.prof_icon)
# validators # validators
# prof mail # prof mail
@@ -55,12 +70,12 @@ class ElsaDialog(QtWidgets.QDialog, Ui_Dialog):
) )
##Variables ##Variables
self.logger = MyLogger("ElsaDialog")
self.db = Database() self.db = Database()
self.graph_data = {"x": [generateSemesterByDate()], "y": [0]} self.graph_data = {"x": [Semester().value], "y": [0]}
self.createProf = False self.createProf = False
self.profs = self.getProfs()
self.elsa_prof.addItems(self.getProfs()) self.elsa_prof.addItems([prof[0] for prof in self.profs])
self.elsa_prof.addItem("") self.elsa_prof.addItem("")
self.elsa_prof.setCurrentText("") self.elsa_prof.setCurrentText("")
# implement a check for the prof name. if name is not in list and has schema of lastname, firstname, show newProf frame # implement a check for the prof name. if name is not in list and has schema of lastname, firstname, show newProf frame
@@ -70,7 +85,7 @@ class ElsaDialog(QtWidgets.QDialog, Ui_Dialog):
self.newProf_title.textChanged.connect(self.checkProfData) self.newProf_title.textChanged.connect(self.checkProfData)
self.loadFrame() self.loadFrame()
log.info("Elsa Dialog loaded") logger.info("Elsa Dialog loaded")
# self.show() # self.show()
def checkProfData(self): def checkProfData(self):
@@ -84,14 +99,20 @@ class ElsaDialog(QtWidgets.QDialog, Ui_Dialog):
): ):
self.elsa_save.setEnabled(True) self.elsa_save.setEnabled(True)
self.elsa_save.setToolTip("") self.elsa_save.setToolTip("")
self.newProf_mail.setToolTip("")
self.newProf_telnr.setToolTip("")
else: else:
self.elsa_save.setEnabled(False) self.elsa_save.setEnabled(False)
self.elsa_save.setToolTip("Bitte erst Daten eingeben") self.elsa_save.setToolTip("Bitte erst Daten eingeben")
self.newProf_mail.setToolTip("Bitte geben Sie eine gültige E-Mail ein")
self.newProf_telnr.setToolTip(
"Bitte geben Sie eine gültige Telefonnummer ein"
)
def checkProf(self): def checkProf(self):
if ( if (
", " in self.elsa_prof.currentText() ", " in self.elsa_prof.currentText()
and self.elsa_prof.currentText() not in self.getProfs() and self.elsa_prof.currentText() not in [prof[0] for prof in self.profs]
): ):
self.newProf.show() self.newProf.show()
self.elsa_save.setEnabled(False) self.elsa_save.setEnabled(False)
@@ -105,7 +126,9 @@ class ElsaDialog(QtWidgets.QDialog, Ui_Dialog):
def getProfs(self): def getProfs(self):
profs = self.db.getProfs() profs = self.db.getProfs()
profs = [f"{prof.lastname}, {prof.firstname}" for prof in profs] profs = [
("{}, {}".format(prof.lastname, prof.firstname), prof.id) for prof in profs
]
profs = list(set(profs)) profs = list(set(profs))
profs.sort() profs.sort()
@@ -161,7 +184,7 @@ class ElsaDialog(QtWidgets.QDialog, Ui_Dialog):
self.elsa_date.setText(QDate.currentDate().toString("dd.MM.yyyy")) self.elsa_date.setText(QDate.currentDate().toString("dd.MM.yyyy"))
def addSemester(self): def addSemester(self):
self.elsa_semester.setText(generateSemesterByDate()) self.elsa_semester.setText(Semester().value)
def update_elsa(self): def update_elsa(self):
prof = self.elsa_prof.currentText() prof = self.elsa_prof.currentText()
@@ -205,11 +228,14 @@ class ElsaDialog(QtWidgets.QDialog, Ui_Dialog):
fullname=f"{prof.split(", ")[0]} {prof.split(", ")[1]}", fullname=f"{prof.split(", ")[0]} {prof.split(", ")[1]}",
) )
prof_id = self.db.getProfId(profdata) prof_id = self.db.getProfId(profdata)
ic(profdata, prof_id) logger.debug(profdata, prof_id)
if prof_id is None: if prof_id is None:
self.db.createProf(profdata) self.db.createProf(profdata)
prof_id = self.db.getProfId(prof) prof_id = self.db.getProfId(prof)
self.profs.append(
"f{}, {}".format(profdata.lastname, profdata.firstname), prof_id
)
elsa_id = self.db.createElsaApparat( elsa_id = self.db.createElsaApparat(
date, date,
prof_id, prof_id,
@@ -228,12 +254,12 @@ class ElsaDialog(QtWidgets.QDialog, Ui_Dialog):
files, files,
elsa_id, elsa_id,
) )
log.info("Stored {} files in the database", len(files)) logger.info("Stored {} files in the database", len(files))
self.cancel_elsa_creation() self.cancel_elsa_creation()
self.refresh_elsa_table() self.refresh_elsa_table()
self.elsa_prof.setCurrentText("") self.elsa_prof.setCurrentText("")
self.quote_entry.setEnabled(False) self.quote_entry.setEnabled(False)
log.info("Saved apparat to database, id {}", elsa_id) logger.info("Saved apparat to database, id {}", elsa_id)
def refresh_elsa_table(self): def refresh_elsa_table(self):
self.elsa_table.setRowCount(0) self.elsa_table.setRowCount(0)
@@ -253,13 +279,13 @@ class ElsaDialog(QtWidgets.QDialog, Ui_Dialog):
def open_elsa(self): def open_elsa(self):
prof = self.elsa_table.item(self.elsa_table.currentRow(), 0).text() prof = self.elsa_table.item(self.elsa_table.currentRow(), 0).text()
print(prof) logger.info("prof", prof)
date = self.elsa_table.item(self.elsa_table.currentRow(), 1).text() date = self.elsa_table.item(self.elsa_table.currentRow(), 1).text()
semester = self.elsa_table.item(self.elsa_table.currentRow(), 2).text() semester = self.elsa_table.item(self.elsa_table.currentRow(), 2).text()
self.elsa_update.setEnabled(True) self.elsa_update.setEnabled(True)
self.elsa_save.setEnabled(False) self.elsa_save.setEnabled(False)
if self.elsa_prof.currentText() == prof and date == self.elsa_date.text(): if self.elsa_prof.currentText() == prof and date == self.elsa_date.text():
self.logger.log_info("Same prof, stopping") logger.debug("Same prof, stopping")
return return
self.create_frame_elsa.setEnabled(True) self.create_frame_elsa.setEnabled(True)
self.dokument_list_elsa.setRowCount(0) self.dokument_list_elsa.setRowCount(0)
@@ -269,24 +295,21 @@ class ElsaDialog(QtWidgets.QDialog, Ui_Dialog):
elsa_apparats = self.db.getElsaApparats() elsa_apparats = self.db.getElsaApparats()
elsa_id = None elsa_id = None
for apparat in elsa_apparats: for apparat in elsa_apparats:
print(apparat)
if ( if (
apparat[1] == date apparat[1] == date
and apparat[2] == semester and apparat[2] == semester
and apparat[3] == self.db.getProfId({"profname": prof}) and apparat[3] == self.db.getProfId({"profname": prof})
): ):
elsa_id = apparat[0] elsa_id = apparat[0]
# print(elsa_id)
break break
self.elsa_date.setText(date) self.elsa_date.setText(date)
self.elsa_semester.setText(semester) self.elsa_semester.setText(semester)
self.elsa_prof.setCurrentText(prof) self.elsa_prof.setCurrentText(prof)
ic(elsa_id) logger.info("Elsa ID is {}", elsa_id)
if elsa_id is None: if elsa_id is None:
return return
documents = self.db.getElsaFiles(elsa_id) documents = self.db.getElsaFiles(elsa_id)
for document in documents: for document in documents:
# print(document)
self.dokument_list_elsa.insertRow(0) self.dokument_list_elsa.insertRow(0)
self.dokument_list_elsa.setItem( self.dokument_list_elsa.setItem(
0, 0, QtWidgets.QTableWidgetItem(document[0]) 0, 0, QtWidgets.QTableWidgetItem(document[0])
@@ -340,13 +363,11 @@ class ElsaDialog(QtWidgets.QDialog, Ui_Dialog):
self.table_elsa_list.setItem(0, 11, QtWidgets.QTableWidgetItem(scan["type"])) self.table_elsa_list.setItem(0, 11, QtWidgets.QTableWidgetItem(scan["type"]))
def addDokumentElsa(self): def addDokumentElsa(self):
# print("Add document")
picker = FilePicker() picker = FilePicker()
files = picker.pick_files() files = picker.pick_files()
datalist = [] datalist = []
for file in files: for file in files:
data = {} data = {}
# print(file)
filename = file.split("/")[-1] filename = file.split("/")[-1]
filetype = filename.split(".")[-1] filetype = filename.split(".")[-1]
self.dokument_list_elsa.insertRow(0) self.dokument_list_elsa.insertRow(0)
@@ -360,27 +381,6 @@ class ElsaDialog(QtWidgets.QDialog, Ui_Dialog):
data["path"] = file data["path"] = file
data["type"] = filetype data["type"] = filetype
datalist.append(data) datalist.append(data)
# elsa_id = self.db.getElsaId(
# self.elsa_prof.currentText(),
# self.elsa_semester.text(),
# self.elsa_date.text(),
# )
# # print(elsa_id)
# if elsa_id is None:
# # create elsa
# self.db.createElsaApparat(
# self.elsa_date.text(),
# self.elsa_prof.currentText(),
# self.elsa_semester.text(),
# )
# elsa_id = self.db.getElsaId(
# self.elsa_prof.currentText(),
# self.elsa_semester.text(),
# self.elsa_date.text(),
# )
# self.db.insertElsaFile(datalist, elsa_id)
# self.elsa_save.setEnabled(False)
# self.refresh_elsa_table()
def parseDokumentElsa(self): def parseDokumentElsa(self):
if self.dokument_list_elsa.rowCount() == 0: if self.dokument_list_elsa.rowCount() == 0:
@@ -389,7 +389,6 @@ class ElsaDialog(QtWidgets.QDialog, Ui_Dialog):
# get the file path of the selected file based on it's row # get the file path of the selected file based on it's row
row = self.dokument_list_elsa.currentRow() row = self.dokument_list_elsa.currentRow()
file = self.dokument_list_elsa.item(row, 3).text() file = self.dokument_list_elsa.item(row, 3).text()
# print(file)
if file == "Database": if file == "Database":
filename = self.dokument_list_elsa.item(row, 0).text() filename = self.dokument_list_elsa.item(row, 0).text()
filetype = self.dokument_list_elsa.item(row, 1).text() filetype = self.dokument_list_elsa.item(row, 1).text()
@@ -397,14 +396,13 @@ class ElsaDialog(QtWidgets.QDialog, Ui_Dialog):
file = recreateElsaFile( file = recreateElsaFile(
filename=filename, filetype=filetype, open=False filename=filename, filetype=filetype, open=False
) )
# print(file)
data, _ = elsa_word_to_csv(file) data, _ = elsa_word_to_csv(file)
elsa_id = self.db.getElsaId( elsa_id = self.db.getElsaId(
self.db.getProfId(Prof(fullname=self.elsa_prof.currentText())), self.db.getProfId(Prof(fullname=self.elsa_prof.currentText())),
self.elsa_semester.text(), self.elsa_semester.text(),
self.elsa_date.text(), self.elsa_date.text(),
) )
ic( logger.debug(
elsa_id, elsa_id,
self.elsa_prof.currentText(), self.elsa_prof.currentText(),
self.elsa_semester.text(), self.elsa_semester.text(),
@@ -441,14 +439,13 @@ class ElsaDialog(QtWidgets.QDialog, Ui_Dialog):
try: try:
self.elsa_statistics.removeTab(1) self.elsa_statistics.removeTab(1)
except: except:
self.logger.log_debug("No tab to remove") logger.debug("No tab to remove")
self.elsa_table.setRowCount(0) self.elsa_table.setRowCount(0)
elsa_apparats = self.db.getElsaApparats() elsa_apparats = self.db.getElsaApparats()
elsa_apparats = natsorted(elsa_apparats, key=lambda x: x[2], reverse=True) elsa_apparats = natsorted(elsa_apparats, key=lambda x: x[2], reverse=True)
# x = semester, y = number of apparats # x = semester, y = number of apparats
for apparat in elsa_apparats: for apparat in elsa_apparats:
# print(apparat)
data = self.insert_elsa_into_table(apparat) data = self.insert_elsa_into_table(apparat)
semester = data[0] semester = data[0]
number = data[1] number = data[1]
@@ -466,7 +463,7 @@ class ElsaDialog(QtWidgets.QDialog, Ui_Dialog):
generateMissing, generateMissing,
"Anzahl der Apparate", "Anzahl der Apparate",
) )
ic(self.graph_data) logger.debug(self.graph_data)
self.elsa_statistics_table.setRowCount(0) self.elsa_statistics_table.setRowCount(0)
for i in range(len(self.graph_data["x"])): for i in range(len(self.graph_data["x"])):
self.elsa_statistics_table.insertRow(0) self.elsa_statistics_table.insertRow(0)
@@ -479,7 +476,7 @@ class ElsaDialog(QtWidgets.QDialog, Ui_Dialog):
self.elsa_statistics.addTab(graph, "Graph") self.elsa_statistics.addTab(graph, "Graph")
def launch(): def launch():
log.debug("Launching Elsa Dialog") logger.debug("Launching Elsa Dialog")
app = QtWidgets.QApplication([]) app = QtWidgets.QApplication([])
window = ElsaDialog() window = ElsaDialog()
window.show() window.show()

View File

@@ -1,3 +1,4 @@
import random import random
from typing import Union from typing import Union

View File

@@ -1,31 +1,28 @@
from .widget_sources.Ui_search_statistic_page import Ui_Dialog from .widget_sources.Ui_search_statistic_page import Ui_Dialog
from PyQt6 import QtWidgets, QtGui, QtCore from PyQt6 import QtWidgets, QtGui, QtCore
from PyQt6.QtCore import pyqtSignal from PyQt6.QtCore import pyqtSignal
from src.backend import Database, generateSemesterByDate from src.backend import Database, Semester
from src.logic import custom_sort, Prof from src import logger
from src import MyLogger from src.logic import custom_sort, Prof, sort_semesters_list
from src.ui import ApparatExtendDialog from src.ui import ApparatExtendDialog
from src.ui.dialogs import Mail_Dialog from src.ui.dialogs import Mail_Dialog
from src.ui.widgets import DataGraph, StatusWidget from src.ui.widgets import DataGraph, StatusWidget
from natsort import natsorted from natsort import natsorted
from icecream import ic
class MyComboBox(QtWidgets.QComboBox): class MyComboBox(QtWidgets.QComboBox):
def __init__(self, parent=None): def __init__(self, parent=None):
super().__init__(parent) super().__init__(parent)
class SearchStatisticPage(QtWidgets.QDialog, Ui_Dialog): class SearchStatisticPage(QtWidgets.QDialog, Ui_Dialog):
apparat_open = pyqtSignal(str) apparat_open = pyqtSignal(str)
reloadSignal = pyqtSignal() reloadSignal = pyqtSignal()
refreshSignal = pyqtSignal() refreshSignal = pyqtSignal()
def __init__(self): def __init__(self):
self.logger = MyLogger("SearchStatisticPage") logger.info("SearchStatisticPage started")
self.logger.log_info("SearchStatisticPage started")
super().__init__() super().__init__()
self.setupUi(self) self.setupUi(self)
self.book_search_result.horizontalHeader().setSectionResizeMode( self.book_search_result.horizontalHeader().setSectionResizeMode(
@@ -51,7 +48,14 @@ class SearchStatisticPage(QtWidgets.QDialog, Ui_Dialog):
self.tableWidget.resizeRowsToContents() self.tableWidget.resizeRowsToContents()
self.db = Database() self.db = Database()
self.box_appnrs.addItems(str(i) for i in self.db.getUnavailableApparatNumbers()) self.box_appnrs.addItems(str(i) for i in self.db.getUnavailableApparatNumbers())
self.splitter = QtWidgets.QSplitter(QtCore.Qt.Orientation.Horizontal)
# insert splitter in apparatResult to allow resizing of the columns
self.splitter.addWidget(self.app_results)
self.splitter.addWidget(self.stats)
self.apparatResult.layout().removeWidget(self.stats)
self.apparatResult.layout().removeWidget(self.app_results)
self.apparatResult.layout().addWidget(self.splitter)
self.semester = Semester().value
self.populate_tab() self.populate_tab()
def restore_apparat(self): def restore_apparat(self):
@@ -90,15 +94,15 @@ class SearchStatisticPage(QtWidgets.QDialog, Ui_Dialog):
extend.exec() extend.exec()
if extend.result() == QtWidgets.QDialog.DialogCode.Accepted: if extend.result() == QtWidgets.QDialog.DialogCode.Accepted:
data = extend.get_data() data = extend.get_data()
ic(data) logger.debug(data)
app_name = self.tableWidget.item(self.tableWidget.currentRow(), 1).text() app_name = self.tableWidget.item(self.tableWidget.currentRow(), 1).text()
app_id = self.db.getApparatId(app_name) app_id = self.db.getApparatId(app_name)
self.db.setNewSemesterDate(app_id, data["semester"], data["dauerapp"]) self.db.setNewSemesterDate(app_id, data["semester"], data["dauerapp"])
#remove the row # remove the row
self.tableWidget.removeRow(self.tableWidget.currentRow()) self.tableWidget.removeRow(self.tableWidget.currentRow())
self.refreshSignal.emit() self.refreshSignal.emit()
def tabW2_changed(self):
def tabW2_changed(self):
if self.tabWidget_2.currentIndex() == 0: if self.tabWidget_2.currentIndex() == 0:
self.stackedWidget_4.setCurrentIndex(0) self.stackedWidget_4.setCurrentIndex(0)
else: else:
@@ -113,12 +117,11 @@ class SearchStatisticPage(QtWidgets.QDialog, Ui_Dialog):
"title": title if title != "" else None, "title": title if title != "" else None,
} }
params = {key: value for key, value in params.items() if value is not None} params = {key: value for key, value in params.items() if value is not None}
# ic(params) logger.debug(params)
retdata = self.db.searchBook(params) retdata = self.db.searchBook(params)
if retdata is None: if retdata is None:
return return
for book in retdata: for book in retdata:
self.book_search_result.insertRow(0) self.book_search_result.insertRow(0)
self.book_search_result.setItem( self.book_search_result.setItem(
0, 0, QtWidgets.QTableWidgetItem(book[0].title) 0, 0, QtWidgets.QTableWidgetItem(book[0].title)
@@ -145,10 +148,9 @@ class SearchStatisticPage(QtWidgets.QDialog, Ui_Dialog):
selected_apparats.append(data) selected_apparats.append(data)
# delete all selected apparats # delete all selected apparats
ic(selected_apparats) logger.debug(selected_apparats)
dialogs = [] dialogs = []
for i in selected_apparats: for i in selected_apparats:
app_id = i["app_id"] app_id = i["app_id"]
app_name = i["app_name"] app_name = i["app_name"]
prof_name = i["prof_name"] prof_name = i["prof_name"]
@@ -206,7 +208,7 @@ class SearchStatisticPage(QtWidgets.QDialog, Ui_Dialog):
self.box_dauerapp.setEnabled(True) self.box_dauerapp.setEnabled(True)
def populate_tab(self, table_or_graph=0): def populate_tab(self, table_or_graph=0):
self.logger.log_info("populate_tab started") logger.info("populate_tab started")
# add default values to the dropdowns # add default values to the dropdowns
self.box_appnrs.clear() self.box_appnrs.clear()
self.box_appnrs.addItem("") self.box_appnrs.addItem("")
@@ -232,9 +234,13 @@ class SearchStatisticPage(QtWidgets.QDialog, Ui_Dialog):
apparats = [str(apparat) for apparat in apparats] apparats = [str(apparat) for apparat in apparats]
self.box_appnrs.addItems(apparats) self.box_appnrs.addItems(apparats)
persons = self.db.getProfs() persons = self.db.getProfs()
self.box_person.addItems([f"{person.lastname}, {person.firstname}" for person in persons]) persons = sorted(persons, key=lambda x: x.lastname)
self.box_person.addItems(
[f"{person.lastname}, {person.firstname}" for person in persons]
)
self.box_fach.addItems(subject[1] for subject in self.db.getSubjects()) self.box_fach.addItems(subject[1] for subject in self.db.getSubjects())
semester = self.db.getSemersters() semester = self.db.getSemesters()
semester = sort_semesters_list(semester)
self.box_erstellsemester.addItems(semester) self.box_erstellsemester.addItems(semester)
self.box_semester.addItems(semester) self.box_semester.addItems(semester)
self.statistics_table.setRowCount(0) self.statistics_table.setRowCount(0)
@@ -269,7 +275,7 @@ class SearchStatisticPage(QtWidgets.QDialog, Ui_Dialog):
# place the graph into tabWidget_3 # place the graph into tabWidget_3
self.tabWidget_3.addTab(graph, "Graph") self.tabWidget_3.addTab(graph, "Graph")
self.tabWidget_3.setCurrentIndex(table_or_graph) self.tabWidget_3.setCurrentIndex(table_or_graph)
self.logger.log_info("populate_tab finished") logger.info("populate_tab finished")
def delete_selected_apparats(self): def delete_selected_apparats(self):
# get all selected apparats # get all selected apparats
@@ -281,9 +287,9 @@ class SearchStatisticPage(QtWidgets.QDialog, Ui_Dialog):
selected_apparat_rows.append(i) selected_apparat_rows.append(i)
# delete all selected apparats # delete all selected apparats
# # print(selected_apparats) # # print(selected_apparats)
self.logger.log_info(f"Deleting apparats: {selected_apparats}") logger.info(f"Deleting apparats: {selected_apparats}")
for apparat in selected_apparats: for apparat in selected_apparats:
self.db.deleteApparat(apparat, generateSemesterByDate()) self.db.deleteApparat(apparat, self.semester)
for row in selected_apparat_rows: for row in selected_apparat_rows:
# set the background of the row to red # set the background of the row to red
for j in range(5): for j in range(5):
@@ -295,10 +301,10 @@ class SearchStatisticPage(QtWidgets.QDialog, Ui_Dialog):
def statistics(self): def statistics(self):
"""Generate the statistics based on the selected filters.""" """Generate the statistics based on the selected filters."""
self.tableWidget.setRowCount(0) self.tableWidget.setRowCount(0)
active_semseter = generateSemesterByDate() active_semseter = self.semester
self.db_err_message.setText("") self.db_err_message.setText("")
self.btn_del_select_apparats.setEnabled(True) self.btn_del_select_apparats.setEnabled(False)
self.btn_notify_for_deletion.setEnabled(True) self.btn_notify_for_deletion.setEnabled(False)
params = { params = {
"appnr": ( "appnr": (
self.box_appnrs.currentText() self.box_appnrs.currentText()
@@ -306,7 +312,7 @@ class SearchStatisticPage(QtWidgets.QDialog, Ui_Dialog):
else None else None
), ),
"prof_id": ( "prof_id": (
self.db.getProfId(self.box_person.currentText()) self.db.getProfId(Prof(fullname=self.box_person.currentText()))
if self.box_person.currentText() != "" if self.box_person.currentText() != ""
else None else None
), ),
@@ -348,29 +354,22 @@ class SearchStatisticPage(QtWidgets.QDialog, Ui_Dialog):
self.db_err_message.setText("Keine Ergebnisse gefunden") self.db_err_message.setText("Keine Ergebnisse gefunden")
return return
data = [] data = []
sem_year = active_semseter.split(" ")[1]
sem_time = active_semseter.split(" ")[0]
if sem_time == "WiSe":
sem_year = int(sem_year.split("/")[0])
else:
sem_year = int(sem_year)
for entry in result: for entry in result:
if "deletable" in params.keys(): if "deletable" in params.keys():
entry_sem_time = entry[5].split(" ")[0] sem = Semester().from_string(
entry_sem_year = entry[5].split(" ")[1] entry[8] if entry[8] is not None else entry[5]
if entry_sem_time == "SoSe": )
entry_sem_year = int(entry_sem_year) logger.info(f"Semester: {sem}")
if (entry_sem_year < sem_year) or ( if sem.isPastSemester(Semester()):
sem_time == "WiSe" and entry_sem_year == sem_year data.append(entry)
):
data.append(entry)
else:
entry_sem_year = int(entry_sem_year.split("/")[0])
if entry_sem_year < sem_year:
data.append(entry)
else: else:
data.append(entry) data.append(entry)
self.tableWidget.setRowCount(len(data)) self.tableWidget.setRowCount(len(data))
if len(data) > 0:
self.btn_del_select_apparats.setEnabled(True)
self.btn_notify_for_deletion.setEnabled(True)
for i in range(len(data)): for i in range(len(data)):
# set the items 0 = clickable checkbox, 1 = appname, 2 = profname, 3 = fach # set the items 0 = clickable checkbox, 1 = appname, 2 = profname, 3 = fach
self.tableWidget.setItem(i, 0, QtWidgets.QTableWidgetItem("")) self.tableWidget.setItem(i, 0, QtWidgets.QTableWidgetItem(""))

View File

@@ -1,3 +1,4 @@
# Form implementation generated from reading ui file 'c:\Users\aky547\GitHub\SemesterapparatsManager\src\ui\widgets\widget_sources\admin_create_user.ui' # Form implementation generated from reading ui file 'c:\Users\aky547\GitHub\SemesterapparatsManager\src\ui\widgets\widget_sources\admin_create_user.ui'
# #
# Created by: PyQt6 UI code generator 6.7.1 # Created by: PyQt6 UI code generator 6.7.1

View File

@@ -1,3 +1,4 @@
# Form implementation generated from reading ui file 'c:\Users\aky547\GitHub\SemesterapparatsManager\src\ui\widgets\widget_sources\admin_edit_prof.ui' # Form implementation generated from reading ui file 'c:\Users\aky547\GitHub\SemesterapparatsManager\src\ui\widgets\widget_sources\admin_edit_prof.ui'
# #
# Created by: PyQt6 UI code generator 6.7.1 # Created by: PyQt6 UI code generator 6.7.1

View File

@@ -1,3 +1,4 @@
# Form implementation generated from reading ui file 'c:\Users\aky547\GitHub\SemesterapparatsManager\src\ui\widgets\widget_sources\admin_edit_user.ui' # Form implementation generated from reading ui file 'c:\Users\aky547\GitHub\SemesterapparatsManager\src\ui\widgets\widget_sources\admin_edit_user.ui'
# #
# Created by: PyQt6 UI code generator 6.7.1 # Created by: PyQt6 UI code generator 6.7.1

View File

@@ -1,3 +1,4 @@
# Form implementation generated from reading ui file 'c:\Users\aky547\GitHub\SemesterapparatsManager\src\ui\widgets\widget_sources\calendar_entry.ui' # Form implementation generated from reading ui file 'c:\Users\aky547\GitHub\SemesterapparatsManager\src\ui\widgets\widget_sources\calendar_entry.ui'
# #
# Created by: PyQt6 UI code generator 6.7.1 # Created by: PyQt6 UI code generator 6.7.1

View File

@@ -1,3 +1,4 @@
# Form implementation generated from reading ui file 'c:\Users\aky547\GitHub\SemesterapparatsManager\src\ui\widgets\widget_sources\elsa_maindialog.ui' # Form implementation generated from reading ui file 'c:\Users\aky547\GitHub\SemesterapparatsManager\src\ui\widgets\widget_sources\elsa_maindialog.ui'
# #
# Created by: PyQt6 UI code generator 6.7.1 # Created by: PyQt6 UI code generator 6.7.1
@@ -187,15 +188,36 @@ class Ui_Dialog(object):
self.verticalLayout.addWidget(self.create_frame_elsa) self.verticalLayout.addWidget(self.create_frame_elsa)
self.horizontalLayout_6 = QtWidgets.QHBoxLayout() self.horizontalLayout_6 = QtWidgets.QHBoxLayout()
self.horizontalLayout_6.setObjectName("horizontalLayout_6") self.horizontalLayout_6.setObjectName("horizontalLayout_6")
self.quote_entry = QtWidgets.QPushButton(parent=Dialog)
self.quote_entry.setObjectName("quote_entry")
self.horizontalLayout_6.addWidget(self.quote_entry)
spacerItem5 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
self.horizontalLayout_6.addItem(spacerItem5)
self.verticalLayout.addLayout(self.horizontalLayout_6) self.verticalLayout.addLayout(self.horizontalLayout_6)
self.horizontalLayout_5 = QtWidgets.QHBoxLayout() self.horizontalLayout_5 = QtWidgets.QHBoxLayout()
self.horizontalLayout_5.setObjectName("horizontalLayout_5") self.horizontalLayout_5.setObjectName("horizontalLayout_5")
self.table_elsa_list = QtWidgets.QTableWidget(parent=Dialog) self.verticalLayout.addLayout(self.horizontalLayout_5)
self.results = QtWidgets.QWidget(parent=Dialog)
self.results.setObjectName("results")
self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.results)
self.horizontalLayout_3.setObjectName("horizontalLayout_3")
self.statistics = QtWidgets.QWidget(parent=self.results)
self.statistics.setObjectName("statistics")
self.horizontalLayout_7 = QtWidgets.QHBoxLayout(self.statistics)
self.horizontalLayout_7.setObjectName("horizontalLayout_7")
self.media_table = QtWidgets.QWidget(parent=self.statistics)
self.media_table.setObjectName("media_table")
self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.media_table)
self.verticalLayout_4.setObjectName("verticalLayout_4")
self.horizontalLayout_9 = QtWidgets.QHBoxLayout()
self.horizontalLayout_9.setObjectName("horizontalLayout_9")
self.quote_entry = QtWidgets.QPushButton(parent=self.media_table)
self.quote_entry.setObjectName("quote_entry")
self.horizontalLayout_9.addWidget(self.quote_entry)
spacerItem5 = QtWidgets.QSpacerItem(
40,
20,
QtWidgets.QSizePolicy.Policy.Expanding,
QtWidgets.QSizePolicy.Policy.Minimum,
)
self.horizontalLayout_9.addItem(spacerItem5)
self.verticalLayout_4.addLayout(self.horizontalLayout_9)
self.table_elsa_list = QtWidgets.QTableWidget(parent=self.media_table)
self.table_elsa_list.setFocusPolicy(QtCore.Qt.FocusPolicy.NoFocus) self.table_elsa_list.setFocusPolicy(QtCore.Qt.FocusPolicy.NoFocus)
self.table_elsa_list.setEditTriggers(QtWidgets.QAbstractItemView.EditTrigger.NoEditTriggers) self.table_elsa_list.setEditTriggers(QtWidgets.QAbstractItemView.EditTrigger.NoEditTriggers)
self.table_elsa_list.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectionBehavior.SelectItems) self.table_elsa_list.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectionBehavior.SelectItems)
@@ -230,13 +252,14 @@ class Ui_Dialog(object):
self.table_elsa_list.setHorizontalHeaderItem(11, item) self.table_elsa_list.setHorizontalHeaderItem(11, item)
self.table_elsa_list.horizontalHeader().setDefaultSectionSize(85) self.table_elsa_list.horizontalHeader().setDefaultSectionSize(85)
self.table_elsa_list.horizontalHeader().setMinimumSectionSize(31) self.table_elsa_list.horizontalHeader().setMinimumSectionSize(31)
self.horizontalLayout_5.addWidget(self.table_elsa_list) self.verticalLayout_4.addWidget(self.table_elsa_list)
self.elsa_statistics = QtWidgets.QTabWidget(parent=Dialog) self.horizontalLayout_7.addWidget(self.media_table)
self.elsa_statistics = QtWidgets.QTabWidget(parent=self.statistics)
self.elsa_statistics.setObjectName("elsa_statistics") self.elsa_statistics.setObjectName("elsa_statistics")
self.tab = QtWidgets.QWidget() self.tab = QtWidgets.QWidget()
self.tab.setObjectName("tab") self.tab.setObjectName("tab")
self.horizontalLayout_7 = QtWidgets.QHBoxLayout(self.tab) self.horizontalLayout_8 = QtWidgets.QHBoxLayout(self.tab)
self.horizontalLayout_7.setObjectName("horizontalLayout_7") self.horizontalLayout_8.setObjectName("horizontalLayout_8")
self.elsa_statistics_table = QtWidgets.QTableWidget(parent=self.tab) self.elsa_statistics_table = QtWidgets.QTableWidget(parent=self.tab)
self.elsa_statistics_table.setFocusPolicy(QtCore.Qt.FocusPolicy.NoFocus) self.elsa_statistics_table.setFocusPolicy(QtCore.Qt.FocusPolicy.NoFocus)
self.elsa_statistics_table.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarPolicy.ScrollBarAlwaysOff) self.elsa_statistics_table.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
@@ -250,14 +273,16 @@ class Ui_Dialog(object):
item = QtWidgets.QTableWidgetItem() item = QtWidgets.QTableWidgetItem()
self.elsa_statistics_table.setHorizontalHeaderItem(1, item) self.elsa_statistics_table.setHorizontalHeaderItem(1, item)
self.elsa_statistics_table.horizontalHeader().setDefaultSectionSize(169) self.elsa_statistics_table.horizontalHeader().setDefaultSectionSize(169)
self.horizontalLayout_7.addWidget(self.elsa_statistics_table) self.horizontalLayout_8.addWidget(self.elsa_statistics_table)
self.elsa_statistics.addTab(self.tab, "") self.elsa_statistics.addTab(self.tab, "")
self.horizontalLayout_5.addWidget(self.elsa_statistics) self.horizontalLayout_7.addWidget(self.elsa_statistics)
self.horizontalLayout_5.setStretch(0, 7) self.horizontalLayout_3.addWidget(self.statistics)
self.horizontalLayout_5.setStretch(1, 3) self.results_table = QtWidgets.QWidget(parent=self.results)
self.verticalLayout.addLayout(self.horizontalLayout_5) self.results_table.setObjectName("results_table")
self.horizontalLayout_3.addWidget(self.results_table)
self.verticalLayout.addWidget(self.results)
self.verticalLayout.setStretch(0, 1) self.verticalLayout.setStretch(0, 1)
self.verticalLayout.setStretch(3, 2) self.verticalLayout.setStretch(4, 2)
self.retranslateUi(Dialog) self.retranslateUi(Dialog)
self.elsa_statistics.setCurrentIndex(0) self.elsa_statistics.setCurrentIndex(0)
@@ -277,12 +302,8 @@ class Ui_Dialog(object):
Dialog.setTabOrder(self.seperateEntries, self.check_file_elsa) Dialog.setTabOrder(self.seperateEntries, self.check_file_elsa)
Dialog.setTabOrder(self.check_file_elsa, self.elsa_save) Dialog.setTabOrder(self.check_file_elsa, self.elsa_save)
Dialog.setTabOrder(self.elsa_save, self.elsa_update) Dialog.setTabOrder(self.elsa_save, self.elsa_update)
Dialog.setTabOrder(self.elsa_update, self.quote_entry) Dialog.setTabOrder(self.elsa_update, self.elsa_table)
Dialog.setTabOrder(self.quote_entry, self.elsa_statistics) Dialog.setTabOrder(self.elsa_table, self.dokument_list_elsa)
Dialog.setTabOrder(self.elsa_statistics, self.table_elsa_list)
Dialog.setTabOrder(self.table_elsa_list, self.elsa_table)
Dialog.setTabOrder(self.elsa_table, self.elsa_statistics_table)
Dialog.setTabOrder(self.elsa_statistics_table, self.dokument_list_elsa)
def retranslateUi(self, Dialog): def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate _translate = QtCore.QCoreApplication.translate

View File

@@ -1,3 +1,4 @@
# Form implementation generated from reading ui file 'c:\Users\aky547\GitHub\SemesterapparatsManager\src\ui\widgets\widget_sources\search_statistic_page.ui' # Form implementation generated from reading ui file 'c:\Users\aky547\GitHub\SemesterapparatsManager\src\ui\widgets\widget_sources\search_statistic_page.ui'
# #
# Created by: PyQt6 UI code generator 6.7.1 # Created by: PyQt6 UI code generator 6.7.1
@@ -12,7 +13,7 @@ from PyQt6 import QtCore, QtGui, QtWidgets
class Ui_Dialog(object): class Ui_Dialog(object):
def setupUi(self, Dialog): def setupUi(self, Dialog):
Dialog.setObjectName("Dialog") Dialog.setObjectName("Dialog")
Dialog.resize(1244, 767) Dialog.resize(1250, 767)
self.verticalLayout = QtWidgets.QVBoxLayout(Dialog) self.verticalLayout = QtWidgets.QVBoxLayout(Dialog)
self.verticalLayout.setObjectName("verticalLayout") self.verticalLayout.setObjectName("verticalLayout")
self.tabWidget_2 = QtWidgets.QTabWidget(parent=Dialog) self.tabWidget_2 = QtWidgets.QTabWidget(parent=Dialog)
@@ -150,24 +151,26 @@ class Ui_Dialog(object):
self.apparatResult.setObjectName("apparatResult") self.apparatResult.setObjectName("apparatResult")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.apparatResult) self.horizontalLayout = QtWidgets.QHBoxLayout(self.apparatResult)
self.horizontalLayout.setObjectName("horizontalLayout") self.horizontalLayout.setObjectName("horizontalLayout")
self.verticalLayout_4 = QtWidgets.QVBoxLayout() self.app_results = QtWidgets.QWidget(parent=self.apparatResult)
self.verticalLayout_4.setObjectName("verticalLayout_4") self.app_results.setObjectName("app_results")
self.verticalLayout_7 = QtWidgets.QVBoxLayout(self.app_results)
self.verticalLayout_7.setObjectName("verticalLayout_7")
self.horizontalLayout_7 = QtWidgets.QHBoxLayout() self.horizontalLayout_7 = QtWidgets.QHBoxLayout()
self.horizontalLayout_7.setObjectName("horizontalLayout_7") self.horizontalLayout_7.setObjectName("horizontalLayout_7")
self.verticalLayout_5 = QtWidgets.QVBoxLayout() self.verticalLayout_5 = QtWidgets.QVBoxLayout()
self.verticalLayout_5.setObjectName("verticalLayout_5") self.verticalLayout_5.setObjectName("verticalLayout_5")
self.horizontalLayout_7.addLayout(self.verticalLayout_5) self.horizontalLayout_7.addLayout(self.verticalLayout_5)
self.btn_del_select_apparats = QtWidgets.QPushButton(parent=self.apparatResult) self.btn_del_select_apparats = QtWidgets.QPushButton(parent=self.app_results)
self.btn_del_select_apparats.setFocusPolicy(QtCore.Qt.FocusPolicy.StrongFocus) self.btn_del_select_apparats.setFocusPolicy(QtCore.Qt.FocusPolicy.StrongFocus)
self.btn_del_select_apparats.setObjectName("btn_del_select_apparats") self.btn_del_select_apparats.setObjectName("btn_del_select_apparats")
self.horizontalLayout_7.addWidget(self.btn_del_select_apparats) self.horizontalLayout_7.addWidget(self.btn_del_select_apparats)
self.btn_notify_for_deletion = QtWidgets.QPushButton(parent=self.apparatResult) self.btn_notify_for_deletion = QtWidgets.QPushButton(parent=self.app_results)
self.btn_notify_for_deletion.setObjectName("btn_notify_for_deletion") self.btn_notify_for_deletion.setObjectName("btn_notify_for_deletion")
self.horizontalLayout_7.addWidget(self.btn_notify_for_deletion) self.horizontalLayout_7.addWidget(self.btn_notify_for_deletion)
spacerItem4 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum) spacerItem4 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
self.horizontalLayout_7.addItem(spacerItem4) self.horizontalLayout_7.addItem(spacerItem4)
self.verticalLayout_4.addLayout(self.horizontalLayout_7) self.verticalLayout_7.addLayout(self.horizontalLayout_7)
self.tableWidget = QtWidgets.QTableWidget(parent=self.apparatResult) self.tableWidget = QtWidgets.QTableWidget(parent=self.app_results)
self.tableWidget.setFocusPolicy(QtCore.Qt.FocusPolicy.NoFocus) self.tableWidget.setFocusPolicy(QtCore.Qt.FocusPolicy.NoFocus)
self.tableWidget.setContextMenuPolicy(QtCore.Qt.ContextMenuPolicy.CustomContextMenu) self.tableWidget.setContextMenuPolicy(QtCore.Qt.ContextMenuPolicy.CustomContextMenu)
self.tableWidget.setEditTriggers(QtWidgets.QAbstractItemView.EditTrigger.NoEditTriggers) self.tableWidget.setEditTriggers(QtWidgets.QAbstractItemView.EditTrigger.NoEditTriggers)
@@ -185,14 +188,18 @@ class Ui_Dialog(object):
item = QtWidgets.QTableWidgetItem() item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(4, item) self.tableWidget.setHorizontalHeaderItem(4, item)
self.tableWidget.horizontalHeader().setStretchLastSection(True) self.tableWidget.horizontalHeader().setStretchLastSection(True)
self.verticalLayout_4.addWidget(self.tableWidget) self.verticalLayout_7.addWidget(self.tableWidget)
self.horizontalLayout.addLayout(self.verticalLayout_4) self.horizontalLayout.addWidget(self.app_results)
self.tabWidget_3 = QtWidgets.QTabWidget(parent=self.apparatResult) self.stats = QtWidgets.QWidget(parent=self.apparatResult)
self.stats.setObjectName("stats")
self.horizontalLayout_5 = QtWidgets.QHBoxLayout(self.stats)
self.horizontalLayout_5.setObjectName("horizontalLayout_5")
self.tabWidget_3 = QtWidgets.QTabWidget(parent=self.stats)
self.tabWidget_3.setObjectName("tabWidget_3") self.tabWidget_3.setObjectName("tabWidget_3")
self.statistic_table = QtWidgets.QWidget() self.statistic_table = QtWidgets.QWidget()
self.statistic_table.setObjectName("statistic_table") self.statistic_table.setObjectName("statistic_table")
self.verticalLayout_6 = QtWidgets.QVBoxLayout(self.statistic_table) self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.statistic_table)
self.verticalLayout_6.setObjectName("verticalLayout_6") self.verticalLayout_4.setObjectName("verticalLayout_4")
self.statistics_table = QtWidgets.QTableWidget(parent=self.statistic_table) self.statistics_table = QtWidgets.QTableWidget(parent=self.statistic_table)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Expanding) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Expanding)
sizePolicy.setHorizontalStretch(0) sizePolicy.setHorizontalStretch(0)
@@ -219,17 +226,16 @@ class Ui_Dialog(object):
self.statistics_table.horizontalHeader().setSortIndicatorShown(True) self.statistics_table.horizontalHeader().setSortIndicatorShown(True)
self.statistics_table.horizontalHeader().setStretchLastSection(False) self.statistics_table.horizontalHeader().setStretchLastSection(False)
self.statistics_table.verticalHeader().setStretchLastSection(True) self.statistics_table.verticalHeader().setStretchLastSection(True)
self.verticalLayout_6.addWidget(self.statistics_table) self.verticalLayout_4.addWidget(self.statistics_table)
self.dataLayout = QtWidgets.QHBoxLayout() self.dataLayout = QtWidgets.QHBoxLayout()
self.dataLayout.setObjectName("dataLayout") self.dataLayout.setObjectName("dataLayout")
self.verticalLayout_6.addLayout(self.dataLayout) self.verticalLayout_4.addLayout(self.dataLayout)
self.tabWidget_3.addTab(self.statistic_table, "") self.tabWidget_3.addTab(self.statistic_table, "")
self.graph_table = QtWidgets.QWidget() self.graph_table = QtWidgets.QWidget()
self.graph_table.setObjectName("graph_table") self.graph_table.setObjectName("graph_table")
self.tabWidget_3.addTab(self.graph_table, "") self.tabWidget_3.addTab(self.graph_table, "")
self.horizontalLayout.addWidget(self.tabWidget_3) self.horizontalLayout_5.addWidget(self.tabWidget_3)
self.horizontalLayout.setStretch(0, 55) self.horizontalLayout.addWidget(self.stats)
self.horizontalLayout.setStretch(1, 45)
self.stackedWidget_4.addWidget(self.apparatResult) self.stackedWidget_4.addWidget(self.apparatResult)
self.bookresult = QtWidgets.QWidget() self.bookresult = QtWidgets.QWidget()
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Expanding) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Expanding)
@@ -285,8 +291,7 @@ class Ui_Dialog(object):
Dialog.setTabOrder(self.box_dauerapp, self.btn_search) Dialog.setTabOrder(self.box_dauerapp, self.btn_search)
Dialog.setTabOrder(self.btn_search, self.btn_del_select_apparats) Dialog.setTabOrder(self.btn_search, self.btn_del_select_apparats)
Dialog.setTabOrder(self.btn_del_select_apparats, self.btn_notify_for_deletion) Dialog.setTabOrder(self.btn_del_select_apparats, self.btn_notify_for_deletion)
Dialog.setTabOrder(self.btn_notify_for_deletion, self.tabWidget_3) Dialog.setTabOrder(self.btn_notify_for_deletion, self.book_search_result)
Dialog.setTabOrder(self.tabWidget_3, self.book_search_result)
Dialog.setTabOrder(self.book_search_result, self.seach_by_signature) Dialog.setTabOrder(self.book_search_result, self.seach_by_signature)
Dialog.setTabOrder(self.seach_by_signature, self.search_by_title) Dialog.setTabOrder(self.seach_by_signature, self.search_by_title)
Dialog.setTabOrder(self.search_by_title, self.book_search) Dialog.setTabOrder(self.search_by_title, self.book_search)

View File

@@ -1,3 +1,4 @@
from .blob import create_blob from .blob import create_blob
from .icon import Icon from .icon import Icon
from .pickles import dump_pickle, load_pickle from .pickles import dump_pickle, load_pickle

View File

@@ -1,3 +1,4 @@
def create_blob(file): def create_blob(file):
""" """
Creates a blob from a file. Creates a blob from a file.

View File

@@ -1,3 +1,4 @@
import darkdetect import darkdetect
from omegaconf import OmegaConf from omegaconf import OmegaConf
from PyQt6 import QtGui from PyQt6 import QtGui

View File

@@ -1,3 +1,4 @@
import pickle import pickle

Some files were not shown because too many files have changed in this diff Show More