Add Adminbereich section with overview and user management pages to navigation, other changes
This commit is contained in:
@@ -94,6 +94,11 @@ jobs:
|
|||||||
- name: Install all dependencies
|
- name: Install all dependencies
|
||||||
run: uv sync --all-groups
|
run: uv sync --all-groups
|
||||||
|
|
||||||
|
- name: Build documentation
|
||||||
|
run: |
|
||||||
|
uv zensical
|
||||||
|
uv run zensical build --clean
|
||||||
|
|
||||||
- name: Build Linux release with Nuitka
|
- name: Build Linux release with Nuitka
|
||||||
run: |
|
run: |
|
||||||
uv run python -m nuitka \
|
uv run python -m nuitka \
|
||||||
@@ -172,6 +177,12 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
& $env:UV_PATH sync --all-groups
|
& $env:UV_PATH sync --all-groups
|
||||||
|
|
||||||
|
- name: Build documentation
|
||||||
|
shell: powershell
|
||||||
|
run: |
|
||||||
|
& $env:UV_PATH run pip install zensical
|
||||||
|
& $env:UV_PATH run zensical build --clean
|
||||||
|
|
||||||
- name: Build Windows release with Nuitka
|
- name: Build Windows release with Nuitka
|
||||||
shell: powershell
|
shell: powershell
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
4
.vscode/settings.json
vendored
4
.vscode/settings.json
vendored
@@ -32,6 +32,7 @@
|
|||||||
"cSpell.words": [
|
"cSpell.words": [
|
||||||
"adis",
|
"adis",
|
||||||
"Adminbereich",
|
"Adminbereich",
|
||||||
|
"akkey",
|
||||||
"Apparatdetails",
|
"Apparatdetails",
|
||||||
"apparate",
|
"apparate",
|
||||||
"appname",
|
"appname",
|
||||||
@@ -54,4 +55,7 @@
|
|||||||
"Strg",
|
"Strg",
|
||||||
"telnr"
|
"telnr"
|
||||||
],
|
],
|
||||||
|
"yaml.schemas": {
|
||||||
|
"https://www.schemastore.org/github-workflow.json": "file:///c%3A/Users/aky547/GitHub/SemesterapparatsManager/.gitea/workflows/release.yml"
|
||||||
|
},
|
||||||
}
|
}
|
||||||
1
docs/admin/uebersicht.md
Normal file
1
docs/admin/uebersicht.md
Normal file
@@ -0,0 +1 @@
|
|||||||
|
# Übersicht
|
||||||
@@ -32,6 +32,16 @@ Die Hauptoberfläche des SemesterapparatsManager besteht aus drei Hauptbereichen
|
|||||||
|
|
||||||
[:octicons-arrow-right-24: Zu ELSA](../elsa/anlegen.md)
|
[:octicons-arrow-right-24: Zu ELSA](../elsa/anlegen.md)
|
||||||
|
|
||||||
|
- :octicons-person-24:{ .lg .middle } **Admin**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Adminbereich (nur wenn der angemeldete Nutzer die `Admin` Rolle hat)
|
||||||
|
|
||||||
|
[:octicons-arrow-right-24: Zur Übersicht](../admin/uebersicht.md)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -54,4 +54,4 @@ Die Anwendung ermöglicht eine benutzerfreundliche Verwaltung von physischen und
|
|||||||
Der SemesterapparatsManager wurde entwickelt von **Alexander Kirchner** für die Pädagogische Hochschule Freiburg.
|
Der SemesterapparatsManager wurde entwickelt von **Alexander Kirchner** für die Pädagogische Hochschule Freiburg.
|
||||||
|
|
||||||
!!! info "Open Source"
|
!!! info "Open Source"
|
||||||
Der Quellcode ist auf GitHub verfügbar und kann nach Absprache eingesehen werden.
|
Der Quellcode ist auf einer privaten [Gitea](https://about.gitea.com/) Instanz und kann bei Bedarf eingesehen werden.
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ Bevor Sie den SemesterapparatsManager installieren können, stellen Sie sicher,
|
|||||||
- [x] Internetzugang für Katalog-Abfragen
|
- [x] Internetzugang für Katalog-Abfragen
|
||||||
- [x] Optional: Zotero-Account für ELSA-Funktionen
|
- [x] Optional: Zotero-Account für ELSA-Funktionen
|
||||||
|
|
||||||
|
!!! warning "Buchmetadaten"
|
||||||
|
Die Metadaten für Bücher können aktuell nur aus dem Hochschulnetz geladen werden, da diese auf ein Internes Format zugreifen, welches nur im Hochschulnetz angezeigt wird.
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
### Für Endanwender
|
### Für Endanwender
|
||||||
@@ -69,7 +71,12 @@ Beim ersten Start werden Sie aufgefordert, sich anzumelden:
|
|||||||
{ loading=lazy }
|
{ loading=lazy }
|
||||||
|
|
||||||
!!! tip "Tipp"
|
!!! tip "Tipp"
|
||||||
Ihre Anmeldedaten werden sicher gespeichert. Bei Fragen zur Einrichtung wenden Sie sich an den Administrator.
|
Ihre Anmeldedaten werden verschlüsselt gespeichert. Sollten Sie Ihr Passwort vergessen, wenden Sie sich bitten an einen Nutzer mir Adminberechtigungen, um das Passwort zu ändern. Bei Fragen zur Einrichtung wenden Sie sich an den Administrator.
|
||||||
|
|
||||||
|
Sofern Sie keine eigenen Zugangsdaten bei der Einrichtung eingegeben haben, sind dies die Standardanmeldedaten:
|
||||||
|
|
||||||
|
**Username**: admin
|
||||||
|
**Password**: admin
|
||||||
|
|
||||||
## Konfiguration
|
## Konfiguration
|
||||||
|
|
||||||
|
|||||||
@@ -1,30 +0,0 @@
|
|||||||
# Zitieren
|
|
||||||
## Oberfläche
|
|
||||||

|
|
||||||
|
|
||||||
Die [ELSA](elsa.md) Oberfläche bietet die Möglichkeit, für Einträge automatisch Zitate zu erstellen. Hierfür wird der Stil `Deutsche Gesellschaft für Psychologie (DGPs)` verwendet.
|
|
||||||
|
|
||||||
Um ein Zitat zu erstellen, muss zuerst ein Eintrag in der Tabelle ausgewählt werden. Über den Knopf **Eintrag zitieren** wird ein Dialog geöffnet, in dem der Eintrag zitiert werden kann.
|
|
||||||
Sollte ein Eintrag mehrere Abschnitte beinhalten, muss nach der automatischen Suche die Seitenzahl angepasst werden. Ist die Seitenzahl in der Tabelle nur für einen Abschnitt, so wird diese automatisch übernommen.
|
|
||||||
|
|
||||||
|
|
||||||
## Zitierdialog
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
Nachdem auf den Knopf **Eintrag zitieren** geklickt wird, wird automatisch der Katalog angefragt und relevante Daten werden in die Felder eingetragen. Ist die Seitenzahl in der Tabelle nur für einen Abschnitt, so wird diese automatisch übernommen.
|
|
||||||
|
|
||||||
!!! info "Erläuterung der Knöpfe"
|
|
||||||
|
|
||||||
- **Suchen** Sucht im Katalog nach dem eingegebenen Identifikator
|
|
||||||
- **Zitat erstellen** Stellt eine Verbindung zu Zotero her, erstellt ein entsprechendes Werk und erhält die Zitate als Ergebnis; wechselt zur Oberfläche der Zitate
|
|
||||||
- **Ok** Schließt den Dialog
|
|
||||||
- **Discard** Entfernt alle Eingaben
|
|
||||||
- **Abbrechen** Schließt den Dialog
|
|
||||||
- **Wiederholen** Geht zu den Eingabefeldern zurück, ermöglicht eine erneute Suche mit geänderten Eingaben
|
|
||||||
|
|
||||||
## Zitate
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
Über den Knopf **Zitat erstellen** wird eine Verbindung zu Zotero hergestellt und ein entsprechendes Werk erstellt. Die Zitate werden als Ergebnis angezeigt. Der Dialog wechselt automatisch zur Oberfläche der Zitate.
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
# Einstellungen
|
|
||||||

|
|
||||||
|
|
||||||
In den Einstellungen werden alle Informationen angezeigt, die in der config.yaml Datei hinterlegt sind. Diese Datei wird beim Start der Datei eingelesen und als globale Klasse `Config` gespeichert. Dadurch können Einstellungen sofort geändert werden und das Programm muss nicht für jede Änderung neu gestartet werden.
|
|
||||||
|
|
||||||
!!! Info
|
|
||||||
Die zuletzt geöffnete Seite wird automatisch beim nächsten Start geöffnet.
|
|
||||||
|
|
||||||
## Seiten
|
|
||||||
### Datenbank
|
|
||||||
|
|
||||||
Hier sind alle Informationen zur Datenbank, sowie den Tempörären Daten hinterlegt.
|
|
||||||
Der Speicherort der Datenbank kann über den Knopf `...` neben dem Datenbanknamen geändert werden. Der Datenbankpfad passt sich automatisch an.
|
|
||||||
|
|
||||||
!!! Warning "Hinweis - Mehrere Nutzer"
|
|
||||||
Sollte die Anwendung von mehreren Nutzern benutzt werden, sollte dieser Pfad nur in absprache geändert werden. Ansonsten kann es zu Problemen kommen.
|
|
||||||
|
|
||||||
### Zotero
|
|
||||||

|
|
||||||
|
|
||||||
In diesem Bereich können die Zugangsdaten für Zotero hinterlegt werden. Diese werden benötigt, um die Zitate für die [ELSA](elsa.md#einträge-zitieren) Zitate zu erstellen.
|
|
||||||
|
|
||||||
|
|
||||||
### e-Mail
|
|
||||||

|
|
||||||
Dieser Bereich ist zweigeteilt, einmal der Allgemeine Teil, und einmal der Teil für die Mailsignatur
|
|
||||||
|
|
||||||
#### Allgemein
|
|
||||||
Hier können die Zugangsdaten für den Mailversand hinterlegt werden. Diese werden benötigt, um die Nachrichten an die ProffessorInnen zu versenden. Mehr Infos: [Mailversand](mail.md)
|
|
||||||
|
|
||||||
#### Signatur
|
|
||||||
Hier kann die Signatur für die Mails hinterlegt werden. Diese wird automatisch an jede Mail angehängt.
|
|
||||||
|
|
||||||
### Icons
|
|
||||||

|
|
||||||
Hier werden sowohl die aktuellen Icons, wie auch die verfügbaren Farben angezeigt.
|
|
||||||
|
|
||||||
## Speichern
|
|
||||||
|
|
||||||
Über den Knopf **Ok** werden die Einstellungen gespeichert. Sollte ein Neustart der Anwendung erforderlich sein, wird darüber informiert. Ansonsten werden die Einstellungen sofort übernommen.
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,90 +0,0 @@
|
|||||||
# Semesterapparat anlegen
|
|
||||||
|
|
||||||
Um einen neuen Semesterapparat anzulegen, muss zuerst der Knopf "neu. App anlegen" gedrückt werden. Das Feld der Apparatdetails wird nun zum bearbeiten entsperrt, und die Daten können in die Felder eingetragen werden.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
## Apparatdetails
|
|
||||||
### Apparat anlegen
|
|
||||||
Um einen Apparat erfolgreich anzulegen, müssen alle Felder, die ein Sternchen (*) haben, ausgefüllt werden. Ist eine Eingabe nicht valide, wird neben der Eingabe ein rotes X angezeigt (siehe Bild).
|
|
||||||
Folgende Felder haben spezielle Formatierungsanforderungen:
|
|
||||||
|
|
||||||
- Prof. Name: Der Name des Professors muss in der Form "Nachname, Vorname" eingegeben werden.
|
|
||||||
- Mail: Die Mailadresse muss in der Form "irgend@etwas.xy" eingegeben werden.
|
|
||||||
- Tel: Die Telefonnummer muss mindestens 3 Ziffern enthalten.
|
|
||||||
- Semester: Das Semester wird wie folgt angegeben:
|
|
||||||
- Wintersemester: Checkbox Winter + aktives Jahr wenn Monat zwischen Oktober und Dezember; ansonsten aktives Jahr - 1
|
|
||||||
- Sommersemester: Checkbox Sommer + aktives Jahr wenn Monat zwischen März und August
|
|
||||||
|
|
||||||
|
|
||||||
Beim Versuch, den Apparat zu speichern, bevor alle Felder korrekt ausgefüllt sind, wird eine Fehlermeldung angezeigt, die auf die fehlerhaften Felder hinweist. Nachdem alle Felder korrekt ausgefüllt sind, kann der Apparat gespeichert werden.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
Über einen Klick auf Ok oder Cancel wird die Meldung geschlossen und der Apparat kann weiter bearbeitet werden.
|
|
||||||
|
|
||||||
### Dokumente hinzufügen
|
|
||||||
|
|
||||||
Dem Apparat können Dokumente hinzugefügt werden. Besonders hilfreich ist das hinzufügen der Antragsformulare, da der SemesterapparatsManager diese Datei lesen und die Bücher automatisch dem Apparat hinzufügen kann.
|
|
||||||
|
|
||||||
Dokumente werden über den Knopf "Dokumente hinzufügen" hinzugefügt werden. Es öffnet sich ein Auswahldialog, bei dem Sie dei Datei(en) auswählen können, die Sie hinzufügen möchten.
|
|
||||||
|
|
||||||
Handelt es sich bei der Datei um den Antrag, so kann dieser mit dem Knopf "Medien aus Dokument hinzufügen" ausgelesen werden.
|
|
||||||
|
|
||||||
!!! Warning "ZU BEACHTEN"
|
|
||||||
|
|
||||||
Wird dieser Knopf gedrückt, wird der Apparat, wenn möglich, gespeichert und angelegt. Dies ist notwendig, da die Medien nur dann dem Apparat hinzugefügt werden können, wenn dieser bereits in der Datenbank existiert.
|
|
||||||
|
|
||||||
Die erkannten Medien werden nun hinzugefügt. Über den Bereich "Medienliste" kann der Fortschritt eingesehen werden. Solange noch Medien hinzugefügt werden, ist es nicht möglich, den Apparat zu bearbeiten, die Auswahl zu beenden oder einen anderen Apparat auszuwählen.
|
|
||||||
|
|
||||||
### Apparat speichern
|
|
||||||
|
|
||||||
Nachdem alle Felder korrekt ausgefüllt sind, kann der Apparat gespeichert werden. Dazu muss der Knopf "Speichern" gedrückt werden. Der Apparat wird nun in der Datenbank gespeichert und wird in der Tabelle angezeigt. Wurde vor dem Speichern der Haken "Mail senden" gesetzt, öffnet sich ein Fenster, in dem einen Mail, basierend auf einem Template, an den Professor gesendet werden kann. (Erfordert Mail Zugangsdaten [siehe Konfiguration](config.md#email))
|
|
||||||
|
|
||||||
## Medienliste
|
|
||||||
|
|
||||||
In der Medienliste werden alle Medien angezeigt, die dem Apparat hinzugefügt wurden. Hier können die Medien bearbeitet, gelöscht oder hinzugefügt werden.
|
|
||||||
|
|
||||||
Wurde ein Apparat ausgewählt, werden einige Felder unterhalb der Medienliste angezeigt:
|
|
||||||

|
|
||||||
|
|
||||||
|
|
||||||
Standardmäßig werden nur Medien angezeigt, die nicht aus dem Apparat entfernt wurden. Über den Checkbox "gel. Medien anzeigen" werden auch gelöschte Medien angezeigt.
|
|
||||||
Der Knopf "im Apparat?" kann für ein einzelnes, oder mehrere Medien verwendet werden, um zu prüfen, ob die ausgewählten Medien inzwischen dem Apparat hinzugefügt wurden.
|
|
||||||
|
|
||||||
Unter der Liste befindet sich ein Knopf "Medien hinzufügen", der es ermöglicht, Medien manuell hinzuzufügen. Hierbei wird ein Dialog geöffnet, in dem die Signaturen der Medien eingetragen werden können. Die Medien werden dann dem Apparat hinzugefügt.
|
|
||||||
|
|
||||||
### Kontextmenü
|
|
||||||
|
|
||||||
Mit einem Rechtsklick auf ein Medium wird ein Kontextmenü geöffnet, das folgende Optionen enthält (Mehrfachauswahl der Medien mit Strg + Linksklick möglich):
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
#### Subbereich Allgemeines
|
|
||||||
|
|
||||||

|
|
||||||
- Bearbeiten: Öffnet ein Fenster, in dem die Metadaten des Mediums eingesehen bzw, bearbeitet werden können. (s. [Metadaten bearbeiten](edit_media.md))
|
|
||||||
- Löschen: Löscht das Medium aus dem Apparat. Das Medium wird nicht gelöscht, sondern nur aus dem Apparat entfernt. (s. [Bild](images.md#Exemplar löschen))
|
|
||||||
|
|
||||||
#### Subbereich Apparate
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
|
|
||||||
- Zum Apparat hinzufügen: *Noch nicht implementiert* (derzeit deaktiviert) Fügt das Medium dem Apparat in aDIS hinzu
|
|
||||||
- In Apparat verschieben: Öffnet ein Fenster, in dem ein anderer Apparat ausgewählt werden kann, in den die ausgewählten Medien verschoben werden sollen.
|
|
||||||
- In Apparat kopieren: Öffnet ein Fenster, in dem ein anderer Apparat ausgewählt werden kann, in den die ausgewählten Medien kopiert werden sollen.
|
|
||||||
|
|
||||||
|
|
||||||
## Medien hinzufügen
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
Um Medien hinzuzufügen, müssen die Signaturen der Medien in das Textfeld eingetragen werden. Jede Signatur muss in die Zeile eingegeben werden und mit Enter bestätigt werden.
|
|
||||||
Nachdem alle Signaturen hinzugefügt werden, können folgende Optionen gesetzt werden:
|
|
||||||
|
|
||||||
- Modus: Gibt an, welche Metadaten verwendet werden. Die beiliegende Tabelle gibt an, welche Metadaten welche Angaben enthalten.
|
|
||||||
- Jedes Buch verwenden: Diese Option ermöglicht es, Medien hinzuzufügen, die noch nicht im Apparat sind
|
|
||||||
- Exakte Signatur: Diese Option teilt dem System mit, dass genau diese Signatur verwendet werden muss. Ist diese Option nicht gesetzt, wird nach der Signatur gesucht, die am ehesten der eingegebenen Signatur entspricht. (Das gefundene Buch ist das gleiche, nur evtl. ein anderes Exemplar)
|
|
||||||
|
|
||||||
Mit dem Knopf "Ok" werden die Medien gesucht und hinzugefügt.
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
# Metadaten bearbeiten
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
In diesem Fenster können die Metadaten eines Mediums bearbeitet werden. Diese bearbeitung macht Sinn, wenn Angaben nicht direkt aus dem Katalog übernommen werden konnten, oder wenn die Angaben nicht korrekt sind.
|
|
||||||
|
|
||||||
Über den Knopf "Ok" werden die geänderten Metadaten gespeichert und das Fenster geschlossen. Über den Knopf "Abbrechen" werden die Änderungen verworfen und das Fenster geschlossen.
|
|
||||||
38
docs/elsa.md
38
docs/elsa.md
@@ -1,38 +0,0 @@
|
|||||||
# ELSA
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
## ELSA anlegen
|
|
||||||
Um einen ELSA zu erstellen, muss der Knopf **Neuer Auftrag** gedrückt werden. Das Feld *Auftragsdaten* wird zum bearbeiten freigeschaltet, der Fokus wird automatisch auf das Feld **Prof.** gesetzt.
|
|
||||||
|
|
||||||
Hier werden automatisch alle bereits vorhandenen Professoren der Semesterapparate eingetragen. Sollte der Professor noch keinen Apparat haben, so kann der Name manuell eingetragen werden. Es wird nun ein neues Element angezeigt:
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
Solange diese Felder nicht ausgefüllt sind, kann der Auftrag nicht gespeichert werden.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Um den ELSA zu speichern, müssen alle Felder ausgefüllt sein. Nach dem Speichern wird der ELSA in der Tabelle angezeigt. Über das Icon  können der aktuelle Tag und das aktuelle Semester eingetragen werden.
|
|
||||||
|
|
||||||
### Dokumente hinzufügen
|
|
||||||

|
|
||||||
|
|
||||||
Hat der Professor ein passendes Formular geliefert, so kann dieses über den Knopf **Dokument hinzufügen** hinzugefügt werden. Das Dokument wird in der Datenbank gespeichert und kann über den Knopf **Dokument öffnen** geöffnet werden. Über den Knopf **Medien aus Dokument hinzufügen** werden alle erkannten Medien aus dem Dokument in die Tabelle eingetragen und können zitiert werden.
|
|
||||||
|
|
||||||
Sollte der Professor mehrere Segmente aus einem Medium in einer Zeile gelistet haben, so können diese als seperate Einträge hinzugefügt werden. Dazu muss ein Haken bei **Abschnitte trennen** gesetzt sein.
|
|
||||||
|
|
||||||
!!! Warn "Hinweis: Datenformat im Dokument"
|
|
||||||
Um die Abschnitte erfolgreich zu trennen, müssen diese durch ein Semikolon getrennt sein.
|
|
||||||
|
|
||||||
Beispiel: `1-5; 18-25; 30-35`
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Durch den Klick auf den Knopf **Medien aus Dokument hinzufügen** wird der Auftrag automatisch gespeichert, die Medien, bzw Abschnitte werden in der Tabelle angezeigt.
|
|
||||||
|
|
||||||
### Einträge zitieren
|
|
||||||
|
|
||||||
Da alle gescannten Dokumente später auf Illias hochgeladen werden, gibt es die Funktion **Eintrag zitieren**. Für diese Funktion muss ein Eintrag in der Tabelle ausgewählt werden. Über den Knopf **Eintrag zitieren** wird ein Dialog geöffnet, in dem der Eintrag zitiert werden kann. Die Angegebene Seitenzahl wird automatisch übernommen.
|
|
||||||
Genauere Beschreibung: [Zitieren](citing.md)
|
|
||||||
|
|
||||||
@@ -34,7 +34,7 @@ Im Feld **Prof.** werden automatisch alle bereits vorhandenen Dozenten aus den S
|
|||||||
|
|
||||||
## Schnelleingabe
|
## Schnelleingabe
|
||||||
|
|
||||||
Über das Kalender-Icon { .twemoji } können automatisch eingetragen werden:
|
Über das Kalender-Icon :octicons-calendar-24: können automatisch eingetragen werden:
|
||||||
|
|
||||||
- [x] Aktuelles Datum
|
- [x] Aktuelles Datum
|
||||||
- [x] Aktuelles Semester
|
- [x] Aktuelles Semester
|
||||||
@@ -83,4 +83,4 @@ Die erkannten Medien erscheinen in der Tabelle und können:
|
|||||||
|
|
||||||
## Dokument öffnen
|
## Dokument öffnen
|
||||||
|
|
||||||
Über **Dokument öffnen** kann das hinzugefügte Formular jederzeit eingesehen werden.
|
Über **Dokument öffnen** kann das hinzugefügte Formular jederzeit eingesehen werden. Es wird hierfür eine temporäre Datei erstellt und im entsprechenden Program (Bspw: Word, Excel, Email) geöffnet.
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
# Verlängerung
|
|
||||||
|
|
||||||
Ein Dialog zum Verlängern eines Apparates.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
Zum Verlängern muss ein Semester ausgewählt, und ein Jahr eingetragen sein. Die Checkbox für den Dauerapparat kann angekreuzt werden, um den Apparat als Dauerapparat zu markieren.
|
|
||||||
|
|
||||||
!!! Info "Info Dauerapparat"
|
|
||||||
Damit der Apparat als Dauerapparat verlängert werden kann, muss ein Semester angegeben werden.
|
|
||||||
|
|
||||||
Nach dem Speichern wird das Semester automatisch angepasst und in den entsprechenden Tabellen angezeigt.
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
# Bilder
|
|
||||||
|
|
||||||
## Admin Aktionen
|
|
||||||

|
|
||||||
|
|
||||||
## Apparatscheckliste
|
|
||||||

|
|
||||||
|
|
||||||
## Medien hinzufügen
|
|
||||||

|
|
||||||
|
|
||||||
## Kalendar
|
|
||||||

|
|
||||||
|
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
# SemesterapparatsManager
|
|
||||||
|
|
||||||
Willkommen zur Dokumentation des **SemesterapparatsManager**!
|
|
||||||
|
|
||||||
{ loading=lazy }
|
|
||||||
|
|
||||||
Der SemesterapparatsManager ist ein grafisches Werkzeug zur Verwaltung von Semesterapparaten an der Pädagogischen Hochschule Freiburg. Die Anwendung ermöglicht eine benutzerfreundliche Verwaltung von physischen und digitalen Semesterapparaten.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## :lucide-rocket: Schnellstart
|
|
||||||
|
|
||||||
<div class="grid cards" markdown>
|
|
||||||
|
|
||||||
- :lucide-download:{ .lg .middle } **Installation**
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
Installieren Sie den SemesterapparatsManager in wenigen Schritten.
|
|
||||||
|
|
||||||
[:octicons-arrow-right-24: Zur Installation](allgemein/installation.md)
|
|
||||||
|
|
||||||
- :lucide-layout-dashboard:{ .lg .middle } **Hauptoberfläche**
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
Lernen Sie die Benutzeroberfläche kennen.
|
|
||||||
|
|
||||||
[:octicons-arrow-right-24: Zur Übersicht](allgemein/hauptoberflaeche.md)
|
|
||||||
|
|
||||||
- :lucide-book-open:{ .lg .middle } **Semesterapparat anlegen**
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
Erstellen Sie Ihren ersten Semesterapparat.
|
|
||||||
|
|
||||||
[:octicons-arrow-right-24: Zum Tutorial](semesterapparat/anlegen.md)
|
|
||||||
|
|
||||||
- :lucide-file-text:{ .lg .middle } **ELSA**
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
Elektronische Semesterapparate verwalten.
|
|
||||||
|
|
||||||
[:octicons-arrow-right-24: Zu ELSA](elsa/anlegen.md)
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## :lucide-folder-tree: Dokumentationsstruktur
|
|
||||||
|
|
||||||
Diese Dokumentation ist in folgende Bereiche unterteilt:
|
|
||||||
|
|
||||||
| Bereich | Beschreibung |
|
|
||||||
|---------|--------------|
|
|
||||||
| **[Allgemein](allgemein/index.md)** | Grundlegende Informationen, Installation und Übersicht der Hauptoberfläche |
|
|
||||||
| **[Semesterapparat](semesterapparat/index.md)** | Anlegen, Verlängern, Löschen und Suchen von Semesterapparaten |
|
|
||||||
| **[ELSA](elsa/index.md)** | Elektronische Semesterapparate anlegen und Zitate erstellen |
|
|
||||||
| **[Sonstiges](sonstiges/index.md)** | Zusätzliche Informationen und Bildmaterial |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## :lucide-sparkles: Features
|
|
||||||
|
|
||||||
<div class="grid" markdown>
|
|
||||||
|
|
||||||
!!! success "Automatisierung"
|
|
||||||
- Automatisches Auslesen von Antragsformularen
|
|
||||||
- Automatische Zitat-Erstellung via Zotero
|
|
||||||
- E-Mail-Benachrichtigungen an Dozenten
|
|
||||||
|
|
||||||
!!! info "Verwaltung"
|
|
||||||
- Zentrale Datenbank für alle Apparate
|
|
||||||
- Statistiken und Auswertungen
|
|
||||||
- Such- und Filterfunktionen
|
|
||||||
|
|
||||||
!!! tip "Integration"
|
|
||||||
- Anbindung an den Bibliothekskatalog
|
|
||||||
- Zotero-Integration für Zitate
|
|
||||||
- Mail-System für Kommunikation
|
|
||||||
|
|
||||||
!!! example "Benutzerfreundlich"
|
|
||||||
- Intuitive grafische Oberfläche
|
|
||||||
- Keyboard-Shortcuts
|
|
||||||
- Kontextmenüs für schnellen Zugriff
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
!!! tip "Tipp: Suche"
|
|
||||||
Nutzen Sie die **Suchfunktion** oben rechts ++ctrl+k++, um schnell zu den gewünschten Informationen zu gelangen.
|
|
||||||
47
docs/mail.md
47
docs/mail.md
@@ -1,47 +0,0 @@
|
|||||||
# Mails
|
|
||||||
|
|
||||||
Der SemesterapparatsManager hat die Option, den Dozenten beim erstellen eines Apparates eine Mail zu schicken. Diese Mail enthält die Information, dass der Apparat erstellt wurde und wie er aufgerufen werden kann.
|
|
||||||
|
|
||||||
Zusätzlich kann beim Löschen eines Apparates eine Mail an den Dozenten geschickt werden. Diese Mail enthält die Information, dass der Apparat gelöscht wurde.
|
|
||||||
|
|
||||||
Über eine neue Oberfläche können neue Mail Templates erstellt werden.
|
|
||||||
|
|
||||||
|
|
||||||
## Mail
|
|
||||||
|
|
||||||
Abhängig davon, ob ein Apparat erstellt oder gelöscht wird/wurde, wird automatisch ein Template geladen. Somit muss nur noch die Anrede und der Text angepasst werden.
|
|
||||||
|
|
||||||
Bsp:
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
!!! Info
|
|
||||||
Die Felder **eMail** und **Prof** sind schreibgeschützt und können nicht verändert werden.
|
|
||||||
|
|
||||||
Über das Dropdown Menü **Art** kann das entsprechende Template ausgewählt werden. Der Knopf recht danaben kann für das [erstellen](#neue-mail-templates) neuer Templates genutzt werden.
|
|
||||||
|
|
||||||
Um die Mail abschicken zu können, muss die Anrede mithilfe der Knöpfe über dem Mailtext konfiguriert werden. Die Anrede passt sich automatisch an, basierend auf der angegebenen Anrede.
|
|
||||||
|
|
||||||
Wird die Mail erfolgreich verschickt, schließt sich das Fenster automatisch, und es wird eine Kopie der Mail an die Mail semesterapparate@ph-freiburg.de geschickt.
|
|
||||||
|
|
||||||
## Neue Mail Templates
|
|
||||||
|
|
||||||
Über den Knopf rechts neben der Auswahl der Email Templates können neue Templates erstellt werden.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
Diese Oberfläche bietet die Möglichkeit, ein neues Template zu erstellen. Mithilfe des Dropdowns **Platzhalter** können Platzhalter ausgewählt und eingefügt werden. Bevor das Template gespeichert werden kann, muss dieses getestet werden. Sollte der Test erfolgreich sein, kann ein Name vergeben werden, das Template wird nun in dem Dropdown angezeigt.
|
|
||||||
|
|
||||||
### Template testen
|
|
||||||
Sollten Angaben fehlen, wird eine Fehlermeldung angezeigt:
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
!!! info
|
|
||||||
Die Fehlermeldung ist dynamisch und gibt immer die fehlenden Angaben an.
|
|
||||||
|
|
||||||
|
|
||||||
### Template speichern
|
|
||||||
Ist das Template fehlerfrei, wird folgender Dialog angezeigt:
|
|
||||||
|
|
||||||

|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
# Hauptoberfläche
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
Die Hauptoberfläche des SemesterapparatsManager besteht aus drei Hauptbereichen:
|
|
||||||
|
|
||||||
- **Anlegen**: Auf dieser Seite können neue Semesterapparate angelegt werden, bestehende Apparate aktualisiert oder gelöscht werden. Weitere Informationen siehe: [Anlegen](create.md)
|
|
||||||
|
|
||||||
- **Suchen/Statistik**: Hier können Semesterapparate gesucht, gefiltert, gelöscht und verlängert werden. Zudem werden Statistiken zum erstellen / löschen von Semesterapparaten angezeigt. Ein zweiter Tab ermöglicht die Suche der Medien in den Semesterapparaten. Weitere Informationen siehe: [Suchen / Statistik](search.md)
|
|
||||||
|
|
||||||
- **ELSA**: Hier können ELSA Apparate angelegt werden, und entsprechende Dateinamen, Beschreibungen und Zitate erstellt werden. Weitere Informationen siehe: [ELSA](elsa.md)
|
|
||||||
|
|
||||||
## Übersichtstabelle
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
In diesem Bereich werden alle erstellten Semesterapparate angezeigt. Über einen Doppelklick auf einen Apparat werden alle Details geladen und in den Apparatdetails angezeigt. Hier können dann auch einige Angaben geändert werden.
|
|
||||||
Weitere Infos siehe: [Anlegen](create.md)
|
|
||||||
|
|
||||||
### Knöpfe
|
|
||||||
Dieser Bereich hat folgende Knöpfe:
|
|
||||||
|
|
||||||
- **Übersicht erstellen**: Erstellt eine Übersicht der angezeigten Apparate, welche am Regal ausgehängt werden kann. Diese Übersicht wird per Mail an den Drucker geschickt. Vor dem Drucken erfolgt einen Bestätigungsabfrage.
|
|
||||||
- **neu. App anlegen**: Schaltet die Apparatdetails frei, um einen neuen Apparat anzulegen. Weiteres siehe: [Anlegen](create.md)
|
|
||||||
- **Auswahl abbrechen**: Entfernt alle Daten aus den Apparatsdetails und schaltet diese wieder auf inaktiv.
|
|
||||||
|
|
||||||
|
|
||||||
106
docs/search.md
106
docs/search.md
@@ -1,106 +0,0 @@
|
|||||||
# Suche und Statistik
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
Auf dieser Seite gibt es zwei Hauptfunktionen: die Suche und die Statistik. Standardmäßig wird die Statistik geöffnet.
|
|
||||||
|
|
||||||
|
|
||||||
## Statistikbereich
|
|
||||||
|
|
||||||
### Suche
|
|
||||||

|
|
||||||
|
|
||||||
In diesem Bereich kann die Suche nach Semesterapparaten durchgeführt werden. Suchoptionen sind:
|
|
||||||
|
|
||||||
- **Appnr**: Die Nummer des Semesterapparates, die Auswahl zeigt alle belegten Semesterapparat an
|
|
||||||
- **Person**: Der Name des Dozenten, der den Semesterapparat erstellt hat
|
|
||||||
- **Fach**: Das Fach des Semesterapparates
|
|
||||||
- **Erstell-** und **Endsemester**: Semester, in denen der Semesterapparat erstellt wurde, bzw enden soll
|
|
||||||
- **Dauerapp**: Alle Apparate, die als Dauerapparat vermerkt sind
|
|
||||||
- **Löschbar**: Überschreibt alle vorhergehenden Parameter und zeigt alle Semesterapparate an, die gelöscht werden können
|
|
||||||
|
|
||||||
!!! Info
|
|
||||||
Um alle Semesterapparate anzuzeigen, kann die Suche ohne Eingabe gestartet werden.
|
|
||||||
|
|
||||||
Die Suche kann durch Klicken auf den Button **Suchen** gestartet werden. Die Ergebnisse werden in der Tabelle darunter angezeigt.
|
|
||||||
|
|
||||||
### Suchergebnisse
|
|
||||||
!!! Info
|
|
||||||
Der Ergebnisbereich kann über den Vertikalen Slider verschoben werden, um mehr Platz für Tabelle, oder den Graphen zu schaffen. Hierzu mit der Maus auf den Raum zwischen den beiden Bereichen klicken und ziehen.
|
|
||||||

|
|
||||||
|
|
||||||
In diesem Bereich werden die Suchergebnisse angezeigt. Für jeden gefundenen Treffer wird eine Zeile angelegt:
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
Angezeigt werden:
|
|
||||||
|
|
||||||
- **Checkbox**
|
|
||||||
- **Apparatsname**
|
|
||||||
- **Apparatsnummer**
|
|
||||||
- **Person**
|
|
||||||
- **Fach**
|
|
||||||
|
|
||||||
!!! failure "Info: Gelöschte Apparate"
|
|
||||||
Gelöschte Apparate werden in der Tabelle mit rotem Hintergrund angezeigt. (s. Ausgewählte Löschen)
|
|
||||||
Über der Tabelle sind zwei Knöpfe: **Ausgewählte Löschen** und **Ausgewählte Benachrichtigen**
|
|
||||||
|
|
||||||
Um diese Aktionen auszuführen, muss mindestens eine Checkbox bei einem Apparat angekreuzt sein.
|
|
||||||
|
|
||||||
#### Ausgewählte Löschen
|
|
||||||

|
|
||||||
|
|
||||||
Nach dem Klicken auf den Button **Ausgewählte Löschen** wird jeder ausgewählte Apparat gelöscht. Die gelöschten Apparate werden in der Tabelle mit rotem Hintergrund angezeigt.
|
|
||||||
|
|
||||||
#### Ausgewählte Benachrichtigen
|
|
||||||
|
|
||||||
Mit dem Klick auf den Button wird ein neues Fenster geöffnet:
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
Bevor die Mail abgeschickt werden kann, muss die Anrede konfiguriert werden. Weitere Infors finden Sie im Abschnitt [Mails](mail.md).
|
|
||||||
|
|
||||||
#### Kontextmenü
|
|
||||||
|
|
||||||
Diese Tabelle bietet auch ein Rechtsklickmenu mit folgenden Optionen:
|
|
||||||
|
|
||||||
- **Verlängern**: Öffnet den [Verlängerungsdialog](extend.md)
|
|
||||||
- **Wiederherstellen**: Stellt einen gelöschten Apparat wieder her
|
|
||||||
|
|
||||||
!!! Info "Info: Wiederherstellen"
|
|
||||||
Diese Option kann für einen oder mehrere gelöschte Apparate verwendet werden. Für mehrere Apprate müssen die entsprechenden Zeilen mit Strg+Klick auf die Zeilennummer markiert werden.
|
|
||||||
|
|
||||||
|
|
||||||
### Apparatsstatistik
|
|
||||||
Rechts neben der Tabelle wird die Statistik der gefundenen Apparate angezeigt:
|
|
||||||

|
|
||||||
Hierbei werden die Angaben sowohl in einer Tabelle als auch in einem Diagramm dargestellt.
|
|
||||||
#### Tabelle
|
|
||||||
In der Tabelle werden alle Verwendeten Semester agegeben, in denen ein Apparat entweder erstellt oder gelöscht wurde.
|
|
||||||
|
|
||||||
Über einen Doppelklick auf ein Semester werden die Apparate angezeigt, die in diesem Semester erstellt oder gelöscht wurden.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
Ein Klick auf das `>` Symbol einer Person zeigt alle erstellten oder gelöschten Apparate der Person an. Ein Doppelklick auf den erstellten Apparat wechselt die Ansicht zur [Hauptoberfläche](mainUI.md) und zeigt alle Daten an.
|
|
||||||
|
|
||||||
!!! Info "Info: Gelöschte Apparate"
|
|
||||||
Gelöschte Apparate können nicht angezeigt werden, die Doppelklick Funktion ist hier deaktiviert.
|
|
||||||
|
|
||||||
#### Diagramm
|
|
||||||
Das Diagramm zeigt die Anzahl der erstellten und gelöschten Apparate in einem Liniendiagramm an.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
## Suchbereich
|
|
||||||
|
|
||||||
Der Suchbereich kann verwendet werden, um zu prüfen, ob ein Exemplar in einem Apparat vorhanden ist. Mögliche Suchkriterien sind:
|
|
||||||
|
|
||||||
- **Titel**: Der Titel des Exemplars (Trunkierung wurd automaticsh durchgeführt)
|
|
||||||
- **Signatur**: Die Signatur des Exemplars (Trunkierung wurd automaticsh durchgeführt)
|
|
||||||
|
|
||||||
Über den Knopf **Suchen** wird die Suche gestartet. Die Ergebnisse werden in der Tabelle darunter angezeigt.
|
|
||||||
|
|
||||||
!!! Info "Info: Exemplarsuche"
|
|
||||||
Im Vergleich zur Apparatssuche kann hier keine Leere Suche durchgeführt werden, da ggf. zu viele Ergebnisse angezeigt werden können.
|
|
||||||
|
|
||||||
@@ -55,10 +55,11 @@ Dem Apparat können Dokumente hinzugefügt werden. Besonders hilfreich ist das H
|
|||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
graph LR
|
graph LR
|
||||||
A[Dokument hinzufügen] --> B{Antragsformular?}
|
A[Dokument hinzufügen] --> B{Nächste Aktion}
|
||||||
B -->|Ja| C[Medien aus Dokument hinzufügen]
|
B -->|"Daten [...] übernehmen"| C[Medien aus Dokument hinzufügen]
|
||||||
B -->|Nein| D[Als Referenz speichern]
|
B -->|Nein| D[Als Referenz speichern]
|
||||||
C --> E[Medien werden automatisch erkannt]
|
C --> E[Medien werden automatisch erkannt]
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
1. Klicken Sie auf **Dokumente hinzufügen**
|
1. Klicken Sie auf **Dokumente hinzufügen**
|
||||||
|
|||||||
30
mkdocs.yml
30
mkdocs.yml
@@ -1,30 +0,0 @@
|
|||||||
site_name: SemesterapparatsManager
|
|
||||||
theme:
|
|
||||||
features:
|
|
||||||
- search.suggest
|
|
||||||
- search.highlight
|
|
||||||
name: material
|
|
||||||
icon:
|
|
||||||
admonition:
|
|
||||||
note: fontawesome/solid/note-sticky
|
|
||||||
abstract: fontawesome/solid/book
|
|
||||||
info: fontawesome/solid/circle-info
|
|
||||||
tip: fontawesome/solid/bullhorn
|
|
||||||
success: fontawesome/solid/check
|
|
||||||
question: fontawesome/solid/circle-question
|
|
||||||
warning: fontawesome/solid/triangle-exclamation
|
|
||||||
failure: fontawesome/solid/bomb
|
|
||||||
danger: fontawesome/solid/skull
|
|
||||||
bug: fontawesome/solid/robot
|
|
||||||
example: fontawesome/solid/flask
|
|
||||||
quote: fontawesome/solid/quote-left
|
|
||||||
|
|
||||||
markdown_extensions:
|
|
||||||
- admonition
|
|
||||||
- pymdownx.details
|
|
||||||
- pymdownx.superfences
|
|
||||||
- tables
|
|
||||||
extra_css:
|
|
||||||
- stylesheets/extra.css
|
|
||||||
plugins:
|
|
||||||
- search
|
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
|
from .utils.icon import Icon
|
||||||
|
|
||||||
__version__ = "1.0.0"
|
__version__ = "1.0.0"
|
||||||
__author__ = "Alexander Kirchner"
|
__author__ = "Alexander Kirchner"
|
||||||
__all__ = ["__version__", "__author__", "Icon", "settings"]
|
__all__ = ["Icon", "__author__", "__version__", "settings"]
|
||||||
|
|
||||||
import os
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
@@ -13,9 +15,9 @@ from config import Config
|
|||||||
app = AppDirs("SemesterApparatsManager", "SAM")
|
app = AppDirs("SemesterApparatsManager", "SAM")
|
||||||
LOG_DIR: str = app.user_log_dir # type: ignore
|
LOG_DIR: str = app.user_log_dir # type: ignore
|
||||||
CONFIG_DIR: str = app.user_config_dir # type: ignore
|
CONFIG_DIR: str = app.user_config_dir # type: ignore
|
||||||
if not os.path.exists(LOG_DIR): # type: ignore
|
if not Path(LOG_DIR).exists(): # type: ignore
|
||||||
os.makedirs(LOG_DIR) # type: ignore
|
os.makedirs(LOG_DIR) # type: ignore
|
||||||
if not os.path.exists(CONFIG_DIR): # type: ignore
|
if not Path(CONFIG_DIR).exists(): # type: ignore
|
||||||
os.makedirs(CONFIG_DIR) # type: ignore
|
os.makedirs(CONFIG_DIR) # type: ignore
|
||||||
|
|
||||||
|
|
||||||
@@ -23,13 +25,12 @@ settings = Config(f"{CONFIG_DIR}/config.yaml")
|
|||||||
DATABASE_DIR: Union[Path, str] = ( # type: ignore
|
DATABASE_DIR: Union[Path, str] = ( # type: ignore
|
||||||
app.user_config_dir if settings.database.path is None else settings.database.path # type: ignore
|
app.user_config_dir if settings.database.path is None else settings.database.path # type: ignore
|
||||||
)
|
)
|
||||||
if not os.path.exists(DATABASE_DIR): # type: ignore
|
if not Path(DATABASE_DIR).exists(): # type: ignore
|
||||||
os.makedirs(DATABASE_DIR) # type: ignore
|
os.makedirs(DATABASE_DIR) # type: ignore
|
||||||
first_launch = settings.exists
|
first_launch = settings.exists
|
||||||
if not os.path.exists(settings.database.temp.expanduser()): # type: ignore
|
if not Path(settings.database.temp.expanduser()).exists(): # type: ignore
|
||||||
settings.database.temp.expanduser().mkdir(parents=True, exist_ok=True) # type: ignore
|
settings.database.temp.expanduser().mkdir(parents=True, exist_ok=True) # type: ignore
|
||||||
from .utils.icon import Icon
|
|
||||||
|
|
||||||
if not os.path.exists("logs"):
|
if not Path("logs").exists():
|
||||||
os.mkdir("logs")
|
Path("logs").mkdir(exist_ok=True)
|
||||||
# open and close the file to create it
|
# open and close the file to create it
|
||||||
|
|||||||
@@ -38,13 +38,13 @@ class Prof:
|
|||||||
|
|
||||||
# add function that sets the data from a tuple
|
# add function that sets the data from a tuple
|
||||||
def from_tuple(self, data: tuple[Union[str, int], ...]) -> "Prof":
|
def from_tuple(self, data: tuple[Union[str, int], ...]) -> "Prof":
|
||||||
setattr(self, "id", data[0])
|
self.id = data[0]
|
||||||
setattr(self, "_title", data[1])
|
self._title = data[1]
|
||||||
setattr(self, "firstname", data[2])
|
self.firstname = data[2]
|
||||||
setattr(self, "lastname", data[3])
|
self.lastname = data[3]
|
||||||
setattr(self, "fullname", data[4])
|
self.fullname = data[4]
|
||||||
setattr(self, "mail", data[5])
|
self.mail = data[5]
|
||||||
setattr(self, "telnr", data[6])
|
self.telnr = data[6]
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def name(self, comma: bool = False) -> Optional[str]:
|
def name(self, comma: bool = False) -> Optional[str]:
|
||||||
@@ -78,7 +78,7 @@ class BookData:
|
|||||||
in_apparat: bool | None = False
|
in_apparat: bool | None = False
|
||||||
adis_idn: str | None = None
|
adis_idn: str | None = None
|
||||||
old_book: Any | None = None
|
old_book: Any | None = None
|
||||||
media_type: str | None = None #
|
media_type: str | None = None
|
||||||
in_library: bool | None = None # whether the book is in the library or not
|
in_library: bool | None = None # whether the book is in the library or not
|
||||||
medianr: int | None = None # Media number in the library system
|
medianr: int | None = None # Media number in the library system
|
||||||
|
|
||||||
@@ -140,8 +140,7 @@ class BookData:
|
|||||||
def get_book_type(self) -> str:
|
def get_book_type(self) -> str:
|
||||||
if "Online" in self.pages:
|
if "Online" in self.pages:
|
||||||
return "eBook"
|
return "eBook"
|
||||||
else:
|
return "Druckausgabe"
|
||||||
return "Druckausgabe"
|
|
||||||
|
|
||||||
def from_string(self, data: str) -> "BookData":
|
def from_string(self, data: str) -> "BookData":
|
||||||
ndata = json.loads(data)
|
ndata = json.loads(data)
|
||||||
@@ -264,8 +263,7 @@ class Apparat:
|
|||||||
def get_semester(self) -> Optional[str]:
|
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:
|
return self.created_semester
|
||||||
return self.created_semester
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
@@ -329,7 +327,7 @@ class Book:
|
|||||||
self.publisher == "",
|
self.publisher == "",
|
||||||
self.signature == "",
|
self.signature == "",
|
||||||
self.internal_notes == "",
|
self.internal_notes == "",
|
||||||
]
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
def from_dict(self, data: dict[str, Any]):
|
def from_dict(self, data: dict[str, Any]):
|
||||||
@@ -369,8 +367,12 @@ class SemapDocument:
|
|||||||
title_length = 0
|
title_length = 0
|
||||||
title_max_length = 0
|
title_max_length = 0
|
||||||
|
|
||||||
def __post_init__(self):
|
def __post_init__(self) -> None:
|
||||||
|
"""."""
|
||||||
self.title_suggestions = []
|
self.title_suggestions = []
|
||||||
|
self.phoneNumber = int(
|
||||||
|
regex.sub(r"[^\d]", "", str(self.phoneNumber)),
|
||||||
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def nameSetter(self):
|
def nameSetter(self):
|
||||||
@@ -389,7 +391,6 @@ class SemapDocument:
|
|||||||
self.title_suggestions.append(suggestion["shortened_string"])
|
self.title_suggestions.append(suggestion["shortened_string"])
|
||||||
else:
|
else:
|
||||||
self.title_suggestions = []
|
self.title_suggestions = []
|
||||||
pass
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def renameSemester(self) -> None:
|
def renameSemester(self) -> None:
|
||||||
@@ -400,7 +401,7 @@ class SemapDocument:
|
|||||||
self.semester = Semester().from_string(self.semester)
|
self.semester = Semester().from_string(self.semester)
|
||||||
else:
|
else:
|
||||||
self.semester = Semester().from_string(
|
self.semester = Semester().from_string(
|
||||||
semester_converter(self.semester)
|
semester_converter(self.semester),
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|||||||
@@ -669,7 +669,7 @@ Nachname, Vorname</string>
|
|||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QToolButton" name="copy_qoute">
|
<widget class="QToolButton" name="copy_quote">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Kopieren</string>
|
<string>Kopieren</string>
|
||||||
</property>
|
</property>
|
||||||
@@ -763,7 +763,7 @@ Nachname, Vorname</string>
|
|||||||
<tabstop>ilias_filename</tabstop>
|
<tabstop>ilias_filename</tabstop>
|
||||||
<tabstop>copy_filename</tabstop>
|
<tabstop>copy_filename</tabstop>
|
||||||
<tabstop>copy_ilias_filename</tabstop>
|
<tabstop>copy_ilias_filename</tabstop>
|
||||||
<tabstop>copy_qoute</tabstop>
|
<tabstop>copy_quote</tabstop>
|
||||||
<tabstop>retryButton</tabstop>
|
<tabstop>retryButton</tabstop>
|
||||||
</tabstops>
|
</tabstops>
|
||||||
<resources/>
|
<resources/>
|
||||||
|
|||||||
@@ -18,13 +18,13 @@ class ElsaAddEntry(QtWidgets.QDialog, Ui_Dialog):
|
|||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
self.setWindowTitle("Eintrag zitieren")
|
self.setWindowTitle("Eintrag zitieren")
|
||||||
self.buttonBox.button(
|
self.buttonBox.button(
|
||||||
QtWidgets.QDialogButtonBox.StandardButton.Ok
|
QtWidgets.QDialogButtonBox.StandardButton.Ok,
|
||||||
).clicked.connect(self.accept)
|
).clicked.connect(self.accept)
|
||||||
self.buttonBox.button(
|
self.buttonBox.button(
|
||||||
QtWidgets.QDialogButtonBox.StandardButton.Cancel
|
QtWidgets.QDialogButtonBox.StandardButton.Cancel,
|
||||||
).clicked.connect(self.close)
|
).clicked.connect(self.close)
|
||||||
self.buttonBox.button(
|
self.buttonBox.button(
|
||||||
QtWidgets.QDialogButtonBox.StandardButton.Discard
|
QtWidgets.QDialogButtonBox.StandardButton.Discard,
|
||||||
).clicked.connect(self.discard)
|
).clicked.connect(self.discard)
|
||||||
self.mode = None
|
self.mode = None
|
||||||
self.btn_search.clicked.connect(self.search)
|
self.btn_search.clicked.connect(self.search)
|
||||||
@@ -33,13 +33,13 @@ class ElsaAddEntry(QtWidgets.QDialog, Ui_Dialog):
|
|||||||
self.btn_hg.clicked.connect(self.stack)
|
self.btn_hg.clicked.connect(self.stack)
|
||||||
self.make_quote.clicked.connect(self.display_data)
|
self.make_quote.clicked.connect(self.display_data)
|
||||||
self.copy_filename.clicked.connect(
|
self.copy_filename.clicked.connect(
|
||||||
lambda: self.copy_to_clipboard(self.filename_edit)
|
lambda: self.copy_to_clipboard(self.filename_edit),
|
||||||
)
|
)
|
||||||
self.copy_ilias_filename.clicked.connect(
|
self.copy_ilias_filename.clicked.connect(
|
||||||
lambda: self.copy_to_clipboard(self.ilias_filename)
|
lambda: self.copy_to_clipboard(self.ilias_filename),
|
||||||
)
|
)
|
||||||
self.copy_qoute.clicked.connect(
|
self.copy_quote.clicked.connect(
|
||||||
lambda: self.copy_to_clipboard(self.file_desc_edit)
|
lambda: self.copy_to_clipboard(self.file_desc_edit),
|
||||||
)
|
)
|
||||||
self.setWindowIcon(Icon("edit").icon)
|
self.setWindowIcon(Icon("edit").icon)
|
||||||
self.stackedWidget.setEnabled(False)
|
self.stackedWidget.setEnabled(False)
|
||||||
@@ -61,11 +61,11 @@ class ElsaAddEntry(QtWidgets.QDialog, Ui_Dialog):
|
|||||||
|
|
||||||
def check_pages(self):
|
def check_pages(self):
|
||||||
if self.source_pages:
|
if self.source_pages:
|
||||||
if self.book_pages.text() != self.source_pages:
|
if (
|
||||||
self.make_quote.setEnabled(True)
|
self.book_pages.text() != self.source_pages
|
||||||
elif self.hg_pages.text() != self.source_pages:
|
or self.hg_pages.text() != self.source_pages
|
||||||
self.make_quote.setEnabled(True)
|
or self.zs_pages.text() != self.source_pages
|
||||||
elif self.zs_pages.text() != self.source_pages:
|
):
|
||||||
self.make_quote.setEnabled(True)
|
self.make_quote.setEnabled(True)
|
||||||
|
|
||||||
def copy_to_clipboard(self, field):
|
def copy_to_clipboard(self, field):
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
# encoding: utf-8
|
from __future__ import annotations
|
||||||
|
|
||||||
import atexit
|
import atexit
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
@@ -6,7 +7,7 @@ import tempfile
|
|||||||
import time
|
import time
|
||||||
import webbrowser
|
import webbrowser
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, List, Optional, Tuple, Union
|
from typing import Any, Optional, Union
|
||||||
|
|
||||||
from natsort import natsorted
|
from natsort import natsorted
|
||||||
from PySide6 import QtCore, QtGui, QtWidgets
|
from PySide6 import QtCore, QtGui, QtWidgets
|
||||||
@@ -15,14 +16,13 @@ from PySide6.QtGui import QRegularExpressionValidator
|
|||||||
from PySide6.QtMultimedia import QAudioOutput, QMediaPlayer
|
from PySide6.QtMultimedia import QAudioOutput, QMediaPlayer
|
||||||
|
|
||||||
from src import Icon
|
from src import Icon
|
||||||
from src.database import Database
|
|
||||||
from src.background import (
|
from src.background import (
|
||||||
AvailChecker,
|
AvailChecker,
|
||||||
BookGrabber,
|
BookGrabber,
|
||||||
DocumentationThread,
|
DocumentationThread,
|
||||||
NewEditionCheckerThread,
|
NewEditionCheckerThread,
|
||||||
)
|
)
|
||||||
from src.utils.files import recreateFile, delete_temp_contents as tempdelete
|
from src.core.constants import APP_NRS
|
||||||
from src.core.models import (
|
from src.core.models import (
|
||||||
Apparat,
|
Apparat,
|
||||||
ApparatData,
|
ApparatData,
|
||||||
@@ -31,15 +31,15 @@ from src.core.models import (
|
|||||||
SemapDocument,
|
SemapDocument,
|
||||||
Semester,
|
Semester,
|
||||||
)
|
)
|
||||||
from src.core.constants import APP_NRS
|
from src.database import Database
|
||||||
from src.parsers import (
|
|
||||||
csv_to_list,
|
|
||||||
)
|
|
||||||
from src.logic import (
|
from src.logic import (
|
||||||
eml_to_semap,
|
eml_to_semap,
|
||||||
pdf_to_semap,
|
pdf_to_semap,
|
||||||
word_to_semap,
|
word_to_semap,
|
||||||
)
|
)
|
||||||
|
from src.parsers import (
|
||||||
|
csv_to_list,
|
||||||
|
)
|
||||||
from src.shared.logging import log
|
from src.shared.logging import log
|
||||||
from src.ui import Ui_Semesterapparat
|
from src.ui import Ui_Semesterapparat
|
||||||
from src.ui.dialogs import (
|
from src.ui.dialogs import (
|
||||||
@@ -71,6 +71,8 @@ from src.ui.widgets import (
|
|||||||
UpdateSignatures,
|
UpdateSignatures,
|
||||||
UserCreate,
|
UserCreate,
|
||||||
)
|
)
|
||||||
|
from src.utils.files import delete_temp_contents as tempdelete
|
||||||
|
from src.utils.files import recreateFile
|
||||||
|
|
||||||
log.success("UI started")
|
log.success("UI started")
|
||||||
valid_input = (0, 0, 0, 0, 0, 0)
|
valid_input = (0, 0, 0, 0, 0, 0)
|
||||||
@@ -86,17 +88,17 @@ class Ui(QtWidgets.QMainWindow, Ui_Semesterapparat):
|
|||||||
self.MainWindow = MainWindow # type:ignore
|
self.MainWindow = MainWindow # type:ignore
|
||||||
# set the window title
|
# set the window title
|
||||||
MainWindow.setWindowTitle(
|
MainWindow.setWindowTitle(
|
||||||
f"Semesterapparatsmanagement Semester: {Semester().value}"
|
f"Semesterapparatsmanagement Semester: {Semester().value}",
|
||||||
) # type:ignore
|
) # type:ignore
|
||||||
MainWindow.setWindowIcon(Icon("logo").icon) # type:ignore
|
MainWindow.setWindowIcon(Icon("logo").icon) # type:ignore
|
||||||
|
|
||||||
self.db = Database()
|
self.db = Database()
|
||||||
self.btn_add_document.clicked.connect(self.add_document) # type:ignore
|
self.btn_add_document.clicked.connect(self.add_document) # type:ignore
|
||||||
self.check_file.clicked.connect( # type:ignore
|
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.btn_extract_data_from_document.clicked.connect( # type:ignore
|
self.btn_extract_data_from_document.clicked.connect( # type:ignore
|
||||||
self.import_data_from_document
|
self.import_data_from_document,
|
||||||
)
|
)
|
||||||
self.create_new_app.clicked.connect(self.btn_create_new_apparat) # type:ignore
|
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)) # type:ignore
|
self.btn_apparat_save.clicked.connect(lambda: self.btn_save_apparat(True)) # type:ignore
|
||||||
@@ -109,17 +111,17 @@ class Ui(QtWidgets.QMainWindow, Ui_Semesterapparat):
|
|||||||
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) # type:ignore
|
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( # type:ignore
|
self.tableWidget_apparat_media.horizontalHeader().setSectionResizeMode( # type:ignore
|
||||||
QtWidgets.QHeaderView.ResizeMode.Stretch
|
QtWidgets.QHeaderView.ResizeMode.Stretch,
|
||||||
)
|
)
|
||||||
self.tableWidget_apparate.horizontalHeader().setSectionResizeMode( # type:ignore
|
self.tableWidget_apparate.horizontalHeader().setSectionResizeMode( # type:ignore
|
||||||
QtWidgets.QHeaderView.ResizeMode.Stretch
|
QtWidgets.QHeaderView.ResizeMode.Stretch,
|
||||||
)
|
)
|
||||||
self.saveandcreate.hide()
|
self.saveandcreate.hide()
|
||||||
|
|
||||||
@@ -140,29 +142,30 @@ class Ui(QtWidgets.QMainWindow, Ui_Semesterapparat):
|
|||||||
self.prof_mail.setValidator(
|
self.prof_mail.setValidator(
|
||||||
QRegularExpressionValidator(
|
QRegularExpressionValidator(
|
||||||
QtCore.QRegularExpression(
|
QtCore.QRegularExpression(
|
||||||
r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}"
|
r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}",
|
||||||
)
|
),
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
self.prof_tel_nr.setValidator(QtGui.QIntValidator())
|
self.prof_tel_nr.setValidator(QtGui.QIntValidator())
|
||||||
self.prof_tel_nr.setValidator(
|
self.prof_tel_nr.setValidator(
|
||||||
QtGui.QRegularExpressionValidator(QtCore.QRegularExpression(r"^\d{3,14}"))
|
QtGui.QRegularExpressionValidator(QtCore.QRegularExpression(r"^\d{3,14}")),
|
||||||
)
|
)
|
||||||
# #log.debug(self.prof_tel_nr.maxLength())
|
# #log.debug(self.prof_tel_nr.maxLength())
|
||||||
self.app_fach.setValidator( # validator to allow typing in the app_fach field
|
self.app_fach.setValidator( # validator to allow typing in the app_fach field
|
||||||
QtGui.QRegularExpressionValidator(
|
QtGui.QRegularExpressionValidator(
|
||||||
QtCore.QRegularExpression(r"[a-zA-Z0-9\s\W]+")
|
QtCore.QRegularExpression(r"[a-zA-Z0-9\s\W]+"),
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
# allow only letters, numbers, whitespaces, symbols for the apparat name
|
# allow only letters, numbers, whitespaces, symbols for the apparat name
|
||||||
self.app_name.setValidator(
|
self.app_name.setValidator(
|
||||||
QtGui.QRegularExpressionValidator(
|
QtGui.QRegularExpressionValidator(
|
||||||
QtCore.QRegularExpression(r"[a-zA-Z0-9\s\W]+")
|
QtCore.QRegularExpression(r"[a-zA-Z0-9\s\W]+"),
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
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) # type:ignore
|
self.tableWidget_apparate.doubleClicked.connect(self.load_app_data) # type:ignore
|
||||||
|
|
||||||
@@ -229,16 +232,16 @@ class Ui(QtWidgets.QMainWindow, Ui_Semesterapparat):
|
|||||||
|
|
||||||
# Context Menus
|
# Context Menus
|
||||||
self.tableWidget_apparate.setContextMenuPolicy(
|
self.tableWidget_apparate.setContextMenuPolicy(
|
||||||
QtCore.Qt.ContextMenuPolicy.CustomContextMenu
|
QtCore.Qt.ContextMenuPolicy.CustomContextMenu,
|
||||||
)
|
)
|
||||||
self.tableWidget_apparat_media.setContextMenuPolicy(
|
self.tableWidget_apparat_media.setContextMenuPolicy(
|
||||||
QtCore.Qt.ContextMenuPolicy.CustomContextMenu
|
QtCore.Qt.ContextMenuPolicy.CustomContextMenu,
|
||||||
)
|
)
|
||||||
self.tableWidget_apparate.customContextMenuRequested.connect( # type:ignore
|
self.tableWidget_apparate.customContextMenuRequested.connect( # type:ignore
|
||||||
self.open_context_menu # type:ignore
|
self.open_context_menu, # type:ignore
|
||||||
)
|
)
|
||||||
self.tableWidget_apparat_media.customContextMenuRequested.connect( # type:ignore
|
self.tableWidget_apparat_media.customContextMenuRequested.connect( # type:ignore
|
||||||
self.media_context_menu # type:ignore
|
self.media_context_menu, # type:ignore
|
||||||
)
|
)
|
||||||
|
|
||||||
# admin buttons
|
# admin buttons
|
||||||
@@ -252,7 +255,7 @@ class Ui(QtWidgets.QMainWindow, Ui_Semesterapparat):
|
|||||||
self.bookGrabber: list[QThread] = []
|
self.bookGrabber: list[QThread] = []
|
||||||
self.availChecker = None
|
self.availChecker = None
|
||||||
self.mail_thread = None
|
self.mail_thread = None
|
||||||
self.autoGrabber = None
|
self.auto_grabber = None
|
||||||
self.newEditionChecker = NewEditionCheckerThread()
|
self.newEditionChecker = NewEditionCheckerThread()
|
||||||
|
|
||||||
self.elsatab.setLayout(QtWidgets.QVBoxLayout())
|
self.elsatab.setLayout(QtWidgets.QVBoxLayout())
|
||||||
@@ -278,7 +281,7 @@ class Ui(QtWidgets.QMainWindow, Ui_Semesterapparat):
|
|||||||
|
|
||||||
# allow files to be dragged into document_list
|
# allow files to be dragged into document_list
|
||||||
self.document_list.setDragDropMode(
|
self.document_list.setDragDropMode(
|
||||||
QtWidgets.QAbstractItemView.DragDropMode.DropOnly
|
QtWidgets.QAbstractItemView.DragDropMode.DropOnly,
|
||||||
)
|
)
|
||||||
self.document_list.setAcceptDrops(True)
|
self.document_list.setAcceptDrops(True)
|
||||||
self.document_list.viewport().setAcceptDrops(True)
|
self.document_list.viewport().setAcceptDrops(True)
|
||||||
@@ -295,24 +298,18 @@ class Ui(QtWidgets.QMainWindow, Ui_Semesterapparat):
|
|||||||
# Only handle events for document_list and its viewport
|
# Only handle events for document_list and its viewport
|
||||||
if obj in (self.document_list, self.document_list.viewport()):
|
if obj in (self.document_list, self.document_list.viewport()):
|
||||||
et = event.type()
|
et = event.type()
|
||||||
if et == QtCore.QEvent.Type.DragEnter:
|
if et == QtCore.QEvent.Type.DragEnter or et == QtCore.QEvent.Type.DragMove:
|
||||||
if event.mimeData().hasUrls():
|
if event.mimeData().hasUrls():
|
||||||
event.setDropAction(QtCore.Qt.CopyAction)
|
event.setDropAction(QtCore.Qt.CopyAction)
|
||||||
event.acceptProposedAction()
|
event.acceptProposedAction()
|
||||||
else:
|
else:
|
||||||
event.ignore()
|
event.ignore()
|
||||||
return True
|
return True
|
||||||
elif et == QtCore.QEvent.Type.DragMove:
|
if et == QtCore.QEvent.Type.Drop:
|
||||||
if event.mimeData().hasUrls():
|
|
||||||
event.setDropAction(QtCore.Qt.CopyAction)
|
|
||||||
event.acceptProposedAction()
|
|
||||||
else:
|
|
||||||
event.ignore()
|
|
||||||
return True
|
|
||||||
elif et == QtCore.QEvent.Type.Drop:
|
|
||||||
if not self.app_group_box.isEnabled():
|
if not self.app_group_box.isEnabled():
|
||||||
self.confirm_popup(
|
self.confirm_popup(
|
||||||
"Bitte öffnen Sie zuerst einen Apparat!", title="Fehler"
|
"Bitte öffnen Sie zuerst einen Apparat!",
|
||||||
|
title="Fehler",
|
||||||
)
|
)
|
||||||
return True
|
return True
|
||||||
if event.mimeData().hasUrls():
|
if event.mimeData().hasUrls():
|
||||||
@@ -474,15 +471,16 @@ class Ui(QtWidgets.QMainWindow, Ui_Semesterapparat):
|
|||||||
|
|
||||||
elsa_layout.addWidget(ElsaDialog())
|
elsa_layout.addWidget(ElsaDialog())
|
||||||
# log.debug("added")
|
# log.debug("added")
|
||||||
pass
|
|
||||||
|
|
||||||
def generateSemester(self, today=False):
|
def generateSemester(self, today=False):
|
||||||
"""Generates the current semester.
|
"""Generates the current semester.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
today (bool, optional): If True, the current semester is generated. Defaults to False.
|
today (bool, optional): If True, the current semester is generated. Defaults to False.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
str: The current semester
|
str: The current semester
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if today:
|
if today:
|
||||||
return Semester()
|
return Semester()
|
||||||
@@ -492,8 +490,7 @@ class Ui(QtWidgets.QMainWindow, Ui_Semesterapparat):
|
|||||||
semester = "SoSe" if self.sem_sommer.isChecked() else "WiSe"
|
semester = "SoSe" if self.sem_sommer.isChecked() else "WiSe"
|
||||||
if semester == "SoSe":
|
if semester == "SoSe":
|
||||||
return "SoSe " + str(currentYear)
|
return "SoSe " + str(currentYear)
|
||||||
else:
|
return f"WiSe {currentYear}/{currentYear + 1}"
|
||||||
return f"WiSe {currentYear}/{currentYear + 1}"
|
|
||||||
|
|
||||||
def open_apparat(self, apparat: Union[int, str]):
|
def open_apparat(self, apparat: Union[int, str]):
|
||||||
if self.load_app_data(apparat):
|
if self.load_app_data(apparat):
|
||||||
@@ -647,7 +644,7 @@ class Ui(QtWidgets.QMainWindow, Ui_Semesterapparat):
|
|||||||
|
|
||||||
def validate_semester(self):
|
def validate_semester(self):
|
||||||
valid = (self.sem_sommer.isChecked() or self.sem_winter.isChecked()) and len(
|
valid = (self.sem_sommer.isChecked() or self.sem_winter.isChecked()) and len(
|
||||||
self.sem_year.text()
|
self.sem_year.text(),
|
||||||
) >= 2
|
) >= 2
|
||||||
if valid or self.check_eternal_app.isChecked():
|
if valid or self.check_eternal_app.isChecked():
|
||||||
self.__setValidState(self.valid_check_semester, 1, self._mand, 5)
|
self.__setValidState(self.valid_check_semester, 1, self._mand, 5)
|
||||||
@@ -749,7 +746,7 @@ class Ui(QtWidgets.QMainWindow, Ui_Semesterapparat):
|
|||||||
def update_document_list(self):
|
def update_document_list(self):
|
||||||
app_id = self.active_apparat
|
app_id = self.active_apparat
|
||||||
prof_id = self.db.getProfByName(
|
prof_id = self.db.getProfByName(
|
||||||
self.drpdwn_prof_name.currentText().replace(",", "")
|
self.drpdwn_prof_name.currentText().replace(",", ""),
|
||||||
).id
|
).id
|
||||||
files = self.db.getFiles(app_id, prof_id)
|
files = self.db.getFiles(app_id, prof_id)
|
||||||
for file in files:
|
for file in files:
|
||||||
@@ -827,7 +824,8 @@ class Ui(QtWidgets.QMainWindow, Ui_Semesterapparat):
|
|||||||
self.progress_label.setText("Bitte warten...")
|
self.progress_label.setText("Bitte warten...")
|
||||||
if data == []:
|
if data == []:
|
||||||
self.confirm_popup(
|
self.confirm_popup(
|
||||||
"Bitte mindestens ein Medium hinzufügen!", title="Fehler"
|
"Bitte mindestens ein Medium hinzufügen!",
|
||||||
|
title="Fehler",
|
||||||
)
|
)
|
||||||
|
|
||||||
app_nr = self.db.getId(self.app_name.text())
|
app_nr = self.db.getId(self.app_name.text())
|
||||||
@@ -866,7 +864,7 @@ class Ui(QtWidgets.QMainWindow, Ui_Semesterapparat):
|
|||||||
|
|
||||||
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(f"{current}/{all_titles}")
|
||||||
|
|
||||||
def _hide_progress_label():
|
def _hide_progress_label():
|
||||||
self.label_20.hide()
|
self.label_20.hide()
|
||||||
@@ -885,8 +883,9 @@ class Ui(QtWidgets.QMainWindow, Ui_Semesterapparat):
|
|||||||
else:
|
else:
|
||||||
links = [
|
links = [
|
||||||
self.tableWidget_apparat_media.item(
|
self.tableWidget_apparat_media.item(
|
||||||
self.tableWidget_apparat_media.currentRow(), 1
|
self.tableWidget_apparat_media.currentRow(),
|
||||||
).text()
|
1,
|
||||||
|
).text(),
|
||||||
]
|
]
|
||||||
# get the number of selected rows from the table
|
# get the number of selected rows from the table
|
||||||
items = self.tableWidget_apparat_media.rowCount()
|
items = self.tableWidget_apparat_media.rowCount()
|
||||||
@@ -961,7 +960,7 @@ class Ui(QtWidgets.QMainWindow, Ui_Semesterapparat):
|
|||||||
# # #log.debug(bd, type(bd))
|
# # #log.debug(bd, type(bd))
|
||||||
# create a new row below the last one
|
# create a new row below the last one
|
||||||
self.tableWidget_apparat_media.insertRow(
|
self.tableWidget_apparat_media.insertRow(
|
||||||
self.tableWidget_apparat_media.rowCount()
|
self.tableWidget_apparat_media.rowCount(),
|
||||||
)
|
)
|
||||||
# #set the data
|
# #set the data
|
||||||
self.tableWidget_apparat_media.setItem(
|
self.tableWidget_apparat_media.setItem(
|
||||||
@@ -989,10 +988,12 @@ class Ui(QtWidgets.QMainWindow, Ui_Semesterapparat):
|
|||||||
label.setTextFormat(QtCore.Qt.TextFormat.RichText)
|
label.setTextFormat(QtCore.Qt.TextFormat.RichText)
|
||||||
label.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
|
label.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
|
||||||
label.setTextInteractionFlags(
|
label.setTextInteractionFlags(
|
||||||
QtCore.Qt.TextInteractionFlag.TextBrowserInteraction
|
QtCore.Qt.TextInteractionFlag.TextBrowserInteraction,
|
||||||
)
|
)
|
||||||
self.tableWidget_apparat_media.setCellWidget(
|
self.tableWidget_apparat_media.setCellWidget(
|
||||||
self.tableWidget_apparat_media.rowCount() - 1, 6, label
|
self.tableWidget_apparat_media.rowCount() - 1,
|
||||||
|
6,
|
||||||
|
label,
|
||||||
)
|
)
|
||||||
if availability == 1:
|
if availability == 1:
|
||||||
# display green checkmark at column 4 in the row
|
# display green checkmark at column 4 in the row
|
||||||
@@ -1003,7 +1004,8 @@ class Ui(QtWidgets.QMainWindow, Ui_Semesterapparat):
|
|||||||
)
|
)
|
||||||
# set tooltip
|
# set tooltip
|
||||||
self.tableWidget_apparat_media.item(
|
self.tableWidget_apparat_media.item(
|
||||||
self.tableWidget_apparat_media.rowCount() - 1, 4
|
self.tableWidget_apparat_media.rowCount() - 1,
|
||||||
|
4,
|
||||||
).setToolTip("Das Medium wurde im Apparat gefunden")
|
).setToolTip("Das Medium wurde im Apparat gefunden")
|
||||||
else:
|
else:
|
||||||
self.tableWidget_apparat_media.setItem(
|
self.tableWidget_apparat_media.setItem(
|
||||||
@@ -1012,21 +1014,21 @@ class Ui(QtWidgets.QMainWindow, Ui_Semesterapparat):
|
|||||||
QtWidgets.QTableWidgetItem("❌"),
|
QtWidgets.QTableWidgetItem("❌"),
|
||||||
)
|
)
|
||||||
self.tableWidget_apparat_media.item(
|
self.tableWidget_apparat_media.item(
|
||||||
self.tableWidget_apparat_media.rowCount() - 1, 4
|
self.tableWidget_apparat_media.rowCount() - 1,
|
||||||
|
4,
|
||||||
).setToolTip("Das Medium wurde nicht im Apparat gefunden")
|
).setToolTip("Das Medium wurde nicht im Apparat gefunden")
|
||||||
|
|
||||||
def open_link(self, item):
|
def open_link(self, item):
|
||||||
def __openLink(link):
|
def __openLink(link):
|
||||||
if link == "":
|
if link == "":
|
||||||
return
|
return None
|
||||||
if "http" not in link:
|
if "http" not in link:
|
||||||
link = "https://" + link
|
link = "https://" + link
|
||||||
return link
|
return link
|
||||||
#
|
|
||||||
|
|
||||||
# get the name of the column
|
# get the name of the column
|
||||||
columnname = self.tableWidget_apparat_media.horizontalHeaderItem(
|
columnname = self.tableWidget_apparat_media.horizontalHeaderItem(
|
||||||
item.column()
|
item.column(),
|
||||||
).text()
|
).text()
|
||||||
if columnname == "Link":
|
if columnname == "Link":
|
||||||
link = __openLink(item.text())
|
link = __openLink(item.text())
|
||||||
@@ -1086,18 +1088,21 @@ class Ui(QtWidgets.QMainWindow, Ui_Semesterapparat):
|
|||||||
_selected_doc_filetype = ""
|
_selected_doc_filetype = ""
|
||||||
try:
|
try:
|
||||||
_selected_doc_name = self.document_list.item(
|
_selected_doc_name = self.document_list.item(
|
||||||
self.document_list.currentRow(), 0
|
self.document_list.currentRow(),
|
||||||
|
0,
|
||||||
).text()
|
).text()
|
||||||
_selected_doc_location = self.document_list.item(
|
_selected_doc_location = self.document_list.item(
|
||||||
self.document_list.currentRow(), 3
|
self.document_list.currentRow(),
|
||||||
|
3,
|
||||||
).text()
|
).text()
|
||||||
_selected_doc_filetype = self.document_list.item(
|
_selected_doc_filetype = self.document_list.item(
|
||||||
self.document_list.currentRow(), 1
|
self.document_list.currentRow(),
|
||||||
|
1,
|
||||||
).text()
|
).text()
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
self.confirm_popup("Bitte erst ein Dokument auswählen!", title="Fehler")
|
self.confirm_popup("Bitte erst ein Dokument auswählen!", title="Fehler")
|
||||||
return
|
return
|
||||||
if not _selected_doc_location == "Database":
|
if _selected_doc_location != "Database":
|
||||||
path = Path(_selected_doc_location)
|
path = Path(_selected_doc_location)
|
||||||
# path: Path = path.resolve()
|
# path: Path = path.resolve()
|
||||||
# path.
|
# path.
|
||||||
@@ -1110,7 +1115,9 @@ class Ui(QtWidgets.QMainWindow, Ui_Semesterapparat):
|
|||||||
os.system(f"open {path}")
|
os.system(f"open {path}")
|
||||||
else:
|
else:
|
||||||
recreateFile(
|
recreateFile(
|
||||||
_selected_doc_name, self.active_apparat, filetype=_selected_doc_filetype
|
_selected_doc_name,
|
||||||
|
self.active_apparat,
|
||||||
|
filetype=_selected_doc_filetype,
|
||||||
)
|
)
|
||||||
|
|
||||||
def add_media_from_file(self):
|
def add_media_from_file(self):
|
||||||
@@ -1138,78 +1145,87 @@ class Ui(QtWidgets.QMainWindow, Ui_Semesterapparat):
|
|||||||
# if files are in the table, and are selected, check for books in the file
|
# if files are in the table, and are selected, check for books in the file
|
||||||
if self.document_list.rowCount() == 0:
|
if self.document_list.rowCount() == 0:
|
||||||
return
|
return
|
||||||
else:
|
# if file is selected, check for books in the file
|
||||||
# if file is selected, check for books in the file
|
if self.document_list.currentRow() != -1:
|
||||||
if self.document_list.currentRow() != -1:
|
# #log.debug("File selected")
|
||||||
# #log.debug("File selected")
|
file = self.document_list.item(
|
||||||
file = self.document_list.item(
|
self.document_list.currentRow(),
|
||||||
self.document_list.currentRow(), 3
|
3,
|
||||||
).text()
|
).text()
|
||||||
|
|
||||||
file_type = self.document_list.item(
|
file_type = self.document_list.item(
|
||||||
self.document_list.currentRow(), 1
|
self.document_list.currentRow(),
|
||||||
).text()
|
1,
|
||||||
file_location = self.document_list.item(
|
).text()
|
||||||
self.document_list.currentRow(), 3
|
file_location = self.document_list.item(
|
||||||
).text()
|
self.document_list.currentRow(),
|
||||||
file_name = self.document_list.item(
|
3,
|
||||||
self.document_list.currentRow(), 0
|
).text()
|
||||||
).text()
|
file_name = self.document_list.item(
|
||||||
if file_location == "Database":
|
self.document_list.currentRow(),
|
||||||
# create a temporaty file to use, delete it after use
|
0,
|
||||||
temp_file = tempfile.NamedTemporaryFile(
|
).text()
|
||||||
delete=False, suffix="." + file_type
|
if file_location == "Database":
|
||||||
|
# create a temporaty file to use, delete it after use
|
||||||
|
temp_file = tempfile.NamedTemporaryFile(
|
||||||
|
delete=False,
|
||||||
|
suffix="." + file_type,
|
||||||
|
)
|
||||||
|
temp_file.write(self.db.getBlob(file_name, int(app_id)))
|
||||||
|
temp_file.close()
|
||||||
|
file = temp_file.name
|
||||||
|
if file_type == "pdf":
|
||||||
|
data = pdf_to_semap(file)
|
||||||
|
signatures = data.signatures
|
||||||
|
data = __open_dialog(signatures)
|
||||||
|
# if no data was returned, return
|
||||||
|
if data == []:
|
||||||
|
return
|
||||||
|
for book in data:
|
||||||
|
if not isinstance(book, BookData):
|
||||||
|
continue
|
||||||
|
self.db.addBookToDatabase(
|
||||||
|
bookdata=book,
|
||||||
|
app_id=app_id,
|
||||||
|
prof_id=prof_id,
|
||||||
)
|
)
|
||||||
temp_file.write(self.db.getBlob(file_name, int(app_id)))
|
if file_type == "csv":
|
||||||
temp_file.close()
|
signatures = csv_to_list(file)
|
||||||
file = temp_file.name
|
data = __open_dialog(signatures)
|
||||||
if file_type == "pdf":
|
# add the data to the database
|
||||||
data = pdf_to_semap(file)
|
for book in data:
|
||||||
signatures = data.signatures
|
if not isinstance(book, BookData):
|
||||||
data = __open_dialog(signatures)
|
continue
|
||||||
# if no data was returned, return
|
self.db.addBookToDatabase(
|
||||||
if data == []:
|
bookdata=book,
|
||||||
return
|
app_id=app_id,
|
||||||
for book in data:
|
prof_id=prof_id,
|
||||||
if not isinstance(book, BookData):
|
)
|
||||||
continue
|
if file_type == "docx":
|
||||||
self.db.addBookToDatabase(
|
data = word_to_semap(file)
|
||||||
bookdata=book,
|
signatures = data.signatures
|
||||||
app_id=app_id,
|
data = __open_dialog(signatures)
|
||||||
prof_id=prof_id,
|
# if no data was returned, return
|
||||||
)
|
if data == []:
|
||||||
if file_type == "csv":
|
return
|
||||||
signatures = csv_to_list(file)
|
for book in data:
|
||||||
data = __open_dialog(signatures)
|
if not isinstance(book, BookData):
|
||||||
# add the data to the database
|
continue
|
||||||
for book in data:
|
self.db.addBookToDatabase(
|
||||||
if not isinstance(book, BookData):
|
bookdata=book,
|
||||||
continue
|
app_id=app_id,
|
||||||
self.db.addBookToDatabase(
|
prof_id=prof_id,
|
||||||
bookdata=book, app_id=app_id, prof_id=prof_id
|
)
|
||||||
)
|
if file_type == "eml":
|
||||||
if file_type == "docx":
|
data = eml_to_semap(file)
|
||||||
data = word_to_semap(file)
|
self.update_app_media_list()
|
||||||
signatures = data.signatures
|
# #log.debug(len(signatures))
|
||||||
data = __open_dialog(signatures)
|
|
||||||
# if no data was returned, return
|
|
||||||
if data == []:
|
|
||||||
return
|
|
||||||
for book in data:
|
|
||||||
if not isinstance(book, BookData):
|
|
||||||
continue
|
|
||||||
self.db.addBookToDatabase(
|
|
||||||
bookdata=book, app_id=app_id, prof_id=prof_id
|
|
||||||
)
|
|
||||||
if file_type == "eml":
|
|
||||||
data = eml_to_semap(file)
|
|
||||||
self.update_app_media_list()
|
|
||||||
# #log.debug(len(signatures))
|
|
||||||
|
|
||||||
def extract_document_data(self) -> Union[list[str], SemapDocument]:
|
def extract_document_data(self) -> list[str] | SemapDocument:
|
||||||
file_type = self.document_list.item(self.document_list.currentRow(), 1).text()
|
file_type = self.document_list.item(self.document_list.currentRow(), 1).text()
|
||||||
file_location = self.document_list.item(
|
file_location = self.document_list.item(
|
||||||
self.document_list.currentRow(), 3
|
self.document_list.currentRow(),
|
||||||
|
3,
|
||||||
).text()
|
).text()
|
||||||
file_name = self.document_list.item(self.document_list.currentRow(), 0).text()
|
file_name = self.document_list.item(self.document_list.currentRow(), 0).text()
|
||||||
file = file_location
|
file = file_location
|
||||||
@@ -1217,10 +1233,12 @@ class Ui(QtWidgets.QMainWindow, Ui_Semesterapparat):
|
|||||||
if file_location == "Database":
|
if file_location == "Database":
|
||||||
# create warning, then return
|
# create warning, then return
|
||||||
file = self.db.recreateFile(
|
file = self.db.recreateFile(
|
||||||
file_name, self.active_apparat, filetype=file_type
|
file_name,
|
||||||
|
self.active_apparat,
|
||||||
|
filetype=file_type,
|
||||||
)
|
)
|
||||||
if file_type == "pdf":
|
if file_type == "pdf":
|
||||||
# Todo: implement parser here
|
# TODO: implement parser here
|
||||||
self.confirm_popup("PDF Dateien werden nicht unterstützt!", title="Fehler")
|
self.confirm_popup("PDF Dateien werden nicht unterstützt!", title="Fehler")
|
||||||
return [""]
|
return [""]
|
||||||
if file_type == "csv":
|
if file_type == "csv":
|
||||||
@@ -1233,8 +1251,14 @@ class Ui(QtWidgets.QMainWindow, Ui_Semesterapparat):
|
|||||||
log.debug("Got the data: {}", data)
|
log.debug("Got the data: {}", data)
|
||||||
|
|
||||||
return data
|
return data
|
||||||
else:
|
if file_type == "eml":
|
||||||
raise ValueError("Dateityp wird nicht unterstützt")
|
data = eml_to_semap(file)
|
||||||
|
log.info("Converted data from eml file")
|
||||||
|
log.debug("Got the data: {}", data)
|
||||||
|
|
||||||
|
return data
|
||||||
|
error = "Dateityp wird nicht unterstützt"
|
||||||
|
raise ValueError(error)
|
||||||
|
|
||||||
def import_data_from_document(self):
|
def import_data_from_document(self):
|
||||||
global valid_input
|
global valid_input
|
||||||
@@ -1254,7 +1278,7 @@ class Ui(QtWidgets.QMainWindow, Ui_Semesterapparat):
|
|||||||
dialog.setModal(True)
|
dialog.setModal(True)
|
||||||
layout = QtWidgets.QVBoxLayout()
|
layout = QtWidgets.QVBoxLayout()
|
||||||
label = QtWidgets.QLabel(
|
label = QtWidgets.QLabel(
|
||||||
f"Bitte wählen Sie einen Titel aus:/nDer Titel darf max. {data.title_max_length} Zeichen lang sein."
|
f"Bitte wählen Sie einen Titel aus:/nDer Titel darf max. {data.title_max_length} Zeichen lang sein.",
|
||||||
)
|
)
|
||||||
layout.addWidget(label)
|
layout.addWidget(label)
|
||||||
dropdown = QtWidgets.QComboBox()
|
dropdown = QtWidgets.QComboBox()
|
||||||
@@ -1264,7 +1288,7 @@ class Ui(QtWidgets.QMainWindow, Ui_Semesterapparat):
|
|||||||
button_box = QtWidgets.QDialogButtonBox()
|
button_box = QtWidgets.QDialogButtonBox()
|
||||||
button_box.setStandardButtons(
|
button_box.setStandardButtons(
|
||||||
QtWidgets.QDialogButtonBox.StandardButton.Cancel
|
QtWidgets.QDialogButtonBox.StandardButton.Cancel
|
||||||
| QtWidgets.QDialogButtonBox.StandardButton.Ok
|
| QtWidgets.QDialogButtonBox.StandardButton.Ok,
|
||||||
)
|
)
|
||||||
button_box.accepted.connect(dialog.accept)
|
button_box.accepted.connect(dialog.accept)
|
||||||
button_box.rejected.connect(dialog.reject)
|
button_box.rejected.connect(dialog.reject)
|
||||||
@@ -1306,7 +1330,7 @@ class Ui(QtWidgets.QMainWindow, Ui_Semesterapparat):
|
|||||||
# get active app_id and prof_id
|
# get active app_id and prof_id
|
||||||
self.tableWidget_apparate.setEnabled(False)
|
self.tableWidget_apparate.setEnabled(False)
|
||||||
self.tableWidget_apparate.setToolTip(
|
self.tableWidget_apparate.setToolTip(
|
||||||
"Bitte warten, bis alle Medien hinzugefügt wurden"
|
"Bitte warten, bis alle Medien hinzugefügt wurden",
|
||||||
)
|
)
|
||||||
app_id = self.active_apparat
|
app_id = self.active_apparat
|
||||||
log.debug(self.profdata)
|
log.debug(self.profdata)
|
||||||
@@ -1336,50 +1360,48 @@ class Ui(QtWidgets.QMainWindow, Ui_Semesterapparat):
|
|||||||
self.tableWidget_apparate.setEnabled(True)
|
self.tableWidget_apparate.setEnabled(True)
|
||||||
self.tableWidget_apparate.setToolTip("")
|
self.tableWidget_apparate.setToolTip("")
|
||||||
return
|
return
|
||||||
|
# if file is selected, check for books in the file
|
||||||
|
# #log.debug("File selected")
|
||||||
|
|
||||||
|
if prof_id is None:
|
||||||
|
prof_id = self.db.getProfId(self.profdata)
|
||||||
|
|
||||||
|
# log.debug("Prof ID is None", prof_id)
|
||||||
|
document = None
|
||||||
|
|
||||||
|
if c_document is None or not isinstance(c_document, SemapDocument):
|
||||||
|
document = self.extract_document_data()
|
||||||
|
if document is None:
|
||||||
|
log.error("Document is None")
|
||||||
|
elif isinstance(document, SemapDocument):
|
||||||
|
signatures = document.signatures
|
||||||
else:
|
else:
|
||||||
# if file is selected, check for books in the file
|
signatures = document
|
||||||
# #log.debug("File selected")
|
if isinstance(signatures, SemapDocument):
|
||||||
|
signatures = signatures.signatures
|
||||||
|
auto_grabber = BookGrabber()
|
||||||
|
auto_grabber.add_values(
|
||||||
|
mode="ARRAY",
|
||||||
|
app_id=app_id,
|
||||||
|
prof_id=int(prof_id),
|
||||||
|
data=signatures,
|
||||||
|
any_book=True,
|
||||||
|
exact=True,
|
||||||
|
)
|
||||||
|
self.label_info.show()
|
||||||
|
self.progress_label.show()
|
||||||
|
self.line_2.show()
|
||||||
|
auto_grabber.finished.connect(self.hide_progress_label)
|
||||||
|
auto_grabber.finished.connect(self.unlock_apparate)
|
||||||
|
auto_grabber.updateSignal.connect(self.update_progress_label)
|
||||||
|
|
||||||
if prof_id is None:
|
auto_grabber.start()
|
||||||
prof_id = self.db.getProfId(self.profdata)
|
self.bookGrabber.append(auto_grabber)
|
||||||
|
# refresh book table
|
||||||
# log.debug("Prof ID is None", prof_id)
|
# end of thread
|
||||||
document = None
|
# self.auto_grabber.exit()
|
||||||
|
# self.__clear_fields()
|
||||||
if c_document is None or not isinstance(c_document, SemapDocument):
|
# self.btn_cancel_active_selection()
|
||||||
document = self.extract_document_data()
|
|
||||||
if document is None:
|
|
||||||
log.error("Document is None")
|
|
||||||
elif isinstance(document, SemapDocument):
|
|
||||||
signatures = document.signatures
|
|
||||||
else:
|
|
||||||
signatures = document
|
|
||||||
autoGrabber = BookGrabber()
|
|
||||||
autoGrabber.add_values(
|
|
||||||
mode="ARRAY",
|
|
||||||
app_id=app_id,
|
|
||||||
prof_id=int(prof_id),
|
|
||||||
data=signatures,
|
|
||||||
any_book=True,
|
|
||||||
exact=True,
|
|
||||||
)
|
|
||||||
self.label_info.show()
|
|
||||||
self.progress_label.show()
|
|
||||||
self.line_2.show()
|
|
||||||
# grabber.finished.connect(thread.quit)
|
|
||||||
# self.autoGrabber.finished.connect(self.autoGrabber.deleteLater)
|
|
||||||
autoGrabber.finished.connect(self.hide_progress_label)
|
|
||||||
autoGrabber.finished.connect(self.unlock_apparate)
|
|
||||||
autoGrabber.updateSignal.connect(self.update_progress_label)
|
|
||||||
# worker.finished.connect(worker.deleteLater)
|
|
||||||
|
|
||||||
autoGrabber.start()
|
|
||||||
self.bookGrabber.append(autoGrabber)
|
|
||||||
# refresh book table
|
|
||||||
# end of thread
|
|
||||||
# self.autoGrabber.exit()
|
|
||||||
# self.__clear_fields()
|
|
||||||
# self.btn_cancel_active_selection()
|
|
||||||
|
|
||||||
def unlock_apparate(self):
|
def unlock_apparate(self):
|
||||||
self.tableWidget_apparate.setEnabled(True)
|
self.tableWidget_apparate.setEnabled(True)
|
||||||
@@ -1442,12 +1464,12 @@ class Ui(QtWidgets.QMainWindow, Ui_Semesterapparat):
|
|||||||
self.add_files()
|
self.add_files()
|
||||||
if error is not None:
|
if error is not None:
|
||||||
self.confirm_popup(error.__str__(), title="Fehler")
|
self.confirm_popup(error.__str__(), title="Fehler")
|
||||||
return
|
return None
|
||||||
appdata = self.db.getAllAparats()
|
appdata = self.db.getAllAparats()
|
||||||
# merge self.appdata and appdata, remove duplicates
|
# merge self.appdata and appdata, remove duplicates
|
||||||
|
|
||||||
self.apparats = self.__uniques(self.apparats, appdata)
|
self.apparats = self.__uniques(self.apparats, appdata)
|
||||||
self.apparats = natsorted(self.apparats, key=lambda x: x[4], reverse=True)
|
self.apparats = natsorted(self.apparats, key=lambda x: x.appnr, reverse=True)
|
||||||
|
|
||||||
self.update_apparat_list()
|
self.update_apparat_list()
|
||||||
|
|
||||||
@@ -1465,7 +1487,7 @@ class Ui(QtWidgets.QMainWindow, Ui_Semesterapparat):
|
|||||||
self.__clear_fields()
|
self.__clear_fields()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def __uniques(self, list1, list2):
|
def __uniques(self, list1: list[Apparat], list2: list[Apparat]) -> list[Apparat]:
|
||||||
seen = set()
|
seen = set()
|
||||||
unique_list = []
|
unique_list = []
|
||||||
for item in list1 + list2:
|
for item in list1 + list2:
|
||||||
@@ -1475,7 +1497,7 @@ class Ui(QtWidgets.QMainWindow, Ui_Semesterapparat):
|
|||||||
unique_list.append(item)
|
unique_list.append(item)
|
||||||
return unique_list
|
return unique_list
|
||||||
|
|
||||||
def send_mail_preview(self):
|
def send_mail_preview(self) -> None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@@ -1491,14 +1513,14 @@ class Ui(QtWidgets.QMainWindow, Ui_Semesterapparat):
|
|||||||
"prof_tel": self.prof_tel_nr.text(),
|
"prof_tel": self.prof_tel_nr.text(),
|
||||||
}
|
}
|
||||||
|
|
||||||
def add_files(self):
|
def add_files(self) -> None:
|
||||||
"""
|
"""Add Files to the associated prof in the database.
|
||||||
Add Files to the associated prof in the database
|
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
prof_id : int, optional
|
prof_id : int, optional
|
||||||
The ID associated to the prof, by default None
|
The ID associated to the prof, by default None
|
||||||
|
|
||||||
"""
|
"""
|
||||||
files: list[dict[str, Any]] = []
|
files: list[dict[str, Any]] = []
|
||||||
for i in range(self.document_list.rowCount()):
|
for i in range(self.document_list.rowCount()):
|
||||||
@@ -1508,7 +1530,7 @@ class Ui(QtWidgets.QMainWindow, Ui_Semesterapparat):
|
|||||||
"type": self.document_list.item(i, 1).text(),
|
"type": self.document_list.item(i, 1).text(),
|
||||||
"date": self.document_list.item(i, 2).text(),
|
"date": self.document_list.item(i, 2).text(),
|
||||||
"path": self.document_list.item(i, 3).text(),
|
"path": self.document_list.item(i, 3).text(),
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
self.document_list.item(i, 2).setText("")
|
self.document_list.item(i, 2).setText("")
|
||||||
|
|
||||||
@@ -1521,7 +1543,7 @@ class Ui(QtWidgets.QMainWindow, Ui_Semesterapparat):
|
|||||||
"profname": self.drpdwn_prof_name.currentText(),
|
"profname": self.drpdwn_prof_name.currentText(),
|
||||||
"prof_mail": self.prof_mail.text(),
|
"prof_mail": self.prof_mail.text(),
|
||||||
"prof_tel": self.prof_tel_nr.text(),
|
"prof_tel": self.prof_tel_nr.text(),
|
||||||
}
|
},
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -1530,7 +1552,7 @@ class Ui(QtWidgets.QMainWindow, Ui_Semesterapparat):
|
|||||||
|
|
||||||
for apparat in self.apparats:
|
for apparat in self.apparats:
|
||||||
self.insert_apparat_into_table(apparat)
|
self.insert_apparat_into_table(apparat)
|
||||||
log.info("Inserted {} apparats into table".format(len(self.apparats)))
|
log.info(f"Inserted {len(self.apparats)} apparats into table")
|
||||||
|
|
||||||
def insert_apparat_into_table(self, apparat: Apparat):
|
def insert_apparat_into_table(self, apparat: Apparat):
|
||||||
# log.debug(apparat)
|
# log.debug(apparat)
|
||||||
@@ -1544,16 +1566,20 @@ class Ui(QtWidgets.QMainWindow, Ui_Semesterapparat):
|
|||||||
)
|
)
|
||||||
self.tableWidget_apparate.insertRow(0)
|
self.tableWidget_apparate.insertRow(0)
|
||||||
self.tableWidget_apparate.setItem(
|
self.tableWidget_apparate.setItem(
|
||||||
0, 0, QtWidgets.QTableWidgetItem(str(apparat.appnr))
|
0,
|
||||||
|
0,
|
||||||
|
QtWidgets.QTableWidgetItem(str(apparat.appnr)),
|
||||||
)
|
)
|
||||||
self.tableWidget_apparate.setItem(
|
self.tableWidget_apparate.setItem(
|
||||||
0, 1, QtWidgets.QTableWidgetItem(str(apparat.name))
|
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.prof_id, add_title=False)
|
self.db.getProfNameById(apparat.prof_id, add_title=False),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
self.tableWidget_apparate.setItem(
|
self.tableWidget_apparate.setItem(
|
||||||
@@ -1562,10 +1588,14 @@ class Ui(QtWidgets.QMainWindow, Ui_Semesterapparat):
|
|||||||
QtWidgets.QTableWidgetItem(str(semester)),
|
QtWidgets.QTableWidgetItem(str(semester)),
|
||||||
)
|
)
|
||||||
self.tableWidget_apparate.setItem(
|
self.tableWidget_apparate.setItem(
|
||||||
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.konto))
|
0,
|
||||||
|
5,
|
||||||
|
QtWidgets.QTableWidgetItem(str(apparat.konto)),
|
||||||
)
|
)
|
||||||
|
|
||||||
def open_context_menu(self, position):
|
def open_context_menu(self, position):
|
||||||
@@ -1584,7 +1614,7 @@ class Ui(QtWidgets.QMainWindow, Ui_Semesterapparat):
|
|||||||
remind_action,
|
remind_action,
|
||||||
new_edition_check,
|
new_edition_check,
|
||||||
order_newedition_action,
|
order_newedition_action,
|
||||||
]
|
],
|
||||||
)
|
)
|
||||||
# convert point to row and column
|
# convert point to row and column
|
||||||
row = self.tableWidget_apparate.rowAt(position.y())
|
row = self.tableWidget_apparate.rowAt(position.y())
|
||||||
@@ -1599,12 +1629,12 @@ class Ui(QtWidgets.QMainWindow, Ui_Semesterapparat):
|
|||||||
remind_action.triggered.connect(self.reminder)
|
remind_action.triggered.connect(self.reminder)
|
||||||
new_edition_check.triggered.connect(lambda: self.check_new_editions())
|
new_edition_check.triggered.connect(lambda: self.check_new_editions())
|
||||||
order_newedition_action.triggered.connect(
|
order_newedition_action.triggered.connect(
|
||||||
lambda: self.order_new_editions(app_id, pid)
|
lambda: self.order_new_editions(app_id, pid),
|
||||||
)
|
)
|
||||||
delete_action.triggered.connect(lambda: self.delete_apparat(pos))
|
delete_action.triggered.connect(lambda: self.delete_apparat(pos))
|
||||||
# pass pos to contact_prof
|
# pass pos to contact_prof
|
||||||
contact_action.triggered.connect(
|
contact_action.triggered.connect(
|
||||||
lambda: self.contact_prof(pid=pid, apparat=app_id)
|
lambda: self.contact_prof(pid=pid, apparat=app_id),
|
||||||
)
|
)
|
||||||
menu.exec(self.tableWidget_apparate.mapToGlobal(position))
|
menu.exec(self.tableWidget_apparate.mapToGlobal(position))
|
||||||
|
|
||||||
@@ -1641,20 +1671,23 @@ class Ui(QtWidgets.QMainWindow, Ui_Semesterapparat):
|
|||||||
pick = selector.selection
|
pick = selector.selection
|
||||||
|
|
||||||
app_id = self.tableWidget_apparate.item(
|
app_id = self.tableWidget_apparate.item(
|
||||||
self.tableWidget_apparate.currentRow(), 0
|
self.tableWidget_apparate.currentRow(),
|
||||||
|
0,
|
||||||
).text()
|
).text()
|
||||||
prof_id: int = self.db.getProfIDByApparat(app_id)
|
prof_id: int = self.db.getProfIDByApparat(app_id)
|
||||||
app_name = self.tableWidget_apparate.item(
|
app_name = self.tableWidget_apparate.item(
|
||||||
self.tableWidget_apparate.currentRow(), 1
|
self.tableWidget_apparate.currentRow(),
|
||||||
|
1,
|
||||||
).text()
|
).text()
|
||||||
subject = self.tableWidget_apparate.item(
|
subject = self.tableWidget_apparate.item(
|
||||||
self.tableWidget_apparate.currentRow(), 4
|
self.tableWidget_apparate.currentRow(),
|
||||||
|
4,
|
||||||
).text()
|
).text()
|
||||||
if pick == "professor":
|
if pick == "professor":
|
||||||
books = self.db.getBooksByProfId(prof_id)
|
books = self.db.getBooksByProfId(prof_id)
|
||||||
app_name = "Sammelmail"
|
app_name = "Sammelmail"
|
||||||
app_id = ", ".join(
|
app_id = ", ".join(
|
||||||
[str(app.appnr) for app in self.db.getApparatsByProf(prof_id)]
|
[str(app.appnr) for app in self.db.getApparatsByProf(prof_id)],
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
apparats_id = self.db.getId(app_name)
|
apparats_id = self.db.getId(app_name)
|
||||||
@@ -1702,10 +1735,9 @@ WHERE m.id = ?""",
|
|||||||
for book in accepted_books:
|
for book in accepted_books:
|
||||||
oldBookId = self.db.getBookIdByPPN(book.old_book.ppn)
|
oldBookId = self.db.getBookIdByPPN(book.old_book.ppn)
|
||||||
apparats_id = self.db.getId(
|
apparats_id = self.db.getId(
|
||||||
self.db.getApparatNameByAppNr(book.old_book.library_location)
|
self.db.getApparatNameByAppNr(book.old_book.library_location),
|
||||||
)
|
)
|
||||||
self.db.insertNewEdition(book, oldBookId, apparats_id)
|
self.db.insertNewEdition(book, oldBookId, apparats_id)
|
||||||
pass
|
|
||||||
|
|
||||||
self.mail_thread = Mail_Dialog(
|
self.mail_thread = Mail_Dialog(
|
||||||
prof_name=self.db.getSpecificProfData(prof_id, ["fullname"]),
|
prof_name=self.db.getSpecificProfData(prof_id, ["fullname"]),
|
||||||
@@ -1799,7 +1831,7 @@ WHERE m.id = ?""",
|
|||||||
apparat_copy_action,
|
apparat_copy_action,
|
||||||
apparat_move_action,
|
apparat_move_action,
|
||||||
replace_old_editions,
|
replace_old_editions,
|
||||||
]
|
],
|
||||||
)
|
)
|
||||||
generalmenu.addActions([edit_action, delete_action, update_data_action]) # type: ignore
|
generalmenu.addActions([edit_action, delete_action, update_data_action]) # type: ignore
|
||||||
# disable apparat_add_action
|
# disable apparat_add_action
|
||||||
@@ -1848,7 +1880,7 @@ WHERE m.id = ?""",
|
|||||||
] # type: ignore
|
] # type: ignore
|
||||||
prof_id = self.db.getProfId(self.profdata) # type: ignore
|
prof_id = self.db.getProfId(self.profdata) # type: ignore
|
||||||
app_id = self.db.getId(self.app_name.text()) # type: ignore
|
app_id = self.db.getId(self.app_name.text()) # type: ignore
|
||||||
books: List[Tuple[int, BookData]] = []
|
books: list[tuple[int, BookData]] = []
|
||||||
for signature in signatures:
|
for signature in signatures:
|
||||||
book = self.db.getBookBasedOnSignature(
|
book = self.db.getBookBasedOnSignature(
|
||||||
app_id=app_id,
|
app_id=app_id,
|
||||||
@@ -1894,7 +1926,7 @@ WHERE m.id = ?""",
|
|||||||
)
|
)
|
||||||
signatures.append(book_id) # type: ignore
|
signatures.append(book_id) # type: ignore
|
||||||
result, apparat = self.confirm_action_dialog( # type: ignore
|
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:
|
||||||
for book_id in signatures:
|
for book_id in signatures:
|
||||||
@@ -1914,7 +1946,7 @@ WHERE m.id = ?""",
|
|||||||
)
|
)
|
||||||
signatures.append(book_id)
|
signatures.append(book_id)
|
||||||
result, apparat = self.confirm_action_dialog(
|
result, apparat = self.confirm_action_dialog(
|
||||||
"In welchen Apparat sollen die Medien verschoben werden?"
|
"In welchen Apparat sollen die Medien verschoben werden?",
|
||||||
)
|
)
|
||||||
if result == 1:
|
if result == 1:
|
||||||
for book_id in signatures:
|
for book_id in signatures:
|
||||||
@@ -1957,13 +1989,14 @@ WHERE m.id = ?""",
|
|||||||
dialog.setLayout(layout)
|
dialog.setLayout(layout)
|
||||||
|
|
||||||
return dialog.exec(), self.db.getApparatId(
|
return dialog.exec(), self.db.getApparatId(
|
||||||
self.db.getApparatNameByAppNr(drpdwn.currentText())
|
self.db.getApparatNameByAppNr(drpdwn.currentText()),
|
||||||
)
|
)
|
||||||
|
|
||||||
def add_to_apparat(self):
|
def add_to_apparat(self):
|
||||||
"""use playwright in background to add medium to apparat"""
|
"""Use playwright in background to add medium to apparat"""
|
||||||
signature = self.tableWidget_apparat_media.item(
|
signature = self.tableWidget_apparat_media.item(
|
||||||
self.tableWidget_apparat_media.currentRow(), 1
|
self.tableWidget_apparat_media.currentRow(),
|
||||||
|
1,
|
||||||
).text()
|
).text()
|
||||||
self.db.getBookBasedOnSignature(
|
self.db.getBookBasedOnSignature(
|
||||||
self.drpdwn_app_nr.currentText(),
|
self.drpdwn_app_nr.currentText(),
|
||||||
@@ -1974,7 +2007,8 @@ WHERE m.id = ?""",
|
|||||||
|
|
||||||
def edit_medium(self):
|
def edit_medium(self):
|
||||||
book = self.tableWidget_apparat_media.item(
|
book = self.tableWidget_apparat_media.item(
|
||||||
self.tableWidget_apparat_media.currentRow(), 1
|
self.tableWidget_apparat_media.currentRow(),
|
||||||
|
1,
|
||||||
).text()
|
).text()
|
||||||
prof_id = self.db.getProfId(self.profdata)
|
prof_id = self.db.getProfId(self.profdata)
|
||||||
data = self.db.getBookBasedOnSignature(
|
data = self.db.getBookBasedOnSignature(
|
||||||
@@ -2004,7 +2038,6 @@ WHERE m.id = ?""",
|
|||||||
self.update_app_media_list()
|
self.update_app_media_list()
|
||||||
else:
|
else:
|
||||||
return
|
return
|
||||||
pass
|
|
||||||
|
|
||||||
def delete_medium(self):
|
def delete_medium(self):
|
||||||
selected_apparat_id = self.active_apparat
|
selected_apparat_id = self.active_apparat
|
||||||
@@ -2013,7 +2046,8 @@ WHERE m.id = ?""",
|
|||||||
selected_rows = self.tableWidget_apparat_media.selectionModel().selectedRows()
|
selected_rows = self.tableWidget_apparat_media.selectionModel().selectedRows()
|
||||||
if len(selected_rows) == 1:
|
if len(selected_rows) == 1:
|
||||||
signature = self.tableWidget_apparat_media.item(
|
signature = self.tableWidget_apparat_media.item(
|
||||||
self.tableWidget_apparat_media.currentRow(), 1
|
self.tableWidget_apparat_media.currentRow(),
|
||||||
|
1,
|
||||||
).text()
|
).text()
|
||||||
book_id = self.db.getBookIdBasedOnSignature(
|
book_id = self.db.getBookIdBasedOnSignature(
|
||||||
selected_apparat_id,
|
selected_apparat_id,
|
||||||
@@ -2026,7 +2060,6 @@ WHERE m.id = ?""",
|
|||||||
if state == 1:
|
if state == 1:
|
||||||
self.db.deleteBook(book_id)
|
self.db.deleteBook(book_id)
|
||||||
self.update_app_media_list()
|
self.update_app_media_list()
|
||||||
pass
|
|
||||||
else:
|
else:
|
||||||
# get all selected rows
|
# get all selected rows
|
||||||
ranges = self.tableWidget_apparat_media.selectedRanges()
|
ranges = self.tableWidget_apparat_media.selectedRanges()
|
||||||
@@ -2057,12 +2090,15 @@ WHERE m.id = ?""",
|
|||||||
# #log.debug(data)
|
# #log.debug(data)
|
||||||
# return data
|
# return data
|
||||||
selected_apparat_id = self.tableWidget_apparate.item(
|
selected_apparat_id = self.tableWidget_apparate.item(
|
||||||
self.tableWidget_apparate.currentRow(), 0
|
self.tableWidget_apparate.currentRow(),
|
||||||
|
0,
|
||||||
).text()
|
).text()
|
||||||
# #log.debug(selected_apparat_id)
|
# #log.debug(selected_apparat_id)
|
||||||
|
|
||||||
self.db.setNewSemesterDate(
|
self.db.setNewSemesterDate(
|
||||||
selected_apparat_id, data["semester"], dauerapp=data["dauerapp"]
|
selected_apparat_id,
|
||||||
|
data["semester"],
|
||||||
|
dauerapp=data["dauerapp"],
|
||||||
)
|
)
|
||||||
# update the table
|
# update the table
|
||||||
self.get_apparats()
|
self.get_apparats()
|
||||||
@@ -2079,9 +2115,7 @@ WHERE m.id = ?""",
|
|||||||
app_id="",
|
app_id="",
|
||||||
):
|
):
|
||||||
log.debug(
|
log.debug(
|
||||||
"Got these values apparat: {}, location: {}, mail: {}, pid: {}, accepted_books: {}, app_id: {}".format(
|
f"Got these values apparat: {apparat}, location: {location}, mail: {mail}, pid: {pid}, accepted_books: {accepted_books}, app_id: {app_id}",
|
||||||
apparat, location, mail, pid, accepted_books, app_id
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
active_apparat_id = (
|
active_apparat_id = (
|
||||||
@@ -2126,7 +2160,8 @@ WHERE m.id = ?""",
|
|||||||
if self.active_apparat == "":
|
if self.active_apparat == "":
|
||||||
if apparat is False:
|
if apparat is False:
|
||||||
self.confirm_popup(
|
self.confirm_popup(
|
||||||
"Bitte erst einen Apparat auswählen!", title="Apparat auswählen"
|
"Bitte erst einen Apparat auswählen!",
|
||||||
|
title="Apparat auswählen",
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -2134,7 +2169,8 @@ WHERE m.id = ?""",
|
|||||||
|
|
||||||
def delete_apparat(self, position):
|
def delete_apparat(self, position):
|
||||||
selected_apparat_id = self.tableWidget_apparate.item(
|
selected_apparat_id = self.tableWidget_apparate.item(
|
||||||
self.tableWidget_apparate.currentRow(), 0
|
self.tableWidget_apparate.currentRow(),
|
||||||
|
0,
|
||||||
).text()
|
).text()
|
||||||
message = f"Soll der Apparat {selected_apparat_id} wirklich gelöscht werden?"
|
message = f"Soll der Apparat {selected_apparat_id} wirklich gelöscht werden?"
|
||||||
state = self.confirm_popup(message, title="Löschen?")
|
state = self.confirm_popup(message, title="Löschen?")
|
||||||
@@ -2146,7 +2182,8 @@ WHERE m.id = ?""",
|
|||||||
apparat = Apparat(
|
apparat = Apparat(
|
||||||
appnr=int(selected_apparat_id),
|
appnr=int(selected_apparat_id),
|
||||||
name=self.tableWidget_apparate.item(
|
name=self.tableWidget_apparate.item(
|
||||||
self.tableWidget_apparate.currentRow(), 1
|
self.tableWidget_apparate.currentRow(),
|
||||||
|
1,
|
||||||
).text(),
|
).text(),
|
||||||
)
|
)
|
||||||
self.db.deleteApparat(apparat=apparat, semester=Semester().value)
|
self.db.deleteApparat(apparat=apparat, semester=Semester().value)
|
||||||
@@ -2189,7 +2226,7 @@ def launch_gui():
|
|||||||
MainWindow.show()
|
MainWindow.show()
|
||||||
# atexit.register()
|
# atexit.register()
|
||||||
app.aboutToQuit.connect(
|
app.aboutToQuit.connect(
|
||||||
aui.validate_thread.quit
|
aui.validate_thread.quit,
|
||||||
) # if that thread uses an event loop
|
) # if that thread uses an event loop
|
||||||
app.aboutToQuit.connect(aui.docu.terminate) # our new slot
|
app.aboutToQuit.connect(aui.docu.terminate) # our new slot
|
||||||
app.aboutToQuit.connect(aui.docu.wait)
|
app.aboutToQuit.connect(aui.docu.wait)
|
||||||
|
|||||||
@@ -30,38 +30,41 @@ class WelcomeWizard(QtWidgets.QWizard, Ui_Wizard):
|
|||||||
|
|
||||||
# allow user to toggle password visibility
|
# allow user to toggle password visibility
|
||||||
self.settings_mail_password.setContextMenuPolicy(
|
self.settings_mail_password.setContextMenuPolicy(
|
||||||
QtCore.Qt.ContextMenuPolicy.CustomContextMenu
|
QtCore.Qt.ContextMenuPolicy.CustomContextMenu,
|
||||||
)
|
)
|
||||||
self.settings_zotero_api_key.setContextMenuPolicy(
|
self.settings_zotero_api_key.setContextMenuPolicy(
|
||||||
QtCore.Qt.ContextMenuPolicy.CustomContextMenu
|
QtCore.Qt.ContextMenuPolicy.CustomContextMenu,
|
||||||
)
|
)
|
||||||
self.settings_openai_api_key.setContextMenuPolicy(
|
self.settings_openai_api_key.setContextMenuPolicy(
|
||||||
QtCore.Qt.ContextMenuPolicy.CustomContextMenu
|
QtCore.Qt.ContextMenuPolicy.CustomContextMenu,
|
||||||
)
|
)
|
||||||
self.sam_password.setContextMenuPolicy(
|
self.sam_password.setContextMenuPolicy(
|
||||||
QtCore.Qt.ContextMenuPolicy.CustomContextMenu
|
QtCore.Qt.ContextMenuPolicy.CustomContextMenu,
|
||||||
)
|
)
|
||||||
self.settings_mail_password.customContextMenuRequested.connect(
|
self.settings_mail_password.customContextMenuRequested.connect(
|
||||||
lambda pos: self.toggle_password_visibility(
|
lambda pos: self.toggle_password_visibility(
|
||||||
pos, self.settings_mail_password
|
pos,
|
||||||
)
|
self.settings_mail_password,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
self.settings_zotero_api_key.customContextMenuRequested.connect(
|
self.settings_zotero_api_key.customContextMenuRequested.connect(
|
||||||
lambda pos: self.toggle_password_visibility(
|
lambda pos: self.toggle_password_visibility(
|
||||||
pos, self.settings_zotero_api_key
|
pos,
|
||||||
)
|
self.settings_zotero_api_key,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
self.settings_openai_api_key.customContextMenuRequested.connect(
|
self.settings_openai_api_key.customContextMenuRequested.connect(
|
||||||
lambda pos: self.toggle_password_visibility(
|
lambda pos: self.toggle_password_visibility(
|
||||||
pos, self.settings_openai_api_key
|
pos,
|
||||||
)
|
self.settings_openai_api_key,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
self.sam_password.customContextMenuRequested.connect(
|
self.sam_password.customContextMenuRequested.connect(
|
||||||
lambda pos: self.toggle_password_visibility(pos, self.sam_password)
|
lambda pos: self.toggle_password_visibility(pos, self.sam_password),
|
||||||
)
|
)
|
||||||
# if button for next page is clicked, run function to store settings
|
# if button for next page is clicked, run function to store settings
|
||||||
self.button(QtWidgets.QWizard.WizardButton.NextButton).clicked.connect(
|
self.button(QtWidgets.QWizard.WizardButton.NextButton).clicked.connect(
|
||||||
self.store_settings
|
self.store_settings,
|
||||||
)
|
)
|
||||||
self.settings_mail_use_user_name.toggled.connect(self.set_check_text)
|
self.settings_mail_use_user_name.toggled.connect(self.set_check_text)
|
||||||
# set initial values for checkbox, database
|
# set initial values for checkbox, database
|
||||||
@@ -69,13 +72,13 @@ class WelcomeWizard(QtWidgets.QWizard, Ui_Wizard):
|
|||||||
self.settings_database.setText(
|
self.settings_database.setText(
|
||||||
str(settings.database.path)
|
str(settings.database.path)
|
||||||
if settings.database.path is not None
|
if settings.database.path is not None
|
||||||
else str(appdirs.user_data_dir)
|
else str(appdirs.user_data_dir),
|
||||||
)
|
)
|
||||||
|
|
||||||
self.settings_temp.setText(
|
self.settings_temp.setText(
|
||||||
str(settings.database.temp)
|
str(settings.database.temp)
|
||||||
if settings.database.temp is not None
|
if settings.database.temp is not None
|
||||||
else str(appdirs.user_cache_dir)
|
else str(appdirs.user_cache_dir),
|
||||||
)
|
)
|
||||||
self.settings_database_name.setText("semesterapparate.db")
|
self.settings_database_name.setText("semesterapparate.db")
|
||||||
|
|
||||||
@@ -199,7 +202,7 @@ class WelcomeWizard(QtWidgets.QWizard, Ui_Wizard):
|
|||||||
file_dialog.setFileMode(QtWidgets.QFileDialog.FileMode.Directory)
|
file_dialog.setFileMode(QtWidgets.QFileDialog.FileMode.Directory)
|
||||||
file_dialog.setViewMode(QtWidgets.QFileDialog.ViewMode.List)
|
file_dialog.setViewMode(QtWidgets.QFileDialog.ViewMode.List)
|
||||||
file_dialog.setWindowFlags(
|
file_dialog.setWindowFlags(
|
||||||
file_dialog.windowFlags() | QtCore.Qt.WindowType.WindowStaysOnTopHint
|
file_dialog.windowFlags() | QtCore.Qt.WindowType.WindowStaysOnTopHint,
|
||||||
)
|
)
|
||||||
# set start dir to appdir.user_data_dir
|
# set start dir to appdir.user_data_dir
|
||||||
file_dialog.setDirectory(str(appdirs.user_data_dir))
|
file_dialog.setDirectory(str(appdirs.user_data_dir))
|
||||||
@@ -230,8 +233,6 @@ def launch_wizard():
|
|||||||
if not app:
|
if not app:
|
||||||
app = QtWidgets.QApplication([])
|
app = QtWidgets.QApplication([])
|
||||||
wizard = WelcomeWizard()
|
wizard = WelcomeWizard()
|
||||||
# wizard.setWindowTitle("Welcome to the Semester Apparatus Manager")
|
|
||||||
# wizard.setWindowIcon(settings.Icon("welcome").icon)
|
|
||||||
wizard.setWizardStyle(QtWidgets.QWizard.WizardStyle.ModernStyle)
|
wizard.setWizardStyle(QtWidgets.QWizard.WizardStyle.ModernStyle)
|
||||||
wizard.setStartId(0)
|
wizard.setStartId(0)
|
||||||
wizard.show()
|
wizard.show()
|
||||||
|
|||||||
@@ -69,6 +69,10 @@ nav = [
|
|||||||
{ "Anlegen" = "elsa/anlegen.md" },
|
{ "Anlegen" = "elsa/anlegen.md" },
|
||||||
{ "Zitieren" = "elsa/zitieren.md" },
|
{ "Zitieren" = "elsa/zitieren.md" },
|
||||||
] },
|
] },
|
||||||
|
{ "Adminbereich" = [
|
||||||
|
{ "Übersicht" = "admin/index.md" },
|
||||||
|
{ "Benutzerverwaltung" = "admin/benutzerverwaltung.md" },
|
||||||
|
] },
|
||||||
{ "Sonstiges" = [
|
{ "Sonstiges" = [
|
||||||
{ "Übersicht" = "sonstiges/index.md" },
|
{ "Übersicht" = "sonstiges/index.md" },
|
||||||
{ "Bilder" = "sonstiges/bilder.md" },
|
{ "Bilder" = "sonstiges/bilder.md" },
|
||||||
|
|||||||
Reference in New Issue
Block a user