Add new changes to main #7
62
.gitea/workflows/release.yml
Normal file
62
.gitea/workflows/release.yml
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
release_notes:
|
||||||
|
description: Release notes (use \n for newlines)
|
||||||
|
type: string
|
||||||
|
required: false
|
||||||
|
github_release:
|
||||||
|
description: 'Create Gitea Release'
|
||||||
|
default: true
|
||||||
|
type: boolean
|
||||||
|
bump:
|
||||||
|
description: 'Bump type'
|
||||||
|
required: false
|
||||||
|
default: 'patch'
|
||||||
|
type: choice
|
||||||
|
options:
|
||||||
|
- 'major'
|
||||||
|
- 'minor'
|
||||||
|
- 'patch'
|
||||||
|
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
bump:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
- name: Install UV
|
||||||
|
uses: astral-sh/setup-uv@v5
|
||||||
|
- name: Set up Python
|
||||||
|
run: uv python install
|
||||||
|
with:
|
||||||
|
python-version-file: "pyproject.toml"
|
||||||
|
- name: Install dependencies
|
||||||
|
run: uv sync --locked --all-extras --dev
|
||||||
|
- name: Install Bump tool
|
||||||
|
run: uv tool install bump-my-version
|
||||||
|
- name: Bump version
|
||||||
|
id: bump_version
|
||||||
|
run: |
|
||||||
|
uv tool run bump-my-version --bump ${{ github.event.inputs.bump }} --tag --allow-dirty
|
||||||
|
- name: Add release notes
|
||||||
|
id: add_release_notes
|
||||||
|
run: |
|
||||||
|
echo "RELEASE_NOTES<<EOF" >> $GITHUB_ENV
|
||||||
|
echo "${{ github.event.inputs.release_notes }}" >> $GITHUB_ENV
|
||||||
|
echo "EOF" >> $GITHUB_ENV
|
||||||
|
- name: Create Gitea Release
|
||||||
|
if: ${{ github.event.inputs.github_release == 'true' }}
|
||||||
|
uses: softprops/action-gh-release@v1
|
||||||
|
with:
|
||||||
|
tag_name: ${{ github.sha }}
|
||||||
|
release_name: Release ${{ github.sha }}
|
||||||
|
body: ${{ env.RELEASE_NOTES }}
|
||||||
|
draft: false
|
||||||
|
prerelease: false
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.TOKEN }}
|
||||||
|
GITHUB_REPOSITORY: ${{ github.repository }}
|
||||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -227,4 +227,6 @@ output
|
|||||||
config.yaml
|
config.yaml
|
||||||
**/tempCodeRunnerFile.py
|
**/tempCodeRunnerFile.py
|
||||||
uv.lock
|
uv.lock
|
||||||
logs/
|
logs/
|
||||||
|
*.pdf
|
||||||
|
*.docx
|
||||||
@@ -583,25 +583,28 @@ class Database:
|
|||||||
return self.query_db("SELECT * FROM subjects")
|
return self.query_db("SELECT * FROM subjects")
|
||||||
|
|
||||||
# Messages
|
# Messages
|
||||||
def addMessage(self, message: dict, user: str, app_id: Union[str, int]):
|
def addMessage(
|
||||||
|
self, messages: list[dict[str, Any]], user: str, app_id: Union[str, int]
|
||||||
|
):
|
||||||
"""add a Message to the database
|
"""add a Message to the database
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
message (dict): the message to be added
|
messages (list[dict[str, Any]]): the messages to be added
|
||||||
user (str): the user who added the message
|
user (str): the user who added the messages
|
||||||
app_id (Union[str,int]): the id of the apparat
|
app_id (Union[str,int]): the id of the apparat
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __getUserId(user):
|
def __getUserId(user: str):
|
||||||
return self.query_db(
|
return self.query_db(
|
||||||
"SELECT id FROM user WHERE username=?", (user,), one=True
|
"SELECT id FROM user WHERE username=?", (user,), one=True
|
||||||
)[0]
|
)[0]
|
||||||
|
|
||||||
user_id = __getUserId(user)
|
user_id = __getUserId(user)
|
||||||
self.query_db(
|
for message in messages:
|
||||||
"INSERT INTO messages (message, user_id, remind_at,appnr) VALUES (?,?,?,?)",
|
self.query_db(
|
||||||
(message["message"], user_id, message["remind_at"], app_id),
|
"INSERT INTO messages (message, user_id, remind_at,appnr) VALUES (?,?,?,?)",
|
||||||
)
|
(message["message"], user_id, message["remind_at"], app_id),
|
||||||
|
)
|
||||||
|
|
||||||
def getAllMessages(self) -> list[dict[str, str, str, str]]:
|
def getAllMessages(self) -> list[dict[str, str, str, str]]:
|
||||||
"""Get all the messages in the database
|
"""Get all the messages in the database
|
||||||
@@ -610,7 +613,7 @@ class Database:
|
|||||||
list[dict[str, str, str, str]]: a list of dictionaries containing the message, the user who added the message, the apparat id and the id of the message
|
list[dict[str, str, str, str]]: a list of dictionaries containing the message, the user who added the message, the apparat id and the id of the message
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __get_user_name(user_id):
|
def __get_user_name(user_id: int):
|
||||||
return self.query_db(
|
return self.query_db(
|
||||||
"SELECT username FROM user WHERE id=?", (user_id,), one=True
|
"SELECT username FROM user WHERE id=?", (user_id,), one=True
|
||||||
)[0]
|
)[0]
|
||||||
@@ -628,17 +631,17 @@ class Database:
|
|||||||
]
|
]
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def getMessages(self, date: str) -> list[dict[str, str, str, str]]:
|
def getMessages(self, date: str) -> list[dict[str, str]]:
|
||||||
"""Get all the messages for a specific date
|
"""Get all the messages for a specific date
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
date (str): a date.datetime object formatted as a string in the format "YYYY-MM-DD"
|
date (str): a date.datetime object formatted as a string in the format "YYYY-MM-DD"
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
list[dict[str, str, str, str]]: a list of dictionaries containing the message, the user who added the message, the apparat id and the id of the message
|
list[dict[str, str]]: a list of dictionaries containing the message, the user who added the message, the apparat id and the id of the message
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __get_user_name(user_id):
|
def __get_user_name(user_id: int):
|
||||||
return self.query_db(
|
return self.query_db(
|
||||||
"SELECT username FROM user WHERE id=?", (user_id,), one=True
|
"SELECT username FROM user WHERE id=?", (user_id,), one=True
|
||||||
)[0]
|
)[0]
|
||||||
@@ -650,7 +653,7 @@ class Database:
|
|||||||
]
|
]
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def deleteMessage(self, message_id):
|
def deleteMessage(self, message_id: int):
|
||||||
"""Delete a message from the database
|
"""Delete a message from the database
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@@ -692,7 +695,9 @@ class Database:
|
|||||||
)[0]
|
)[0]
|
||||||
return f"{title} " if title is not None else ""
|
return f"{title} " if title is not None else ""
|
||||||
|
|
||||||
def getSpecificProfData(self, prof_id: Union[str, int], fields: List[str]) -> tuple:
|
def getSpecificProfData(
|
||||||
|
self, prof_id: Union[str, int], fields: List[str]
|
||||||
|
) -> tuple[Any, ...]:
|
||||||
"""A customisable function to get specific data of a professor based on the id
|
"""A customisable function to get specific data of a professor based on the id
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@@ -761,7 +766,7 @@ class Database:
|
|||||||
return [Prof().from_tuple(prof) for prof in profs]
|
return [Prof().from_tuple(prof) for prof in profs]
|
||||||
|
|
||||||
# Apparat
|
# Apparat
|
||||||
def getAllAparats(self, deleted=0) -> list[tuple]:
|
def getAllAparats(self, deleted: int = 0) -> list[Apparat]:
|
||||||
"""Get all the apparats in the database
|
"""Get all the apparats in the database
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@@ -770,9 +775,13 @@ class Database:
|
|||||||
Returns:
|
Returns:
|
||||||
list[tuple]: a list of tuples containing the apparats
|
list[tuple]: a list of tuples containing the apparats
|
||||||
"""
|
"""
|
||||||
return self.query_db(
|
apparats = self.query_db(
|
||||||
"SELECT * FROM semesterapparat WHERE deletion_status=?", (deleted,)
|
"SELECT * FROM semesterapparat WHERE deletion_status=?", (deleted,)
|
||||||
)
|
)
|
||||||
|
ret: list[Apparat] = []
|
||||||
|
for apparat in apparats:
|
||||||
|
ret.append(Apparat().from_tuple(apparat))
|
||||||
|
return ret
|
||||||
|
|
||||||
def getApparatData(self, appnr, appname) -> ApparatData:
|
def getApparatData(self, appnr, appname) -> ApparatData:
|
||||||
"""Get the Apparat data based on the apparat number and the name
|
"""Get the Apparat data based on the apparat number and the name
|
||||||
@@ -1595,7 +1604,7 @@ class Database:
|
|||||||
else:
|
else:
|
||||||
return Prof()
|
return Prof()
|
||||||
|
|
||||||
def getProfIDByApparat(self, apprarat_id):
|
def getProfIDByApparat(self, apprarat_id: int) -> Optional[int]:
|
||||||
"""Get the prof id based on the semesterapparat id from the database
|
"""Get the prof id based on the semesterapparat id from the database
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@@ -1613,7 +1622,7 @@ class Database:
|
|||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def copyBookToApparat(self, book_id, apparat):
|
def copyBookToApparat(self, book_id: int, apparat: int):
|
||||||
# get book data
|
# get book data
|
||||||
new_apparat_id = apparat
|
new_apparat_id = apparat
|
||||||
new_prof_id = self.getProfIDByApparat(new_apparat_id)
|
new_prof_id = self.getProfIDByApparat(new_apparat_id)
|
||||||
@@ -1634,7 +1643,7 @@ class Database:
|
|||||||
connection.commit()
|
connection.commit()
|
||||||
connection.close()
|
connection.close()
|
||||||
|
|
||||||
def moveBookToApparat(self, book_id, appratat):
|
def moveBookToApparat(self, book_id: int, appratat: int):
|
||||||
"""Move the book to the new apparat
|
"""Move the book to the new apparat
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@@ -1649,7 +1658,7 @@ class Database:
|
|||||||
connection.commit()
|
connection.commit()
|
||||||
connection.close()
|
connection.close()
|
||||||
|
|
||||||
def getApparatNameByAppNr(self, appnr):
|
def getApparatNameByAppNr(self, appnr: int):
|
||||||
query = f"SELECT name FROM semesterapparat WHERE appnr = '{appnr}' and deletion_status = 0"
|
query = f"SELECT name FROM semesterapparat WHERE appnr = '{appnr}' and deletion_status = 0"
|
||||||
data = self.query_db(query)
|
data = self.query_db(query)
|
||||||
if data:
|
if data:
|
||||||
|
|||||||
@@ -1,38 +1,38 @@
|
|||||||
|
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
|
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
import json
|
import json
|
||||||
|
from typing import Union, Any, Optional
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Prof:
|
class Prof:
|
||||||
id: int = None
|
id: Optional[int] = None
|
||||||
_title: str = None
|
_title: Optional[str] = None
|
||||||
firstname: str = None
|
firstname: Optional[str] = None
|
||||||
lastname: str = None
|
lastname: Optional[str] = None
|
||||||
fullname: str = None
|
fullname: Optional[str] = None
|
||||||
mail: str = None
|
mail: Optional[str] = None
|
||||||
telnr: str = None
|
telnr: Optional[str] = None
|
||||||
|
|
||||||
# add function that sets the data based on a dict
|
# add function that sets the data based on a dict
|
||||||
def from_dict(self, data: dict):
|
def from_dict(self, data: dict[str, Union[str, int]]):
|
||||||
for key, value in data.items():
|
for key, value in data.items():
|
||||||
if hasattr(self, key):
|
if hasattr(self, key):
|
||||||
setattr(self, key, value)
|
setattr(self, key, value)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def title(self):
|
def title(self) -> str:
|
||||||
if self._title is None or self._title == "None":
|
if self._title is None or self._title == "None":
|
||||||
return ""
|
return ""
|
||||||
return self._title
|
return self._title
|
||||||
|
|
||||||
@title.setter
|
@title.setter
|
||||||
def title(self, value):
|
def title(self, value: str):
|
||||||
self._title = value
|
self._title = value
|
||||||
|
|
||||||
# add function that sets the data from a tuple
|
# add function that sets the data from a tuple
|
||||||
def from_tuple(self, data: tuple):
|
def from_tuple(self, data: tuple[Union[str, int], ...]):
|
||||||
setattr(self, "id", data[0])
|
setattr(self, "id", data[0])
|
||||||
setattr(self, "_title", data[1])
|
setattr(self, "_title", data[1])
|
||||||
setattr(self, "firstname", data[2])
|
setattr(self, "firstname", data[2])
|
||||||
@@ -42,7 +42,7 @@ class Prof:
|
|||||||
setattr(self, "telnr", data[6])
|
setattr(self, "telnr", data[6])
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def name(self, comma=False):
|
def name(self, comma: bool = False) -> Optional[str]:
|
||||||
if self.firstname is None and self.lastname is None:
|
if self.firstname is None and self.lastname is None:
|
||||||
if "," in self.fullname:
|
if "," in self.fullname:
|
||||||
self.firstname = self.fullname.split(",")[1].strip()
|
self.firstname = self.fullname.split(",")[1].strip()
|
||||||
@@ -62,9 +62,9 @@ class BookData:
|
|||||||
signature: str | None = None
|
signature: str | None = None
|
||||||
edition: str | None = None
|
edition: str | None = None
|
||||||
link: str | None = None
|
link: str | None = None
|
||||||
isbn: str | list | None = field(default_factory=list)
|
isbn: Union[str, list[str], None] = field(default_factory=list)
|
||||||
author: str | None = None
|
author: str | None = None
|
||||||
language: str | list | None = field(default_factory=list)
|
language: Union[str, list[str], None] = field(default_factory=list)
|
||||||
publisher: str | None = None
|
publisher: str | None = None
|
||||||
place: str | None = None
|
place: str | None = None
|
||||||
year: str | None = None
|
year: str | None = None
|
||||||
@@ -73,31 +73,33 @@ class BookData:
|
|||||||
in_apparat: bool | None = False
|
in_apparat: bool | None = False
|
||||||
adis_idn: str | None = None
|
adis_idn: str | None = None
|
||||||
|
|
||||||
def from_dict(self, data: dict):
|
def from_dict(self, data: dict) -> "BookData":
|
||||||
for key, value in data.items():
|
for key, value in data.items():
|
||||||
setattr(self, key, value)
|
setattr(self, key, value)
|
||||||
|
return self
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def to_dict(self):
|
def to_dict(self) -> str:
|
||||||
"""Convert the dataclass to a dictionary."""
|
"""Convert the dataclass to a dictionary."""
|
||||||
return json.dumps(self.__dict__, ensure_ascii=False)
|
return json.dumps(self.__dict__, ensure_ascii=False)
|
||||||
|
|
||||||
def from_dataclass(self, dataclass):
|
def from_dataclass(self, dataclass: Optional[Any]) -> None:
|
||||||
|
if dataclass is None:
|
||||||
|
return
|
||||||
for key, value in dataclass.__dict__.items():
|
for key, value in dataclass.__dict__.items():
|
||||||
setattr(self, key, value)
|
setattr(self, key, value)
|
||||||
|
|
||||||
def from_string(self, data: str):
|
def from_string(self, data: str) -> "BookData":
|
||||||
data = json.loads(data)
|
ndata = json.loads(data)
|
||||||
|
return BookData(**ndata)
|
||||||
return BookData(**data)
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class MailData:
|
class MailData:
|
||||||
subject: str | None = None
|
subject: Optional[str] = None
|
||||||
body: str | None = None
|
body: Optional[str] = None
|
||||||
mailto: str | None = None
|
mailto: Optional[str] = None
|
||||||
prof: str | None = None
|
prof: Optional[str] = None
|
||||||
|
|
||||||
|
|
||||||
class Subjects(Enum):
|
class Subjects(Enum):
|
||||||
@@ -127,15 +129,15 @@ class Subjects(Enum):
|
|||||||
ECONOMICS = (24, "Wirtschaftslehre")
|
ECONOMICS = (24, "Wirtschaftslehre")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def id(self):
|
def id(self) -> int:
|
||||||
return self.value[0]
|
return self.value[0]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self) -> str:
|
||||||
return self.value[1]
|
return self.value[1]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_index(cls, name):
|
def get_index(cls, name: str) -> Optional[int]:
|
||||||
for i in cls:
|
for i in cls:
|
||||||
if i.name == name:
|
if i.name == name:
|
||||||
return i.id - 1
|
return i.id - 1
|
||||||
@@ -158,7 +160,7 @@ class Apparat:
|
|||||||
prof_id_adis: str | None = None
|
prof_id_adis: str | None = None
|
||||||
konto: int | None = None
|
konto: int | None = None
|
||||||
|
|
||||||
def from_tuple(self, data: tuple):
|
def from_tuple(self, data: tuple[Any, ...]) -> "Apparat":
|
||||||
self.id = data[0]
|
self.id = data[0]
|
||||||
self.name = data[1]
|
self.name = data[1]
|
||||||
self.prof_id = data[2]
|
self.prof_id = data[2]
|
||||||
@@ -176,7 +178,7 @@ class Apparat:
|
|||||||
return self
|
return self
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def get_semester(self):
|
def get_semester(self) -> Optional[str]:
|
||||||
if self.extend_until is not None:
|
if self.extend_until is not None:
|
||||||
return self.extend_until
|
return self.extend_until
|
||||||
else:
|
else:
|
||||||
@@ -190,7 +192,7 @@ class ELSA:
|
|||||||
semester: str | None = None
|
semester: str | None = None
|
||||||
prof_id: int | None = None
|
prof_id: int | None = None
|
||||||
|
|
||||||
def from_tuple(self, data):
|
def from_tuple(self, data: tuple[Any, ...]) -> "ELSA":
|
||||||
self.id = data[0]
|
self.id = data[0]
|
||||||
self.date = data[1]
|
self.date = data[1]
|
||||||
self.semester = data[2]
|
self.semester = data[2]
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Form implementation generated from reading ui file 'c:\Users\aky547\GitHub\SemesterapparatsManager\src\ui\dialogs\dialog_sources\settings.ui'
|
# Form implementation generated from reading ui file 'c:\Users\aky547\GitHub\SemesterapparatsManager\src\ui\dialogs\dialog_sources\settings.ui'
|
||||||
#
|
#
|
||||||
# Created by: PyQt6 UI code generator 6.8.0
|
# Created by: PyQt6 UI code generator 6.9.0
|
||||||
#
|
#
|
||||||
# WARNING: Any manual changes made to this file will be lost when pyuic6 is
|
# WARNING: Any manual changes made to this file will be lost when pyuic6 is
|
||||||
# run again. Do not edit this file unless you know what you are doing.
|
# run again. Do not edit this file unless you know what you are doing.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Form implementation generated from reading ui file '/home/alexander/GitHub/Semesterapparate/ui/dialogs/parsed_titles.ui'
|
# Form implementation generated from reading ui file 'c:\Users\aky547\GitHub\SemesterapparatsManager\src\ui\dialogs\parsed_titles.ui'
|
||||||
#
|
#
|
||||||
# Created by: PyQt6 UI code generator 6.5.3
|
# Created by: PyQt6 UI code generator 6.9.0
|
||||||
#
|
#
|
||||||
# WARNING: Any manual changes made to this file will be lost when pyuic6 is
|
# WARNING: Any manual changes made to this file will be lost when pyuic6 is
|
||||||
# run again. Do not edit this file unless you know what you are doing.
|
# run again. Do not edit this file unless you know what you are doing.
|
||||||
@@ -38,12 +38,7 @@ class Ui_Form(object):
|
|||||||
self.label_2 = QtWidgets.QLabel(parent=self.horizontalLayoutWidget)
|
self.label_2 = QtWidgets.QLabel(parent=self.horizontalLayoutWidget)
|
||||||
self.label_2.setObjectName("label_2")
|
self.label_2.setObjectName("label_2")
|
||||||
self.horizontalLayout.addWidget(self.label_2)
|
self.horizontalLayout.addWidget(self.label_2)
|
||||||
spacerItem = QtWidgets.QSpacerItem(
|
spacerItem = 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(spacerItem)
|
self.horizontalLayout.addItem(spacerItem)
|
||||||
self.frame_2 = QtWidgets.QFrame(parent=Form)
|
self.frame_2 = QtWidgets.QFrame(parent=Form)
|
||||||
self.frame_2.setGeometry(QtCore.QRect(10, 80, 381, 201))
|
self.frame_2.setGeometry(QtCore.QRect(10, 80, 381, 201))
|
||||||
@@ -59,9 +54,7 @@ class Ui_Form(object):
|
|||||||
self.listWidget = QtWidgets.QListWidget(parent=self.horizontalLayoutWidget_2)
|
self.listWidget = QtWidgets.QListWidget(parent=self.horizontalLayoutWidget_2)
|
||||||
self.listWidget.setObjectName("listWidget")
|
self.listWidget.setObjectName("listWidget")
|
||||||
self.horizontalLayout_2.addWidget(self.listWidget)
|
self.horizontalLayout_2.addWidget(self.listWidget)
|
||||||
self.listWidget_done = QtWidgets.QListWidget(
|
self.listWidget_done = QtWidgets.QListWidget(parent=self.horizontalLayoutWidget_2)
|
||||||
parent=self.horizontalLayoutWidget_2
|
|
||||||
)
|
|
||||||
self.listWidget_done.setObjectName("listWidget_done")
|
self.listWidget_done.setObjectName("listWidget_done")
|
||||||
self.horizontalLayout_2.addWidget(self.listWidget_done)
|
self.horizontalLayout_2.addWidget(self.listWidget_done)
|
||||||
self.progressBar = QtWidgets.QProgressBar(parent=Form)
|
self.progressBar = QtWidgets.QProgressBar(parent=Form)
|
||||||
@@ -70,10 +63,7 @@ class Ui_Form(object):
|
|||||||
self.progressBar.setObjectName("progressBar")
|
self.progressBar.setObjectName("progressBar")
|
||||||
self.buttonBox = QtWidgets.QDialogButtonBox(parent=Form)
|
self.buttonBox = QtWidgets.QDialogButtonBox(parent=Form)
|
||||||
self.buttonBox.setGeometry(QtCore.QRect(230, 290, 156, 23))
|
self.buttonBox.setGeometry(QtCore.QRect(230, 290, 156, 23))
|
||||||
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.toolButton = QtWidgets.QToolButton(parent=Form)
|
self.toolButton = QtWidgets.QToolButton(parent=Form)
|
||||||
self.toolButton.setGeometry(QtCore.QRect(20, 290, 25, 19))
|
self.toolButton.setGeometry(QtCore.QRect(20, 290, 25, 19))
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ from PyQt6 import QtWidgets
|
|||||||
from .dialog_sources.reminder_ui import Ui_Erinnerung as Ui_Dialog
|
from .dialog_sources.reminder_ui import Ui_Erinnerung as Ui_Dialog
|
||||||
from src import Icon
|
from src import Icon
|
||||||
import datetime as date
|
import datetime as date
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
class ReminderDialog(QtWidgets.QDialog, Ui_Dialog):
|
class ReminderDialog(QtWidgets.QDialog, Ui_Dialog):
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
@@ -13,8 +13,10 @@ class ReminderDialog(QtWidgets.QDialog, Ui_Dialog):
|
|||||||
self.setWindowTitle("Erinnerung")
|
self.setWindowTitle("Erinnerung")
|
||||||
self.dateEdit.setDate(date.datetime.now())
|
self.dateEdit.setDate(date.datetime.now())
|
||||||
|
|
||||||
def return_message(self) -> dict:
|
def return_message(self) -> list[dict[str, Any]]:
|
||||||
return {
|
return [
|
||||||
"message": self.message_box.toPlainText(),
|
{
|
||||||
"remind_at": self.dateEdit.date().toString("yyyy-MM-dd"),
|
"message": self.message_box.toPlainText(),
|
||||||
}
|
"remind_at": self.dateEdit.date().toString("yyyy-MM-dd"),
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Form implementation generated from reading ui file 'c:\Users\aky547\GitHub\SemesterapparatsManager\src\ui\sounds\semesterapparat_ui.ui'
|
# Form implementation generated from reading ui file 'c:\Users\aky547\GitHub\SemesterapparatsManager\src\ui\sounds\semesterapparat_ui.ui'
|
||||||
#
|
#
|
||||||
# Created by: PyQt6 UI code generator 6.8.0
|
# Created by: PyQt6 UI code generator 6.9.0
|
||||||
#
|
#
|
||||||
# WARNING: Any manual changes made to this file will be lost when pyuic6 is
|
# WARNING: Any manual changes made to this file will be lost when pyuic6 is
|
||||||
# run again. Do not edit this file unless you know what you are doing.
|
# run again. Do not edit this file unless you know what you are doing.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# encoding: utf-8
|
# encoding: utf-8
|
||||||
import atexit
|
import atexit
|
||||||
import os
|
import os
|
||||||
|
import time
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
import webbrowser
|
import webbrowser
|
||||||
@@ -260,7 +260,7 @@ class Ui(Ui_Semesterapparat):
|
|||||||
def create_doc(self):
|
def create_doc(self):
|
||||||
log.debug("Creating document")
|
log.debug("Creating document")
|
||||||
# open DocumentPrintDialog
|
# open DocumentPrintDialog
|
||||||
dialog = DocumentPrintDialog(self.MainWindow)
|
dialog = DocumentPrintDialog(self.MainWindow) # type: ignore
|
||||||
dialog.show()
|
dialog.show()
|
||||||
|
|
||||||
def checkValidInput(self):
|
def checkValidInput(self):
|
||||||
@@ -269,24 +269,24 @@ class Ui(Ui_Semesterapparat):
|
|||||||
else:
|
else:
|
||||||
self.check_file.setEnabled(False)
|
self.check_file.setEnabled(False)
|
||||||
|
|
||||||
def setWidget(self, widget):
|
def setWidget(self, widget: QtWidgets.QWidget):
|
||||||
# remove all widgets from localwidget
|
# remove all widgets from localwidget
|
||||||
|
|
||||||
self.hideWidget()
|
self.hideWidget()
|
||||||
# add widget to localwidget
|
# add widget to localwidget
|
||||||
self.admin_action.layout().addWidget(widget)
|
self.admin_action.layout().addWidget(widget) # type: ignore
|
||||||
|
|
||||||
def hideWidget(self):
|
def hideWidget(self):
|
||||||
try:
|
try:
|
||||||
widgets = [
|
widgets = [
|
||||||
self.admin_action.layout().itemAt(i).widget()
|
self.admin_action.layout().itemAt(i).widget() # type: ignore
|
||||||
for i in range(self.admin_action.layout().count())
|
for i in range(self.admin_action.layout().count()) # type: ignore
|
||||||
]
|
]
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
return
|
return
|
||||||
for widget in widgets:
|
for widget in widgets:
|
||||||
self.admin_action.layout().removeWidget(widget)
|
self.admin_action.layout().removeWidget(widget) # type: ignore
|
||||||
widget.deleteLater()
|
widget.deleteLater() # type: ignore
|
||||||
|
|
||||||
def adminActions(self):
|
def adminActions(self):
|
||||||
if self.select_action_box.currentText() == "Nutzer anlegen":
|
if self.select_action_box.currentText() == "Nutzer anlegen":
|
||||||
@@ -302,7 +302,7 @@ class Ui(Ui_Semesterapparat):
|
|||||||
self.hideWidget()
|
self.hideWidget()
|
||||||
self.admin_action.setTitle("")
|
self.admin_action.setTitle("")
|
||||||
|
|
||||||
def toggleButton(self, button):
|
def toggleButton(self, button: QtWidgets.QCheckBox):
|
||||||
if button.isChecked():
|
if button.isChecked():
|
||||||
button.setChecked(False)
|
button.setChecked(False)
|
||||||
self.validate_semester()
|
self.validate_semester()
|
||||||
@@ -317,7 +317,7 @@ class Ui(Ui_Semesterapparat):
|
|||||||
|
|
||||||
def get_apparats(self):
|
def get_apparats(self):
|
||||||
alist = self.db.getAllAparats(deleted=0)
|
alist = self.db.getAllAparats(deleted=0)
|
||||||
alist = natsorted(alist, key=lambda x: x[4], reverse=True)
|
alist = natsorted(alist, key=lambda x: x.appnr, reverse=True)
|
||||||
self.tableWidget_apparate.setRowCount(0)
|
self.tableWidget_apparate.setRowCount(0)
|
||||||
for apparat in alist:
|
for apparat in alist:
|
||||||
self.insert_apparat_into_table(apparat)
|
self.insert_apparat_into_table(apparat)
|
||||||
@@ -327,15 +327,16 @@ class Ui(Ui_Semesterapparat):
|
|||||||
self.app_fach.clear()
|
self.app_fach.clear()
|
||||||
self.app_fach.addItem("")
|
self.app_fach.addItem("")
|
||||||
self.app_fach.setCurrentText("")
|
self.app_fach.setCurrentText("")
|
||||||
self.app_fach.addItems([subject[1] for subject in self.db.getSubjects()])
|
self.app_fach.addItems([subject[1] for subject in self.db.getSubjects()]) # type: ignore
|
||||||
|
|
||||||
def open_documentation(self):
|
def open_documentation(self):
|
||||||
log.info("Opening Documentation")
|
log.info("Opening Documentation")
|
||||||
if not self.docu.isRunning():
|
if not self.docu.isRunning():
|
||||||
self.docu.start()
|
self.docu.start()
|
||||||
|
time.sleep(5)
|
||||||
webbrowser.open("http://localhost:8000")
|
webbrowser.open("http://localhost:8000")
|
||||||
|
|
||||||
def update_calendar(self, data):
|
def update_calendar(self, data: list[dict[str, Any]]):
|
||||||
self.calendarWidget.setMessages([data])
|
self.calendarWidget.setMessages([data])
|
||||||
self.calendarWidget.updateCells()
|
self.calendarWidget.updateCells()
|
||||||
|
|
||||||
@@ -459,8 +460,7 @@ class Ui(Ui_Semesterapparat):
|
|||||||
else self.sem_winter.text() + " " + self.sem_year.text()
|
else self.sem_winter.text() + " " + self.sem_year.text()
|
||||||
)
|
)
|
||||||
app.prof_id_adis = self.prof_id_adis.text()
|
app.prof_id_adis = self.prof_id_adis.text()
|
||||||
prof_id = self.db.getProfByName(prof.fullname).id
|
self.add_files()
|
||||||
self.add_files(prof_id)
|
|
||||||
app.apparat_id_adis = self.apparat_id_adis.text()
|
app.apparat_id_adis = self.apparat_id_adis.text()
|
||||||
appdata = ApparatData(prof=prof, apparat=app)
|
appdata = ApparatData(prof=prof, apparat=app)
|
||||||
self.db.updateApparat(appdata)
|
self.db.updateApparat(appdata)
|
||||||
@@ -1305,7 +1305,7 @@ class Ui(Ui_Semesterapparat):
|
|||||||
"prof_tel": self.prof_tel_nr.text(),
|
"prof_tel": self.prof_tel_nr.text(),
|
||||||
}
|
}
|
||||||
|
|
||||||
def add_files(self, prof_id=None):
|
def add_files(self):
|
||||||
"""
|
"""
|
||||||
Add Files to the associated prof in the database
|
Add Files to the associated prof in the database
|
||||||
|
|
||||||
@@ -1346,24 +1346,28 @@ class Ui(Ui_Semesterapparat):
|
|||||||
self.insert_apparat_into_table(apparat)
|
self.insert_apparat_into_table(apparat)
|
||||||
log.info("Inserted {} apparats into table".format(len(self.apparats)))
|
log.info("Inserted {} apparats into table".format(len(self.apparats)))
|
||||||
|
|
||||||
def insert_apparat_into_table(self, apparat):
|
def insert_apparat_into_table(self, apparat: Apparat):
|
||||||
# log.debug(apparat)
|
# log.debug(apparat)
|
||||||
def __dauer_check(apparat):
|
def __dauer_check(apparat: Apparat):
|
||||||
return "Ja" if apparat[7] == 1 else "Nein"
|
return "Ja" if apparat.eternal == 1 else "Nein"
|
||||||
|
|
||||||
semester = apparat[8] if apparat[8] is not None else apparat[5]
|
semester = (
|
||||||
|
apparat.extend_until
|
||||||
|
if apparat.extend_until is not None
|
||||||
|
else apparat.created_semester
|
||||||
|
)
|
||||||
self.tableWidget_apparate.insertRow(0)
|
self.tableWidget_apparate.insertRow(0)
|
||||||
self.tableWidget_apparate.setItem(
|
self.tableWidget_apparate.setItem(
|
||||||
0, 0, QtWidgets.QTableWidgetItem(str(apparat[4]))
|
0, 0, QtWidgets.QTableWidgetItem(str(apparat.appnr))
|
||||||
)
|
)
|
||||||
self.tableWidget_apparate.setItem(
|
self.tableWidget_apparate.setItem(
|
||||||
0, 1, QtWidgets.QTableWidgetItem(str(apparat[1]))
|
0, 1, QtWidgets.QTableWidgetItem(str(apparat.name))
|
||||||
)
|
)
|
||||||
self.tableWidget_apparate.setItem(
|
self.tableWidget_apparate.setItem(
|
||||||
0,
|
0,
|
||||||
2,
|
2,
|
||||||
QtWidgets.QTableWidgetItem(
|
QtWidgets.QTableWidgetItem(
|
||||||
self.db.getProfNameById(apparat[2], add_title=False)
|
self.db.getProfNameById(apparat.prof_id, add_title=False)
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
self.tableWidget_apparate.setItem(
|
self.tableWidget_apparate.setItem(
|
||||||
@@ -1375,7 +1379,7 @@ class Ui(Ui_Semesterapparat):
|
|||||||
0, 4, QtWidgets.QTableWidgetItem(__dauer_check(apparat))
|
0, 4, QtWidgets.QTableWidgetItem(__dauer_check(apparat))
|
||||||
)
|
)
|
||||||
self.tableWidget_apparate.setItem(
|
self.tableWidget_apparate.setItem(
|
||||||
0, 5, QtWidgets.QTableWidgetItem(str(apparat[13]))
|
0, 5, QtWidgets.QTableWidgetItem(str(apparat.konto))
|
||||||
)
|
)
|
||||||
|
|
||||||
def open_context_menu(self, position):
|
def open_context_menu(self, position):
|
||||||
@@ -1440,7 +1444,7 @@ 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))
|
dialog.repaintSignal.connect(lambda: self.calendarWidget.reload(selected_date)) # type: ignore
|
||||||
|
|
||||||
def open_settings(self):
|
def open_settings(self):
|
||||||
# log.debug(settings.dict())
|
# log.debug(settings.dict())
|
||||||
@@ -1463,7 +1467,7 @@ class Ui(Ui_Semesterapparat):
|
|||||||
else:
|
else:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def media_context_menu(self, position):
|
def media_context_menu(self, position): # type: ignore
|
||||||
menu = QtWidgets.QMenu()
|
menu = QtWidgets.QMenu()
|
||||||
|
|
||||||
delete_action = QtGui.QAction("Löschen")
|
delete_action = QtGui.QAction("Löschen")
|
||||||
@@ -1475,36 +1479,36 @@ class Ui(Ui_Semesterapparat):
|
|||||||
|
|
||||||
apparatmenu = menu.addMenu("Apparate")
|
apparatmenu = menu.addMenu("Apparate")
|
||||||
generalmenu = menu.addMenu("Allgemeines")
|
generalmenu = menu.addMenu("Allgemeines")
|
||||||
apparatmenu.addActions(
|
apparatmenu.addActions( # type: ignore
|
||||||
[apparat_add_action, apparat_copy_action, apparat_move_action]
|
[apparat_add_action, apparat_copy_action, apparat_move_action]
|
||||||
)
|
)
|
||||||
generalmenu.addActions([edit_action, delete_action, update_data_action])
|
generalmenu.addActions([edit_action, delete_action, update_data_action]) # type: ignore
|
||||||
# disable apparat_add_action
|
# disable apparat_add_action
|
||||||
apparat_add_action.setEnabled(False)
|
apparat_add_action.setEnabled(False)
|
||||||
delete_action.triggered.connect(self.delete_medium)
|
delete_action.triggered.connect(self.delete_medium) # type: ignore
|
||||||
edit_action.triggered.connect(self.edit_medium)
|
edit_action.triggered.connect(self.edit_medium) # type: ignore
|
||||||
apparat_add_action.triggered.connect(self.add_to_apparat)
|
apparat_add_action.triggered.connect(self.add_to_apparat) # type: ignore
|
||||||
apparat_copy_action.triggered.connect(self.copy_to_apparat)
|
apparat_copy_action.triggered.connect(self.copy_to_apparat) # type: ignore
|
||||||
apparat_move_action.triggered.connect(self.move_to_apparat)
|
apparat_move_action.triggered.connect(self.move_to_apparat) # type: ignore
|
||||||
update_data_action.triggered.connect(self.update_data)
|
update_data_action.triggered.connect(self.update_data) # type: ignore
|
||||||
menu.exec(self.tableWidget_apparat_media.mapToGlobal(position))
|
menu.exec(self.tableWidget_apparat_media.mapToGlobal(position)) # type: ignore
|
||||||
|
|
||||||
def update_data(self):
|
def update_data(self):
|
||||||
# TODO: use link in table, parse data and if needed, update location / signature
|
# TODO: use link in table, parse data and if needed, update location / signature
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def copy_to_apparat(self):
|
def copy_to_apparat(self):
|
||||||
selected_rows = self.tableWidget_apparat_media.selectionModel().selectedRows()
|
selected_rows = self.tableWidget_apparat_media.selectionModel().selectedRows() # type: ignore
|
||||||
signatures = []
|
signatures: list[int] = []
|
||||||
for row in selected_rows:
|
for row in selected_rows:
|
||||||
signature = self.tableWidget_apparat_media.item(row.row(), 1).text()
|
signature = self.tableWidget_apparat_media.item(row.row(), 1).text() # type: ignore
|
||||||
book_id = self.db.getBookIdBasedOnSignature(
|
book_id = self.db.getBookIdBasedOnSignature(
|
||||||
self.active_apparat,
|
self.active_apparat,
|
||||||
self.db.getProfId(self.profdata),
|
self.db.getProfId(self.profdata), # type: ignore
|
||||||
signature,
|
signature,
|
||||||
)
|
)
|
||||||
signatures.append(book_id)
|
signatures.append(book_id) # type: ignore
|
||||||
result, apparat = self.confirm_action_dialog(
|
result, apparat = self.confirm_action_dialog( # type: ignore
|
||||||
"In welchen Apparat sollen die Medien kopiert werden?"
|
"In welchen Apparat sollen die Medien kopiert werden?"
|
||||||
)
|
)
|
||||||
if result == 1:
|
if result == 1:
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ from PyQt6 import QtWidgets, QtCore
|
|||||||
from PyQt6.QtCore import QDate
|
from PyQt6.QtCore import QDate
|
||||||
from PyQt6.QtGui import QColor, QPen
|
from PyQt6.QtGui import QColor, QPen
|
||||||
from src.backend import Database
|
from src.backend import Database
|
||||||
|
from typing import Any
|
||||||
import darkdetect
|
import darkdetect
|
||||||
import loguru
|
import loguru
|
||||||
import sys
|
import sys
|
||||||
@@ -37,7 +38,7 @@ class MessageCalendar(QtWidgets.QCalendarWidget):
|
|||||||
self.messages.remove(message)
|
self.messages.remove(message)
|
||||||
self.updateCells()
|
self.updateCells()
|
||||||
|
|
||||||
def setMessages(self, messages):
|
def setMessages(self, messages: list[dict[str, Any]]):
|
||||||
# remove all drawn circles
|
# remove all drawn circles
|
||||||
|
|
||||||
for message in messages:
|
for message in messages:
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import random
|
import random
|
||||||
from typing import Union
|
from typing import Union, Any
|
||||||
|
|
||||||
import pyqtgraph as pg
|
import pyqtgraph as pg
|
||||||
from PyQt6 import QtWidgets
|
from PyQt6 import QtWidgets
|
||||||
@@ -12,8 +12,8 @@ log.add(sys.stdout)
|
|||||||
log.add("logs/application.log", rotation="1 MB", retention="10 days")
|
log.add("logs/application.log", rotation="1 MB", retention="10 days")
|
||||||
|
|
||||||
|
|
||||||
def mergedicts(d1, d2):
|
def mergedicts(d1: dict[str, Any], d2: dict[str, Any]):
|
||||||
res = {}
|
res: dict[str, Any] = {}
|
||||||
d1_data = list(d1.items())
|
d1_data = list(d1.items())
|
||||||
d2_data = list(d2.items())
|
d2_data = list(d2.items())
|
||||||
for i in range(len(d1)):
|
for i in range(len(d1)):
|
||||||
@@ -24,18 +24,18 @@ def mergedicts(d1, d2):
|
|||||||
d1_dict = dict([d1_data_slice])
|
d1_dict = dict([d1_data_slice])
|
||||||
d2_dict = dict([d2_data_slice])
|
d2_dict = dict([d2_data_slice])
|
||||||
# merge the dicts
|
# merge the dicts
|
||||||
res.update(d1_dict)
|
res.update(d1_dict) # type: ignore
|
||||||
res.update(d2_dict)
|
res.update(d2_dict) # type: ignore
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
||||||
class DataGraph(QtWidgets.QWidget):
|
class DataGraph(QtWidgets.QWidget):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
title,
|
title: str,
|
||||||
data=Union[dict[list, list] | dict[list[dict[str, list]]]],
|
data=Union[dict[list, list], dict[list[dict[str, list[Any]]]]],
|
||||||
generateMissing=False,
|
generateMissing: bool = False,
|
||||||
label=None,
|
label: str = None,
|
||||||
):
|
):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
log.debug(
|
log.debug(
|
||||||
|
|||||||
Reference in New Issue
Block a user