Compare commits
20 Commits
v0.2.0-dev
...
dev_pyside
| Author | SHA1 | Date | |
|---|---|---|---|
| 0458ccd443 | |||
| 98ac7377ac | |||
| 5923bfd7ff | |||
| 7abe3d8cc0 | |||
| b4c6169649 | |||
| 8b83b8c305 | |||
| 3d2be0fd47 | |||
| bbeb9cf701 | |||
| eb0b7a1fec | |||
| 80b96865e7 | |||
| da0e9e0725 | |||
| f0148d8855 | |||
| 9cc08e2d91 | |||
| 921a84304f | |||
| 6ff7a70d11 | |||
| ac32b86b17 | |||
| dbefd2049f | |||
| 50dd03aee7 | |||
| f1724058b0 | |||
| d225c1d4e8 |
@@ -1,19 +1,7 @@
|
|||||||
[tool.bumpversion]
|
[tool.bumpversion]
|
||||||
current_version = "0.2.0-dev0"
|
current_version = "0.2.1"
|
||||||
parse = """(?x)
|
parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)"
|
||||||
(?P<major>0|[1-9]\\d*)\\.
|
serialize = ["{major}.{minor}.{patch}"]
|
||||||
(?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}"
|
search = "{current_version}"
|
||||||
replace = "{new_version}"
|
replace = "{new_version}"
|
||||||
regex = false
|
regex = false
|
||||||
@@ -30,8 +18,5 @@ commit_args = ""
|
|||||||
setup_hooks = []
|
setup_hooks = []
|
||||||
pre_commit_hooks = []
|
pre_commit_hooks = []
|
||||||
post_commit_hooks = []
|
post_commit_hooks = []
|
||||||
[tool.bumpversion.parts.pre_l]
|
|
||||||
values = ["dev", "rc", "final"]
|
|
||||||
optional_value = "final"
|
|
||||||
[[tool.bumpversion.files]]
|
[[tool.bumpversion.files]]
|
||||||
filename = "src/__init__.py"
|
filename = "src/__init__.py"
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -228,3 +228,4 @@ config.yaml
|
|||||||
**/tempCodeRunnerFile.py
|
**/tempCodeRunnerFile.py
|
||||||
uv.lock
|
uv.lock
|
||||||
uv.lock
|
uv.lock
|
||||||
|
logs
|
||||||
|
|||||||
28
README.md
28
README.md
@@ -1,3 +1,27 @@
|
|||||||
# Semesterapparate
|
# SemesterapparatsManager
|
||||||
|
|
||||||
this repo will be used to create a GUI application to manage the semesterapparate of the PH Freiburg.
|
SemesterapparatsManager is a graphical tool for managing semester apparatuses in the University of Education Freiburg. It allows the users to manage the semester apparatuses in a user-friendly way. It's functions include management of physical and digital semester apparatuses, as well as creating the citations for the digital files of the digital semester apparatuses. For that it uses Zotero, an open source reference management software. The semester apparatuses are stored in a SQLite database, which is created and managed by the SemesterapparatsManager. The SemesterapparatsManager is written in Python and uses the PyQt6 library for the graphical user interface
|
||||||
|
|
||||||
|
|
||||||
|
## Features
|
||||||
|
- Manage physical semester apparatuses
|
||||||
|
- Add semester apparatuses
|
||||||
|
- Edit semester apparatuses
|
||||||
|
- Delete semester apparatuses
|
||||||
|
- Extend semester apparatuses
|
||||||
|
- Notify professors about semester apparatuses creation or deletion
|
||||||
|
- Add messages to all semester apparatuses, or an individual semester apparatus
|
||||||
|
- Manage digital semester apparatuses
|
||||||
|
- Use text parsing to extract information from the submitted form and create the scans
|
||||||
|
- if a book is used multiple parts of a book are used, it can be split into the parts
|
||||||
|
- Create the matching citations for the files
|
||||||
|
- Statistics and Search
|
||||||
|
- Search semester apparatuses by various criteria
|
||||||
|
- Show statistics about the semester apparatuses creation and deletion
|
||||||
|
- Edit user data
|
||||||
|
|
||||||
|
|
||||||
|
## Images
|
||||||
|
|
||||||
|

|
||||||
|

|
||||||
@@ -37,6 +37,7 @@ class Mail:
|
|||||||
sender: str
|
sender: str
|
||||||
password: str
|
password: str
|
||||||
use_user_name: bool
|
use_user_name: bool
|
||||||
|
printer_mail: str
|
||||||
user_name: str
|
user_name: str
|
||||||
signature: str | None = None
|
signature: str | None = None
|
||||||
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">
|
||||||
|
|||||||
BIN
docs/images/statistics.png
Normal file
BIN
docs/images/statistics.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 30 KiB |
@@ -0,0 +1,18 @@
|
|||||||
|
Subject: Information zur Auflösung des Semesterapparates {AppNr} - {Appname}
|
||||||
|
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;">{greeting}</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Ihr Semesterapparat "{Appname} ({AppNr})" wurde wie besprochen aufgelöst. </p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Die Medien sind von nun an wieder in den Regalen zu finden.</p>
|
||||||
|
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><pre class="moz-signature" cols="72">-- </p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">{signature}</p>
|
||||||
|
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></pre></p></body></html>
|
||||||
@@ -1,27 +1,16 @@
|
|||||||
import sys
|
|
||||||
from config import Config
|
from config import Config
|
||||||
import os
|
import os
|
||||||
from loguru import logger as log
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
settings = Config("config/config.yaml")
|
settings = Config("config/config.yaml")
|
||||||
|
if not os.path.exists(settings.database.temp):
|
||||||
|
os.mkdir(settings.database.temp)
|
||||||
from .utils.icon import Icon
|
from .utils.icon import Icon
|
||||||
|
|
||||||
__version__ = "0.2.0-dev0"
|
__version__ = "0.2.1"
|
||||||
__author__ = "Alexander Kirchner"
|
__author__ = "Alexander Kirchner"
|
||||||
|
|
||||||
|
|
||||||
if not os.path.exists("logs"):
|
if not os.path.exists("logs"):
|
||||||
os.mkdir("logs")
|
os.mkdir("logs")
|
||||||
# open and close the file to create it
|
# open and close the file to create it
|
||||||
logger = log
|
|
||||||
logger.remove()
|
|
||||||
logger.add("logs/application.log", rotation="1 week", enqueue=True)
|
|
||||||
log.add(
|
|
||||||
f"logs/{datetime.now().strftime('%Y-%m-%d')}.log",
|
|
||||||
rotation="1 day",
|
|
||||||
compression="zip",
|
|
||||||
)
|
|
||||||
|
|
||||||
# logger.add(sys.stderr, format="{time} {level} {message}", level="INFO")
|
|
||||||
logger.add(sys.stdout)
|
|
||||||
|
|||||||
@@ -5,9 +5,18 @@ from pathlib import Path
|
|||||||
from src.backend.database import Database
|
from src.backend.database import Database
|
||||||
|
|
||||||
db = Database()
|
db = Database()
|
||||||
|
import loguru
|
||||||
|
import sys
|
||||||
|
|
||||||
|
log = loguru.logger
|
||||||
|
log.remove()
|
||||||
|
log.add("application.log", rotation="1 week", retention="1 month")
|
||||||
|
log.add(
|
||||||
|
sys.stdout,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def recreateFile(name, app_id, filetype, open=True) -> Path:
|
def recreateFile(name: str, app_id: int, filetype: str, open: bool = True) -> Path:
|
||||||
"""
|
"""
|
||||||
recreateFile creates a file from the database and opens it in the respective program, if the open parameter is set to True.
|
recreateFile creates a file from the database and opens it in the respective program, if the open parameter is set to True.
|
||||||
|
|
||||||
@@ -24,6 +33,7 @@ def recreateFile(name, app_id, filetype, open=True) -> Path:
|
|||||||
"""
|
"""
|
||||||
path = db.recreateFile(name, app_id, filetype=filetype)
|
path = db.recreateFile(name, app_id, filetype=filetype)
|
||||||
path = Path(path)
|
path = Path(path)
|
||||||
|
log.info(f"File created: {path}")
|
||||||
if open:
|
if open:
|
||||||
if os.getenv("OS") == "Windows_NT":
|
if os.getenv("OS") == "Windows_NT":
|
||||||
path = path.resolve()
|
path = path.resolve()
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ from pathlib import Path
|
|||||||
from src import settings
|
from src import settings
|
||||||
from typing import Any, List, Optional, Tuple, Union
|
from typing import Any, List, Optional, Tuple, Union
|
||||||
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,
|
||||||
@@ -25,6 +25,20 @@ 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 Semester
|
from .semester import Semester
|
||||||
from string import ascii_lowercase as lower, digits, punctuation
|
from string import ascii_lowercase as lower, digits, punctuation
|
||||||
|
import sys
|
||||||
|
from loguru import logger as log
|
||||||
|
|
||||||
|
logger = log
|
||||||
|
logger.remove()
|
||||||
|
logger.add("logs/database.log", rotation="1 week", enqueue=True)
|
||||||
|
log.add(
|
||||||
|
"logs/application.log",
|
||||||
|
rotation="1 day",
|
||||||
|
compression="zip",
|
||||||
|
)
|
||||||
|
|
||||||
|
# logger.add(sys.stderr, format="{time} {level} {message}", level="INFO")
|
||||||
|
logger.add(sys.stdout)
|
||||||
|
|
||||||
|
|
||||||
ascii_lowercase = lower + digits + punctuation
|
ascii_lowercase = lower + digits + punctuation
|
||||||
@@ -47,6 +61,7 @@ class Database:
|
|||||||
if db_path is None:
|
if db_path is None:
|
||||||
self.db_path = self.database.path + self.database.name
|
self.db_path = self.database.path + self.database.name
|
||||||
self.db_path = self.db_path.replace("~", str(Path.home()))
|
self.db_path = self.db_path.replace("~", str(Path.home()))
|
||||||
|
logger.debug(self.db_path)
|
||||||
else:
|
else:
|
||||||
self.db_path = db_path
|
self.db_path = db_path
|
||||||
self.checkDatabaseStatus()
|
self.checkDatabaseStatus()
|
||||||
@@ -54,7 +69,6 @@ class Database:
|
|||||||
def checkDatabaseStatus(self):
|
def checkDatabaseStatus(self):
|
||||||
path = self.database.path
|
path = self.database.path
|
||||||
path = path.replace("~", str(Path.home()))
|
path = path.replace("~", str(Path.home()))
|
||||||
# print(path)
|
|
||||||
path = os.path.abspath(path)
|
path = os.path.abspath(path)
|
||||||
if not os.path.exists(path):
|
if not os.path.exists(path):
|
||||||
# create path
|
# create path
|
||||||
@@ -181,7 +195,7 @@ class Database:
|
|||||||
# log_message = f"Querying database with query {query}"
|
# log_message = f"Querying database with query {query}"
|
||||||
if "INTO user" in query:
|
if "INTO user" in query:
|
||||||
log_message = f"Querying database with query {query}"
|
log_message = f"Querying database with query {query}"
|
||||||
logger.debug(log_message)
|
# logger.debug(f"DB Query: {log_message}")
|
||||||
try:
|
try:
|
||||||
cursor.execute(query, args)
|
cursor.execute(query, args)
|
||||||
rv = cursor.fetchall()
|
rv = cursor.fetchall()
|
||||||
@@ -204,6 +218,7 @@ class Database:
|
|||||||
app_id (str): The apparat id where the book should be added to
|
app_id (str): The apparat id where the book should be added to
|
||||||
prof_id (str): The id of the professor where the book should be added to.
|
prof_id (str): The id of the professor where the book should be added to.
|
||||||
"""
|
"""
|
||||||
|
logger.info(f"Adding book {bookdata.signature} to database")
|
||||||
if app_id is None or prof_id is None:
|
if app_id is None or prof_id is None:
|
||||||
raise ValueError("Apparate ID or Prof ID is None")
|
raise ValueError("Apparate ID or Prof ID is None")
|
||||||
conn = self.connect()
|
conn = self.connect()
|
||||||
@@ -387,7 +402,7 @@ class Database:
|
|||||||
|
|
||||||
def getBooks(
|
def getBooks(
|
||||||
self, app_id: Union[str, int], prof_id: Union[str, int], deleted=0
|
self, app_id: Union[str, int], prof_id: Union[str, int], deleted=0
|
||||||
) -> list[dict[int, BookData, int]]:
|
) -> list[dict[str, Union[BookData, int]]]:
|
||||||
"""
|
"""
|
||||||
Get the Books based on the apparat id and the professor id
|
Get the Books based on the apparat id and the professor id
|
||||||
|
|
||||||
@@ -406,14 +421,14 @@ class Database:
|
|||||||
if qdata is None:
|
if qdata is None:
|
||||||
return []
|
return []
|
||||||
for result_a in qdata:
|
for result_a in qdata:
|
||||||
data = {"id": int, "bookdata": BookData, "available": int}
|
data: dict[str, Any] = {"id": int, "bookdata": BookData, "available": int}
|
||||||
data["id"] = result_a[0]
|
data["id"] = result_a[0]
|
||||||
data["bookdata"] = load_pickle(result_a[1])
|
data["bookdata"] = load_pickle(result_a[1])
|
||||||
data["available"] = result_a[2]
|
data["available"] = result_a[2]
|
||||||
ret_result.append(data)
|
ret_result.append(data)
|
||||||
return ret_result
|
return ret_result
|
||||||
|
|
||||||
def updateBookdata(self, book_id, bookdata: BookData):
|
def updateBookdata(self, book_id: int, bookdata: BookData):
|
||||||
"""
|
"""
|
||||||
Update the bookdata in the database
|
Update the bookdata in the database
|
||||||
|
|
||||||
@@ -487,7 +502,7 @@ class Database:
|
|||||||
str: The filename of the recreated file
|
str: The filename of the recreated file
|
||||||
"""
|
"""
|
||||||
blob = self.getBlob(filename, app_id)
|
blob = self.getBlob(filename, app_id)
|
||||||
tempdir = self.database.tempdir
|
tempdir = self.database.temp
|
||||||
tempdir = tempdir.replace("~", str(Path.home()))
|
tempdir = tempdir.replace("~", str(Path.home()))
|
||||||
tempdir_path = Path(tempdir)
|
tempdir_path = Path(tempdir)
|
||||||
if not os.path.exists(tempdir_path):
|
if not os.path.exists(tempdir_path):
|
||||||
@@ -816,7 +831,7 @@ class Database:
|
|||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
self.query_db(
|
self.query_db(
|
||||||
"UPDATE semesterapparat SET verlängerung_bis=?, verlängerung_am=? WHERE appnr=?",
|
"UPDATE semesterapparat SET verlängerung_bis=?, verlängert_am=? WHERE appnr=?",
|
||||||
(newDate, today, app_id),
|
(newDate, today, app_id),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -1183,7 +1198,7 @@ class Database:
|
|||||||
"UPDATE user SET password=? WHERE username=?", (new_password, user)
|
"UPDATE user SET password=? WHERE username=?", (new_password, user)
|
||||||
)
|
)
|
||||||
|
|
||||||
def getRole(self, user):
|
def getRole(self, user: str) -> str:
|
||||||
"""get the role of the user
|
"""get the role of the user
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@@ -1510,7 +1525,7 @@ class Database:
|
|||||||
else:
|
else:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def getProfId(self, profdata: dict | Prof):
|
def getProfId(self, profdata: dict[str, Any] | Prof):
|
||||||
"""Get the prof ID based on the profdata
|
"""Get the prof ID based on the profdata
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
|||||||
@@ -11,7 +11,9 @@ class Semester:
|
|||||||
_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"Initialized Semester class with values: month: {_month}, semester: {_semester}, year {_year}"
|
||||||
|
)
|
||||||
def __post_init__(self):
|
def __post_init__(self):
|
||||||
if isinstance(self._year, str):
|
if isinstance(self._year, str):
|
||||||
self._year = int(self._year)
|
self._year = int(self._year)
|
||||||
@@ -27,7 +29,7 @@ class Semester:
|
|||||||
return self.value
|
return self.value
|
||||||
|
|
||||||
def generateSemester(self):
|
def generateSemester(self):
|
||||||
if self._month < 4 or self._month < 9:
|
if self._month <= 3 or self._month > 9:
|
||||||
self._semester = "WiSe"
|
self._semester = "WiSe"
|
||||||
else:
|
else:
|
||||||
self._semester = "SoSe"
|
self._semester = "SoSe"
|
||||||
@@ -36,11 +38,12 @@ class Semester:
|
|||||||
def computeValue(self):
|
def computeValue(self):
|
||||||
# year is only last two digits
|
# year is only last two digits
|
||||||
year = self._year
|
year = self._year
|
||||||
|
valueyear = str(year)
|
||||||
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)
|
||||||
else:
|
else:
|
||||||
valueyear = str(year)
|
valueyear = str(year) + "/" + str(year + 1)
|
||||||
self.value = f"{self._semester} {valueyear}"
|
self.value = f"{self._semester} {valueyear}"
|
||||||
|
|
||||||
@logger.catch
|
@logger.catch
|
||||||
|
|||||||
@@ -5,13 +5,27 @@ from PyQt6.QtCore import pyqtSignal as Signal
|
|||||||
from src.backend import Database
|
from src.backend import Database
|
||||||
|
|
||||||
from src.logic.webrequest import BibTextTransformer, WebRequest
|
from src.logic.webrequest import BibTextTransformer, WebRequest
|
||||||
|
import sys
|
||||||
|
from loguru import logger as log
|
||||||
|
|
||||||
|
logger = log
|
||||||
|
logger.remove()
|
||||||
|
logger.add("logs/bookgrabber_thread.log", rotation="1 week", enqueue=True)
|
||||||
|
log.add(
|
||||||
|
"logs/application.log",
|
||||||
|
rotation="1 day",
|
||||||
|
compression="zip",
|
||||||
|
)
|
||||||
|
|
||||||
|
# logger.add(sys.stderr, format="{time} {level} {message}", level="INFO")
|
||||||
|
logger.add(sys.stdout)
|
||||||
|
|
||||||
|
|
||||||
class BookGrabber(QThread):
|
class BookGrabber(QThread):
|
||||||
updateSignal = Signal(int, int)
|
updateSignal = Signal(int, int)
|
||||||
done = Signal()
|
done = Signal()
|
||||||
|
|
||||||
def __init__(self, appnr):
|
def __init__(self, appnr: int):
|
||||||
super(BookGrabber, self).__init__(parent=None)
|
super(BookGrabber, self).__init__(parent=None)
|
||||||
self.is_Running = True
|
self.is_Running = True
|
||||||
logger.info("Starting worker thread")
|
logger.info("Starting worker thread")
|
||||||
@@ -25,7 +39,9 @@ class BookGrabber(QThread):
|
|||||||
self.appnr = appnr
|
self.appnr = appnr
|
||||||
self.tstate = (self.app_id, self.prof_id, self.mode, self.data)
|
self.tstate = (self.app_id, self.prof_id, self.mode, self.data)
|
||||||
|
|
||||||
def add_values(self, app_id, prof_id, mode, data, any_book=False, exact=False):
|
def add_values(
|
||||||
|
self, app_id: int, prof_id: int, mode: str, data, any_book=False, exact=False
|
||||||
|
):
|
||||||
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
|
||||||
@@ -85,11 +101,13 @@ class BookGrabber(QThread):
|
|||||||
break
|
break
|
||||||
|
|
||||||
logger.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:
|
print("Added book to database")
|
||||||
|
except Exception as e:
|
||||||
logger.error(f"Failed to update availability: {e}")
|
logger.error(f"Failed to update availability: {e}")
|
||||||
|
print("Failed to update availability: " + str(e))
|
||||||
|
|
||||||
# time.sleep(5)
|
# time.sleep(5)
|
||||||
item += 1
|
item += 1
|
||||||
@@ -102,87 +120,89 @@ class BookGrabber(QThread):
|
|||||||
self.is_Running = False
|
self.is_Running = False
|
||||||
|
|
||||||
|
|
||||||
# class BookGrabber(object):
|
class BookGrabberTest(QThread):
|
||||||
# updateSignal = Signal(int, int)
|
updateSignal = Signal(int, int)
|
||||||
# done = Signal()
|
done = Signal()
|
||||||
|
|
||||||
# def __init__(self, app_id, prof_id, mode, data, parent=None):
|
def __init__(self, appnr: int):
|
||||||
# super(BookGrabber, self).__init__(parent=None)
|
super(BookGrabberTest, self).__init__(parent=None)
|
||||||
# self.is_Running = True
|
self.is_Running = True
|
||||||
# logger = MyLogger("Worker")
|
logger.info("Starting worker thread")
|
||||||
# logger.info("Starting worker thread")
|
self.data = None
|
||||||
# self.data = data
|
self.app_id = None
|
||||||
# logger.info(f"Working on {len(self.data)} entries")
|
self.prof_id = None
|
||||||
# self.app_id = app_id
|
self.mode = None
|
||||||
# self.prof_id = prof_id
|
self.book_id = None
|
||||||
# self.mode = mode
|
self.use_any = False
|
||||||
# self.book_id = None
|
self.use_exact = False
|
||||||
# self.state = (self.app_id, self.prof_id, self.mode, self.data)
|
self.appnr = appnr
|
||||||
# # print(self.state)
|
self.tstate = (self.app_id, self.prof_id, self.mode, self.data)
|
||||||
# logger.info("state: " + str(self.state))
|
self.results = []
|
||||||
# # time.sleep(2)
|
|
||||||
|
|
||||||
# def resetValues(self):
|
def add_values(
|
||||||
# self.app_id = None
|
self, app_id: int, prof_id: int, mode: str, data, any_book=False, exact=False
|
||||||
# self.prof_id = None
|
):
|
||||||
# self.mode = None
|
self.app_id = app_id
|
||||||
# self.data = None
|
self.prof_id = prof_id
|
||||||
# self.book_id = None
|
self.mode = mode
|
||||||
|
self.data = data
|
||||||
|
self.use_any = any_book
|
||||||
|
self.use_exact = exact
|
||||||
|
logger.info(f"Working on {len(self.data)} entries")
|
||||||
|
self.tstate = (self.app_id, self.prof_id, self.mode, self.data)
|
||||||
|
logger.debug("State: " + str(self.tstate))
|
||||||
|
# print(self.tstate)
|
||||||
|
|
||||||
# def run(self):
|
def run(self):
|
||||||
# while self.is_Running:
|
item = 0
|
||||||
# self.db = Database()
|
iterdata = self.data
|
||||||
# item = 0
|
# print(iterdata)
|
||||||
# iterdata = self.data
|
for entry in iterdata:
|
||||||
# # print(iterdata)
|
# print(entry)
|
||||||
# for entry in iterdata:
|
signature = str(entry)
|
||||||
# # print(entry)
|
logger.info("Processing entry: " + signature)
|
||||||
# signature = str(entry)
|
|
||||||
# logger.info("Processing entry: " + signature)
|
|
||||||
|
|
||||||
# webdata = WebRequest().get_ppn(entry).get_data()
|
webdata = WebRequest().set_apparat(self.appnr).get_ppn(entry)
|
||||||
# if webdata == "error":
|
if self.use_any:
|
||||||
# continue
|
webdata = webdata.use_any_book
|
||||||
# bd = BibTextTransformer(self.mode).get_data(webdata).return_data()
|
webdata = webdata.get_data()
|
||||||
# transformer = BibTextTransformer("RDS")
|
|
||||||
# rds = transformer.get_data(webdata).return_data("rds_availability")
|
|
||||||
# bd.signature = entry
|
|
||||||
# # confirm lock is acquired
|
|
||||||
# self.db.addBookToDatabase(bd, self.app_id, self.prof_id)
|
|
||||||
# # get latest book id
|
|
||||||
# self.book_id = self.db.getLastBookId()
|
|
||||||
# logger.info("Added book to database")
|
|
||||||
# state = 0
|
|
||||||
# # print(len(rds.items))
|
|
||||||
# for rds_item in rds.items:
|
|
||||||
# sign = rds_item.superlocation
|
|
||||||
# loc = rds_item.location
|
|
||||||
# # logger.debug(sign, loc)
|
|
||||||
# # logger.debug(rds_item)
|
|
||||||
# if self.app_id in sign or self.app_id in loc:
|
|
||||||
# state = 1
|
|
||||||
# break
|
|
||||||
|
|
||||||
# logger.info(f"State of {signature}: {state}")
|
if webdata == "error":
|
||||||
# # print(
|
continue
|
||||||
# "updating availability of "
|
|
||||||
# + str(self.book_id)
|
|
||||||
# + " to "
|
|
||||||
# + str(state)
|
|
||||||
# )
|
|
||||||
# try:
|
|
||||||
# self.db.setAvailability(self.book_id, state)
|
|
||||||
# except sqlite3.OperationalError as e:
|
|
||||||
# logger.error(f"Failed to update availability: {e}")
|
|
||||||
|
|
||||||
# # time.sleep(5)
|
bd = BibTextTransformer(self.mode)
|
||||||
# item += 1
|
if self.mode == "ARRAY":
|
||||||
# self.updateSignal.emit(item, len(self.data))
|
if self.use_exact:
|
||||||
# logger.info("Worker thread finished")
|
bd = bd.use_signature(entry)
|
||||||
# # self.done.emit()
|
bd = bd.get_data(webdata).return_data()
|
||||||
# self.stop()
|
if bd is None:
|
||||||
# if not self.is_Running:
|
# bd = BookData
|
||||||
# break
|
continue
|
||||||
|
bd.signature = entry
|
||||||
|
transformer = (
|
||||||
|
BibTextTransformer("RDS").get_data(webdata).return_data("rds_data")
|
||||||
|
)
|
||||||
|
|
||||||
# def stop(self):
|
# confirm lock is acquired
|
||||||
# self.is_Running = False
|
# get latest book id
|
||||||
|
logger.info("Added book to database")
|
||||||
|
state = 0
|
||||||
|
for result in transformer.RDS_DATA:
|
||||||
|
# print(result.RDS_LOCATION)
|
||||||
|
if str(self.app_id) in result.RDS_LOCATION:
|
||||||
|
state = 1
|
||||||
|
break
|
||||||
|
|
||||||
|
logger.info(f"State of {signature}: {state}")
|
||||||
|
# print("updating availability of " + str(self.book_id) + " to " + str(state))
|
||||||
|
self.results.append(bd)
|
||||||
|
|
||||||
|
# time.sleep(5)
|
||||||
|
item += 1
|
||||||
|
self.updateSignal.emit(item, len(self.data))
|
||||||
|
logger.info("Worker thread finished")
|
||||||
|
# self.done.emit()
|
||||||
|
self.quit()
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
self.is_Running = False
|
||||||
|
|||||||
@@ -2,5 +2,5 @@ from .dataclass import ApparatData, BookData, Prof, Apparat, ELSA
|
|||||||
from .c_sort import custom_sort, sort_semesters_list
|
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, word_to_semap
|
||||||
from .zotero import ZoteroController
|
from .zotero import ZoteroController
|
||||||
|
|||||||
@@ -1,13 +1,106 @@
|
|||||||
import pandas as pd
|
import pandas as pd
|
||||||
from docx import Document
|
from docx import Document
|
||||||
|
from dataclasses import dataclass
|
||||||
|
import sys
|
||||||
|
from loguru import logger as log
|
||||||
|
|
||||||
|
logger = log
|
||||||
|
logger.remove()
|
||||||
|
logger.add("logs/wordparser.log", rotation="1 week", enqueue=True)
|
||||||
|
log.add(
|
||||||
|
f"logs/application.log",
|
||||||
|
rotation="1 day",
|
||||||
|
compression="zip",
|
||||||
|
enqueue=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
# logger.add(sys.stderr, format="{time} {level} {message}", level="INFO")
|
||||||
|
logger.add(sys.stdout)
|
||||||
|
|
||||||
|
|
||||||
letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
||||||
|
|
||||||
|
|
||||||
def word_docx_to_csv(path) -> pd.DataFrame:
|
@dataclass
|
||||||
|
class Book:
|
||||||
|
author: str = None
|
||||||
|
year: str = None
|
||||||
|
edition: str = None
|
||||||
|
title: str = None
|
||||||
|
location: str = None
|
||||||
|
publisher: str = None
|
||||||
|
signature: str = None
|
||||||
|
internal_notes: str = None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def has_signature(self) -> bool:
|
||||||
|
return self.signature is not None and self.signature != ""
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_empty(self) -> bool:
|
||||||
|
return all(
|
||||||
|
[
|
||||||
|
self.author == "",
|
||||||
|
self.year == "",
|
||||||
|
self.edition == "",
|
||||||
|
self.title == "",
|
||||||
|
self.location == "",
|
||||||
|
self.publisher == "",
|
||||||
|
self.signature == "",
|
||||||
|
self.internal_notes == "",
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
def from_dict(self, data: dict):
|
||||||
|
for key, value in data.items():
|
||||||
|
if value == "\u2002\u2002\u2002\u2002\u2002":
|
||||||
|
value = ""
|
||||||
|
|
||||||
|
if key == "Autorenname(n):Nachname, Vorname":
|
||||||
|
self.author = value
|
||||||
|
elif key == "Jahr/Auflage":
|
||||||
|
self.year = value.split("/")[0] if "/" in value else value
|
||||||
|
self.edition = value.split("/")[1] if "/" in value else ""
|
||||||
|
elif key == "Titel":
|
||||||
|
self.title = value
|
||||||
|
elif key == "Ort und Verlag":
|
||||||
|
self.location = value.split(",")[0] if "," in value else value
|
||||||
|
self.publisher = value.split(",")[1] if "," in value else ""
|
||||||
|
elif key == "Standnummer":
|
||||||
|
self.signature = value
|
||||||
|
elif key == "Interne Vermerke":
|
||||||
|
self.internal_notes = value
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class SemapDocument:
|
||||||
|
subject: str = None
|
||||||
|
phoneNumber: int = None
|
||||||
|
mail: str = None
|
||||||
|
title: str = None
|
||||||
|
semester: str = None
|
||||||
|
books: list[Book] = None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def renameSemester(self) -> None:
|
||||||
|
if self.semester is not None:
|
||||||
|
if "sommersemester" in self.semester.lower():
|
||||||
|
year = self.semester.split(" ")[-1]
|
||||||
|
self.semester = f"SoSe {year}"
|
||||||
|
elif "wintersemester" in self.semester.lower():
|
||||||
|
year = self.semester.split(" ")[-1]
|
||||||
|
self.semester = f"WiSe {year}"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def signatures(self) -> list[str]:
|
||||||
|
if self.books is not None:
|
||||||
|
return [book.signature for book in self.books if book.has_signature]
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
def word_docx_to_csv(path: str) -> list[pd.DataFrame]:
|
||||||
doc = Document(path)
|
doc = Document(path)
|
||||||
tables = doc.tables
|
tables = doc.tables
|
||||||
|
|
||||||
m_data = []
|
m_data = []
|
||||||
for table in tables:
|
for table in tables:
|
||||||
data = []
|
data = []
|
||||||
@@ -24,8 +117,9 @@ def word_docx_to_csv(path) -> pd.DataFrame:
|
|||||||
|
|
||||||
m_data.append(df)
|
m_data.append(df)
|
||||||
|
|
||||||
df = m_data[2]
|
# for df[0, 1]: merge i and i+1 as key, value
|
||||||
return df
|
|
||||||
|
return m_data
|
||||||
|
|
||||||
|
|
||||||
def makeDict():
|
def makeDict():
|
||||||
@@ -122,6 +216,45 @@ def elsa_word_to_csv(path):
|
|||||||
return tuple_to_dict(data, doctype), doctype
|
return tuple_to_dict(data, doctype), doctype
|
||||||
|
|
||||||
|
|
||||||
|
def word_to_semap(word_path: str) -> SemapDocument:
|
||||||
|
logger.info("Parsing Word Document {}", word_path)
|
||||||
|
semap = SemapDocument()
|
||||||
|
df = word_docx_to_csv(word_path)
|
||||||
|
apparatdata = df[0]
|
||||||
|
apparatdata = apparatdata.to_dict()
|
||||||
|
keys = list(apparatdata.keys())
|
||||||
|
appdata = {keys[i]: keys[i + 1] for i in range(0, len(keys), 2)}
|
||||||
|
semap.phoneNumber = appdata["Telefon:"]
|
||||||
|
semap.subject = appdata["Ihr Fach:"]
|
||||||
|
semap.mail = appdata["Mailadresse:"]
|
||||||
|
apparatdata = df[1]
|
||||||
|
apparatdata = apparatdata.to_dict()
|
||||||
|
keys = list(apparatdata.keys())
|
||||||
|
appdata = {keys[i]: keys[i + 1] for i in range(0, len(keys), 2)}
|
||||||
|
semap.title = appdata["Veranstaltung:"]
|
||||||
|
semap.semester = appdata["Semester:"]
|
||||||
|
semap.renameSemester
|
||||||
|
books = df[2]
|
||||||
|
booklist = []
|
||||||
|
for i in range(len(books)):
|
||||||
|
if books.iloc[i].isnull().all():
|
||||||
|
continue
|
||||||
|
data = books.iloc[i].to_dict()
|
||||||
|
book = Book()
|
||||||
|
book.from_dict(data)
|
||||||
|
if book.is_empty:
|
||||||
|
continue
|
||||||
|
elif not book.has_signature:
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
booklist.append(book)
|
||||||
|
logger.info("Found {} books", len(booklist))
|
||||||
|
semap.books = booklist
|
||||||
|
|
||||||
|
return semap
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
else_df = elsa_word_to_csv("C:/Users/aky547/Desktop/Antrag ELSA Schweitzer.docx")
|
else_df = word_to_semap(
|
||||||
# print(else_df)
|
"C:/Users/aky547/Desktop/SA 80 titelmeldung_SoSe2025 Burth.docx"
|
||||||
|
)
|
||||||
|
|||||||
@@ -14,10 +14,7 @@ class Ui_Dialog(object):
|
|||||||
Dialog.setObjectName("Dialog")
|
Dialog.setObjectName("Dialog")
|
||||||
Dialog.setWindowModality(QtCore.Qt.WindowModality.NonModal)
|
Dialog.setWindowModality(QtCore.Qt.WindowModality.NonModal)
|
||||||
Dialog.resize(651, 679)
|
Dialog.resize(651, 679)
|
||||||
sizePolicy = QtWidgets.QSizePolicy(
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.MinimumExpanding, QtWidgets.QSizePolicy.Policy.MinimumExpanding)
|
||||||
QtWidgets.QSizePolicy.Policy.MinimumExpanding,
|
|
||||||
QtWidgets.QSizePolicy.Policy.MinimumExpanding,
|
|
||||||
)
|
|
||||||
sizePolicy.setHorizontalStretch(0)
|
sizePolicy.setHorizontalStretch(0)
|
||||||
sizePolicy.setVerticalStretch(0)
|
sizePolicy.setVerticalStretch(0)
|
||||||
sizePolicy.setHeightForWidth(Dialog.sizePolicy().hasHeightForWidth())
|
sizePolicy.setHeightForWidth(Dialog.sizePolicy().hasHeightForWidth())
|
||||||
@@ -25,10 +22,7 @@ class Ui_Dialog(object):
|
|||||||
self.verticalLayout = QtWidgets.QVBoxLayout(Dialog)
|
self.verticalLayout = QtWidgets.QVBoxLayout(Dialog)
|
||||||
self.verticalLayout.setObjectName("verticalLayout")
|
self.verticalLayout.setObjectName("verticalLayout")
|
||||||
self.toolBox = QtWidgets.QToolBox(parent=Dialog)
|
self.toolBox = QtWidgets.QToolBox(parent=Dialog)
|
||||||
sizePolicy = QtWidgets.QSizePolicy(
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.MinimumExpanding, QtWidgets.QSizePolicy.Policy.MinimumExpanding)
|
||||||
QtWidgets.QSizePolicy.Policy.MinimumExpanding,
|
|
||||||
QtWidgets.QSizePolicy.Policy.MinimumExpanding,
|
|
||||||
)
|
|
||||||
sizePolicy.setHorizontalStretch(0)
|
sizePolicy.setHorizontalStretch(0)
|
||||||
sizePolicy.setVerticalStretch(0)
|
sizePolicy.setVerticalStretch(0)
|
||||||
sizePolicy.setHeightForWidth(self.toolBox.sizePolicy().hasHeightForWidth())
|
sizePolicy.setHeightForWidth(self.toolBox.sizePolicy().hasHeightForWidth())
|
||||||
@@ -37,10 +31,7 @@ class Ui_Dialog(object):
|
|||||||
self.toolBox.setObjectName("toolBox")
|
self.toolBox.setObjectName("toolBox")
|
||||||
self.page_1 = QtWidgets.QWidget()
|
self.page_1 = QtWidgets.QWidget()
|
||||||
self.page_1.setGeometry(QtCore.QRect(0, 0, 633, 511))
|
self.page_1.setGeometry(QtCore.QRect(0, 0, 633, 511))
|
||||||
sizePolicy = QtWidgets.QSizePolicy(
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.MinimumExpanding, QtWidgets.QSizePolicy.Policy.MinimumExpanding)
|
||||||
QtWidgets.QSizePolicy.Policy.MinimumExpanding,
|
|
||||||
QtWidgets.QSizePolicy.Policy.MinimumExpanding,
|
|
||||||
)
|
|
||||||
sizePolicy.setHorizontalStretch(0)
|
sizePolicy.setHorizontalStretch(0)
|
||||||
sizePolicy.setVerticalStretch(0)
|
sizePolicy.setVerticalStretch(0)
|
||||||
sizePolicy.setHeightForWidth(self.page_1.sizePolicy().hasHeightForWidth())
|
sizePolicy.setHeightForWidth(self.page_1.sizePolicy().hasHeightForWidth())
|
||||||
@@ -73,12 +64,7 @@ class Ui_Dialog(object):
|
|||||||
self.save_path = QtWidgets.QLineEdit(parent=self.page_1)
|
self.save_path = QtWidgets.QLineEdit(parent=self.page_1)
|
||||||
self.save_path.setObjectName("save_path")
|
self.save_path.setObjectName("save_path")
|
||||||
self.gridLayout_3.addWidget(self.save_path, 2, 1, 1, 1)
|
self.gridLayout_3.addWidget(self.save_path, 2, 1, 1, 1)
|
||||||
spacerItem = QtWidgets.QSpacerItem(
|
spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Expanding)
|
||||||
20,
|
|
||||||
40,
|
|
||||||
QtWidgets.QSizePolicy.Policy.Minimum,
|
|
||||||
QtWidgets.QSizePolicy.Policy.Expanding,
|
|
||||||
)
|
|
||||||
self.gridLayout_3.addItem(spacerItem, 3, 1, 1, 1)
|
self.gridLayout_3.addItem(spacerItem, 3, 1, 1, 1)
|
||||||
self.toolBox.addItem(self.page_1, "")
|
self.toolBox.addItem(self.page_1, "")
|
||||||
self.page_2 = QtWidgets.QWidget()
|
self.page_2 = QtWidgets.QWidget()
|
||||||
@@ -99,10 +85,7 @@ class Ui_Dialog(object):
|
|||||||
self.label_3.setObjectName("label_3")
|
self.label_3.setObjectName("label_3")
|
||||||
self.gridLayout.addWidget(self.label_3, 1, 0, 1, 1)
|
self.gridLayout.addWidget(self.label_3, 1, 0, 1, 1)
|
||||||
self.zotero_api_key = QtWidgets.QLineEdit(parent=self.page_2)
|
self.zotero_api_key = QtWidgets.QLineEdit(parent=self.page_2)
|
||||||
self.zotero_api_key.setInputMethodHints(
|
self.zotero_api_key.setInputMethodHints(QtCore.Qt.InputMethodHint.ImhHiddenText|QtCore.Qt.InputMethodHint.ImhSensitiveData)
|
||||||
QtCore.Qt.InputMethodHint.ImhHiddenText
|
|
||||||
| QtCore.Qt.InputMethodHint.ImhSensitiveData
|
|
||||||
)
|
|
||||||
self.zotero_api_key.setObjectName("zotero_api_key")
|
self.zotero_api_key.setObjectName("zotero_api_key")
|
||||||
self.gridLayout.addWidget(self.zotero_api_key, 0, 2, 1, 1)
|
self.gridLayout.addWidget(self.zotero_api_key, 0, 2, 1, 1)
|
||||||
self.label_2 = QtWidgets.QLabel(parent=self.page_2)
|
self.label_2 = QtWidgets.QLabel(parent=self.page_2)
|
||||||
@@ -112,12 +95,7 @@ class Ui_Dialog(object):
|
|||||||
self.toggle_api_visibility.setText("")
|
self.toggle_api_visibility.setText("")
|
||||||
self.toggle_api_visibility.setObjectName("toggle_api_visibility")
|
self.toggle_api_visibility.setObjectName("toggle_api_visibility")
|
||||||
self.gridLayout.addWidget(self.toggle_api_visibility, 0, 3, 1, 1)
|
self.gridLayout.addWidget(self.toggle_api_visibility, 0, 3, 1, 1)
|
||||||
spacerItem1 = QtWidgets.QSpacerItem(
|
spacerItem1 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Expanding)
|
||||||
20,
|
|
||||||
40,
|
|
||||||
QtWidgets.QSizePolicy.Policy.Minimum,
|
|
||||||
QtWidgets.QSizePolicy.Policy.Expanding,
|
|
||||||
)
|
|
||||||
self.gridLayout.addItem(spacerItem1, 3, 2, 1, 1)
|
self.gridLayout.addItem(spacerItem1, 3, 2, 1, 1)
|
||||||
self.toolBox.addItem(self.page_2, "")
|
self.toolBox.addItem(self.page_2, "")
|
||||||
self.page_3 = QtWidgets.QWidget()
|
self.page_3 = QtWidgets.QWidget()
|
||||||
@@ -133,67 +111,63 @@ class Ui_Dialog(object):
|
|||||||
self.horizontalLayout_4.setObjectName("horizontalLayout_4")
|
self.horizontalLayout_4.setObjectName("horizontalLayout_4")
|
||||||
self.gridLayout_2 = QtWidgets.QGridLayout()
|
self.gridLayout_2 = QtWidgets.QGridLayout()
|
||||||
self.gridLayout_2.setObjectName("gridLayout_2")
|
self.gridLayout_2.setObjectName("gridLayout_2")
|
||||||
self.smtp_address = QtWidgets.QLineEdit(parent=self.email_settingsPage1_2)
|
self.use_username_smtp_login = QtWidgets.QCheckBox(parent=self.email_settingsPage1_2)
|
||||||
self.smtp_address.setClearButtonEnabled(True)
|
|
||||||
self.smtp_address.setObjectName("smtp_address")
|
|
||||||
self.gridLayout_2.addWidget(self.smtp_address, 0, 1, 1, 1)
|
|
||||||
self.label_8 = QtWidgets.QLabel(parent=self.email_settingsPage1_2)
|
|
||||||
self.label_8.setObjectName("label_8")
|
|
||||||
self.gridLayout_2.addWidget(self.label_8, 3, 0, 1, 1)
|
|
||||||
self.use_username_smtp_login = QtWidgets.QCheckBox(
|
|
||||||
parent=self.email_settingsPage1_2
|
|
||||||
)
|
|
||||||
self.use_username_smtp_login.setTristate(False)
|
self.use_username_smtp_login.setTristate(False)
|
||||||
self.use_username_smtp_login.setObjectName("use_username_smtp_login")
|
self.use_username_smtp_login.setObjectName("use_username_smtp_login")
|
||||||
self.gridLayout_2.addWidget(self.use_username_smtp_login, 4, 1, 1, 1)
|
self.gridLayout_2.addWidget(self.use_username_smtp_login, 4, 1, 1, 1)
|
||||||
|
self.label_6 = QtWidgets.QLabel(parent=self.email_settingsPage1_2)
|
||||||
|
self.label_6.setObjectName("label_6")
|
||||||
|
self.gridLayout_2.addWidget(self.label_6, 1, 0, 1, 1)
|
||||||
|
self.smtp_port = QtWidgets.QLineEdit(parent=self.email_settingsPage1_2)
|
||||||
|
self.smtp_port.setInputMethodHints(QtCore.Qt.InputMethodHint.ImhDigitsOnly|QtCore.Qt.InputMethodHint.ImhPreferNumbers)
|
||||||
|
self.smtp_port.setClearButtonEnabled(True)
|
||||||
|
self.smtp_port.setObjectName("smtp_port")
|
||||||
|
self.gridLayout_2.addWidget(self.smtp_port, 1, 1, 1, 1)
|
||||||
|
self.label_7 = QtWidgets.QLabel(parent=self.email_settingsPage1_2)
|
||||||
|
self.label_7.setObjectName("label_7")
|
||||||
|
self.gridLayout_2.addWidget(self.label_7, 2, 0, 1, 1)
|
||||||
|
self.sender_email = QtWidgets.QLineEdit(parent=self.email_settingsPage1_2)
|
||||||
|
self.sender_email.setInputMethodHints(QtCore.Qt.InputMethodHint.ImhEmailCharactersOnly)
|
||||||
|
self.sender_email.setClearButtonEnabled(True)
|
||||||
|
self.sender_email.setObjectName("sender_email")
|
||||||
|
self.gridLayout_2.addWidget(self.sender_email, 2, 1, 1, 1)
|
||||||
self.mail_username = QtWidgets.QLineEdit(parent=self.email_settingsPage1_2)
|
self.mail_username = QtWidgets.QLineEdit(parent=self.email_settingsPage1_2)
|
||||||
self.mail_username.setClearButtonEnabled(True)
|
self.mail_username.setClearButtonEnabled(True)
|
||||||
self.mail_username.setObjectName("mail_username")
|
self.mail_username.setObjectName("mail_username")
|
||||||
self.gridLayout_2.addWidget(self.mail_username, 3, 1, 1, 1)
|
self.gridLayout_2.addWidget(self.mail_username, 3, 1, 1, 1)
|
||||||
self.smtp_port = QtWidgets.QLineEdit(parent=self.email_settingsPage1_2)
|
|
||||||
self.smtp_port.setInputMethodHints(
|
|
||||||
QtCore.Qt.InputMethodHint.ImhDigitsOnly
|
|
||||||
| QtCore.Qt.InputMethodHint.ImhPreferNumbers
|
|
||||||
)
|
|
||||||
self.smtp_port.setClearButtonEnabled(True)
|
|
||||||
self.smtp_port.setObjectName("smtp_port")
|
|
||||||
self.gridLayout_2.addWidget(self.smtp_port, 1, 1, 1, 1)
|
|
||||||
self.label_10 = QtWidgets.QLabel(parent=self.email_settingsPage1_2)
|
|
||||||
self.label_10.setObjectName("label_10")
|
|
||||||
self.gridLayout_2.addWidget(self.label_10, 5, 0, 1, 1)
|
|
||||||
self.label_7 = QtWidgets.QLabel(parent=self.email_settingsPage1_2)
|
|
||||||
self.label_7.setObjectName("label_7")
|
|
||||||
self.gridLayout_2.addWidget(self.label_7, 2, 0, 1, 1)
|
|
||||||
self.label_9 = QtWidgets.QLabel(parent=self.email_settingsPage1_2)
|
self.label_9 = QtWidgets.QLabel(parent=self.email_settingsPage1_2)
|
||||||
self.label_9.setText("")
|
self.label_9.setText("")
|
||||||
self.label_9.setObjectName("label_9")
|
self.label_9.setObjectName("label_9")
|
||||||
self.gridLayout_2.addWidget(self.label_9, 6, 0, 1, 1)
|
self.gridLayout_2.addWidget(self.label_9, 7, 0, 1, 1)
|
||||||
self.sender_email = QtWidgets.QLineEdit(parent=self.email_settingsPage1_2)
|
|
||||||
self.sender_email.setInputMethodHints(
|
|
||||||
QtCore.Qt.InputMethodHint.ImhEmailCharactersOnly
|
|
||||||
)
|
|
||||||
self.sender_email.setClearButtonEnabled(True)
|
|
||||||
self.sender_email.setObjectName("sender_email")
|
|
||||||
self.gridLayout_2.addWidget(self.sender_email, 2, 1, 1, 1)
|
|
||||||
self.label = QtWidgets.QLabel(parent=self.email_settingsPage1_2)
|
|
||||||
self.label.setObjectName("label")
|
|
||||||
self.gridLayout_2.addWidget(self.label, 0, 0, 1, 1)
|
|
||||||
self.password = QtWidgets.QLineEdit(parent=self.email_settingsPage1_2)
|
self.password = QtWidgets.QLineEdit(parent=self.email_settingsPage1_2)
|
||||||
self.password.setInputMethodHints(
|
self.password.setInputMethodHints(QtCore.Qt.InputMethodHint.ImhHiddenText|QtCore.Qt.InputMethodHint.ImhSensitiveData)
|
||||||
QtCore.Qt.InputMethodHint.ImhHiddenText
|
|
||||||
| QtCore.Qt.InputMethodHint.ImhSensitiveData
|
|
||||||
)
|
|
||||||
self.password.setClearButtonEnabled(True)
|
self.password.setClearButtonEnabled(True)
|
||||||
self.password.setObjectName("password")
|
self.password.setObjectName("password")
|
||||||
self.gridLayout_2.addWidget(self.password, 5, 1, 1, 1)
|
self.gridLayout_2.addWidget(self.password, 5, 1, 1, 1)
|
||||||
self.label_6 = QtWidgets.QLabel(parent=self.email_settingsPage1_2)
|
self.smtp_address = QtWidgets.QLineEdit(parent=self.email_settingsPage1_2)
|
||||||
self.label_6.setObjectName("label_6")
|
self.smtp_address.setClearButtonEnabled(True)
|
||||||
self.gridLayout_2.addWidget(self.label_6, 1, 0, 1, 1)
|
self.smtp_address.setObjectName("smtp_address")
|
||||||
|
self.gridLayout_2.addWidget(self.smtp_address, 0, 1, 1, 1)
|
||||||
|
self.label = QtWidgets.QLabel(parent=self.email_settingsPage1_2)
|
||||||
|
self.label.setObjectName("label")
|
||||||
|
self.gridLayout_2.addWidget(self.label, 0, 0, 1, 1)
|
||||||
|
self.label_10 = QtWidgets.QLabel(parent=self.email_settingsPage1_2)
|
||||||
|
self.label_10.setObjectName("label_10")
|
||||||
|
self.gridLayout_2.addWidget(self.label_10, 5, 0, 1, 1)
|
||||||
self.togglePassword = QtWidgets.QPushButton(parent=self.email_settingsPage1_2)
|
self.togglePassword = QtWidgets.QPushButton(parent=self.email_settingsPage1_2)
|
||||||
self.togglePassword.setFocusPolicy(QtCore.Qt.FocusPolicy.NoFocus)
|
self.togglePassword.setFocusPolicy(QtCore.Qt.FocusPolicy.NoFocus)
|
||||||
self.togglePassword.setText("")
|
self.togglePassword.setText("")
|
||||||
self.togglePassword.setObjectName("togglePassword")
|
self.togglePassword.setObjectName("togglePassword")
|
||||||
self.gridLayout_2.addWidget(self.togglePassword, 5, 2, 1, 1)
|
self.gridLayout_2.addWidget(self.togglePassword, 5, 2, 1, 1)
|
||||||
|
self.label_8 = QtWidgets.QLabel(parent=self.email_settingsPage1_2)
|
||||||
|
self.label_8.setObjectName("label_8")
|
||||||
|
self.gridLayout_2.addWidget(self.label_8, 3, 0, 1, 1)
|
||||||
|
self.label_13 = QtWidgets.QLabel(parent=self.email_settingsPage1_2)
|
||||||
|
self.label_13.setObjectName("label_13")
|
||||||
|
self.gridLayout_2.addWidget(self.label_13, 6, 0, 1, 1)
|
||||||
|
self.printermail = QtWidgets.QLineEdit(parent=self.email_settingsPage1_2)
|
||||||
|
self.printermail.setObjectName("printermail")
|
||||||
|
self.gridLayout_2.addWidget(self.printermail, 6, 1, 1, 1)
|
||||||
self.horizontalLayout_4.addLayout(self.gridLayout_2)
|
self.horizontalLayout_4.addLayout(self.gridLayout_2)
|
||||||
self.email_settings.addTab(self.email_settingsPage1_2, "")
|
self.email_settings.addTab(self.email_settingsPage1_2, "")
|
||||||
self.email_settingsPage2_2 = QtWidgets.QWidget()
|
self.email_settingsPage2_2 = QtWidgets.QWidget()
|
||||||
@@ -204,12 +178,7 @@ class Ui_Dialog(object):
|
|||||||
self.verticalLayout_2.setObjectName("verticalLayout_2")
|
self.verticalLayout_2.setObjectName("verticalLayout_2")
|
||||||
self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
|
self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
|
||||||
self.horizontalLayout_3.setObjectName("horizontalLayout_3")
|
self.horizontalLayout_3.setObjectName("horizontalLayout_3")
|
||||||
spacerItem2 = QtWidgets.QSpacerItem(
|
spacerItem2 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
|
||||||
40,
|
|
||||||
20,
|
|
||||||
QtWidgets.QSizePolicy.Policy.Expanding,
|
|
||||||
QtWidgets.QSizePolicy.Policy.Minimum,
|
|
||||||
)
|
|
||||||
self.horizontalLayout_3.addItem(spacerItem2)
|
self.horizontalLayout_3.addItem(spacerItem2)
|
||||||
self.bold = QtWidgets.QPushButton(parent=self.email_settingsPage2_2)
|
self.bold = QtWidgets.QPushButton(parent=self.email_settingsPage2_2)
|
||||||
self.bold.setCheckable(True)
|
self.bold.setCheckable(True)
|
||||||
@@ -223,12 +192,7 @@ class Ui_Dialog(object):
|
|||||||
self.underscore.setCheckable(True)
|
self.underscore.setCheckable(True)
|
||||||
self.underscore.setObjectName("underscore")
|
self.underscore.setObjectName("underscore")
|
||||||
self.horizontalLayout_3.addWidget(self.underscore)
|
self.horizontalLayout_3.addWidget(self.underscore)
|
||||||
spacerItem3 = QtWidgets.QSpacerItem(
|
spacerItem3 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
|
||||||
40,
|
|
||||||
20,
|
|
||||||
QtWidgets.QSizePolicy.Policy.Expanding,
|
|
||||||
QtWidgets.QSizePolicy.Policy.Minimum,
|
|
||||||
)
|
|
||||||
self.horizontalLayout_3.addItem(spacerItem3)
|
self.horizontalLayout_3.addItem(spacerItem3)
|
||||||
self.verticalLayout_2.addLayout(self.horizontalLayout_3)
|
self.verticalLayout_2.addLayout(self.horizontalLayout_3)
|
||||||
self.horizontalLayout = QtWidgets.QHBoxLayout()
|
self.horizontalLayout = QtWidgets.QHBoxLayout()
|
||||||
@@ -254,12 +218,7 @@ class Ui_Dialog(object):
|
|||||||
self.font_size.addItem("")
|
self.font_size.addItem("")
|
||||||
self.font_size.addItem("")
|
self.font_size.addItem("")
|
||||||
self.horizontalLayout.addWidget(self.font_size)
|
self.horizontalLayout.addWidget(self.font_size)
|
||||||
spacerItem4 = QtWidgets.QSpacerItem(
|
spacerItem4 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
|
||||||
40,
|
|
||||||
20,
|
|
||||||
QtWidgets.QSizePolicy.Policy.Expanding,
|
|
||||||
QtWidgets.QSizePolicy.Policy.Minimum,
|
|
||||||
)
|
|
||||||
self.horizontalLayout.addItem(spacerItem4)
|
self.horizontalLayout.addItem(spacerItem4)
|
||||||
self.verticalLayout_2.addLayout(self.horizontalLayout)
|
self.verticalLayout_2.addLayout(self.horizontalLayout)
|
||||||
self.verticalLayout_3.addLayout(self.verticalLayout_2)
|
self.verticalLayout_3.addLayout(self.verticalLayout_2)
|
||||||
@@ -316,10 +275,7 @@ class Ui_Dialog(object):
|
|||||||
self.verticalLayout.addWidget(self.toolBox)
|
self.verticalLayout.addWidget(self.toolBox)
|
||||||
self.buttonBox = QtWidgets.QDialogButtonBox(parent=Dialog)
|
self.buttonBox = QtWidgets.QDialogButtonBox(parent=Dialog)
|
||||||
self.buttonBox.setOrientation(QtCore.Qt.Orientation.Horizontal)
|
self.buttonBox.setOrientation(QtCore.Qt.Orientation.Horizontal)
|
||||||
self.buttonBox.setStandardButtons(
|
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.StandardButton.Cancel|QtWidgets.QDialogButtonBox.StandardButton.Ok)
|
||||||
QtWidgets.QDialogButtonBox.StandardButton.Cancel
|
|
||||||
| QtWidgets.QDialogButtonBox.StandardButton.Ok
|
|
||||||
)
|
|
||||||
self.buttonBox.setObjectName("buttonBox")
|
self.buttonBox.setObjectName("buttonBox")
|
||||||
self.verticalLayout.addWidget(self.buttonBox)
|
self.verticalLayout.addWidget(self.buttonBox)
|
||||||
self.label_5.setBuddy(self.db_name)
|
self.label_5.setBuddy(self.db_name)
|
||||||
@@ -327,63 +283,39 @@ class Ui_Dialog(object):
|
|||||||
self.label_11.setBuddy(self.db_path)
|
self.label_11.setBuddy(self.db_path)
|
||||||
|
|
||||||
self.retranslateUi(Dialog)
|
self.retranslateUi(Dialog)
|
||||||
self.toolBox.setCurrentIndex(3)
|
self.toolBox.setCurrentIndex(2)
|
||||||
self.email_settings.setCurrentIndex(0)
|
self.email_settings.setCurrentIndex(0)
|
||||||
self.buttonBox.accepted.connect(Dialog.accept) # type: ignore
|
self.buttonBox.accepted.connect(Dialog.accept) # type: ignore
|
||||||
self.buttonBox.rejected.connect(Dialog.reject) # type: ignore
|
self.buttonBox.rejected.connect(Dialog.reject) # type: ignore
|
||||||
QtCore.QMetaObject.connectSlotsByName(Dialog)
|
QtCore.QMetaObject.connectSlotsByName(Dialog)
|
||||||
|
|
||||||
def retranslateUi(self, Dialog):
|
def retranslateUi(self, Dialog):
|
||||||
_translate = QtCore.QCoreApplication.translate
|
_translate = QtCore.QCoreApplication.translate
|
||||||
Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
|
Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
|
||||||
self.db_name.setText(_translate("Dialog", "sap.db"))
|
self.db_name.setText(_translate("Dialog", "sap.db"))
|
||||||
self.label_5.setToolTip(
|
self.label_5.setToolTip(_translate("Dialog", "<html><head/><body><p>Name der Datenbank, welche verwendet werden soll. <span style=\" font-weight:600;\">Muss</span> auf .db enden</p></body></html>"))
|
||||||
_translate(
|
|
||||||
"Dialog",
|
|
||||||
'<html><head/><body><p>Name der Datenbank, welche verwendet werden soll. <span style=" font-weight:600;">Muss</span> auf .db enden</p></body></html>',
|
|
||||||
)
|
|
||||||
)
|
|
||||||
self.label_5.setText(_translate("Dialog", "Datenbankname"))
|
self.label_5.setText(_translate("Dialog", "Datenbankname"))
|
||||||
self.label_12.setToolTip(
|
self.label_12.setToolTip(_translate("Dialog", "Pfad, an dem heruntergeladene Dateien gespeichert werden sollen"))
|
||||||
_translate(
|
|
||||||
"Dialog",
|
|
||||||
"Pfad, an dem heruntergeladene Dateien gespeichert werden sollen",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
self.label_12.setText(_translate("Dialog", "Temporäre Dateien"))
|
self.label_12.setText(_translate("Dialog", "Temporäre Dateien"))
|
||||||
self.label_11.setText(_translate("Dialog", "Datenbankpfad"))
|
self.label_11.setText(_translate("Dialog", "Datenbankpfad"))
|
||||||
self.tb_set_save_path.setText(_translate("Dialog", "..."))
|
self.tb_set_save_path.setText(_translate("Dialog", "..."))
|
||||||
self.tb_select_db.setText(_translate("Dialog", "..."))
|
self.tb_select_db.setText(_translate("Dialog", "..."))
|
||||||
self.toolBox.setItemText(
|
self.toolBox.setItemText(self.toolBox.indexOf(self.page_1), _translate("Dialog", "Datenbank"))
|
||||||
self.toolBox.indexOf(self.page_1), _translate("Dialog", "Datenbank")
|
|
||||||
)
|
|
||||||
self.label_4.setText(_translate("Dialog", "Bibliothekstyp"))
|
self.label_4.setText(_translate("Dialog", "Bibliothekstyp"))
|
||||||
self.label_3.setText(_translate("Dialog", "Bibliotheks-ID"))
|
self.label_3.setText(_translate("Dialog", "Bibliotheks-ID"))
|
||||||
self.label_2.setText(_translate("Dialog", "API Key"))
|
self.label_2.setText(_translate("Dialog", "API Key"))
|
||||||
self.toolBox.setItemText(
|
self.toolBox.setItemText(self.toolBox.indexOf(self.page_2), _translate("Dialog", "Zotero"))
|
||||||
self.toolBox.indexOf(self.page_2), _translate("Dialog", "Zotero")
|
self.use_username_smtp_login.setStatusTip(_translate("Dialog", "Anklicken, wenn Nutzername benötigt wird, um sich beim Server anzumelden"))
|
||||||
)
|
self.use_username_smtp_login.setText(_translate("Dialog", "Nutzername zum\n"
|
||||||
self.label_8.setText(_translate("Dialog", "Nutzername"))
|
" Anmelden verwenden"))
|
||||||
self.use_username_smtp_login.setStatusTip(
|
|
||||||
_translate(
|
|
||||||
"Dialog",
|
|
||||||
"Anklicken, wenn Nutzername benötigt wird, um sich beim Server anzumelden",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
self.use_username_smtp_login.setText(
|
|
||||||
_translate("Dialog", "Nutzername zum\n Anmelden verwenden")
|
|
||||||
)
|
|
||||||
self.mail_username.setStatusTip(
|
|
||||||
_translate("Dialog", "Kürzel, von der Hochschule vergeben, bsp: Aky547")
|
|
||||||
)
|
|
||||||
self.label_10.setText(_translate("Dialog", "Passwort"))
|
|
||||||
self.label_7.setText(_translate("Dialog", "Sender-eMail"))
|
|
||||||
self.label.setText(_translate("Dialog", "SMTP-Server"))
|
|
||||||
self.label_6.setText(_translate("Dialog", "Port"))
|
self.label_6.setText(_translate("Dialog", "Port"))
|
||||||
self.email_settings.setTabText(
|
self.label_7.setText(_translate("Dialog", "Sender-eMail"))
|
||||||
self.email_settings.indexOf(self.email_settingsPage1_2),
|
self.mail_username.setStatusTip(_translate("Dialog", "Kürzel, von der Hochschule vergeben, bsp: Aky547"))
|
||||||
_translate("Dialog", "Allgemeines"),
|
self.label.setText(_translate("Dialog", "SMTP-Server"))
|
||||||
)
|
self.label_10.setText(_translate("Dialog", "Passwort"))
|
||||||
|
self.label_8.setText(_translate("Dialog", "Nutzername"))
|
||||||
|
self.label_13.setText(_translate("Dialog", "Printmail"))
|
||||||
|
self.email_settings.setTabText(self.email_settings.indexOf(self.email_settingsPage1_2), _translate("Dialog", "Allgemeines"))
|
||||||
self.bold.setText(_translate("Dialog", "Fett"))
|
self.bold.setText(_translate("Dialog", "Fett"))
|
||||||
self.italic.setText(_translate("Dialog", "Kursiv"))
|
self.italic.setText(_translate("Dialog", "Kursiv"))
|
||||||
self.underscore.setText(_translate("Dialog", "Unterstrichen"))
|
self.underscore.setText(_translate("Dialog", "Unterstrichen"))
|
||||||
@@ -403,14 +335,7 @@ class Ui_Dialog(object):
|
|||||||
self.font_size.setItemText(13, _translate("Dialog", "48"))
|
self.font_size.setItemText(13, _translate("Dialog", "48"))
|
||||||
self.font_size.setItemText(14, _translate("Dialog", "72"))
|
self.font_size.setItemText(14, _translate("Dialog", "72"))
|
||||||
self.debug.setText(_translate("Dialog", "Debug"))
|
self.debug.setText(_translate("Dialog", "Debug"))
|
||||||
self.email_settings.setTabText(
|
self.email_settings.setTabText(self.email_settings.indexOf(self.email_settingsPage2_2), _translate("Dialog", "Signatur"))
|
||||||
self.email_settings.indexOf(self.email_settingsPage2_2),
|
self.toolBox.setItemText(self.toolBox.indexOf(self.page_3), _translate("Dialog", "e-Mail"))
|
||||||
_translate("Dialog", "Signatur"),
|
|
||||||
)
|
|
||||||
self.toolBox.setItemText(
|
|
||||||
self.toolBox.indexOf(self.page_3), _translate("Dialog", "e-Mail")
|
|
||||||
)
|
|
||||||
self.groupBox.setTitle(_translate("Dialog", "Farben"))
|
self.groupBox.setTitle(_translate("Dialog", "Farben"))
|
||||||
self.toolBox.setItemText(
|
self.toolBox.setItemText(self.toolBox.indexOf(self.page_4), _translate("Dialog", "Icons"))
|
||||||
self.toolBox.indexOf(self.page_4), _translate("Dialog", "Icons")
|
|
||||||
)
|
|
||||||
|
|||||||
@@ -35,7 +35,7 @@
|
|||||||
<set>Qt::ImhNone</set>
|
<set>Qt::ImhNone</set>
|
||||||
</property>
|
</property>
|
||||||
<property name="currentIndex">
|
<property name="currentIndex">
|
||||||
<number>3</number>
|
<number>2</number>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="page_1">
|
<widget class="QWidget" name="page_1">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
@@ -232,20 +232,6 @@
|
|||||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||||
<item>
|
<item>
|
||||||
<layout class="QGridLayout" name="gridLayout_2">
|
<layout class="QGridLayout" name="gridLayout_2">
|
||||||
<item row="0" column="1">
|
|
||||||
<widget class="QLineEdit" name="smtp_address">
|
|
||||||
<property name="clearButtonEnabled">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="0">
|
|
||||||
<widget class="QLabel" name="label_8">
|
|
||||||
<property name="text">
|
|
||||||
<string>Nutzername</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="1">
|
<item row="4" column="1">
|
||||||
<widget class="QCheckBox" name="use_username_smtp_login">
|
<widget class="QCheckBox" name="use_username_smtp_login">
|
||||||
<property name="statusTip">
|
<property name="statusTip">
|
||||||
@@ -260,13 +246,10 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="1">
|
<item row="1" column="0">
|
||||||
<widget class="QLineEdit" name="mail_username">
|
<widget class="QLabel" name="label_6">
|
||||||
<property name="statusTip">
|
<property name="text">
|
||||||
<string>Kürzel, von der Hochschule vergeben, bsp: Aky547</string>
|
<string>Port</string>
|
||||||
</property>
|
|
||||||
<property name="clearButtonEnabled">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@@ -280,13 +263,6 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="0">
|
|
||||||
<widget class="QLabel" name="label_10">
|
|
||||||
<property name="text">
|
|
||||||
<string>Passwort</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0">
|
<item row="2" column="0">
|
||||||
<widget class="QLabel" name="label_7">
|
<widget class="QLabel" name="label_7">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@@ -294,13 +270,6 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="6" column="0">
|
|
||||||
<widget class="QLabel" name="label_9">
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="1">
|
<item row="2" column="1">
|
||||||
<widget class="QLineEdit" name="sender_email">
|
<widget class="QLineEdit" name="sender_email">
|
||||||
<property name="inputMethodHints">
|
<property name="inputMethodHints">
|
||||||
@@ -311,10 +280,20 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="0">
|
<item row="3" column="1">
|
||||||
<widget class="QLabel" name="label">
|
<widget class="QLineEdit" name="mail_username">
|
||||||
|
<property name="statusTip">
|
||||||
|
<string>Kürzel, von der Hochschule vergeben, bsp: Aky547</string>
|
||||||
|
</property>
|
||||||
|
<property name="clearButtonEnabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="7" column="0">
|
||||||
|
<widget class="QLabel" name="label_9">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>SMTP-Server</string>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@@ -328,10 +307,24 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0">
|
<item row="0" column="1">
|
||||||
<widget class="QLabel" name="label_6">
|
<widget class="QLineEdit" name="smtp_address">
|
||||||
|
<property name="clearButtonEnabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Port</string>
|
<string>SMTP-Server</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="0">
|
||||||
|
<widget class="QLabel" name="label_10">
|
||||||
|
<property name="text">
|
||||||
|
<string>Passwort</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@@ -345,6 +338,23 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QLabel" name="label_8">
|
||||||
|
<property name="text">
|
||||||
|
<string>Nutzername</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="6" column="0">
|
||||||
|
<widget class="QLabel" name="label_13">
|
||||||
|
<property name="text">
|
||||||
|
<string>Printmail</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="6" column="1">
|
||||||
|
<widget class="QLineEdit" name="printermail"/>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
|||||||
@@ -78,6 +78,8 @@ class Settings(QtWidgets.QDialog, _settings):
|
|||||||
self.sender_email.setText(settings.mail.sender)
|
self.sender_email.setText(settings.mail.sender)
|
||||||
self.mail_username.setText(settings.mail.user_name)
|
self.mail_username.setText(settings.mail.user_name)
|
||||||
self.password.setText(settings.mail.password)
|
self.password.setText(settings.mail.password)
|
||||||
|
self.printermail.setText(settings.mail.printer_mail)
|
||||||
|
self.printermail.setPlaceholderText("E-Mail-Adresse des Druckers")
|
||||||
self.use_username_smtp_login.setChecked(
|
self.use_username_smtp_login.setChecked(
|
||||||
settings.mail.use_user_name if settings.mail.use_user_name else False
|
settings.mail.use_user_name if settings.mail.use_user_name else False
|
||||||
)
|
)
|
||||||
@@ -200,6 +202,7 @@ class Settings(QtWidgets.QDialog, _settings):
|
|||||||
settings.set_mail_attr(
|
settings.set_mail_attr(
|
||||||
"use_user_name", self.use_username_smtp_login.isChecked()
|
"use_user_name", self.use_username_smtp_login.isChecked()
|
||||||
)
|
)
|
||||||
|
settings.set_mail_attr("printer_mail", self.printermail.text())
|
||||||
settings.set_mail_attr("signature", signature)
|
settings.set_mail_attr("signature", signature)
|
||||||
settings.set_zotero_attr("api_key", self.zotero_api_key.text())
|
settings.set_zotero_attr("api_key", self.zotero_api_key.text())
|
||||||
settings.set_zotero_attr("library_id", self.zotero_library_id.text())
|
settings.set_zotero_attr("library_id", self.zotero_library_id.text())
|
||||||
|
|||||||
@@ -6,13 +6,13 @@ import sys
|
|||||||
import tempfile
|
import tempfile
|
||||||
import webbrowser
|
import webbrowser
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from typing import Any
|
||||||
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, logger
|
from src import Icon, settings
|
||||||
from src.backend import Database, BookGrabber, AvailChecker, DocumentationThread
|
from src.backend import Database, BookGrabber, AvailChecker, DocumentationThread
|
||||||
from src.backend.semester import Semester
|
from src.backend.semester import Semester
|
||||||
from src.backend.create_file import recreateFile
|
from src.backend.create_file import recreateFile
|
||||||
@@ -24,7 +24,7 @@ from src.logic import (
|
|||||||
ApparatData,
|
ApparatData,
|
||||||
BookData,
|
BookData,
|
||||||
csv_to_list,
|
csv_to_list,
|
||||||
word_docx_to_csv,
|
word_to_semap,
|
||||||
Prof,
|
Prof,
|
||||||
Apparat,
|
Apparat,
|
||||||
)
|
)
|
||||||
@@ -51,64 +51,79 @@ from src.ui.widgets import (
|
|||||||
EditProf,
|
EditProf,
|
||||||
)
|
)
|
||||||
from src.utils import SemesterDocument
|
from src.utils import SemesterDocument
|
||||||
|
from datetime import datetime
|
||||||
|
from loguru import logger as log
|
||||||
|
|
||||||
|
logger = log
|
||||||
|
logger.remove()
|
||||||
|
logger.add("logs/application.log", rotation="1 week", enqueue=True)
|
||||||
|
log.add(
|
||||||
|
f"logs/{datetime.now().strftime('%Y-%m-%d')}.log",
|
||||||
|
rotation="1 day",
|
||||||
|
compression="zip",
|
||||||
|
)
|
||||||
|
|
||||||
|
# logger.add(sys.stderr, format="{time} {level} {message}", level="INFO")
|
||||||
|
logger.add(sys.stdout)
|
||||||
|
|
||||||
|
|
||||||
valid_input = (0, 0, 0, 0, 0, 0)
|
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: # type:ignore
|
||||||
logger.info("Starting Semesterapparatsmanagement")
|
logger.info("Starting Semesterapparatsmanagement")
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.active_user = username
|
self.active_user = username
|
||||||
self.setupUi(MainWindow)
|
self.setupUi(MainWindow) # type:ignore
|
||||||
self.MainWindow = MainWindow
|
self.MainWindow = MainWindow # type:ignore
|
||||||
# set the window title
|
# set the window title
|
||||||
MainWindow.setWindowTitle("Semesterapparatsmanagement")
|
MainWindow.setWindowTitle("Semesterapparatsmanagement") # type:ignore
|
||||||
MainWindow.setWindowIcon(Icon("logo").icon)
|
MainWindow.setWindowIcon(Icon("logo").icon) # type:ignore
|
||||||
|
|
||||||
self.db = Database()
|
self.db = Database()
|
||||||
self.btn_add_document.clicked.connect(self.add_document)
|
self.btn_add_document.clicked.connect(self.add_document) # type:ignore
|
||||||
self.check_file.clicked.connect(
|
self.check_file.clicked.connect( # type:ignore
|
||||||
self.btn_check_file_threaded
|
self.btn_check_file_threaded
|
||||||
) # default: self.add_media_from_file
|
) # default: self.add_media_from_file
|
||||||
self.create_new_app.clicked.connect(self.btn_create_new_apparat)
|
self.create_new_app.clicked.connect(self.btn_create_new_apparat) # type:ignore
|
||||||
self.btn_apparat_save.clicked.connect(lambda: self.btn_save_apparat(True))
|
self.btn_apparat_save.clicked.connect(lambda: self.btn_save_apparat(True)) # type:ignore
|
||||||
self.btn_apparat_apply.clicked.connect(self.update_apparat)
|
self.btn_apparat_apply.clicked.connect(self.update_apparat) # type:ignore
|
||||||
self.btn_open_document.clicked.connect(self.open_document)
|
self.btn_open_document.clicked.connect(self.open_document) # type:ignore
|
||||||
self.add_medium.clicked.connect(self.btn_add_medium)
|
self.add_medium.clicked.connect(self.btn_add_medium) # type:ignore
|
||||||
self.btn_copy_adis_command.clicked.connect(self.text_to_clipboard)
|
self.btn_copy_adis_command.clicked.connect(self.text_to_clipboard) # type:ignore
|
||||||
self.btn_reserve.clicked.connect(self.check_availability)
|
self.btn_reserve.clicked.connect(self.check_availability) # type:ignore
|
||||||
self.create_document.clicked.connect(self.create_doc)
|
self.create_document.clicked.connect(self.create_doc) # type:ignore
|
||||||
self.calendarWidget = MessageCalendar(self.calendar_frame)
|
self.calendarWidget = MessageCalendar(self.calendar_frame)
|
||||||
self.calendarWidget.setGridVisible(True)
|
self.calendarWidget.setGridVisible(True)
|
||||||
self.calendarWidget.setVerticalHeaderFormat(
|
self.calendarWidget.setVerticalHeaderFormat(
|
||||||
QtWidgets.QCalendarWidget.VerticalHeaderFormat.NoVerticalHeader
|
QtWidgets.QCalendarWidget.VerticalHeaderFormat.NoVerticalHeader
|
||||||
)
|
)
|
||||||
self.calendarWidget.setObjectName("MessageCalendar")
|
self.calendarWidget.setObjectName("MessageCalendar")
|
||||||
self.calendarWidget.clicked.connect(self.open_reminder)
|
self.calendarWidget.clicked.connect(self.open_reminder) # type:ignore
|
||||||
# assign a context menu to the calendar
|
# assign a context menu to the calendar
|
||||||
self.calendarlayout.addWidget(self.calendarWidget)
|
self.calendarlayout.addWidget(self.calendarWidget)
|
||||||
self.tableWidget_apparat_media.horizontalHeader().setSectionResizeMode(
|
self.tableWidget_apparat_media.horizontalHeader().setSectionResizeMode( # type:ignore
|
||||||
QtWidgets.QHeaderView.ResizeMode.Stretch
|
QtWidgets.QHeaderView.ResizeMode.Stretch
|
||||||
)
|
)
|
||||||
self.tableWidget_apparate.horizontalHeader().setSectionResizeMode(
|
self.tableWidget_apparate.horizontalHeader().setSectionResizeMode( # type:ignore
|
||||||
QtWidgets.QHeaderView.ResizeMode.Stretch
|
QtWidgets.QHeaderView.ResizeMode.Stretch
|
||||||
)
|
)
|
||||||
self.tableWidget_apparate.setSortingEnabled(True)
|
self.tableWidget_apparate.setSortingEnabled(True)
|
||||||
self.saveandcreate.hide()
|
self.saveandcreate.hide()
|
||||||
|
|
||||||
# Actions
|
# Actions
|
||||||
self.actionEinstellungen.triggered.connect(self.open_settings)
|
self.actionEinstellungen.triggered.connect(self.open_settings) # type:ignore
|
||||||
Icon("settings", self.actionEinstellungen)
|
Icon("settings", self.actionEinstellungen)
|
||||||
self.actionDokumentation_lokal.triggered.connect(self.open_documentation)
|
self.actionDokumentation_lokal.triggered.connect(self.open_documentation) # type:ignore
|
||||||
Icon("offAction", self.actionBeenden)
|
Icon("offAction", self.actionBeenden)
|
||||||
self.actionBeenden.triggered.connect(self.quit)
|
self.actionBeenden.triggered.connect(self.quit) # type:ignore
|
||||||
self.actionAbout.triggered.connect(self.open_about)
|
self.actionAbout.triggered.connect(self.open_about) # type:ignore
|
||||||
|
|
||||||
# set validators
|
# set validators
|
||||||
self.sem_sommer.clicked.connect(lambda: self.toggleButton(self.sem_winter))
|
self.sem_sommer.clicked.connect(lambda: self.toggleButton(self.sem_winter)) # type:ignore
|
||||||
self.sem_winter.clicked.connect(lambda: self.toggleButton(self.sem_sommer))
|
self.sem_winter.clicked.connect(lambda: self.toggleButton(self.sem_sommer)) # type:ignore
|
||||||
self.sem_year.setText(str(QtCore.QDate.currentDate().year()))
|
self.sem_year.setText(str(QtCore.QDate.currentDate().year()))
|
||||||
self.prof_mail.setValidator(
|
self.prof_mail.setValidator(
|
||||||
QRegularExpressionValidator(
|
QRegularExpressionValidator(
|
||||||
@@ -137,7 +152,7 @@ class Ui(Ui_Semesterapparat):
|
|||||||
self.tableWidget_apparate.addScrollBarWidget(
|
self.tableWidget_apparate.addScrollBarWidget(
|
||||||
QtWidgets.QScrollBar(), QtCore.Qt.AlignmentFlag.AlignRight
|
QtWidgets.QScrollBar(), QtCore.Qt.AlignmentFlag.AlignRight
|
||||||
)
|
)
|
||||||
self.tableWidget_apparate.doubleClicked.connect(self.load_app_data)
|
self.tableWidget_apparate.doubleClicked.connect(self.load_app_data) # type:ignore
|
||||||
|
|
||||||
# #print(f"user:{self.active_user}")
|
# #print(f"user:{self.active_user}")
|
||||||
userrole = self.db.getRole(self.active_user)
|
userrole = self.db.getRole(self.active_user)
|
||||||
@@ -150,18 +165,18 @@ class Ui(Ui_Semesterapparat):
|
|||||||
self.populate_prof_dropdown()
|
self.populate_prof_dropdown()
|
||||||
self.populate_appfach_dropdown()
|
self.populate_appfach_dropdown()
|
||||||
# if the focus is changed from the prof name dropdown, set the prof data if the prof exists in the database, otherwise show a message
|
# if the focus is changed from the prof name dropdown, set the prof data if the prof exists in the database, otherwise show a message
|
||||||
self.drpdwn_prof_name.currentIndexChanged.connect(self.set_prof_data)
|
self.drpdwn_prof_name.currentIndexChanged.connect(self.set_prof_data) # type:ignore
|
||||||
self.cancel_active_selection.clicked.connect(self.btn_cancel_active_selection)
|
self.cancel_active_selection.clicked.connect(self.btn_cancel_active_selection) # type:ignore
|
||||||
self.check_eternal_app.stateChanged.connect(self.set_state)
|
self.check_eternal_app.stateChanged.connect(self.set_state) # type:ignore
|
||||||
# validate inputs
|
# validate inputs
|
||||||
self.prof_mail.textChanged.connect(self.validate_prof_mail)
|
self.prof_mail.textChanged.connect(self.validate_prof_mail) # type:ignore
|
||||||
self.drpdwn_prof_name.editTextChanged.connect(self.validate_prof_name)
|
self.drpdwn_prof_name.editTextChanged.connect(self.validate_prof_name) # type:ignore
|
||||||
self.prof_tel_nr.textChanged.connect(self.validate_prof_tel)
|
self.prof_tel_nr.textChanged.connect(self.validate_prof_tel) # type:ignore
|
||||||
self.app_name.textChanged.connect(self.validate_app_name)
|
self.app_name.textChanged.connect(self.validate_app_name) # type:ignore
|
||||||
self.app_fach.currentTextChanged.connect(self.validate_app_fach)
|
self.app_fach.currentTextChanged.connect(self.validate_app_fach) # type:ignore
|
||||||
self.sem_year.textChanged.connect(self.validate_semester)
|
self.sem_year.textChanged.connect(self.validate_semester) # type:ignore
|
||||||
self.check_eternal_app.stateChanged.connect(self.validate_semester)
|
self.check_eternal_app.stateChanged.connect(self.validate_semester) # type:ignore
|
||||||
self.chkbx_show_del_media.stateChanged.connect(self.update_app_media_list)
|
self.chkbx_show_del_media.stateChanged.connect(self.update_app_media_list) # type:ignore
|
||||||
self.progress_label.setText("Bitte warten...")
|
self.progress_label.setText("Bitte warten...")
|
||||||
|
|
||||||
# Set visibility/enabled state of certain entries
|
# Set visibility/enabled state of certain entries
|
||||||
@@ -178,16 +193,16 @@ class Ui(Ui_Semesterapparat):
|
|||||||
self.automation_add_selected_books.hide()
|
self.automation_add_selected_books.hide()
|
||||||
# self.btn_del_select_apparats.setEnabled(False)
|
# self.btn_del_select_apparats.setEnabled(False)
|
||||||
|
|
||||||
self.tabWidget.currentChanged.connect(self.tabW1_changed)
|
self.tabWidget.currentChanged.connect(self.tabW1_changed) # type:ignore
|
||||||
|
|
||||||
# create a thread, that continually checks the validity of the inputs
|
# create a thread, that continually checks the validity of the inputs
|
||||||
self.validate_thread = QThread()
|
self.validate_thread = QThread()
|
||||||
self.validate_thread.started.connect(self.thread_check)
|
self.validate_thread.started.connect(self.thread_check) # type:ignore
|
||||||
self.validate_thread.start()
|
self.validate_thread.start()
|
||||||
self.add_medium.setEnabled(False)
|
self.add_medium.setEnabled(False)
|
||||||
self.docu = DocumentationThread()
|
self.docu = DocumentationThread()
|
||||||
self.docu.start()
|
self.docu.start()
|
||||||
self.actionDokumentation_lokal.triggered.connect(self.open_documentation)
|
self.actionDokumentation_lokal.triggered.connect(self.open_documentation) # type:ignore
|
||||||
|
|
||||||
# get all current apparats and cache them in a list
|
# get all current apparats and cache them in a list
|
||||||
self.apparats = self.get_apparats()
|
self.apparats = self.get_apparats()
|
||||||
@@ -203,15 +218,15 @@ class Ui(Ui_Semesterapparat):
|
|||||||
self.tableWidget_apparat_media.setContextMenuPolicy(
|
self.tableWidget_apparat_media.setContextMenuPolicy(
|
||||||
QtCore.Qt.ContextMenuPolicy.CustomContextMenu
|
QtCore.Qt.ContextMenuPolicy.CustomContextMenu
|
||||||
)
|
)
|
||||||
self.tableWidget_apparate.customContextMenuRequested.connect(
|
self.tableWidget_apparate.customContextMenuRequested.connect( # type:ignore
|
||||||
self.open_context_menu
|
self.open_context_menu # type:ignore
|
||||||
)
|
)
|
||||||
self.tableWidget_apparat_media.customContextMenuRequested.connect(
|
self.tableWidget_apparat_media.customContextMenuRequested.connect( # type:ignore
|
||||||
self.media_context_menu
|
self.media_context_menu # type:ignore
|
||||||
)
|
)
|
||||||
|
|
||||||
# admin buttons
|
# admin buttons
|
||||||
self.select_action_box.currentTextChanged.connect(self.adminActions)
|
self.select_action_box.currentTextChanged.connect(self.adminActions) # type:ignore
|
||||||
self.select_action_box.addItem("")
|
self.select_action_box.addItem("")
|
||||||
self.select_action_box.setCurrentText("")
|
self.select_action_box.setCurrentText("")
|
||||||
self.admin_action.setLayout(QtWidgets.QVBoxLayout())
|
self.admin_action.setLayout(QtWidgets.QVBoxLayout())
|
||||||
@@ -241,7 +256,8 @@ class Ui(Ui_Semesterapparat):
|
|||||||
"Mit dem Klick auf Okay wird eine Übersicht aller aktiven Semesterapparate erstellt und an den FollowME Drucker gesendet. Es kann bis zu 10 Minuten dauern, bis das document im Drucker angezeigt wird",
|
"Mit dem Klick auf Okay wird eine Übersicht aller aktiven Semesterapparate erstellt und an den FollowME Drucker gesendet. Es kann bis zu 10 Minuten dauern, bis das document im Drucker angezeigt wird",
|
||||||
"document erstellen?",
|
"document erstellen?",
|
||||||
)
|
)
|
||||||
if result == QtWidgets.QDialog.DialogCode.Accepted:
|
logger.debug(f"Result: {result}")
|
||||||
|
if result == 1:
|
||||||
# print("Creating document")
|
# print("Creating document")
|
||||||
apparats = self.apparats
|
apparats = self.apparats
|
||||||
apps = []
|
apps = []
|
||||||
@@ -250,15 +266,19 @@ class Ui(Ui_Semesterapparat):
|
|||||||
data = (apparat[4], f"{prof.lastname} ({apparat[1]})")
|
data = (apparat[4], f"{prof.lastname} ({apparat[1]})")
|
||||||
apps.append(data)
|
apps.append(data)
|
||||||
# print(apps)
|
# print(apps)
|
||||||
|
logger.info("Using apparats: {}", apps)
|
||||||
doc = SemesterDocument(
|
doc = SemesterDocument(
|
||||||
semester=Semester(),
|
semester=Semester().value,
|
||||||
filename="Semesterapparate",
|
filename="Semesterapparate",
|
||||||
apparats=apps,
|
apparats=apps,
|
||||||
|
full=True,
|
||||||
|
config=settings,
|
||||||
)
|
)
|
||||||
doc.make_document()
|
# doc.make_document()
|
||||||
doc.create_pdf()
|
# doc.create_pdf()
|
||||||
doc.print_document()
|
# doc.print_document()
|
||||||
doc.cleanup()
|
# doc.cleanup()
|
||||||
|
# logger.info("Document created and sent to printer")
|
||||||
|
|
||||||
# kill thread after execution done
|
# kill thread after execution done
|
||||||
|
|
||||||
@@ -758,7 +778,6 @@ class Ui(Ui_Semesterapparat):
|
|||||||
return
|
return
|
||||||
|
|
||||||
def check_availability(self):
|
def check_availability(self):
|
||||||
|
|
||||||
def _update_progress(current, all_titles):
|
def _update_progress(current, all_titles):
|
||||||
self.avail_status.setText("{}/{}".format(current, all_titles))
|
self.avail_status.setText("{}/{}".format(current, all_titles))
|
||||||
|
|
||||||
@@ -906,7 +925,7 @@ class Ui(Ui_Semesterapparat):
|
|||||||
).setToolTip("Das Medium wurde nicht im Apparat gefunden")
|
).setToolTip("Das Medium wurde nicht im Apparat gefunden")
|
||||||
|
|
||||||
# make table link clickable
|
# make table link clickable
|
||||||
#self.tableWidget_apparat_media.itemClicked.connect(self.open_link)
|
# self.tableWidget_apparat_media.itemClicked.connect(self.open_link)
|
||||||
# self.tableWidget_apparat_media.
|
# self.tableWidget_apparat_media.
|
||||||
|
|
||||||
def open_link(self, item):
|
def open_link(self, item):
|
||||||
@@ -926,7 +945,7 @@ class Ui(Ui_Semesterapparat):
|
|||||||
link = __openLink(item.text())
|
link = __openLink(item.text())
|
||||||
if link is not None:
|
if link is not None:
|
||||||
webbrowser.open(link)
|
webbrowser.open(link)
|
||||||
#os.system("start " + link)
|
# os.system("start " + link)
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
pass
|
pass
|
||||||
@@ -999,11 +1018,11 @@ 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)
|
||||||
|
|
||||||
def __open_dialog(signatures):
|
def __open_dialog(signatures: list[str]):
|
||||||
dialog = QtWidgets.QDialog()
|
dialog = QtWidgets.QDialog()
|
||||||
frame = parsed_titles_ui()
|
frame = parsed_titles_ui()
|
||||||
frame.setupUi(dialog)
|
frame.setupUi(dialog)
|
||||||
dialog.show()
|
dialogger.show()
|
||||||
frame.signatures = signatures
|
frame.signatures = signatures
|
||||||
frame.populate_table()
|
frame.populate_table()
|
||||||
frame.progressBar.setMaximum(len(signatures))
|
frame.progressBar.setMaximum(len(signatures))
|
||||||
@@ -1064,12 +1083,8 @@ class Ui(Ui_Semesterapparat):
|
|||||||
bookdata=book, app_id=app_id, prof_id=prof_id
|
bookdata=book, app_id=app_id, prof_id=prof_id
|
||||||
)
|
)
|
||||||
if file_type == "docx":
|
if file_type == "docx":
|
||||||
data = word_docx_to_csv(file)
|
data = word_to_semap(file)
|
||||||
signatures = [
|
signatures = data.signatures
|
||||||
i
|
|
||||||
for i in data["Standnummer"].values
|
|
||||||
if i != "\u2002\u2002\u2002\u2002\u2002"
|
|
||||||
]
|
|
||||||
data = __open_dialog(signatures)
|
data = __open_dialog(signatures)
|
||||||
# if no data was returned, return
|
# if no data was returned, return
|
||||||
if data == []:
|
if data == []:
|
||||||
@@ -1100,21 +1115,20 @@ class Ui(Ui_Semesterapparat):
|
|||||||
# if app_id not in database, create apparat
|
# if app_id not in database, create apparat
|
||||||
created = False
|
created = False
|
||||||
if not self.db.checkApparatExistsById(app_id):
|
if not self.db.checkApparatExistsById(app_id):
|
||||||
|
logger.info("Apparat does not exist, creating new apparat")
|
||||||
# create apparat
|
# create apparat
|
||||||
# #print("Creating apparat")
|
# #print("Creating apparat")
|
||||||
if not self.btn_save_apparat(False):
|
if not self.btn_save_apparat(False):
|
||||||
return
|
return
|
||||||
created = True
|
created = True
|
||||||
if self.document_list.rowCount() == 0:
|
if self.document_list.rowCount() == 0:
|
||||||
# #print("No file selected")
|
logger.info("No file selected")
|
||||||
self.tableWidget_apparate.setEnabled(True)
|
self.tableWidget_apparate.setEnabled(True)
|
||||||
self.tableWidget_apparate.setToolTip("")
|
self.tableWidget_apparate.setToolTip("")
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
# if file is selected, check for books in the file
|
# if file is selected, check for books in the file
|
||||||
# #print("File selected")
|
# #print("File selected")
|
||||||
file = self.document_list.item(self.document_list.currentRow(), 3).text()
|
|
||||||
|
|
||||||
file_type = self.document_list.item(
|
file_type = self.document_list.item(
|
||||||
self.document_list.currentRow(), 1
|
self.document_list.currentRow(), 1
|
||||||
).text()
|
).text()
|
||||||
@@ -1124,10 +1138,15 @@ class Ui(Ui_Semesterapparat):
|
|||||||
file_name = self.document_list.item(
|
file_name = self.document_list.item(
|
||||||
self.document_list.currentRow(), 0
|
self.document_list.currentRow(), 0
|
||||||
).text()
|
).text()
|
||||||
|
logger.info("File selected: {}, {}", file_name, file_location)
|
||||||
if file_location == "Database":
|
if file_location == "Database":
|
||||||
|
logger.debug("Using file from database")
|
||||||
file = recreateFile(file_name, app_id, file_type, open=False)
|
file = recreateFile(file_name, app_id, file_type, open=False)
|
||||||
|
logger.debug("recreated file from database")
|
||||||
else:
|
else:
|
||||||
|
logger.debug("File not in database")
|
||||||
if not created:
|
if not created:
|
||||||
|
logger.debug("File was not created, ")
|
||||||
self.add_files(prof_id)
|
self.add_files(prof_id)
|
||||||
if file_type == "pdf":
|
if file_type == "pdf":
|
||||||
# Todo: implement parser here
|
# Todo: implement parser here
|
||||||
@@ -1139,16 +1158,11 @@ class Ui(Ui_Semesterapparat):
|
|||||||
signatures = csv_to_list(file)
|
signatures = csv_to_list(file)
|
||||||
# add the data to the database
|
# add the data to the database
|
||||||
if file_type == "docx":
|
if file_type == "docx":
|
||||||
data = word_docx_to_csv(file)
|
data = word_to_semap(file)
|
||||||
signatures = [
|
logger.info("Converted data from semap file")
|
||||||
i
|
logger.debug("Got the data: {}", data)
|
||||||
for i in data["Standnummer"].values
|
signatures = data.signatures
|
||||||
if i != "\u2002\u2002\u2002\u2002\u2002"
|
logger.info("Got the signatures: {}", signatures)
|
||||||
]
|
|
||||||
|
|
||||||
signatures = [i for i in signatures if i != ""]
|
|
||||||
# logger.debug(signatures)
|
|
||||||
# #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)
|
||||||
|
|
||||||
@@ -1171,6 +1185,8 @@ class Ui(Ui_Semesterapparat):
|
|||||||
autoGrabber.start()
|
autoGrabber.start()
|
||||||
while autoGrabber.isRunning():
|
while autoGrabber.isRunning():
|
||||||
QtWidgets.QApplication.processEvents()
|
QtWidgets.QApplication.processEvents()
|
||||||
|
# refresh book table
|
||||||
|
self.update_app_media_list()
|
||||||
# end of thread
|
# end of thread
|
||||||
# self.autoGrabber.exit()
|
# self.autoGrabber.exit()
|
||||||
# self.__clear_fields()
|
# self.__clear_fields()
|
||||||
@@ -1276,7 +1292,15 @@ class Ui(Ui_Semesterapparat):
|
|||||||
}
|
}
|
||||||
|
|
||||||
def add_files(self, prof_id=None):
|
def add_files(self, prof_id=None):
|
||||||
files = []
|
"""
|
||||||
|
Add Files to the associated prof in the database
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
prof_id : int, optional
|
||||||
|
The ID associated to the prof, by default None
|
||||||
|
"""
|
||||||
|
files: list[dict[str, Any]] = []
|
||||||
for i in range(self.document_list.rowCount()):
|
for i in range(self.document_list.rowCount()):
|
||||||
files.append(
|
files.append(
|
||||||
{
|
{
|
||||||
@@ -1372,7 +1396,7 @@ class Ui(Ui_Semesterapparat):
|
|||||||
reminder.exec()
|
reminder.exec()
|
||||||
tableposition = self.tableWidget_apparate.currentRow()
|
tableposition = self.tableWidget_apparate.currentRow()
|
||||||
appnr = self.tableWidget_apparate.item(tableposition, 0).text()
|
appnr = self.tableWidget_apparate.item(tableposition, 0).text()
|
||||||
if reminder.result() == QtWidgets.QDialog.DialogCode.Accepted:
|
if reminder.result() == QtWidgets.QDialogger.DialogCode.Accepted:
|
||||||
data = reminder.return_message()
|
data = reminder.return_message()
|
||||||
# #print(data)
|
# #print(data)
|
||||||
self.db.addMessage(
|
self.db.addMessage(
|
||||||
@@ -1402,14 +1426,16 @@ class Ui(Ui_Semesterapparat):
|
|||||||
dialog = CalendarEntry(messages=messages, date=selected_date)
|
dialog = CalendarEntry(messages=messages, date=selected_date)
|
||||||
# append dialog to self.frame_2
|
# append dialog to self.frame_2
|
||||||
self.calendarlayout.addWidget(dialog)
|
self.calendarlayout.addWidget(dialog)
|
||||||
dialog.repaintSignal.connect(lambda: self.calendarWidget.reload(selected_date))
|
dialogger.repaintSignal.connect(
|
||||||
|
lambda: self.calendarWidget.reload(selected_date)
|
||||||
|
)
|
||||||
|
|
||||||
def open_settings(self):
|
def open_settings(self):
|
||||||
# print(settings.dict())
|
# print(settings.dict())
|
||||||
settingsUI = Settings(self.active_user)
|
settingsUI = Settings(self.active_user)
|
||||||
settingsUI.exec()
|
settingsUI.exec()
|
||||||
|
|
||||||
if settingsUI.result() == QtWidgets.QDialog.DialogCode.Accepted:
|
if settingsUI.result() == QtWidgets.QDialogger.DialogCode.Accepted:
|
||||||
settingsUI.save()
|
settingsUI.save()
|
||||||
# print(settings.dict())
|
# print(settings.dict())
|
||||||
|
|
||||||
@@ -1499,7 +1525,7 @@ class Ui(Ui_Semesterapparat):
|
|||||||
self.confirm_popup("Keine weiteren Apparate vorhanden", title="Fehler")
|
self.confirm_popup("Keine weiteren Apparate vorhanden", title="Fehler")
|
||||||
return (None, None)
|
return (None, None)
|
||||||
dialog = QtWidgets.QDialog()
|
dialog = QtWidgets.QDialog()
|
||||||
dialog.setWindowTitle(title)
|
dialogger.setWindowTitle(title)
|
||||||
# add a label to the dialog
|
# add a label to the dialog
|
||||||
label = QtWidgets.QLabel()
|
label = QtWidgets.QLabel()
|
||||||
label.setText(message)
|
label.setText(message)
|
||||||
@@ -1518,12 +1544,12 @@ class Ui(Ui_Semesterapparat):
|
|||||||
cancel_button = QtWidgets.QPushButton("Abbrechen")
|
cancel_button = QtWidgets.QPushButton("Abbrechen")
|
||||||
layout.addWidget(okay_button)
|
layout.addWidget(okay_button)
|
||||||
layout.addWidget(cancel_button)
|
layout.addWidget(cancel_button)
|
||||||
okay_button.clicked.connect(dialog.accept)
|
okay_button.clicked.connect(dialogger.accept)
|
||||||
cancel_button.clicked.connect(dialog.reject)
|
cancel_button.clicked.connect(dialogger.reject)
|
||||||
|
|
||||||
dialog.setLayout(layout)
|
dialogger.setLayout(layout)
|
||||||
|
|
||||||
return dialog.exec(), self.db.getApparatId(
|
return dialogger.exec(), self.db.getApparatId(
|
||||||
self.db.getApparatNameByAppNr(drpdwn.currentText())
|
self.db.getApparatNameByAppNr(drpdwn.currentText())
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -1562,7 +1588,7 @@ class Ui(Ui_Semesterapparat):
|
|||||||
widget.setWindowTitle("Metadaten")
|
widget.setWindowTitle("Metadaten")
|
||||||
bookedit.populate_fields(data)
|
bookedit.populate_fields(data)
|
||||||
widget.exec()
|
widget.exec()
|
||||||
if widget.result() == QtWidgets.QDialog.DialogCode.Accepted:
|
if widget.result() == QtWidgets.QDialogger.DialogCode.Accepted:
|
||||||
data = bookedit.get_data()
|
data = bookedit.get_data()
|
||||||
# #print(data)
|
# #print(data)
|
||||||
self.db.updateBookdata(bookdata=data, book_id=book_id)
|
self.db.updateBookdata(bookdata=data, book_id=book_id)
|
||||||
@@ -1621,7 +1647,7 @@ class Ui(Ui_Semesterapparat):
|
|||||||
framework = ApparatExtendDialog()
|
framework = ApparatExtendDialog()
|
||||||
framework.exec()
|
framework.exec()
|
||||||
# return data from dialog if ok is pressed
|
# return data from dialog if ok is pressed
|
||||||
if framework.result() == QtWidgets.QDialog.DialogCode.Accepted:
|
if framework.result() == QtWidgets.QDialogger.DialogCode.Accepted:
|
||||||
data = framework.get_data()
|
data = framework.get_data()
|
||||||
# #print(data)
|
# #print(data)
|
||||||
# return data
|
# return data
|
||||||
@@ -1745,10 +1771,10 @@ def launch_gui():
|
|||||||
|
|
||||||
elif ui.lresult == 0:
|
elif ui.lresult == 0:
|
||||||
warning_dialog = QtWidgets.QMessageBox()
|
warning_dialog = QtWidgets.QMessageBox()
|
||||||
warning_dialog.setIcon(QtWidgets.QMessageBox.Icon.Warning)
|
warning_dialogger.setIcon(QtWidgets.QMessageBox.Icon.Warning)
|
||||||
warning_dialog.setText("Invalid username or password. Please try again.")
|
warning_dialogger.setText("Invalid username or password. Please try again.")
|
||||||
warning_dialog.setWindowTitle("Login Failed")
|
warning_dialogger.setWindowTitle("Login Failed")
|
||||||
warning_dialog.exec()
|
warning_dialogger.exec()
|
||||||
atexit.register(tempdelete)
|
atexit.register(tempdelete)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ class ElsaDialog(QtWidgets.QDialog, Ui_Dialog):
|
|||||||
|
|
||||||
##Variables
|
##Variables
|
||||||
self.db = Database()
|
self.db = Database()
|
||||||
self.graph_data = {"x": [Semester().value], "y": [0]}
|
self.graph_data = {"x": [""], "y": [0]}
|
||||||
self.createProf = False
|
self.createProf = False
|
||||||
self.profs = self.getProfs()
|
self.profs = self.getProfs()
|
||||||
|
|
||||||
|
|||||||
@@ -6,22 +6,57 @@ from docx.oxml import OxmlElement
|
|||||||
from docx.oxml.ns import qn
|
from docx.oxml.ns import qn
|
||||||
import os
|
import os
|
||||||
from os.path import basename
|
from os.path import basename
|
||||||
|
from loguru import logger as log
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
logger = log
|
||||||
|
logger.remove()
|
||||||
|
logger.add("logs/application.log", rotation="1 week", enqueue=True)
|
||||||
|
log.add(
|
||||||
|
f"logs/{datetime.now().strftime('%Y-%m-%d')}.log",
|
||||||
|
rotation="1 day",
|
||||||
|
compression="zip",
|
||||||
|
)
|
||||||
|
|
||||||
|
# logger.add(sys.stderr, format="{time} {level} {message}", level="INFO")
|
||||||
|
logger.add(sys.stdout)
|
||||||
|
|
||||||
|
|
||||||
|
class SemesterError(Exception):
|
||||||
|
"""Custom exception for semester-related errors."""
|
||||||
|
|
||||||
|
def __init__(self, message):
|
||||||
|
super().__init__(message)
|
||||||
|
logger.error(message)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"SemesterError: {self.args[0]}"
|
||||||
|
|
||||||
|
|
||||||
class SemesterDocument:
|
class SemesterDocument:
|
||||||
def __init__(self, apparats: list[tuple[int, str]], semester: str, filename):
|
def __init__(
|
||||||
assert isinstance(apparats, list), "Apparats must be a list of tuples"
|
self,
|
||||||
assert all(isinstance(apparat, tuple) for apparat in apparats), (
|
apparats: list[tuple[int, str]],
|
||||||
|
semester: str,
|
||||||
|
filename,
|
||||||
|
config,
|
||||||
|
full: bool = False,
|
||||||
|
):
|
||||||
|
assert isinstance(apparats, list), SemesterError(
|
||||||
"Apparats must be a list of tuples"
|
"Apparats must be a list of tuples"
|
||||||
)
|
)
|
||||||
assert all(isinstance(apparat[0], int) for apparat in apparats), (
|
assert all(isinstance(apparat, tuple) for apparat in apparats), SemesterError(
|
||||||
|
"Apparats must be a list of tuples"
|
||||||
|
)
|
||||||
|
assert all(isinstance(apparat[0], int) for apparat in apparats), SemesterError(
|
||||||
"Apparat numbers must be integers"
|
"Apparat numbers must be integers"
|
||||||
)
|
)
|
||||||
assert all(isinstance(apparat[1], str) for apparat in apparats), (
|
assert all(isinstance(apparat[1], str) for apparat in apparats), SemesterError(
|
||||||
"Apparat names must be strings"
|
"Apparat names must be strings"
|
||||||
)
|
)
|
||||||
assert isinstance(semester, str), "Semester must be a string"
|
assert isinstance(semester, str), SemesterError("Semester must be a string")
|
||||||
assert "." not in filename and isinstance(filename, str), (
|
assert "." not in filename and isinstance(filename, str), SemesterError(
|
||||||
"Filename must be a string and not contain an extension"
|
"Filename must be a string and not contain an extension"
|
||||||
)
|
)
|
||||||
self.doc = Document()
|
self.doc = Document()
|
||||||
@@ -35,7 +70,17 @@ class SemesterDocument:
|
|||||||
self.color_red = RGBColor(255, 0, 0)
|
self.color_red = RGBColor(255, 0, 0)
|
||||||
self.color_blue = RGBColor(0, 0, 255)
|
self.color_blue = RGBColor(0, 0, 255)
|
||||||
self.filename = filename
|
self.filename = filename
|
||||||
|
self.settings = config
|
||||||
|
if full:
|
||||||
|
logger.info("Full document generation")
|
||||||
|
self.make_document()
|
||||||
|
logger.info("Document created")
|
||||||
|
self.create_pdf()
|
||||||
|
logger.info("PDF created")
|
||||||
|
self.print_document()
|
||||||
|
logger.info("Document printed")
|
||||||
|
self.cleanup()
|
||||||
|
logger.info("Cleanup done")
|
||||||
def set_table_border(self, table):
|
def set_table_border(self, table):
|
||||||
"""
|
"""
|
||||||
Adds a full border to the table.
|
Adds a full border to the table.
|
||||||
@@ -161,13 +206,13 @@ class SemesterDocument:
|
|||||||
from email.mime.multipart import MIMEMultipart
|
from email.mime.multipart import MIMEMultipart
|
||||||
from email.mime.application import MIMEApplication
|
from email.mime.application import MIMEApplication
|
||||||
from email.mime.text import MIMEText
|
from email.mime.text import MIMEText
|
||||||
from src import settings as config
|
|
||||||
|
|
||||||
|
config = self.settings
|
||||||
smtp = config.mail.smtp_server
|
smtp = config.mail.smtp_server
|
||||||
port = config.mail.port
|
port = config.mail.port
|
||||||
sender_email = config.mail.sender
|
sender_email = config.mail.sender
|
||||||
password = config.mail.password
|
password = config.mail.password
|
||||||
receiver = "mobileprint@ph-freiburg.de"
|
receiver = config.mail.printer_mail
|
||||||
message = MIMEMultipart()
|
message = MIMEMultipart()
|
||||||
message["From"] = sender_email
|
message["From"] = sender_email
|
||||||
message["To"] = receiver
|
message["To"] = receiver
|
||||||
@@ -202,7 +247,7 @@ class SemesterDocument:
|
|||||||
doc.SaveAs(f"{curdir}/{self.filename}.pdf", FileFormat=17)
|
doc.SaveAs(f"{curdir}/{self.filename}.pdf", FileFormat=17)
|
||||||
doc.Close()
|
doc.Close()
|
||||||
word.Quit()
|
word.Quit()
|
||||||
print("PDF saved")
|
logger.debug("PDF saved")
|
||||||
|
|
||||||
def cleanup(self):
|
def cleanup(self):
|
||||||
os.remove(f"{self.filename}.docx")
|
os.remove(f"{self.filename}.docx")
|
||||||
@@ -210,14 +255,15 @@ class SemesterDocument:
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
apparat = [(i, f"Item {i}") for i in range(405, 438)]
|
pass
|
||||||
doc = SemesterDocument(
|
# apparat = [(i, f"Item {i}") for i in range(405, 438)]
|
||||||
apparat,
|
# doc = SemesterDocument(
|
||||||
"WiSe 24/25",
|
# apparat,
|
||||||
"semap",
|
# "WiSe 24/25",
|
||||||
)
|
# "semap",
|
||||||
doc.make_document()
|
# )
|
||||||
doc.create_pdf()
|
# doc.make_document()
|
||||||
|
# doc.create_pdf()
|
||||||
# doc.print_document()
|
# doc.print_document()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user