96 Commits
v0.1.1 ... dev

Author SHA1 Message Date
79f51852e5 initial commit 2025-04-03 19:57:34 +02:00
c0db86dfcc update code 2025-02-05 12:47:38 +01:00
057117521c feat: set focus to book ident on change 2025-02-05 09:15:50 +01:00
18be111dc1 adding build file, updating gititgnore, adding check in backup to create archive if source is present 2025-02-05 08:18:37 +01:00
7140032109 Bump version: 0.3.1 → 0.3.2 2025-02-03 14:43:39 +01:00
50534d46b1 updating readme for new run and build process 2025-02-03 14:43:18 +01:00
776346748e set window icon 2025-02-03 13:56:41 +01:00
d01cafcbb7 add archive to keep databases permanently stored in an archive folder 2025-02-03 13:56:13 +01:00
8b8c115091 update version, change help text 2025-01-30 11:10:20 +01:00
df2f9af726 Bump version: 0.3.0 → 0.3.1 2025-01-30 10:58:25 +01:00
348e944c73 update documentation to reflect latest changes 2025-01-30 10:54:36 +01:00
7171d2a4da add option to add books manually, fix multiple user selection bug 2025-01-30 10:42:52 +01:00
5501cbf97c Bump version: 0.2.19 → 0.3.0 2025-01-29 11:13:57 +01:00
0f71f82a3f update project, launch files 2025-01-29 11:13:11 +01:00
b5015b11d9 enable the addition of the signature in the report in the UI, update docs 2025-01-29 11:09:34 +01:00
21e09d1dc0 fix typo 2025-01-29 09:52:04 +01:00
aa4ca0bac7 update documentation settings, enable live-reload 2025-01-29 09:40:54 +01:00
761ac541da update documentation (p3) 2025-01-29 09:25:45 +01:00
3bfbcbc3e0 add option to show signature in report and update settings UI 2025-01-29 09:16:26 +01:00
9d50115cb2 update documentation (p2) 2025-01-28 16:24:38 +01:00
75c12ffda5 fix crash in Loan Window 2025-01-28 16:10:56 +01:00
96a519a8f3 fix typo in settings 2025-01-28 16:03:08 +01:00
91d1576939 update documentation (p1) 2025-01-28 16:02:47 +01:00
00cdd5c36b replace icon, remove variable 2025-01-28 14:25:18 +01:00
2a451dc749 fix report generation bug, change modality 2025-01-28 14:17:43 +01:00
1d213e1f6a fix typo 2025-01-28 13:52:37 +01:00
3ecc918dd7 update settings, icons 2025-01-28 13:52:30 +01:00
049992f0a7 fix some small stuff, add icons to main UI, add shortcuts 2025-01-28 13:52:03 +01:00
d3cc6a35a3 disable log 2025-01-27 11:37:09 +01:00
c427202b2a add explanation about auto signature generation, fix loan ui bug
loan UI now colors rows correctly and data is being displayed on change
2025-01-27 10:53:55 +01:00
20b53cea69 fix dependency issue 2025-01-24 10:51:00 +01:00
cef79c9375 exclude dev group from being synced automatically 2025-01-24 10:43:55 +01:00
17fd893875 Bump version: 0.2.18 → 0.2.19 2025-01-24 10:38:11 +01:00
b7eb2a1820 update 2025-01-24 10:35:42 +01:00
f1ee4089a3 update documentation, rework documentation thread, rework book dataclass, fix newentry bug 2025-01-24 10:17:16 +01:00
b112b09e82 update launch scripts to use uv 2025-01-24 08:24:32 +01:00
05c76d49fd delete unneeded files 2025-01-24 08:23:30 +01:00
c929739210 add omegaconf dependency, rework launch scripts to check if venv exists 2025-01-24 08:10:59 +01:00
056546a920 add launch scripts for windows 2025-01-23 19:29:49 +01:00
708cd39f8e Bump version: 0.2.17 → 0.2.18 2025-01-21 16:32:20 +01:00
9cbbd696dc update changelog for v0.2.17 with additional tests for the release script 2025-01-21 15:20:26 +01:00
8eee280226 Bump version: 0.2.16 → 0.2.17 2025-01-21 15:19:37 +01:00
a007cb4c96 Bump version: 0.2.15 → 0.2.16 2025-01-21 13:56:12 +01:00
3ba1693674 Bump version: 0.2.14 → 0.2.15 2025-01-21 13:54:01 +01:00
3f8124c925 Bump version: 0.2.13 → 0.2.14 2025-01-21 13:51:12 +01:00
ab7cffffad update changelog 2025-01-21 13:49:02 +01:00
1a7c6426e7 Bump version: 0.2.12 → 0.2.13 2025-01-21 13:48:24 +01:00
5547aad98f Bump version: 0.2.11 → 0.2.12 2025-01-21 13:48:17 +01:00
f1b1c3f5ee Bump version: 0.2.10 → 0.2.11 2025-01-21 13:48:08 +01:00
9ed7dfabb0 update changelog 2025-01-21 13:48:01 +01:00
1c7e34f9fc Bump version: 0.2.9 → 0.2.10 2025-01-21 12:41:38 +01:00
f6da80ca11 Bump version: 0.2.8 → 0.2.9 2025-01-21 12:23:31 +01:00
f5e27a8605 update changelog 2025-01-21 12:23:25 +01:00
131161eed2 Bump version: 0.2.7 → 0.2.8 2025-01-21 11:22:45 +01:00
2a688ffd8f Bump version: 0.2.6 → 0.2.7 2025-01-21 09:17:20 +01:00
a0a6f63974 update task, changelog 2025-01-21 09:17:15 +01:00
54ca85e4ef Bump version: 0.2.5 → 0.2.6 2025-01-20 11:20:08 +01:00
bc6ffb098a rm lockfile 2025-01-20 11:19:52 +01:00
344d436d63 update .gitignore 2025-01-20 11:18:33 +01:00
9cf49b8f38 update build command 2025-01-20 11:16:19 +01:00
c276ab587b format code 2025-01-20 11:13:36 +01:00
430878b41f Bump version: 0.2.4 → 0.2.5 2025-01-17 09:42:52 +01:00
9493ed2e24 version change 2025-01-17 09:42:42 +01:00
6ec0a9f104 revert version 2025-01-17 09:23:27 +01:00
2ef0ea42e8 version change 2025-01-17 09:22:51 +01:00
ce03d28936 version change 2025-01-17 09:11:47 +01:00
359f5e78a2 version change 2025-01-17 09:10:41 +01:00
dc470798d2 change version 2025-01-17 09:07:36 +01:00
4351e581e6 update 2025-01-17 09:06:43 +01:00
8ed1801a50 revert version 2025-01-17 08:44:59 +01:00
0775c66e4a enable tag creation 2025-01-17 08:44:22 +01:00
6c10589508 allow commits, change bumpversion toml 2025-01-13 12:45:02 +01:00
d73a62c3ea temporarily ignore config 2025-01-13 11:16:25 +01:00
62e0f279d0 add newLine 2025-01-13 11:15:03 +01:00
daf8d87b9d update deps, change config to restore changes, color overdue red in main, in loan color based on state 2025-01-13 11:14:27 +01:00
148adb937d filechanges 2025-01-13 11:13:00 +01:00
17e8d3c2b2 switch to maintained fork 2025-01-13 11:12:08 +01:00
9567d24cfa Bump version: 0.2.2 → 0.2.3 2025-01-13 08:09:01 +01:00
4b16bfd501 changes, add dotenv dependency 2025-01-13 08:08:54 +01:00
ee256040d9 Bump version: 0.2.1 → 0.2.2 2025-01-10 10:40:22 +01:00
1291f1eddc add changelog, release.ps1 2025-01-10 10:40:16 +01:00
c7a596f6d0 changes 2025-01-10 10:39:30 +01:00
d208013192 Bump version: 0.2.0 → 0.2.1 2025-01-10 09:35:48 +01:00
60fa34c235 change tasks, config 2025-01-10 09:35:43 +01:00
0d7dc28876 update code, switch to loguru 2025-01-10 09:35:18 +01:00
e915b47dda updates 2025-01-09 15:15:18 +01:00
6316fc72ab Merge pull request 'main to dev' (#10) from main into dev
Reviewed-on: WorldTeacher/LibrarySystem#10
2025-01-09 13:15:31 +01:00
3d4d1f2601 bump version files 2025-01-09 13:13:27 +01:00
c697a3b78e add uv files 2025-01-09 13:11:39 +01:00
e5bec6f2f9 Bump version: 0.1.2 → 0.2.0 2025-01-09 13:06:56 +01:00
2c90699fe3 remove unneeded print 2025-01-09 13:06:14 +01:00
5aae18dc09 remove comment 2025-01-09 12:52:50 +01:00
1403646426 small changes 2025-01-09 12:52:34 +01:00
462322fcc5 remove dependency 2025-01-09 12:45:24 +01:00
0475811315 Bump version: 0.1.1 → 0.1.2 2024-11-08 08:47:09 +01:00
d71151ff2b changes as test 2024-11-08 08:47:03 +01:00
107 changed files with 2562 additions and 1312 deletions

View File

@@ -1,8 +0,0 @@
[bumpversion]
current_version = 0.1.1
tag = True
commit = True
[bumpversion:file:src/__init__.py]
search = __version__ = "{current_version}"
replace = __version__ = "{new_version}"

22
.bumpversion.toml Normal file
View File

@@ -0,0 +1,22 @@
[tool.bumpversion]
current_version = "0.3.2"
parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)"
serialize = ["{major}.{minor}.{patch}"]
search = "{current_version}"
replace = "{new_version}"
regex = false
ignore_missing_version = false
tag = true
sign_tags = false
tag_name = "v{new_version}"
tag_message = "Bump version: {current_version} → {new_version}"
allow_dirty = false
commit = true
message = "Bump version: {current_version} → {new_version}"
commit_args = ""
[[tool.bumpversion.files]]
filename = ".version"
[[tool.bumpversion.files]]
filename = "src/__init__.py"
[[tool.bumpversion.files]]
filename = "pyproject.toml"

19
.gitignore vendored
View File

@@ -216,10 +216,19 @@ compile_commands.json
*_qmlcache.qrc *_qmlcache.qrc
.history/*
.history
depend
output/output/LOGtoJSON.exe
.pytest_cache
output
docs/
config.yaml
**/tempCodeRunnerFile.py **/tempCodeRunnerFile.py
output/** uv.lock
.history
# Rust .venv
target/ venv
*.log

1
.python-version Normal file
View File

@@ -0,0 +1 @@
3.12

9
.trunk/.gitignore vendored
View File

@@ -1,9 +0,0 @@
*out
*logs
*actions
*notifications
*tools
plugins
user_trunk.yaml
user.yaml
tmp

View File

@@ -1,10 +0,0 @@
# This file controls the behavior of Trunk: https://docs.trunk.io/cli
# To learn more about the format of this file, see https://docs.trunk.io/reference/trunk-yaml
version: 0.1
cli:
version: 1.22.8
plugins:
sources:
- id: trunk
ref: v1.6.4
uri: https://github.com/trunk-io/plugins

1
.version Normal file
View File

@@ -0,0 +1 @@
0.3.2

16
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,16 @@
{
"files.exclude": {
"**/.git": true,
"**/.svn": true,
"**/.hg": true,
"**/CVS": true,
"**/.DS_Store": true,
"**/Thumbs.db": true,
"**/.trunk/*actions/": true,
"**/.trunk/*logs/": true,
"**/.trunk/*notifications/": true,
"**/.trunk/*out/": true,
"**/.trunk/*plugins/": true
},
"hide-files.files": []
}

130
.vscode/tasks.json vendored
View File

@@ -2,26 +2,13 @@
"version": "2.0.0", "version": "2.0.0",
"tasks": [ "tasks": [
{ {
"label": "Build LibrarySystem (Debug)", "label": "Build New Release",
"type": "shell", "type": "shell",
"command": "pyinstaller", "dependsOn": [
"args": [ "Build LibrarySystem (Release)",
"--noconfirm", "Build LibrarySystem (Debug)"
"--onedir",
"--console",
"--icon",
"'${config:ApplicationIconPath}'",
"--name",
"LibrarySystem-debug",
"--contents-directory",
".",
"--clean",
"--add-data",
"'${config:configPath};config/'",
"--add-data",
"'${config:iconsPath};icons/'",
"'${workspaceFolder}/main_dev.py'"
], ],
"command": "python setup.py",
"group": { "group": {
"kind": "build", "kind": "build",
"isDefault": true "isDefault": true
@@ -31,29 +18,29 @@
"panel": "new", "panel": "new",
"focus": false "focus": false
}, },
"dependsOn": "Compress dist Folder Debug", // "dependsOn": "Compress dist Folder Debug",
"problemMatcher": "$pyinstaller" "problemMatcher": "$python"
}, },
{ {
"label": "Build LibrarySystem (Release)", "label": "Build LibrarySystem (Debug)",
"type": "shell", "type": "shell",
"command": "pyinstaller", "command": "uv",
"args": [ "args": [
"--noconfirm", "run",
"--onedir", "python",
"--windowed", "-m",
"--name", "nuitka",
"LibrarySystem", "--standalone",
"--contents-directory", "--output-dir=dist",
".", "--include-package=PyQt6",
"--clean", "--include-package=pygments",
"--add-data", "--include-data-dir=./config=config",
"'${config:configPath};config/'", "--include-data-dir=./docs=docs",
"--add-data", "--include-data-dir=./icons=icons",
"'${config:iconsPath};icons/'", "--include-data-dir=./.venv/Lib/site-packages/PyQt6/=PyQt6/",
"--icon", "--windows-icon-from-ico=icons/icon.ico",
"'${config:ApplicationIconPath}'", "main_dev.py",
"'${workspaceFolder}/main.py'" "--debug"
], ],
"group": { "group": {
"kind": "build", "kind": "build",
@@ -62,50 +49,57 @@
"presentation": { "presentation": {
"reveal": "always", "reveal": "always",
"panel": "new", "panel": "new",
"focus": false "focus": false,
"close": true
}, },
"dependsOn": "Compress dist Folder Release", // "dependsOn": "Compress dist Folder Debug",
"problemMatcher": "$pyinstaller" "problemMatcher": "$python"
},
{
"label": "Build LibrarySystem (Release)",
"type": "shell",
"command": "uv",
"args": [
"run",
"python",
"-m",
"nuitka",
"--standalone",
"--output-dir=dist",
"--include-package=PyQt6",
"--include-package=pygments",
"--include-data-dir=./config=config",
"--include-data-dir=./docs=docs",
"--include-data-dir=./icons=icons",
"--include-data-dir=./.venv/Lib/site-packages/PyQt6/Qt6/plugins=PyQt6/Qt/plugins",
"--windows-icon-from-ico=icons/icon.ico",
"main.py"
],
"group": {
"kind": "build",
"isDefault": false
},
"presentation": {
"reveal": "always",
"panel": "new",
"focus": false,
"close": true
},
"problemMatcher": "$python"
}, },
{ {
"label": "Run LibrarySystem (live)", "label": "Run LibrarySystem (live)",
"type": "shell", "type": "shell",
"command": "c:/Users/aky547/GitHub/LibrarySystem/.venv/Scripts/python.exe", "command": "c:/Users/aky547/GitHub/LibrarySystem/.venv/Scripts/python.exe",
"args": [ "args": [
"'c:/Users/aky547/GitHub/LibrarySystem/main_dev.py'", "'c:/Users/aky547/GitHub/LibrarySystem/main.py'",
"--ic-logging" "--debug"
], ],
"group": { "group": {
"kind": "test", "kind": "test",
"isDefault": true "isDefault": true
}, },
"problemMatcher": "$python" "problemMatcher": "$python"
},
{
"label": "Compress dist Folder Debug",
"type": "shell",
"command": "Compress-Archive",
"args": [
"-Path",
"${workspaceFolder}/dist/LibrarySystem-debug/",
"-DestinationPath",
"${workspaceFolder}/output/LibrarySystem-debug.zip",
],
"group": "build",
"presentation": "panel"
},
{
"label": "Compress dist Folder Release",
"type": "shell",
"command": "Compress-Archive",
"args": [
"-Path",
"${workspaceFolder}/dist/LibrarySystem/",
"-DestinationPath",
"${workspaceFolder}/output/LibrarySystem.zip",
],
"group": "build",
"presentation": "panel"
} }
] ]
} }

View File

@@ -1,4 +1,4 @@
## Icons ## Icons
if not stated elsewhere, all Icons are part of the Material Symbols Package provided by Google if not stated elsewhere, all Icons are part of the Material Symbols Package provided by Google
### Specific Icons ### Specific Icons
- borrow_boks.svg Credits to Maxicons, Icon downloaded frmo thenounproject.com [Link](https://thenounproject.com/icon/borrow-book-3317975/) - borrow_boks.svg Credits to Maxicons, Icon downloaded from thenounproject.com [Link](https://thenounproject.com/icon/borrow-book-3317975/)

20
LICENSE
View File

@@ -1,9 +1,21 @@
MIT License MIT License
Copyright (c) 2024 WorldTeacher Copyright (c) 2025 WorldTeacher
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -1,6 +1,6 @@
# LibrarySystem # LibrarySystem
universal library system for facilities in the university. Currently hard-coded for the Library of the University of Education in Freiburg, Germany. universal library system for facilities in the university. Currently hard-coded for the Library of the University of Education in Freiburg, Germany, but can be adapted to fit other libraries as long as the catalogue has a suitable format, or an open API
Other Libraries can be supported by rewriting the catalog and it's corresponding functions. Other Libraries can be supported by rewriting the catalog and it's corresponding functions.
@@ -10,24 +10,31 @@ This is a library system for the different facilities in our university. Because
### Installation ### Installation
#### Windows #### Windows
using the latest git commit version: For windows, there are two ways to install the software:
```
git clone https://git.theprivateserver.de/WorldTeacher/LibrarySystem.git
cd LibrarySystem
python -m venv venv
source venv/bin/activate
pip install -r requirements.txt
python main.py
```
building the software:
```
download the installer.bat
execute the file in a terminal
```
1. using the latest git commit version:
~~or head over to [releases](https://git.theprivateserver.de/WorldTeacher/LibrarySystem/releases) Prerequisites:
and download the latest version~~ (not yet supported) - [uv](https://docs.astral.sh/uv/getting-started/installation/) and [Git](https://git-scm.com/downloads/win) are installed
```bash
git clone https://git.theprivateserver.de/WorldTeacher/LibrarySystem.git
cd LibrarySystem
uv sync # This will install all dependencies, including dev dependencies
source venv/Scrpits/activate(.bat|ps1) # This will activate the virtual environment
uv run python main.py
```
building the software:
```bash
uv run python build.py
```
This will create a build folder with the application in it. You can move the folder of the application anywhere you want
2. using the release:
~~see: [releases](https://git.theprivateserver.de/WorldTeacher/LibrarySystem/releases)
and download the latest version~~ (not yet supported)
### Configuration ### Configuration

0
backup/library.db Normal file
View File

View File

@@ -1,61 +0,0 @@
{
"version": "auto-py-to-exe-configuration_v1",
"pyinstallerOptions": [
{
"optionDest": "noconfirm",
"value": true
},
{
"optionDest": "onefile",
"value": false
},
{
"optionDest": "console",
"value": false
},
{
"optionDest": "name",
"value": "LibrarySystem"
},
{
"optionDest": "contents_directory",
"value": "."
},
{
"optionDest": "clean_build",
"value": true
},
{
"optionDest": "strip",
"value": false
},
{
"optionDest": "noupx",
"value": false
},
{
"optionDest": "disable_windowed_traceback",
"value": false
},
{
"optionDest": "uac_admin",
"value": false
},
{
"optionDest": "uac_uiaccess",
"value": false
},
{
"optionDest": "argv_emulation",
"value": false
},
{
"optionDest": "bootloader_ignore_signals",
"value": false
}
],
"nonPyinstallerOptions": {
"increaseRecursionLimit": true,
"manualArguments": ""
}
}

View File

@@ -1,77 +0,0 @@
{
"version": "auto-py-to-exe-configuration_v1",
"pyinstallerOptions": [
{
"optionDest": "noconfirm",
"value": true
},
{
"optionDest": "filenames",
"value": "C:/Users/aky547/GitHub/LibrarySystem/main_dev.py"
},
{
"optionDest": "onefile",
"value": false
},
{
"optionDest": "console",
"value": true
},
{
"optionDest": "icon_file",
"value": "C:/Users/aky547/Downloads/1490971308-map-icons-7_82746.ico"
},
{
"optionDest": "name",
"value": "LibrarySystem-debug"
},
{
"optionDest": "contents_directory",
"value": "."
},
{
"optionDest": "clean_build",
"value": true
},
{
"optionDest": "strip",
"value": false
},
{
"optionDest": "noupx",
"value": false
},
{
"optionDest": "disable_windowed_traceback",
"value": false
},
{
"optionDest": "uac_admin",
"value": false
},
{
"optionDest": "uac_uiaccess",
"value": false
},
{
"optionDest": "argv_emulation",
"value": false
},
{
"optionDest": "bootloader_ignore_signals",
"value": false
},
{
"optionDest": "datas",
"value": "C:/Users/aky547/GitHub/LibrarySystem/config;config/"
},
{
"optionDest": "datas",
"value": "C:/Users/aky547/GitHub/LibrarySystem/icons;icons/"
}
],
"nonPyinstallerOptions": {
"increaseRecursionLimit": true,
"manualArguments": ""
}
}

17
build.py Normal file
View File

@@ -0,0 +1,17 @@
import os
import shutil
def build_release():
print("Building Application")
os.system(
"uv run python -m nuitka --standalone --output-dir=build --include-package=PyQt6 --include-package=pygments --include-data-dir=./config=config --include-data-dir=./docs=docs --include-data-dir=./icons=icons --include-data-dir=./.venv/Lib/site-packages/PyQt6/=PyQt6 --windows-icon-from-ico=icons/icon.ico main.py"
)
shutil.copytree(
".venv/Lib/site-packages/PyQt6/", "build/main.dist/PyQt6/", dirs_exist_ok=True
)
shutil.move("build/main.dist", "build/LibrarySystem")
if __name__ == "__main__":
build_release()

View File

@@ -1,77 +0,0 @@
{
"version": "auto-py-to-exe-configuration_v1",
"pyinstallerOptions": [
{
"optionDest": "noconfirm",
"value": true
},
{
"optionDest": "filenames",
"value": "C:/Users/aky547/GitHub/LibrarySystem/main.py"
},
{
"optionDest": "onefile",
"value": false
},
{
"optionDest": "console",
"value": false
},
{
"optionDest": "icon_file",
"value": "C:/Users/aky547/Downloads/1490971308-map-icons-7_82746.ico"
},
{
"optionDest": "name",
"value": "LibrarySystem"
},
{
"optionDest": "contents_directory",
"value": "."
},
{
"optionDest": "clean_build",
"value": true
},
{
"optionDest": "strip",
"value": false
},
{
"optionDest": "noupx",
"value": false
},
{
"optionDest": "disable_windowed_traceback",
"value": false
},
{
"optionDest": "uac_admin",
"value": false
},
{
"optionDest": "uac_uiaccess",
"value": false
},
{
"optionDest": "argv_emulation",
"value": false
},
{
"optionDest": "bootloader_ignore_signals",
"value": false
},
{
"optionDest": "datas",
"value": "C:/Users/aky547/GitHub/LibrarySystem/config;config/"
},
{
"optionDest": "datas",
"value": "C:/Users/aky547/GitHub/LibrarySystem/icons;icons/"
}
],
"nonPyinstallerOptions": {
"increaseRecursionLimit": true,
"manualArguments": ""
}
}

33
changelog.md Normal file
View File

@@ -0,0 +1,33 @@
# Changelog
## v0.2.17
- More tests for the release script
## v0.2.13
- Release bugfixes
## v0.2.10
- Small changes to the release script, trying to fix a bug where assets are not added to the release
## v0.2.8
- Updated the release script to use the tea application to create releases with files
- Updated the release script to use the new release system
## v0.2.7
- reworked release script to create releases
## v0.2.6
- changed build command
- small fixes, coloring the user loan table based on book status
## v0.2.4 - v0.2.5
-Testing only
## v0.2.3
- started implementing the updated release script, aimimg to create automated releases that can be grabbed using the updater, which will be created thereafter
## v0.2.2
- fixed minor bugs in release script
## v0.2.1
- Changed logging to use loguru
- reworked cli arguments to be working
- suppressed mkdocs server from hogging the cli and not showing debug info when requested

View File

@@ -107,26 +107,7 @@ class Config:
if self._config is None: if self._config is None:
raise RuntimeError("Configuration not loaded") raise RuntimeError("Configuration not loaded")
self._config.debug = value self._config.debug = value
@property
def log_debug(self)->bool:
if self._config is None:
raise RuntimeError("Configuration not loaded")
return self._config.log_debug
@log_debug.setter
def log_debug(self, value: bool):
if self._config is None:
raise RuntimeError("Configuration not loaded")
self._config.log_debug = value
@property
def ic_logging(self)->bool:
if self._config is None:
raise RuntimeError("Configuration not loaded")
return self._config.ic_logging
@ic_logging.setter
def ic_logging(self, value:bool):
if self._config is None:
raise RuntimeError("Configuration not loaded")
self._config.ic_logging = value
def save(self): def save(self):
if self._config is None: if self._config is None:
raise RuntimeError("Configuration not loaded") raise RuntimeError("Configuration not loaded")
@@ -167,10 +148,37 @@ class Config:
raise KeyError(f"Option {keys[0]} not found in configuration") raise KeyError(f"Option {keys[0]} not found in configuration")
else: else:
self._config[key] = value self._config[key] = value
def get_changes(self, other):
# compare self to other, return changes
changes = {}
for key in self._config:
if self._config[key] != other[key]:
changes[key] = self._config[key]
return changes
if __name__ == "__main__": if __name__ == "__main__":
cfg = Config("config/settings.yaml") cfg = Config("config/settings.yaml")
#print(cfg.database.path) other = {
cfg.database.path = "nopathhere" "institution_name": "Test",
#print(cfg.database.path) "default_loan_duration": 7,
cfg.save() "inactive_user_deletion": 365,
#cfg.updateValue("database.path", "Test") "database": {
"path": "./database",
"name": "library.db",
"backupLocation": "./backup",
"do_backup": True,
},
"report": {"generate_report": True, "path": "./report", "report_day": 0},
"shortcuts": [
{"name": "Rueckgabemodus", "default": "F5", "current": "F5"},
{"name": "Nutzer", "default": "F6", "current": "F6"},
{"name": "Hilfe", "default": "F1", "current": "F1"},
{"name": "Bericht_erstellen", "default": "F7", "current": "F7"},
{"name": "Ausleihhistorie", "default": "F8", "current": "F8"},
],
"advanced_refresh": False,
"catalogue": True,
"debug": True,
"documentation": True,
}
print(cfg.get_changes(other))

View File

@@ -1,4 +1,4 @@
institution_name: Test institution_name: Testbibliothek Psychologie
default_loan_duration: 7 default_loan_duration: 7
inactive_user_deletion: 365 inactive_user_deletion: 365
database: database:
@@ -10,6 +10,7 @@ report:
generate_report: true generate_report: true
path: ./report path: ./report
report_day: 0 report_day: 0
show_signature: true
shortcuts: shortcuts:
- name: Rueckgabemodus - name: Rueckgabemodus
default: F5 default: F5
@@ -29,6 +30,4 @@ shortcuts:
advanced_refresh: false advanced_refresh: false
catalogue: true catalogue: true
debug: false debug: false
log_debug: false documentation: true
ic_logging: false
documentation: true

BIN
database/library.db Normal file

Binary file not shown.

15
docs/Allgemeines.md Normal file
View File

@@ -0,0 +1,15 @@
# Allgemeines
Hier werden alle allgemeinen Informationen zur Anwendung aufgeführt, die nicht direkt in die anderen Bereiche passen.
## Datenbankbackup
Bei jedem Schließen der Anwendung wird ein Backup der Datenbank erstellt. Dieses Backup wird im Sicherungspfad gespeichert, der Sicherungspfad ist in den Einstellungen einsehbar und änderbar.
Sollte der normale Speicherpfad nicht existieren oder nicht erreichbar sein (im Falle eines Netzwerklaufwerks), wird der Backuppfad verwendet. Beim Schließen der Anwendung wird ein Fehler angezeigt, dass das Erstellen des Backups nicht erfolgreich war. Solange der originale Pfad nicht erreichbar ist, wird der Backuppfad verwendet.
Sobald der originale Pfad wieder erreichbar ist, wird die Datenbank in den originalen Pfad kopiert, die veraltete Datenbank wird gelöscht und der Backuppfad wird wieder verwendet.
## Datenbankarchiv
Um eventuelle Datenbeschädigungen zu vermeiden, wird die Datenbank bei jedem Beenden der Anwendung in ein Archiv kopiert. Dieses Archiv wird im Archivpfad gespeichert, der Archivpfad nutzt den Sicherungspfad als grundlage und erstellt einen neuen Ordner "archive" in diesem Pfad.

View File

@@ -14,3 +14,8 @@ Wenn "Yes" geklickt wird, erscheint ein neues Fenster zum anlegen eines neuen Ex
![AddNewBook](images/book_addNew.png) ![AddNewBook](images/book_addNew.png)
Über das + Symbol können neue Exemplare hinzugefügt werden. Es ist empfohlen, die Signatur jeweils um +1 zu erhöhen, um eine eindeutige Zuordnung zu gewährleisten. Über das + Symbol können neue Exemplare hinzugefügt werden. Es ist empfohlen, die Signatur jeweils um +1 zu erhöhen, um eine eindeutige Zuordnung zu gewährleisten.
!!! Info
Die neueste Version erstellt die Nummer `+X` automatisch, basierend auf Basis des bereits entliehenen Buchs

View File

@@ -3,7 +3,7 @@
!!! info !!! info
Die Ausleihhistorie kann vom Ausleihsystem immer aufgerufen werden. Dazu kann man entweder das Menu öffnen (Fenster -> Ausleihhistorie) oder den festgelegten Shortcut verwenden. Die Ausleihhistorie kann vom Ausleihsystem immer aufgerufen werden. Dazu kann man entweder das Menu öffnen (Fenster -> Ausleihhistorie) oder den festgelegten Shortcut verwenden.
# Bedienung # Bedienung
Hier werden alle Medien angezeigt. Hier werden alle Medien angezeigt.

View File

@@ -4,7 +4,7 @@
## Oberfläche ## Oberfläche
![Nutzeroberfläche ohne Bewerkungen](images/main_marked%20areas.png) ![Nutzeroberfläche ohne Bemerkungen](images/main_marked%20areas.png)
Die Oberfläche kann generell in drei Bereiche unterteilt werden: Die Oberfläche kann generell in drei Bereiche unterteilt werden:
@@ -27,6 +27,10 @@ Hier werden folgende Daten angezeigt
- Ausleihe bis: bis wann das Medium ausgeliehen wird, Zeitraum wird in den Einstellungen angepasst - Ausleihe bis: bis wann das Medium ausgeliehen wird, Zeitraum wird in den Einstellungen angepasst
- Nutzer anlegen: ein Knopf, um einen neuen Nutzer anzulegen (2) - Nutzer anlegen: ein Knopf, um einen neuen Nutzer anzulegen (2)
!!! Info "Manuell Medien hinzufügen"
Über das Plus (8) können manuell Medien hinzugefügt werden. Dies kann sowohl im Ausleih- als auch Rückgabemodus durchgeführt werden. Im Ausleihmodus wird das Medium direkt auf das offene Konto entliehen, im Rückgabemodus wird das Medium nur in die Datenbank eingetragen.
### Nutzerdaten ### Nutzerdaten
Hier werden die Nutzerdaten angezeigt. Vorraussetzung ist, dass ein Nutzer angelegt und geöffnet wurde, oder dass ein Medium zurückgegeben wurde. Hier werden die Nutzerdaten angezeigt. Vorraussetzung ist, dass ein Nutzer angelegt und geöffnet wurde, oder dass ein Medium zurückgegeben wurde.
Dieser Bereich beschränkt sich auf folgende Inhalte: Dieser Bereich beschränkt sich auf folgende Inhalte:
@@ -46,13 +50,13 @@ Das Feld der Historie listet alle Medien auf, die im aktiven Prozess ausgeliehen
## Ausleihen ## Ausleihen
Um ein Medium auszuleihen, muss zuerst ein Nutzer geöffnet sein. Dazu entweder den Knopf neben Modus drücken, oder den Shortcut (Standard: `F5`) verwenden. Um ein Medium auszuleihen, muss zuerst ein Nutzer geöffnet werden. Dazu entweder den Knopf neben Modus drücken, oder den Shortcut (Standard: `F5`) verwenden.
Die Oberfläche sieht dann wie folgt aus: Die Oberfläche sieht dann wie folgt aus:
![Ausleihe](images/main_loan_active.png) ![Ausleihe](images/main_loan_active.png)
Der Cursor wird automatisch auf die Matrikelnummer gesetzt. Hier kann entweder die vollständige Nummer, oder ein Teil eingegeben werden. Sollten mehrere Nummern dem Teilfilter ensprechen, wird eine Auswahl angezeigt. (s. [MultiUser](MultiUser.md)) Der Cursor wird automatisch auf die Matrikelnummer gesetzt. Hier kann entweder die vollständige Nummer oder ein Teil eingegeben werden. Sollten mehrere Nummern dem Teilfilter entsprechen, wird eine Auswahl angezeigt. (s. [MultiUser](MultiUser.md))
Nach der Auswahl wird das entsprechende Konto geöffnet und die Ausleihe kann durchgeführt werden. Nach der Auswahl wird das entsprechende Konto geöffnet und die Ausleihe kann durchgeführt werden.
![Ausleihe](images/activeLoan.png) ![Ausleihe](images/activeLoan.png)
@@ -60,7 +64,7 @@ Nach der Auswahl wird das entsprechende Konto geöffnet und die Ausleihe kann du
Sollte der aktive Nutzer aktive Ausleihen haben, so wird die Anzahl der Medien neben "Anzahl Ausleihen" angezeigt. Das nächste Rückgabedatum wird ebenfalls angezeigt. Über einen Klick auf die Zahl der Ausleihen gelangen Sie zur [Übersicht der Ausleihen des Nutzers](Nutzeroberfläche.md). Sollte der aktive Nutzer aktive Ausleihen haben, so wird die Anzahl der Medien neben "Anzahl Ausleihen" angezeigt. Das nächste Rückgabedatum wird ebenfalls angezeigt. Über einen Klick auf die Zahl der Ausleihen gelangen Sie zur [Übersicht der Ausleihen des Nutzers](Nutzeroberfläche.md).
Um ein Medium auszuleihen, muss die Signatur in die entsprechende Zeile eingegeben werden. Sollte die Signatur nicht in der Datenbank existieren, wird der definierte Katalog geprüft. Wird das Medium gefunden, wird es in die Datenbank übernommen und die Ausleihe wird durchgeführt. Sollte das Medium nicht gefunden werden, wird eine Fehlermeldung angezeigt. Um ein Medium auszuleihen, muss die Signatur in die entsprechende Zeile eingegeben werden. Sollte die Signatur nicht in der Datenbank existieren, wird der zuvor festgelegte Katalog geprüft. Wird das Medium gefunden, wird es in die Datenbank übernommen und die Ausleihe wird durchgeführt. Sollte das Medium nicht gefunden werden, wird eine Fehlermeldung angezeigt.
![FehlerAusleihe](images/err_noBook.png) ![FehlerAusleihe](images/err_noBook.png)
@@ -68,7 +72,7 @@ Um ein Medium auszuleihen, muss die Signatur in die entsprechende Zeile eingegeb
Die Signatur muss mindestens ein Leerzeichen enthalten, ansonsten wird eine Fehlermeldung angezeigt. Die Signatur muss mindestens ein Leerzeichen enthalten, ansonsten wird eine Fehlermeldung angezeigt.
Sonderfälle siehe [AusleiheSonderfälle](Ausleihe_Sonderfälle.md) Sonderfälle siehe [Sonderfälle in der Ausleihe](Ausleihe_Sonderfälle.md)
## Rückgaben ## Rückgaben

View File

@@ -11,10 +11,14 @@ Diese Oberfläche kann immer von der [Hauptoberfläche](Ausleihsystem.md) geöff
Um einen Bericht zu erstellen, müssen folgende Kriterien erfüllt sein: Um einen Bericht zu erstellen, müssen folgende Kriterien erfüllt sein:
- Zeitspanne festgelegt (Entweder über den Slider, oder über die Woche / Monat / Jahr Knöpfe) - Zeitspanne festgelegt (Entweder über den Slider, oder über die Buttons für Woche / Monat / Jahr)
- Datenformat ausgewählt - Dateiformat muss festgelegt worden sein.
Nachdem diese Kriterien erfüllt sind, kann der Bericht über den Knopf `Bericht erstellen` erstellt werden. Der Bericht wird erstellt, bei größeren Datensätzen kann es länger dauern, eine Fortschrittsanzeige gibt an, wie weit der Prozess ist. !!! info "Optional: Signatur"
Optional kann ein Haken bei `Signatur anzeigen` gesetzt werden. Der Bericht wird nun die Signatur der ausgeführten Aktion enthalten.
Bei größeren Datensätzen kann es länger dauern. Eine Fortschrittsanzeige gibt an, wie weit der Prozess ist.
Wurde der Bericht erfolgreich erstellt, sieht die Oberfläche wie folgt aus: Wurde der Bericht erfolgreich erstellt, sieht die Oberfläche wie folgt aus:

View File

@@ -2,8 +2,50 @@
![Einstellungen](images/settings.png) ![Einstellungen](images/settings.png)
## Bedienung ## Bedienung
Hier werden die Einstellungen geändert. Sobald ein Wert geändert wird, ist es möglich die Einstellungen rückgängig zu machen, oder die Änderungen zu speichern. Hier werden die Einstellungen geändert. Sobald ein Wert geändert wird, ist es möglich die Einstellungen rückgängig zu machen oder die Änderungen zu speichern.
## Einstellungsoptionen
### Name der Einrichtung
Hier kann der Name der Einrichtung geändert werden. Dieser wird in der Kopfzeile der Anwendung angezeigt und im Katalog verwendet um Exemplare zu finden.
### Leihdauer
Hier kann die Leihdauer festgelegt werden. Standardmäßig ist diese auf 7 Tage gesetzt
### Inaktive Nutzer löschen
Hier kann festgelegt werden, wie lange Inaktive Nutzer im System bleiben. Dieser Zeitraum wird ab dem letzten Öffnen des Nutzerkontos berechnet. Standardmäßig ist dieser auf 365 Tage gesetzt.
### Erweiterter Rückgabemodus
Wird hier der Haken gesetzt, ändert sich die Bedienung der Anwendung. Der Shortcut "F5" wechselt nicht länger zwischen Ausleihe und Rückgabe. Stattdessen führt ein Druck auf "F5" dazu, dass das offene Rückgabekonto geschlossen wird. Dies ist dann vorteilhaft, wenn mehrere Medien von verschiedenen Personen zurückgebucht werden sollen.
### Datenbank
Hier werden die Datenbankoptionen geändert.
- **Speicherort**: Hier wird der Speicherort der Datenbank geändert. Standardmäßig ist dieser auf den Ordner der Anwendung gesetzt (database)
- **Datenbankname**: Hier wird der Name der Datenbank geändert. Standardmäßig ist dieser auf "library.db" gesetzt
- **Sicherungspfad**: Hier wird der Pfad für die Sicherung der Datenbank geändert. Standardmäßig ist dieser auf den Ordner der Anwendung gesetzt (backup)
### Bericht
Hier werden die Einstellungen für die Berichte geändert.
- **Tag**: Der Wochentag, an dem die Berichte erstellt werden sollen
- **Berichte erstellen**: Ist der Haken gesetzt, werden Berichte automatisch erstellt
- **Signatur anzeigen**: Ist der Haken gesetzt, wird die Signatur in den Berichten angezeigt
- **Speicherpfad**: Speicherort für Berichte, standardmäßig ist dieser auf den Ordner der Anwendung gesetzt (report)
!!! Info
Automatische Berichte werden in diesem Format erstellt:
`report_<Jahr>_<Kalenderwoche>.tsv`
Wird die Anwendung am Tag der Berichterstellung mehrfach geöffnet, wird nur ein Bericht erstellt
### Shortcuts
Hier können die Shortcuts angepasst werden. Eine Änderung kann über einen Doppelklick auf das Feld "Aktuell" initiiert werden.
Anschließend kann der gewünschte Shortcut eingegeben werden.
(Eine Änderung der Shortcuts erfordert einen Neustart der Anwendung)
## Besonderheiten ## Besonderheiten
Der Knopf neben Speicherort, Datenbankname, Sicherungspfad und Speicherpfad kann verwendet werden, um den Pfad gezielt zu setzen. Der Knopf neben Speicherort, Datenbankname, Sicherungspfad und Speicherpfad kann verwendet werden, um den Pfad gezielt zu setzen.
@@ -11,11 +53,8 @@ Beim Datenbanknamen wird allerdings nur der Name der Datenbank übernommen
## Hinweis ## Hinweis
Einige Aktionen (bspw. Änderungen der Shortcuts) erfordern einen Neustart der Anwendung. Dies wird beim Speichern der Einstellungen mit folgendem Dialog dargestelt: Einige Aktionen (bspw. Änderungen der Shortcuts) erfordern einen Neustart der Anwendung. Dies wird beim Speichern der Einstellungen mit folgendem Dialog dargestellt:
![restart](images/restart.png) ![restart](images/restart.png)
Im Anschluss an diesen Dialog erscheint ein neuer Dialog: Mit einem Klick auf "Ja" wird die Anwendung neu gestartet und die Änderungen übernommen. Mit einem Klick auf "Nein" werden die Änderungen nicht übernommen und die Anwendung bleibt im aktuellen Zustand.
![restart Application](images/settings_changed_restart.png)

View File

@@ -2,7 +2,7 @@
![alt text](images/user_main.png) ![alt text](images/user_main.png)
!!! info !!! info
Die Nutzeroberfläche kann nur geöffnet werden, wenn ein Nutzer offen ist. Ansonsten wird ein Fehler angezeigt. (s. unten) Die Nutzeroberfläche kann nur geöffnet werden, wenn ein Nutzer ausgewählt wurde. Ansonsten wird ein Fehler angezeigt. (s. unten)
![Error](images/err_nouser.png) ![Error](images/err_nouser.png)
@@ -18,14 +18,14 @@
- (4) Medien: - (4) Medien:
Umfasst unter anderem Feld (5), welches ein neues Fenster zum [verlängern](ausleihe verlängern.md) der Ausleihe öffnet. Umfasst unter anderem Feld (5), welches ein neues Fenster zum [verlängern](ausleihe verlängern.md) der Ausleihe öffnet.
Mit einem Klick auf Mit einem Klick auf
- Alle Ausleihen - Alle Ausleihen
- Aktuell entliehen - Aktuell entliehen
- Überzogen - Überzogen
werden die Einträge der Tabelle gefiltert. Zusätzlich kann mithilfe der Eingabezeile unter den Filteroptionen gezielt nach einem Titel oder einer Signatur gesucht werden. werden die Einträge der Tabelle gefiltert. Zusätzlich kann mithilfe der Eingabezeile unter den Filteroptionen gezielt nach einem Titel oder einer Signatur gesucht werden.
- (5) Verlängern: - (5) Verlängern:
Um Medien zu verlängern, müssen diese in der Tabelle angeklickt werden. Mit Strg können mehrere Medien gleichzeitig ausgewählt und verlängert werden. Hierzu wird ein neues Fenster geöffnet, siehe [Ausleihe verlängern](ausleihe verlängern.md). Um Medien zu verlängern, müssen diese in der Tabelle angeklickt werden. Mit Strg können mehrere Medien gleichzeitig ausgewählt und verlängert werden. Hierzu wird ein neues Fenster geöffnet, siehe [Ausleihe verlängern](ausleihe verlängern.md).

View File

@@ -2,8 +2,7 @@
![Oberfläche](images/extend.png) ![Oberfläche](images/extend.png)
## Information ## Information
Die Ausleihe verlängern kann nur geöffnet werden, wenn ein Nutzer offen ist. Um eine Ausleihe zu verlängern, öffnen Sie zunächst den Nutzer und klicken Sie auf "Fenster" > "Nutzer". Wählen Sie den oder die zu verlängernden Titel aus und klicken Sie auf "Ausgewählte Verlängern". Um mehrere Titel auf einmal zu verlängern, halten Sie die Strg-Taste gedrückt und klicken Sie auf die gewünschten Titel. Anschließend klicken Sie auf "Ausgewählte Verlängern".
Hierzu muss ein neues, in der Zukunft liegendes Datum ausgewählt und mit OK bestätigt werden.
Diese Oberfläche erlaubt es, eine oder mehrere Medien zu verlängern. Hierzu muss ein neues, in der Zukunft liegendes Datum ausgewählt und mit OK bestätigt werden.
In der Datenbank wird nun das neue Datum gespeichert und die Einträge in der Tabelle werden aktualisiert. In der Datenbank wird nun das neue Datum gespeichert und die Einträge in der Tabelle werden aktualisiert.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.7 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 26 KiB

View File

@@ -17,5 +17,6 @@ Unterbereiche umfassen:
- [Ausleihhistorie](Ausleihhistorie.md) - Historie der Ausleihen - [Ausleihhistorie](Ausleihhistorie.md) - Historie der Ausleihen
- [Bericht erstellen](Bericht erstellen.md) - Bericht für einen festgelegten Zeitrahmen erstellen - [Bericht erstellen](Bericht erstellen.md) - Bericht für einen festgelegten Zeitrahmen erstellen
- [Einstellungen](Einstellungen.md) - Einstellungen der Anwendung ändern - [Einstellungen](Einstellungen.md) - Einstellungen der Anwendung ändern
- [Allgemeines](Allgemeines.md) - Allgemeine Informationen zur Anwendung

View File

@@ -1,103 +0,0 @@
import os
import shutil
from pathlib import Path
ORIGIN = "C:/testing/source_2"
BACKUP = "C:/Databasebackup"
FILE = "database.db"
def handle_file():
"""
Handles file creation, movement, and backup based on path and backup existence.
Args:
path (str): The desired path for the file.
filename (str): The name of the file.
backup_location (str): The location for backups.
Returns:
str: The final path of the file.
"""
full = Path(ORIGIN) / FILE
full_path = str(full)
backup = Path(BACKUP) / FILE
backup_path = str(backup)
origin_reachable = os.path.exists(full_path)
backup_reachable = os.path.exists(backup_path)
print(origin_reachable, backup_reachable)
if not origin_reachable and not backup_reachable:
make_dirs(ORIGIN, BACKUP)
# if not os.path.exists(full_path):
# print("File does not exist, creating file")
# create_file(full_path)
if os.path.exists(backup_path) and ".backup" in os.listdir(BACKUP):
print("Used backup previously, overwriting file")
#overwrite file at source with backup
shutil.copy(backup_path, full_path)
os.remove(BACKUP + "/.backup")
def make_dirs(full_path, backup_path):
"""
Creates directories if they do not exist and moves the file to the desired location.
Args:
full_path (str): The full path of the file.
backup_path (str): The backup path of the file.
"""
if not os.path.exists(full_path):
os.makedirs(full_path)
if not os.path.exists(backup_path):
os.makedirs(backup_path)
def create_file(full_path):
"""
Creates a file at the desired location.
Args:
full_path (str): The full path of the file.
"""
with open(full_path, "w") as f:
f.write("")
def handle_folder_reachability(original_path, backup_path):
"""
Checks if the original folder is reachable. If not, creates a backup.
If the original folder becomes reachable again, restores the backup.
Args:
original_path (str): Path to the original folder.
backup_path (str): Path to the backup folder.
Returns:
str: Path to the current accessible folder.
"""
backup_file = os.path.join(backup_path, ".backup")
try:
os.makedirs(original_path)
except FileExistsError:
pass
if not os.path.exists(original_path):
#original folder not reachable, use backup path and create .backup file
if not os.path.exists(backup_path):
os.makedirs(backup_path)
with open(backup_file, "w") as f:
f.write("")
# Create an empty backup file as a marker
return backup_path +"/" + FILE
else:
# Original folder is reachable, check for backup
if os.path.exists(backup_file):
# Restore backup
shutil.rmtree(original_path) # Remove original folder to avoid conflicts
shutil.move(backup_path, original_path)
#os.remove(backup_file)
#remove backup file from original path
os.remove(original_path + "/.backup")
os.makedirs(backup_path)
return original_path +"/" + FILE
if __name__=="__main__":
print(handle_folder_reachability(ORIGIN, BACKUP)) # should create a new file at C:/newdatabase/database.db)

1
icons/add.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e8eaed"><path d="M440-440H200v-80h240v-240h80v240h240v80H520v240h-80v-240Z"/></svg>

After

Width:  |  Height:  |  Size: 182 B

1
icons/help.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e8eaed"><path d="M478-240q21 0 35.5-14.5T528-290q0-21-14.5-35.5T478-340q-21 0-35.5 14.5T428-290q0 21 14.5 35.5T478-240Zm-36-154h74q0-33 7.5-52t42.5-52q26-26 41-49.5t15-56.5q0-56-41-86t-97-30q-57 0-92.5 30T342-618l66 26q5-18 22.5-39t53.5-21q32 0 48 17.5t16 38.5q0 20-12 37.5T506-526q-44 39-54 59t-10 73Zm38 314q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/></svg>

After

Width:  |  Height:  |  Size: 695 B

1
icons/history.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e8eaed"><path d="M480-120q-138 0-240.5-91.5T122-440h82q14 104 92.5 172T480-200q117 0 198.5-81.5T760-480q0-117-81.5-198.5T480-760q-69 0-129 32t-101 88h110v80H120v-240h80v94q51-64 124.5-99T480-840q75 0 140.5 28.5t114 77q48.5 48.5 77 114T840-480q0 75-28.5 140.5t-77 114q-48.5 48.5-114 77T480-120Zm112-192L440-464v-216h80v184l128 128-56 56Z"/></svg>

After

Width:  |  Height:  |  Size: 444 B

View File

@@ -1,4 +1,4 @@
color: '#B89230' #Hex code of the color color: '#737373' #Hex code of the color
icons: icons:
addBook: add_book.svg addBook: add_book.svg
add_user: add_user.svg add_user: add_user.svg
@@ -16,3 +16,8 @@ icons:
warning: warning.svg warning: warning.svg
delete: delete.svg delete: delete.svg
restart: restart.svg restart: restart.svg
quit: quit.svg
history: history.svg
help: help.svg
support: support.svg
add: add.svg

1
icons/quit.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e8eaed"><path d="M480-80q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-84 31.5-156.5T197-763l56 56q-44 44-68.5 102T160-480q0 134 93 227t227 93q134 0 227-93t93-227q0-67-24.5-125T707-707l56-56q54 54 85.5 126.5T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm-40-360v-440h80v440h-80Z"/></svg>

After

Width:  |  Height:  |  Size: 396 B

1
icons/support.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e8eaed"><path d="M480-280q17 0 28.5-11.5T520-320q0-17-11.5-28.5T480-360q-17 0-28.5 11.5T440-320q0 17 11.5 28.5T480-280Zm-40-160h80v-240h-80v240ZM330-120 120-330v-300l210-210h300l210 210v300L630-120H330Zm34-80h232l164-164v-232L596-760H364L200-596v232l164 164Zm116-280Z"/></svg>

After

Width:  |  Height:  |  Size: 375 B

View File

@@ -1,76 +0,0 @@
@echo off
echo print Installing Python 3.12.7
echo downloading..... please wait
curl -o python-3.12.7-amd64.exe https://www.python.org/ftp/python/3.12.7/python-3.12.7-amd64.exe
echo Installing Python 3.12.7
python-3.12.7-amd64.exe /quiet InstallAllUsers=0 PrependPath=1 Include_test=0
echo Python 3.12.7 installed
echo Please confirm the installation by opening a new terminal and typing python --version
echo If the version is 3.12.7, then the installation was successful
pause
echo downloading the repository
curl -o LibrarySystem.zip https://git.theprivateserver.de/WorldTeacher/LibrarySystem/archive/main.zip
echo Extracting the repository
tar -xf LibrarySystem.zip
cd into the extracted folder
cd librarysystem
echo Installing the required packages
python -m venv venv
call venv\Scripts\activate.bat
echo Activated the virtual environment
echo Cleaning up the environment
@echo off
echo Uninstalling all Python packages...
@REM Uninstall all packages in the virtual environment
pip freeze > temp_requirements.txt
for /F "delims=" %%i in (temp_requirements.txt) do pip uninstall -y %%i
@REM Clean up the temporary file
del temp_requirements.txt
echo All packages uninstalled.
echo Installing the required packages
pip install -r requirements.txt
echo Installation completed
echo Building the application
call pyinstaller --noconfirm --onedir --windowed --icon "icons/icon.ico" --name "LibrarySystem" --clean --add-data "config;config/" --add-data "icons;icons/" "main.py"
echo compiling done, please confirm the build by checking the dist folder
echo If the build is successful, you can run the application by running the LibrarySystem.exe file in the folder
pause
set /p compile="Build successful? (y/n) "
if %compile% == y (
echo Build successful
exit
) else (
echo Build failed
echo switching over to manual mode using auto-py-to-exe
echo installing auto-py-to-exe
pip install auto-py-to-exe
echo auto-py-to-exe installed
echo running auto-py-to-exe
echo --------------------
echo Please go to settings > Import config.json
echo Select the build.app.json
echo Change / Set these values:
echo - Script Location: main.py
echo - Icon: icons/icon.ico
echo - Additional Files:
echo - config: config/
echo - icons: icons/
echo - site: site/
echo Click on the Convert .py to .exe button
echo the completed build will be in the output folder
echo --------------------
call auto-py-to-exe
pause
)

24
launch.cmd Normal file
View File

@@ -0,0 +1,24 @@
@echo off
REM Check if .venv exists
if exist .venv (
REM Activate the virtual environment
call .venv\Scripts\activate.bat
) else (
REM Run uv sync if .venv does not exist
uv sync
call .venv\Scripts\activate.bat
)
REM Perform a git pull
git pull
REM Run uv sync if .venv exists (already activated)
uv sync
REM Start main.py
uv run python main.py
REM Deactivate the virtual environment if it was activated
if exist .venv (
deactivate
)

22
launch.ps1 Normal file
View File

@@ -0,0 +1,22 @@
# Check if .venv exists
if (Test-Path .venv) {
# Activate the virtual environment
.\.venv\Scripts\Activate.ps1
} else {
# Run uv sync if .venv does not exist
uv sync
.\.venv\Scripts\Activate.ps1
}
# Perform a git pull
git pull
# Run uv sync if .venv exists (already activated)
uv sync
# Start main.py
uv run python main.py
# Deactivate the virtual environment if it was activated
if (Test-Path .venv) {
deactivate
}

View File

@@ -2,4 +2,3 @@ from src.ui.main_ui import launch
if __name__ == "__main__": if __name__ == "__main__":
launch() launch()

View File

@@ -1,5 +1,4 @@
from src.ui.main_ui import launch from src.ui.main_ui import launch
if __name__ == "__main__": if __name__ == "__main__":
launch("--debug") launch()

View File

@@ -1,4 +1,5 @@
site_name: LibrarySystem site_name: LibrarySystem
repo_url: https://git.theprivateserver.de/WorldTeacher/LibrarySystem
theme: theme:
features: features:
- search.suggest - search.suggest

38
pyproject.toml Normal file
View File

@@ -0,0 +1,38 @@
[project]
name = "librarysystem"
version = "0.3.2"
description = "A library system for loaning books and managing the users."
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
"beautifulsoup4>=4.12.3",
"loguru>=0.7.3",
"mkdocs>=1.6.1",
"mkdocs-material>=9.5.49",
"mkdocs-material-extensions>=1.3.1",
"omegaconf>=2.3.0",
"prettytable>=3.12.0",
"pyqt6>=6.8.0",
"requests>=2.32.3",
]
[dependency-groups]
dev = [
"bump-my-version>=0.29.0",
"icecream>=2.1.4",
"nuitka>=2.5.9",
"python-dotenv>=1.0.1",
"ruff>=0.9.2",
]
[tool.ruff]
exclude = [
"dist",
".git",
".vscode",
]
indent-width = 4
include = ["pyproject.toml", "src/**/*.py", "scripts/**/*.py","tests/**/*.py"]
[tool.ruff.lint]
fixable = ["ALL"]

47
release.ps1 Normal file
View File

@@ -0,0 +1,47 @@
# Enable strict mode
Set-StrictMode -Version Latest
# Run Python setup.py
Write-Host "Running setup.py..."
python setup.py
if ($LASTEXITCODE -ne 0) {
Write-Error "Python script failed. Exiting."
exit 1
}
# Get the latest Git tag
Write-Host "Fetching the latest Git tag..."
$latestTag = git describe --tags --abbrev=0
if (-not $latestTag) {
Write-Error "No Git tags found. Exiting."
exit 1
}
Write-Host "Latest tag: $latestTag"
# Read the changelog for the current version
Write-Host "Reading changelog for version $latestTag..."
$changelogPath = "changelog.md"
if (-not (Test-Path $changelogPath)) {
Write-Error "Changelog file not found at $changelogPath. Exiting."
exit 1
}
# Extract the changes for the current version from the changelog
$changelogContent = Get-Content $changelogPath -Raw
$changesPattern = "(?s)# $latestTag\b(.*?)(?=^#|\Z)"
$changes = if ($changelogContent -match $changesPattern) {
$matches[1].Trim()
} else {
Write-Error "No changes found for version $latestTag in the changelog. Exiting."
exit 1
}
# Create a new release with tea
Write-Host "Creating a new release with tea..."
$releaseTitle = "LibrarySystem - Version $latestTag"
$rel_comment = "#Changes in this release: `n$changes`n"
$rel = tea release create --title $releaseTitle --note $rel_comment --tag $latestTag
if (-not $rel) {
Write-Error "Failed to create a new release. Exiting."
exit 1
}

Binary file not shown.

47
setup.py Normal file
View File

@@ -0,0 +1,47 @@
import os
with open("pyproject.toml", "r") as file:
lines = file.readlines()
for line in lines:
if "name" in line:
name = line.split("=")[1].strip().replace('"', "")
break
with open(".version", "r") as file:
version = file.read().strip()
print(f"Name: {name}, Version: {version}")
def rename_folders():
for folder in os.listdir("dist"):
if folder.endswith(".dist"):
if "_dev" in folder:
os.rename(
os.path.join("dist", folder),
os.path.join("dist", f"{name}-{version}-dev"),
)
else:
os.rename(
os.path.join("dist", folder),
os.path.join("dist", f"{name}-{version}"),
)
def remove_other_folders():
for folder in os.listdir("dist"):
if not name in folder:
os.remove(os.path.join("dist", folder))
def compress_folders():
print("Compressing folders")
import shutil
for folder in os.listdir("dist"):
if name in folder and not folder.endswith(".zip"):
print(f"Compressing {folder}")
shutil.make_archive(f"dist/{folder}", "zip", f"dist/{folder}")
if __name__ == "__main__":
rename_folders()
compress_folders()

View File

@@ -1,61 +1,82 @@
import sys import sys
from config import Config from config import Config
__version__ = "0.1.1" from loguru import logger
from datetime import datetime
import atexit
import argparse
__version__ = "0.3.2"
__author__ = "Alexander Kirchner" __author__ = "Alexander Kirchner"
__email__ = "alexander.kirchner@ph-freiburg.de" __email__ = "alexander.kirchner@ph-freiburg.de"
__contacts__ = "alexander.kirchner@ph-freiburg.de,christian.berger@ph-freiburg.de"
__license__ = "MIT" __license__ = "MIT"
docport = 6543 docport = 8000
config = Config("config/settings.yaml") config = Config("config/settings.yaml")
valid_args = ["--debug", "--log", "--no-backup", "--ic-logging", "--version", "-h","--no-documentation"] _config = Config("config/settings.yaml")._config
# Store original values that might be overridden by CLI
args_description = {
"--debug": "Enable debug mode",
"--log": "Enable logging",
"--no-backup": "Disable database backup",
"--ic-logging": "Enable icecream logging (not available in production)",
"--version": "Show version",
"-h": "Show help message and exit",
"--no-documentation": "Disable documentation server and shortcut"
}
args = sys.argv[1:] args = argparse.ArgumentParser()
if any(arg not in valid_args for arg in args): args.add_argument(
print("Invalid argument present") "--debug", help="Debugging mode, active for the active run", action="store_true"
print([arg for arg in args if arg not in valid_args]) )
sys.exit() args.add_argument(
"--no-backup", help="Disable backups for the active run", action="store_true"
def help(): )
print("Ausleihsystem") args.add_argument("--version", help="Print version", action="store_true")
print("Ein Ausleihsystem für Handbibliotheken") args.add_argument(
print("Version: {}".format(__version__)) "--no-documentation",
print("Valide Argumente:") help="Disable documentation for the active run",
print("args") action="store_true",
print("--------") )
print("usage: main.py [-h] [--debug] [--log] [--no-backup] [--ic-logging] [--version] [--no-documentation]") args = args.parse_args()
print("options:")
for arg in valid_args: if args.version:
print(f"{arg} : {args_description[arg]}") print(f"Version: {__version__}")
sys.exit(0)
# based on the arguments, set the config values
if"-h" in args: # Override config values temporarily without saving
help() changes_made = False
sys.exit()
if "--debug" in args: if args.debug:
config.debug = True config.debug = True
if "--log" in args: changes_made = True
config.log_debug = True if args.no_backup:
if "--no-backup" in args: config.database.do_backup = False
config.no_backup = True changes_made = True
if "--ic-logging" in args: if args.no_documentation:
config.ic_logging = True
if "--no-documentation" in args:
config.documentation = False config.documentation = False
if "--version" in args: changes_made = True
print(__version__)
sys.exit() if changes_made:
config.save()
log = logger
log.remove()
log.add("logs/application.log", rotation="1 week", compression="zip")
# add a log for the current day
log.add(
f"logs/{datetime.now().strftime('%Y-%m-%d')}.log",
rotation="1 day",
compression="zip",
)
if config.debug:
import sys
log.add(
sys.stderr,
)
def restore_config():
log.debug("Restoring configuration")
if not changes_made:
return
values = config.get_changes(_config)
config._config = _config
config.save()
log.debug(f"Restored configuration, changed values: {values}")

View File

@@ -1,4 +1,5 @@
__help__ = "This package contains the logic of the application." __help__ = "This package contains the logic of the application."
from .database import Database from .database import Database
from .catalogue import Catalogue from .catalogue import Catalogue
from .backup import Backup from .backup import Backup
from .documentation_thread import DocumentationThread

View File

@@ -1,8 +1,7 @@
import os import os
import sys
import shutil import shutil
from src import config from src import config
import datetime
class Backup: class Backup:
def __init__(self): def __init__(self):
@@ -11,7 +10,16 @@ class Backup:
self.backup = False self.backup = False
if not os.path.exists(config.database.backupLocation): if not os.path.exists(config.database.backupLocation):
os.makedirs(config.database.backupLocation) os.makedirs(config.database.backupLocation)
if config.database.do_backup == True: backupPath = config.database.backupLocation
# create an archive path based on the backuppath, one level up with a new folder called archive
# example: backuppath = /home/user/backup
# result: archivepath = /home/user/archive
self.archivePath = os.path.join(os.path.dirname(backupPath), "archive")
# check if the archive path exists, if not create it
if not os.path.exists(self.archivePath):
os.makedirs(self.archivePath)
if config.database.do_backup is True:
self.checkpaths() self.checkpaths()
config.database.do_backup = self.backup config.database.do_backup = self.backup
@@ -20,6 +28,17 @@ class Backup:
self.backup = True self.backup = True
def createBackup(self): def createBackup(self):
if os.path.exists(self.archivePath) and os.path.exists(self.source_path):
# copy the active database to the archive path, add _[date]
day = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
# copy the active database to the archive path, add _[date]
shutil.copy(
self.source_path,
os.path.join(
self.archivePath, config.database.name + "_" + day + ".archive"
),
)
if self.backup: if self.backup:
if os.path.exists(self.source_path): if os.path.exists(self.source_path):
if os.path.exists(self.backup_path): if os.path.exists(self.backup_path):

View File

@@ -1,12 +1,11 @@
import requests import requests
from bs4 import BeautifulSoup from bs4 import BeautifulSoup
from src import config from src import config, log
from src.schemas import Book from src.schemas import Book
from src.utils import Log
URL = "https://rds.ibs-bw.de/phfreiburg/opac/RDSIndex/Search?type0%5B%5D=allfields&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND&type0%5B%5D=au&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND&type0%5B%5D=ti&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND&type0%5B%5D=ct&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND&type0%5B%5D=isn&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND&type0%5B%5D=ta&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND&type0%5B%5D=co&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND&type0%5B%5D=py&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND&type0%5B%5D=pp&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND&type0%5B%5D=pu&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND&type0%5B%5D=si&lookfor0%5B%5D={}&join=AND&bool0%5B%5D=AND&type0%5B%5D=zr&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND&type0%5B%5D=cc&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND" URL = "https://rds.ibs-bw.de/phfreiburg/opac/RDSIndex/Search?type0%5B%5D=allfields&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND&type0%5B%5D=au&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND&type0%5B%5D=ti&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND&type0%5B%5D=ct&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND&type0%5B%5D=isn&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND&type0%5B%5D=ta&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND&type0%5B%5D=co&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND&type0%5B%5D=py&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND&type0%5B%5D=pp&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND&type0%5B%5D=pu&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND&type0%5B%5D=si&lookfor0%5B%5D={}&join=AND&bool0%5B%5D=AND&type0%5B%5D=zr&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND&type0%5B%5D=cc&lookfor0%5B%5D=&join=AND&bool0%5B%5D=AND"
BASE = "https://rds.ibs-bw.de" BASE = "https://rds.ibs-bw.de"
log = Log("Catalogue")
class Catalogue: class Catalogue:
def __init__(self, timeout=5): def __init__(self, timeout=5):
@@ -24,6 +23,7 @@ class Catalogue:
return True return True
except requests.exceptions.RequestException as e: except requests.exceptions.RequestException as e:
log.error(f"Could not connect to google.com: {e}") log.error(f"Could not connect to google.com: {e}")
def search_book(self, searchterm: str): def search_book(self, searchterm: str):
response = requests.get(URL.format(searchterm), timeout=self.timeout) response = requests.get(URL.format(searchterm), timeout=self.timeout)
return response.text return response.text

View File

@@ -1,36 +1,39 @@
import sqlite3 as sql import sqlite3 as sql
import os import os
import shutil import shutil
from src import config from src import config, log
from src.schemas import USERS, MEDIA, LOANS, User, Book, Loan from src.schemas import USERS, MEDIA, LOANS, User, Book, Loan
from src.utils import stringToDate, Log, debugMessage as dbg from src.utils import stringToDate
from PyQt6 import QtCore from PyQt6 import QtCore
log = Log("Database")
FILE = config.database.name FILE = config.database.name
class Database: class Database:
def __init__(self, db_path: str = None): def __init__(self, db_path: str = None):
''' """
Default constructor for the database class Default constructor for the database class
Args: Args:
db_path (str, optional): Optional Path for testing / specific purposes. Defaults to None. db_path (str, optional): Optional Path for testing / specific purposes. Defaults to None.
''' """
if db_path is None: if db_path is None:
self.db_path = self.handle_folder_reachability(config.database.path, config.database.backupLocation) self.db_path = self.handle_folder_reachability(
config.database.path, config.database.backupLocation
)
else: else:
self.db_path = db_path self.db_path = db_path
if not os.path.exists(config.database.path): if not os.path.exists(config.database.path):
try: try:
os.makedirs(config.database.path) os.makedirs(config.database.path)
except FileNotFoundError: except FileNotFoundError:
dbg(self.db_path) log.error(f"Path {config.database.path} not found")
if not os.path.exists(config.database.backupLocation): if not os.path.exists(config.database.backupLocation):
os.makedirs(config.database.backupLocation) os.makedirs(config.database.backupLocation)
#if main path does not exist, try to create it. if that fails, use the backuplocation # if main path does not exist, try to create it. if that fails, use the backuplocation
dbg(self.db_path) log.debug("Checking Database Path {}", self.db_path)
self.checkDatabaseStatus() self.checkDatabaseStatus()
def handle_folder_reachability(self, original_path, backup_path): def handle_folder_reachability(self, original_path, backup_path):
@@ -49,50 +52,59 @@ class Database:
backup_file = os.path.join(backup_path, ".backup") backup_file = os.path.join(backup_path, ".backup")
if not os.path.exists(original_path): if not os.path.exists(original_path):
#original folder not reachable, use backup path and create .backup file # original folder not reachable, use backup path and create .backup file
if not os.path.exists(backup_path): if not os.path.exists(backup_path):
os.makedirs(backup_path) os.makedirs(backup_path)
with open(backup_file, "w") as f: with open(backup_file, "w") as f:
f.write("") f.write("")
# Create an empty backup file as a marker # Create an empty backup file as a marker
return backup_path +"/" + FILE return backup_path + "/" + FILE
else: else:
dbg("Original Path Exists, using this path") log.info("Original Path Exists, using this path")
# Original folder is reachable, check for backup # Original folder is reachable, check for backup
if os.path.exists(backup_file): if os.path.exists(backup_file):
# Restore backup # Restore backup
shutil.rmtree(original_path) # Remove original folder to avoid conflicts shutil.rmtree(
original_path
) # Remove original folder to avoid conflicts
os.rename(backup_path, original_path) os.rename(backup_path, original_path)
# (backup_path, original_path) # (backup_path, original_path)
#os.remove(backup_file) # os.remove(backup_file)
#remove backup file from original path # remove backup file from original path
os.remove(original_path + "/.backup") os.remove(original_path + "/.backup")
os.makedirs(backup_path) os.makedirs(backup_path)
return original_path +"/" + FILE return original_path + "/" + FILE
def checkDatabasePath(self): def checkDatabasePath(self):
self.db_path = config.database.path + "/" + config.database.name self.db_path = config.database.path + "/" + config.database.name
#if backup file in backup location, move database to main location, delete backup file # if backup file in backup location, move database to main location, delete backup file
if os.path.exists(config.database.backupLocation + "/backup"): if os.path.exists(config.database.backupLocation + "/backup"):
if os.path.exists(self.db_path): if os.path.exists(self.db_path):
os.remove(self.db_path) os.remove(self.db_path)
os.rename(f"{config.database.backupLocation}/{config.database.name}", self.db_path) os.rename(
#remove backup file f"{config.database.backupLocation}/{config.database.name}",
self.db_path,
)
# remove backup file
os.remove(config.database.backupLocation + "/backup") os.remove(config.database.backupLocation + "/backup")
return self.db_path return self.db_path
else: else:
#keep using backup file # keep using backup file
self.db_path = config.database.backupLocation + "/" + config.database.name self.db_path = (
config.database.backupLocation + "/" + config.database.name
)
if not os.path.exists(config.database.path): if not os.path.exists(config.database.path):
try: try:
os.makedirs(config.database.path) os.makedirs(config.database.path)
except: except:
self.db_path = config.database.backupLocation + "/" + config.database.name self.db_path = (
config.database.backupLocation + "/" + config.database.name
)
if not os.path.exists(config.database.backupLocation): if not os.path.exists(config.database.backupLocation):
os.makedirs(config.database.backupLocation) os.makedirs(config.database.backupLocation)
#create a backup file in the backup location # create a backup file in the backup location
with open(f"{config.database.backupLocation}/backup.txt", "w") as f: with open(f"{config.database.backupLocation}/backup.txt", "w") as f:
f.write("Backup File") f.write("Backup File")
return self.db_path return self.db_path
@@ -105,27 +117,27 @@ class Database:
# self.insertSubjects() # self.insertSubjects()
def connect(self) -> sql.Connection: def connect(self) -> sql.Connection:
''' """
Connect to the database Connect to the database
Returns: Returns:
sql.Connection: The active connection to the database sql.Connection: The active connection to the database
''' """
return sql.connect(self.db_path) return sql.connect(self.db_path)
def close_connection(self, conn: sql.Connection): def close_connection(self, conn: sql.Connection):
''' """
closes the connection to the database closes the connection to the database
Args: Args:
---- ----
- conn (sql.Connection): the connection to be closed - conn (sql.Connection): the connection to be closed
''' """
conn.close() conn.close()
def createDatabase(self): def createDatabase(self):
log.info("Creating Database") log.info("Creating Database")
#print("Creating Database") # print("Creating Database")
if not os.path.exists(self.db_path): if not os.path.exists(self.db_path):
os.makedirs(self.db_path) os.makedirs(self.db_path)
conn = self.connect() conn = self.connect()
@@ -150,12 +162,12 @@ class Database:
def tableCheck(self): def tableCheck(self):
# check if database has tables # check if database has tables
''' """
Get the contents of the Get the contents of the
Returns: Returns:
Union[List[Tuple], None]: Returns a list of tuples containing the table names or None if no tables are present Union[List[Tuple], None]: Returns a list of tuples containing the table names or None if no tables are present
''' """
try: try:
with sql.connect(self.db_path) as conn: with sql.connect(self.db_path) as conn:
cursor = conn.cursor() cursor = conn.cursor()
@@ -171,6 +183,7 @@ class Database:
result = cursor.fetchall() result = cursor.fetchall()
self.close_connection(conn) self.close_connection(conn)
return result return result
def checkUserExists(self, key, value) -> list[User] | bool: def checkUserExists(self, key, value) -> list[User] | bool:
query = f"SELECT * FROM users WHERE {key} like '%{value}%'" query = f"SELECT * FROM users WHERE {key} like '%{value}%'"
conn = self.connect() conn = self.connect()
@@ -182,7 +195,9 @@ class Database:
users = cursor.fetchall() users = cursor.fetchall()
for index, user in enumerate(users): for index, user in enumerate(users):
users[index] = User(userid=user[1], username=user[2], email=user[3], id=user[0]) users[index] = User(
userid=user[1], username=user[2], email=user[3], id=user[0]
)
self.close_connection(conn) self.close_connection(conn)
return users return users
@@ -199,7 +214,7 @@ class Database:
return False return False
self.close_connection(conn) self.close_connection(conn)
return True return True
def getUserBy(self, key, value) -> User: def getUserBy(self, key, value) -> User:
conn = self.connect() conn = self.connect()
cursor = conn.cursor() cursor = conn.cursor()
@@ -210,7 +225,6 @@ class Database:
return user return user
def getUser(self, user_id) -> User: def getUser(self, user_id) -> User:
conn = self.connect() conn = self.connect()
cursor = conn.cursor() cursor = conn.cursor()
cursor.execute(f"SELECT * FROM users") cursor.execute(f"SELECT * FROM users")
@@ -220,20 +234,16 @@ class Database:
for res in result: for res in result:
if res[0] == user_id: if res[0] == user_id:
user = User(userid=res[1], username=res[2], email=res[3], id=res[0]) user = User(userid=res[1], username=res[2], email=res[3], id=res[0])
dbg(f"Returning User {user}") log.debug(f"Returning User {user}")
log.info(f"Returning User {user}")
return user return user
else: else:
for res in result: for res in result:
if res[1] == user_id: if res[1] == user_id:
user = User(userid=res[1], username=res[2], email=res[3], id=res[0]) user = User(userid=res[1], username=res[2], email=res[3], id=res[0])
dbg(f"Returning User {user}") log.debug(f"Returning User {user}")
log.info(f"Returning User {user}") log.info(f"Returning User {user}")
return user return user
raise ValueError(f"User {user_id} not found") raise ValueError(f"User {user_id} not found")
#return User(userid="gelöscht", username="gelöscht", email="gelöscht", id="gelöscht")
# user = User(userid=result[1], username=result[2], email=result[3],id = result[0])
# return user
def getUserId(self, username) -> User: def getUserId(self, username) -> User:
conn = self.connect() conn = self.connect()
@@ -241,12 +251,12 @@ class Database:
cursor.execute(f"SELECT * FROM users WHERE username = '{username}'") cursor.execute(f"SELECT * FROM users WHERE username = '{username}'")
result = cursor.fetchone() result = cursor.fetchone()
self.close_connection(conn) self.close_connection(conn)
user = User(userid=result[1], username=result[2], email=result[3],id = result[0]) user = User(userid=result[1], username=result[2], email=result[3], id=result[0])
log.info(f"Returning User {user}") log.info(f"Returning User {user}")
return user return user
def updateUser(self, username, user_id, usermail): def updateUser(self, username, user_id, usermail):
log.debug(f"Updating User {userno}, {username}, {usermail}") log.debug(f"Updating User {user_id}, {username}, {usermail}")
conn = self.connect() conn = self.connect()
cursor = conn.cursor() cursor = conn.cursor()
cursor.execute( cursor.execute(
@@ -254,17 +264,21 @@ class Database:
) )
conn.commit() conn.commit()
self.close_connection(conn) self.close_connection(conn)
def setUserActiveDate(self, userid,date): def setUserActiveDate(self, userid, date):
query = f"UPDATE users SET lastActive = '{date}' WHERE user_id = '{userid}'" query = f"UPDATE users SET lastActive = '{date}' WHERE user_id = '{userid}'"
conn = self.connect() conn = self.connect()
cursor = conn.cursor() cursor = conn.cursor()
cursor.execute(query) cursor.execute(query)
conn.commit() conn.commit()
dbg(f"Setting User {userid} to active on {date}") log.debug(f"Setting User {userid} to active on {date}")
def renameInactiveUsers(self): def renameInactiveUsers(self):
lastYear = QtCore.QDate.currentDate().addDays(int(f"-{config.delete_inactive_user_duration}")).toString("yyyy-MM-dd") lastYear = (
QtCore.QDate.currentDate()
.addDays(int(f"-{config.delete_inactive_user_duration}"))
.toString("yyyy-MM-dd")
)
query = f"SELECT id FROM users WHERE lastActive < '{lastYear}'" query = f"SELECT id FROM users WHERE lastActive < '{lastYear}'"
conn = self.connect() conn = self.connect()
cursor = conn.cursor() cursor = conn.cursor()
@@ -276,26 +290,28 @@ class Database:
hasLoans = self.hasLoans(user[0]) hasLoans = self.hasLoans(user[0])
if not hasLoans: if not hasLoans:
self.deleteUser(user) self.deleteUser(user)
def hasLoans(self, userid)->bool: def hasLoans(self, userid) -> bool:
query = f"SELECT * FROM loans WHERE user_id = '{userid}' AND returned = 0" query = f"SELECT * FROM loans WHERE user_id = '{userid}' AND returned = 0"
conn = self.connect() conn = self.connect()
cursor = conn.cursor() cursor = conn.cursor()
cursor.execute(query) cursor.execute(query)
result = cursor.fetchall() result = cursor.fetchall()
self.close_connection(conn) self.close_connection(conn)
return False if len(result) == 0 else True return False if len(result) == 0 else True
def deleteUser(self, userid): def deleteUser(self, userid):
log.debug(f"Deleting User {userid}") log.debug(f"Deleting User {userid}")
conn = self.connect() conn = self.connect()
cursor = conn.cursor() cursor = conn.cursor()
cursor.execute(f"UPDATE users SET username='gelöscht', usermail = 'gelöscht', user_id='gelöscht' WHERE id = '{userid}'") cursor.execute(
f"UPDATE users SET username='gelöscht', usermail = 'gelöscht', user_id='gelöscht' WHERE id = '{userid}'"
)
conn.commit() conn.commit()
self.close_connection(conn) self.close_connection(conn)
def getActiveLoans(self, userid): def getActiveLoans(self, userid):
dbg("id", str(userid)) log.debug("id: {}", userid)
conn = self.connect() conn = self.connect()
cursor = conn.cursor() cursor = conn.cursor()
try: try:
@@ -312,8 +328,9 @@ class Database:
def getMediaList(self): def getMediaList(self):
query = "SELECT signature FROM media" query = "SELECT signature FROM media"
result = self.query(query) result = self.query(query)
return [res[0] for res in result] return [res[0] for res in result]
def getAllLoans(self): def getAllLoans(self):
loan_data = [] loan_data = []
query = "SELECT * FROM loans" query = "SELECT * FROM loans"
@@ -335,6 +352,7 @@ class Database:
) )
loan_data.append(l) loan_data.append(l)
return loan_data return loan_data
def insertLoan(self, userid, mediaid, loandate, duedate): def insertLoan(self, userid, mediaid, loandate, duedate):
log.debug(f"Inserting Loan {userid}, {mediaid}, {loandate}, {duedate}") log.debug(f"Inserting Loan {userid}, {mediaid}, {loandate}, {duedate}")
query = f"INSERT INTO loans (user_id, media_id, loan_date, return_date) Values ('{userid}', '{mediaid}', '{loandate}', '{duedate}')" query = f"INSERT INTO loans (user_id, media_id, loan_date, return_date) Values ('{userid}', '{mediaid}', '{loandate}', '{duedate}')"
@@ -344,7 +362,7 @@ class Database:
conn.commit() conn.commit()
self.close_connection(conn) self.close_connection(conn)
def insertMedia(self, media): def insertMedia(self, media: Book):
log.debug(f"Inserting Media {media}") log.debug(f"Inserting Media {media}")
query = f"INSERT OR IGNORE INTO media (ppn, title, signature, isbn,link) VALUES ('{media.ppn}', '{media.title}', '{media.signature}', '{media.isbn}','{media.link}')" # , '{media.link}' query = f"INSERT OR IGNORE INTO media (ppn, title, signature, isbn,link) VALUES ('{media.ppn}', '{media.title}', '{media.signature}', '{media.isbn}','{media.link}')" # , '{media.link}'
log.info(f"Query: |{query}|") log.info(f"Query: |{query}|")
@@ -360,6 +378,7 @@ class Database:
def getLoansBy(self, field, value): def getLoansBy(self, field, value):
# query all loans, sort by date descending and return # query all loans, sort by date descending and return
pass pass
def getMediaSimilarSignatureByID(self, media_id) -> list[Book]: def getMediaSimilarSignatureByID(self, media_id) -> list[Book]:
log.info(f"Getting Media Similar to {media_id}") log.info(f"Getting Media Similar to {media_id}")
query = f"SELECT * FROM media WHERE id = '{media_id}'" query = f"SELECT * FROM media WHERE id = '{media_id}'"
@@ -368,7 +387,7 @@ class Database:
cursor.execute(query) cursor.execute(query)
result = cursor.fetchone() result = cursor.fetchone()
signature = result[1] signature = result[1]
#print(signature) # print(signature)
query = f"SELECT * FROM media WHERE signature LIKE '%{signature}%'" query = f"SELECT * FROM media WHERE signature LIKE '%{signature}%'"
cursor.execute(query) cursor.execute(query)
result = cursor.fetchall() result = cursor.fetchall()
@@ -405,7 +424,7 @@ class Database:
) )
return res return res
def getAllMedia(self, user_id): def getAllMedia(self, user_id) -> list[Book]:
# get all books that have the user id in the loans table # get all books that have the user id in the loans table
query = f"SELECT * FROM loans WHERE user_id = '{user_id}'" query = f"SELECT * FROM loans WHERE user_id = '{user_id}'"
conn = self.connect() conn = self.connect()
@@ -488,7 +507,7 @@ class Database:
cursor = conn.cursor() cursor = conn.cursor()
cursor.execute(query) cursor.execute(query)
result = cursor.fetchone() result = cursor.fetchone()
dbg("Result", response=result) log.debug(f"Result: {result}")
self.close_connection(conn) self.close_connection(conn)
if result is not None: if result is not None:
return result[0] return result[0]

View File

@@ -1,9 +1,10 @@
from PyQt6.QtCore import QThread, pyqtSignal from PyQt6.QtCore import QThread, pyqtSignal
from src.utils import launch_documentation from src.utils.documentation import run_mkdocs
class DocumentationThread(QThread): class DocumentationThread(QThread):
def __init__(self): def __init__(self):
super().__init__() super().__init__()
def run(self): def run(self):
launch_documentation() # launch_documentation()
run_mkdocs()

3
src/logic/k10plus.py Normal file
View File

@@ -0,0 +1,3 @@
import requests
URL = "https://sru.k10plus.de/opac-de-627!rec=1?version=1.1&operation=searchRetrieve&query="

View File

@@ -1,4 +1,4 @@
from .database import LOANS, MEDIA, USERS from .database import LOANS, MEDIA, USERS
from .user import User from .user import User
from .book import Book from .book import Book
from .loan import Loan from .loan import Loan

View File

@@ -3,14 +3,14 @@ from dataclasses import dataclass
@dataclass @dataclass
class Book: class Book:
title: str = "" title: str | None = None
ppn: int = "" ppn: int | None = None
signature: str = "" signature: str | None = None
isbn: str = "" isbn: str | None = None
link: str = "" link: str | None = None
database_id: int = "" database_id: int | None = None
link: str = "" link: str | None = None
loan_from: str = "" loan_from: str | None = None
loan_to: str = "" loan_to: str | None = None
returned: int = "" returned: int | None = None
returned_date: str = "" returned_date: str | None = None

View File

@@ -5,7 +5,7 @@ username TEXT NOT NULL,
usermail TEXT NOT NULL, usermail TEXT NOT NULL,
lastActive TEXT); lastActive TEXT);
""" # id == matrikelnr, """ # id == matrikelnr,
#matrikelnr TEXT NOT NULL, # matrikelnr TEXT NOT NULL,
MEDIA = """CREATE TABLE IF NOT EXISTS media ( MEDIA = """CREATE TABLE IF NOT EXISTS media (
id INTEGER PRIMARY KEY AUTOINCREMENT, id INTEGER PRIMARY KEY AUTOINCREMENT,
signature TEXT NOT NULL, signature TEXT NOT NULL,

View File

@@ -12,4 +12,4 @@ class Loan:
returned: int returned: int
returned_date: str returned_date: str
book: Book book: Book
user_name: str user_name: str

View File

@@ -1,12 +1,23 @@
from dataclasses import dataclass from dataclasses import dataclass
from typing import Any from typing import Any
@dataclass @dataclass
class User: class User:
username: str username: str
userid: Any userid: Any
email: str email: str
id : int = None id: int = None
def __repr__(self): def __repr__(self):
return f"Name: {self.username}\nMatrikelnr.: {self.userid}\neMail: {self.email}" return f"Name: {self.username}\nMatrikelnr.: {self.userid}\neMail: {self.email}"
def match(self, testuser: "User"):
name = testuser.username
user_id = testuser.userid
email = testuser.email
if name == self.username and email == self.email and user_id == self.userid:
return True
else:
return False

25
src/ui/addBook.py Normal file
View File

@@ -0,0 +1,25 @@
from .sources.Ui_dialog_addBook import Ui_Dialog
from PyQt6 import QtWidgets, QtCore, QtGui
from src.logic.database import Database
from src.schemas.book import Book
from src.utils import Icon
class addBook(QtWidgets.QDialog, Ui_Dialog):
def __init__(self):
super(addBook, self).__init__()
self.setupUi(self)
self.setWindowTitle("Buch hinzufügen")
self.setWindowIcon(Icon("addBook").icon)
self.btn_save.clicked.connect(self.addBook)
self.btn_cancel.clicked.connect(self.close)
self.db = Database()
self.book_id = None
def addBook(self):
title = self.book_title.text()
signature = self.book_signature.text()
book = Book(title=title, signature=signature)
id = self.db.insertMedia(book)
if id:
self.book_id = id
self.accept()

View File

@@ -1,8 +1,10 @@
from src import log
from .sources.Ui_dialog_createUser import Ui_Dialog from .sources.Ui_dialog_createUser import Ui_Dialog
from PyQt6 import QtCore, QtGui, QtWidgets from PyQt6 import QtCore, QtGui, QtWidgets
from PyQt6.QtGui import QRegularExpressionValidator from PyQt6.QtGui import QRegularExpressionValidator
from src.logic import Database from src.logic import Database
from src.utils import Icon, Log from src.utils import Icon
class CreateUser(QtWidgets.QDialog, Ui_Dialog): class CreateUser(QtWidgets.QDialog, Ui_Dialog):
def __init__(self, fieldname, data): def __init__(self, fieldname, data):
@@ -38,6 +40,8 @@ class CreateUser(QtWidgets.QDialog, Ui_Dialog):
self.userno.textChanged.connect( self.userno.textChanged.connect(
lambda: self.validateInputUserno(self.userno.text(), "int") lambda: self.validateInputUserno(self.userno.text(), "int")
) )
log.info("User creation dialog opened")
def checkFields(self): def checkFields(self):
if ( if (
self.username.hasAcceptableInput() self.username.hasAcceptableInput()
@@ -58,7 +62,11 @@ class CreateUser(QtWidgets.QDialog, Ui_Dialog):
usermail = self.user_mail.text() usermail = self.user_mail.text()
if self.db.insertUser(username, userno, usermail): if self.db.insertUser(username, userno, usermail):
self.userid = userno self.userid = userno
log.info(f"User {username} created")
else: else:
log.error(
f"User {username} could not be created, input was: {username}, {userno}, {usermail}"
)
self.setStatusTipMessage( self.setStatusTipMessage(
"Benutzer konnte nicht erstellt werden, bitte überprüfen Sie die Eingaben" "Benutzer konnte nicht erstellt werden, bitte überprüfen Sie die Eingaben"
) )
@@ -85,4 +93,4 @@ class CreateUser(QtWidgets.QDialog, Ui_Dialog):
def launch(): def launch():
app = QtWidgets.QApplication([]) app = QtWidgets.QApplication([])
window = CreateUser("id", "123456") window = CreateUser("id", "123456")
window.exec() window.exec()

View File

@@ -2,6 +2,7 @@ from .sources.Ui_dialog_extendLoanDuration import Ui_Dialog
from PyQt6 import QtWidgets, QtCore from PyQt6 import QtWidgets, QtCore
from src.utils import Icon from src.utils import Icon
class ExtendLoan(QtWidgets.QDialog, Ui_Dialog): class ExtendLoan(QtWidgets.QDialog, Ui_Dialog):
def __init__(self, user, media): def __init__(self, user, media):
super(ExtendLoan, self).__init__() super(ExtendLoan, self).__init__()
@@ -17,9 +18,9 @@ class ExtendLoan(QtWidgets.QDialog, Ui_Dialog):
self.buttonBox.accepted.connect(self.extendLoan) self.buttonBox.accepted.connect(self.extendLoan)
def extendLoan(self): def extendLoan(self):
#print("Extend Loan") # print("Extend Loan")
selectedDate = self.extenduntil.selectedDate() selectedDate = self.extenduntil.selectedDate()
#print(selectedDate) # print(selectedDate)
self.extendDate = selectedDate self.extendDate = selectedDate
self.close() self.close()

View File

@@ -1,9 +1,9 @@
from .sources.Ui_main_Loans import Ui_MainWindow from .sources.Ui_main_Loans import Ui_MainWindow
from PyQt6 import QtCore, QtGui, QtWidgets from PyQt6 import QtCore, QtGui, QtWidgets
from src import log
from .user import UserUI from .user import UserUI
from src.logic import Database from src.logic import Database
from src.utils import stringToDate, Icon from src.utils import stringToDate, Icon
from src.utils import debugMessage as dbg
from icecream import ic from icecream import ic
TABLETOFIELDTRANSLATE = { TABLETOFIELDTRANSLATE = {
@@ -23,8 +23,7 @@ class LoanWindow(QtWidgets.QMainWindow, Ui_MainWindow):
QtWidgets.QHeaderView.ResizeMode.Stretch QtWidgets.QHeaderView.ResizeMode.Stretch
) )
self.db = Database() self.db = Database()
self.loans = [] self.loans = self.loadLoans()
self.loadLoans()
# lineedits # lineedits
self.searchbar.textChanged.connect(self.limitResults) self.searchbar.textChanged.connect(self.limitResults)
@@ -37,15 +36,15 @@ class LoanWindow(QtWidgets.QMainWindow, Ui_MainWindow):
# table # table
self.loanTable.doubleClicked.connect(self.showUser) self.loanTable.doubleClicked.connect(self.showUser)
log.info("Loan history window opened")
self.show() self.show()
def selfpass(self): def selfpass(self):
pass pass
def insertRow(self, data): def insertRow(self, data):
dbg(contents=data) log.debug(f"Inserting row: {data}")
retdate = "" retdate = ""
if data.returned_date != "": if data.returned_date != "":
retdate = stringToDate(data.returned_date).toString("dd.MM.yyyy") retdate = stringToDate(data.returned_date).toString("dd.MM.yyyy")
@@ -74,12 +73,45 @@ class LoanWindow(QtWidgets.QMainWindow, Ui_MainWindow):
), ),
) )
self.loanTable.setItem(0, 6, QtWidgets.QTableWidgetItem(retdate)) self.loanTable.setItem(0, 6, QtWidgets.QTableWidgetItem(retdate))
book = data.book
book.loan_to = data.return_date
book.load_from = data.loan_date
book.returned = data.returned
match self.check_book(book):
case "overdue":
for i in range(7):
self.loanTable.item(0, i).setBackground(
QtGui.QColor(255, 0, 0, 100)
)
case "ok":
for i in range(7):
self.loanTable.item(0, i).setBackground(
QtGui.QColor(105, 255, 51, 100)
)
case "returned":
for i in range(7):
self.loanTable.item(0, i).setBackground(
QtGui.QColor(102, 153, 153, 100)
)
def check_book(self, book):
today = QtCore.QDate.currentDate().toString("yyyy-MM-dd")
returnDate = stringToDate(book.loan_to).toString("yyyy-MM-dd")
returned = book.returned
if returned == 1:
return "returned"
else:
if returnDate < today:
return "overdue"
else:
return "ok"
def loadLoans(self): def loadLoans(self):
loans = self.db.getAllLoans() loans = self.db.getAllLoans()
for loan in loans: for loan in loans:
self.insertRow(loan) self.insertRow(loan)
self.loans = loans
return loans
def filterResults(self): def filterResults(self):
mode = ( mode = (
@@ -89,6 +121,7 @@ class LoanWindow(QtWidgets.QMainWindow, Ui_MainWindow):
if self.radio_current.isChecked() if self.radio_current.isChecked()
else "overdue" else "overdue"
) )
log.debug("Switching mode to {}", mode)
self.loanTable.setRowCount(0) self.loanTable.setRowCount(0)
today = QtCore.QDate.currentDate() today = QtCore.QDate.currentDate()
for loan in self.loans: for loan in self.loans:
@@ -112,7 +145,7 @@ class LoanWindow(QtWidgets.QMainWindow, Ui_MainWindow):
limiter = str(limiter) limiter = str(limiter)
searchfield = self.searchFields.currentText() searchfield = self.searchFields.currentText()
searchfield = TABLETOFIELDTRANSLATE[searchfield] searchfield = TABLETOFIELDTRANSLATE[searchfield]
dbg(limiter=limiter, search=searchfield) log.debug(f"Searching for: {limiter} in {searchfield}")
self.loanTable.setRowCount(0) self.loanTable.setRowCount(0)
for loan in self.loans: for loan in self.loans:
fielddata = eval(f"loan.{searchfield}") fielddata = eval(f"loan.{searchfield}")
@@ -125,7 +158,7 @@ class LoanWindow(QtWidgets.QMainWindow, Ui_MainWindow):
row = self.loanTable.currentRow() row = self.loanTable.currentRow()
user_name = self.loanTable.item(row, 3).text() user_name = self.loanTable.item(row, 3).text()
user = self.db.getUserId(user_name) user = self.db.getUserId(user_name)
self.user = UserUI(user.username, user.id, user.email) self.user = UserUI(user)
self.user.show() self.user.show()

View File

@@ -1,11 +1,13 @@
import os
import sys import sys
import atexit import atexit
import datetime import datetime
import webbrowser import webbrowser
from src import config, __email__, docport from PyQt6 import QtCore, QtWidgets
from src.logic import Database, Catalogue, Backup from omegaconf import OmegaConf
from src.utils import stringToDate, Icon, Log from src import config, __contacts__, docport, log, restore_config
from src.utils import debugMessage as dbg from src.logic import Database, Catalogue, Backup, DocumentationThread
from src.utils import stringToDate, Icon
from src.utils.createReport import generate_report from src.utils.createReport import generate_report
from src.schemas import Book from src.schemas import Book
from .sources.Ui_main_UserInterface import Ui_MainWindow from .sources.Ui_main_UserInterface import Ui_MainWindow
@@ -17,18 +19,17 @@ from .settings import Settings
from .newBook import NewBook from .newBook import NewBook
from .loans import LoanWindow from .loans import LoanWindow
from .reportUi import ReportUi from .reportUi import ReportUi
from PyQt6 import QtCore, QtWidgets from .addBook import addBook
from omegaconf import OmegaConf
from src.logic.documentation_thread import DocumentationThread
backup = Backup() backup = Backup()
cat = Catalogue() cat = Catalogue()
log = Log("main")
dbg(backup=config.database.do_backup, catalogue=config.catalogue)
def getShortcut(shortcuts, name): def getShortcut(shortcuts, name):
shortcut = [cut for cut in shortcuts if cut["name"] == name][0] shortcut = [cut for cut in shortcuts if cut["name"] == name][0]
return shortcut["current"] return shortcut["current"]
class MainUI(QtWidgets.QMainWindow, Ui_MainWindow): class MainUI(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self): def __init__(self):
super(MainUI, self).__init__() super(MainUI, self).__init__()
@@ -46,10 +47,12 @@ class MainUI(QtWidgets.QMainWindow, Ui_MainWindow):
self.actionBericht_erstellen.triggered.connect(self.generateReport) self.actionBericht_erstellen.triggered.connect(self.generateReport)
self.actionDokumentation_ffnen.triggered.connect(self.openDocumentation) self.actionDokumentation_ffnen.triggered.connect(self.openDocumentation)
self.actionBeenden.triggered.connect(self.shutdown) self.actionBeenden.triggered.connect(self.shutdown)
def __mail(): def __mail():
webbrowser.open(f"mailto:{__email__}") webbrowser.open(f"mailto:{__contacts__}")
self.actionProblem_melden.triggered.connect(__mail) self.actionProblem_melden.triggered.connect(__mail)
#if close button is pressed call shutdown # if close button is pressed call shutdown
self.closeEvent = self.shutdown self.closeEvent = self.shutdown
# Buttons # Buttons
self.btn_show_lentmedia.clicked.connect(self.showUser) self.btn_show_lentmedia.clicked.connect(self.showUser)
@@ -57,6 +60,7 @@ class MainUI(QtWidgets.QMainWindow, Ui_MainWindow):
self.btn_createNewUser.setText("") self.btn_createNewUser.setText("")
self.btn_createNewUser.setIcon(Icon("add_user").overwriteColor("#1E90FF")) self.btn_createNewUser.setIcon(Icon("add_user").overwriteColor("#1E90FF"))
self.mode.clicked.connect(self.changeMode) self.mode.clicked.connect(self.changeMode)
self.addBook.clicked.connect(self.addBookAction)
# LineEdits # LineEdits
self.input_userno.returnPressed.connect( self.input_userno.returnPressed.connect(
@@ -98,30 +102,54 @@ class MainUI(QtWidgets.QMainWindow, Ui_MainWindow):
log.info("Backup enabled") log.info("Backup enabled")
else: else:
log.warning("Backup disabled") log.warning("Backup disabled")
# set Action Icons
Icon("settings", self.actionEinstellungen)
Icon("user", self.actionNutzer)
Icon("quit", self.actionBeenden)
Icon("report", self.actionBericht_erstellen)
Icon("history", self.actionAusleihhistorie)
Icon("help", self.actionDokumentation_ffnen)
Icon("support", self.actionProblem_melden)
Icon("add", self.addBook)
self.show() self.show()
def addBookAction(self):
add = addBook()
add.setWindowModality(QtCore.Qt.WindowModality.ApplicationModal)
add.exec()
result = add.result()
book_id = add.book_id
if result == 1:
if self.activeUser:
self.loanMedia(self.activeUser.id, book_id)
# log.debug(f"UserID: {self.activeUser.id}, BookID: {book_id}")
def shutdown(self, *args): def shutdown(self, *args):
#kill documentation thread # kill documentation thread
log.info("Shutting down") log.info("Shutting down")
if config.documentation: if config.documentation:
self.docu.terminate() self.docu.terminate()
sys.exit() sys.exit()
def assignShortcuts(self): def assignShortcuts(self):
shortcuts = config.shortcuts shortcuts = config.shortcuts
shortcuts = OmegaConf.to_container(shortcuts) shortcuts = OmegaConf.to_container(shortcuts)
#convert to dictconfig # convert to dictconfig
self.actionDokumentation_ffnen.setShortcut(getShortcut(shortcuts, "Hilfe")) self.actionDokumentation_ffnen.setShortcut(getShortcut(shortcuts, "Hilfe"))
self.actionAusleihhistorie.setShortcut(getShortcut(shortcuts, "Ausleihhistorie")) self.actionAusleihhistorie.setShortcut(
self.actionBericht_erstellen.setShortcut(getShortcut(shortcuts, "Bericht_erstellen")) getShortcut(shortcuts, "Ausleihhistorie")
)
self.actionBericht_erstellen.setShortcut(
getShortcut(shortcuts, "Bericht_erstellen")
)
self.actionNutzer.setShortcut(getShortcut(shortcuts, "Nutzer")) self.actionNutzer.setShortcut(getShortcut(shortcuts, "Nutzer"))
self.actionRueckgabemodus.setShortcut(getShortcut(shortcuts, "Rueckgabemodus")) self.actionRueckgabemodus.setShortcut(getShortcut(shortcuts, "Rueckgabemodus"))
def generateReport(self): def generateReport(self):
log.info("Generating Report") log.info("Generating Report")
report = ReportUi() report = ReportUi()
report.setWindowModality(QtCore.Qt.WindowModality.ApplicationModal)
report.exec() report.exec()
def showLoanHistory(self): def showLoanHistory(self):
@@ -141,20 +169,22 @@ class MainUI(QtWidgets.QMainWindow, Ui_MainWindow):
settings = Settings() settings = Settings()
settings.exec() settings.exec()
result = settings.result() result = settings.result()
print(settings.settingschanged, settings.restart_required) # print(settings.settingschanged, settings.restart_required)
if result == 1: if result == 1 and settings.restart_required:
#dialog to ask if program should be restarted # dialog to ask if program should be restarted
dialog = QtWidgets.QMessageBox() dialog = QtWidgets.QMessageBox()
dialog.setWindowTitle("Einstellungen geändert") dialog.setWindowTitle("Einstellungen geändert")
dialog.setIcon(QtWidgets.QMessageBox.Icon.Information) dialog.setIcon(QtWidgets.QMessageBox.Icon.Information)
dialog.setWindowIcon(Icon("settings").icon) dialog.setWindowIcon(Icon("restart").icon)
dialog.setText("Einstellungen wurden geändert\nProgramm neu starten?") dialog.setText(
"Einstellungen wurden geändert\nDas Programm muss neu gestartet werden?"
)
dialog.setStandardButtons( dialog.setStandardButtons(
QtWidgets.QMessageBox.StandardButton.Yes QtWidgets.QMessageBox.StandardButton.Yes
| QtWidgets.QMessageBox.StandardButton.No | QtWidgets.QMessageBox.StandardButton.No
) )
dialog.setDefaultButton(QtWidgets.QMessageBox.StandardButton.No) dialog.setDefaultButton(QtWidgets.QMessageBox.StandardButton.No)
#translate buttons # translate buttons
yes = dialog.button(QtWidgets.QMessageBox.StandardButton.Yes) yes = dialog.button(QtWidgets.QMessageBox.StandardButton.Yes)
yes.setText("Ja") yes.setText("Ja")
no = dialog.button(QtWidgets.QMessageBox.StandardButton.No) no = dialog.button(QtWidgets.QMessageBox.StandardButton.No)
@@ -164,7 +194,7 @@ class MainUI(QtWidgets.QMainWindow, Ui_MainWindow):
if result == QtWidgets.QMessageBox.StandardButton.Yes: if result == QtWidgets.QMessageBox.StandardButton.Yes:
self.restart() self.restart()
# reload settings # reload settings
#print(config) # print(config)
def openDocumentation(self): def openDocumentation(self):
log.info("Opening Documentation") log.info("Opening Documentation")
@@ -178,22 +208,18 @@ class MainUI(QtWidgets.QMainWindow, Ui_MainWindow):
dialog.setText("Dokumentation nicht verfügbar") dialog.setText("Dokumentation nicht verfügbar")
dialog.exec() dialog.exec()
def restart(self): def restart(self):
#log restart # log restart
dbg("Restarting Program") log.info("Restarting Program")
import os import os
python_executable = sys.executable python_executable = sys.executable
args = sys.argv[:] args = sys.argv[:]
args.insert(0, sys.executable) args.insert(0, sys.executable)
os.execvp(python_executable, args) os.execvp(python_executable, args)
def changeMode(self): def changeMode(self):
log.info("Changing Mode") log.info("Changing Mode, current mode is {}", self.activeState)
dbg(f"Current mode: {self.activeState}")
self.input_username.clear() self.input_username.clear()
stayReturn = False stayReturn = False
if config.advanced_refresh and self.userdata.toPlainText() != "": if config.advanced_refresh and self.userdata.toPlainText() != "":
@@ -205,18 +231,18 @@ class MainUI(QtWidgets.QMainWindow, Ui_MainWindow):
self.label_7.hide() self.label_7.hide()
self.nextReturnDate.hide() self.nextReturnDate.hide()
self.mediaOverview.setRowCount(0) self.mediaOverview.setRowCount(0)
self.activeUser = None #! remove if last user should be kept self.activeUser = None #! remove if last user should be kept
if self.activeState == "Rückgabe": if self.activeState == "Rückgabe":
if stayReturn: if stayReturn:
self.activateReturnMode() self.activateReturnMode()
else: self.activateLoanMode() else:
self.activateLoanMode()
else: else:
self.activateReturnMode() self.activateReturnMode()
def activateLoanMode(self): def activateLoanMode(self):
dbg("Activating Loan Mode") log.info("Activating Loan Mode")
self.input_username.setEnabled(True) self.input_username.setEnabled(True)
self.input_userno.setEnabled(True) self.input_userno.setEnabled(True)
self.duedate.setEnabled(True) self.duedate.setEnabled(True)
@@ -229,12 +255,14 @@ class MainUI(QtWidgets.QMainWindow, Ui_MainWindow):
self.activeState = "Ausleihe" self.activeState = "Ausleihe"
if self.input_userno.text() == "" or self.input_username.text() == "": if self.input_userno.text() == "" or self.input_username.text() == "":
self.input_file_ident.setEnabled(False) self.input_file_ident.setEnabled(False)
self.input_file_ident.setPlaceholderText("Bitte zuerst Nutzerdaten eingeben") self.input_file_ident.setPlaceholderText(
"Bitte zuerst Nutzerdaten eingeben"
)
else: else:
self.input_file_ident.setEnabled(True) self.input_file_ident.setEnabled(True)
def activateReturnMode(self): def activateReturnMode(self):
dbg("Activating Return Mode") log.info("Activating Return Mode")
self.input_username.setEnabled(False) self.input_username.setEnabled(False)
self.input_userno.setEnabled(False) self.input_userno.setEnabled(False)
# set mode background color to orange # set mode background color to orange
@@ -244,11 +272,12 @@ class MainUI(QtWidgets.QMainWindow, Ui_MainWindow):
self.mode.setText("Rückgabe") self.mode.setText("Rückgabe")
self.input_file_ident.setEnabled(True) self.input_file_ident.setEnabled(True)
self.input_file_ident.setPlaceholderText("Buchidentifikation eingeben") self.input_file_ident.setPlaceholderText("Buchidentifikation eingeben")
self.input_username.setPlaceholderText("Bitte erst in den Ausleihmodus wechseln") self.input_username.setPlaceholderText(
"Bitte erst in den Ausleihmodus wechseln"
)
self.input_userno.setPlaceholderText("Bitte erst in den Ausleihmodus wechseln") self.input_userno.setPlaceholderText("Bitte erst in den Ausleihmodus wechseln")
self.input_file_ident.setFocus()
def showUser(self): def showUser(self):
log.info(f"Showing User {self.activeUser}")
if self.activeUser is None: if self.activeUser is None:
# create warning dialog # create warning dialog
log.info("Showing no user selected warning") log.info("Showing no user selected warning")
@@ -260,12 +289,10 @@ class MainUI(QtWidgets.QMainWindow, Ui_MainWindow):
dialog.exec() dialog.exec()
return return
self.user_ui = UserUI( self.user_ui = UserUI(self.activeUser)
self.activeUser
)
# self.user_ui.setFields("John Doe", "123456789", "test@mail.com") # self.user_ui.setFields("John Doe", "123456789", "test@mail.com")
self.user_ui.show() self.user_ui.show()
def setUserData(self): def setUserData(self):
log.info("Setting User Data") log.info("Setting User Data")
self.input_username.setText(str(self.activeUser.username)) self.input_username.setText(str(self.activeUser.username))
@@ -277,9 +304,11 @@ class MainUI(QtWidgets.QMainWindow, Ui_MainWindow):
def createUser(self): def createUser(self):
log.info("Creating User") log.info("Creating User")
user = CreateUser(fieldname="id", data="") user = CreateUser(fieldname="id", data="")
user.setWindowModality(
QtCore.Qt.WindowModality.ApplicationModal
) # Block MainUI fom being accessed
user.exec() user.exec()
userid = user.userid userid = user.userid
print(userid)
if userid: if userid:
log.info(f"User created {userid}") log.info(f"User created {userid}")
data = self.db.getUserBy("user_id", userid) data = self.db.getUserBy("user_id", userid)
@@ -295,7 +324,7 @@ class MainUI(QtWidgets.QMainWindow, Ui_MainWindow):
def checkUser(self, fieldname, data): def checkUser(self, fieldname, data):
log.info(f"Checking User {fieldname}, {data}") log.info(f"Checking User {fieldname}, {data}")
#print("Checking User", fieldname, data) # print("Checking User", fieldname, data)
# set fieldname as key and data as variable # set fieldname as key and data as variable
user = self.db.checkUserExists(fieldname, data) user = self.db.checkUserExists(fieldname, data)
if not user: if not user:
@@ -315,28 +344,32 @@ class MainUI(QtWidgets.QMainWindow, Ui_MainWindow):
multi.exec() multi.exec()
self.activeUser = multi.userdata self.activeUser = multi.userdata
else: else:
#print("User found", user[0])
self.activeUser = user[0] self.activeUser = user[0]
log.debug("User: {}", self.activeUser)
if self.activeUser is not None: if self.activeUser is not None:
log.info(f"User found {self.activeUser}") log.debug(self.activeUser.__dict__)
#print("User found", self.activeUser)
self.setUserData() self.setUserData()
self.input_file_ident.setFocus() self.input_file_ident.setFocus()
self.mode.setText("Ausleihe") self.mode.setText("Ausleihe")
#print(self.activeUser.__dict__)
loans = self.db.getActiveLoans(self.activeUser.id) loans = self.db.getActiveLoans(self.activeUser.id)
dbg(loans=loans) log.debug("Active Loans", loans)
self.btn_show_lentmedia.setText(loans) self.btn_show_lentmedia.setText(loans)
retdate = self.db.selectClosestReturnDate(self.activeUser.id) retdate = self.db.selectClosestReturnDate(self.activeUser.id)
if retdate: if retdate:
date = stringToDate(retdate).toString("dd.MM.yyyy") date = stringToDate(retdate).toString("dd.MM.yyyy")
today = QtCore.QDate.currentDate().toString("yyyy-MM-dd")
# if retdate is in past, set nextReturnDate color to red
if retdate < today:
self.nextReturnDate.setStyleSheet("color: red")
else:
self.nextReturnDate.setStyleSheet("color: black")
self.nextReturnDate.setText(date) self.nextReturnDate.setText(date)
self.nextReturnDate.show() self.nextReturnDate.show()
self.label_7.show() self.label_7.show()
self.input_file_ident.setEnabled(True) self.input_file_ident.setEnabled(True)
self.input_file_ident.setPlaceholderText("Buchidentifikation eingeben") self.input_file_ident.setPlaceholderText("Buchidentifikation eingeben")
self.input_file_ident.setFocus() self.input_file_ident.setFocus()
def moveToLine(self, line): def moveToLine(self, line):
log.debug("Moving to Line", line) log.debug("Moving to Line", line)
line.setFocus() line.setFocus()
@@ -354,13 +387,15 @@ class MainUI(QtWidgets.QMainWindow, Ui_MainWindow):
dialog.setWindowTitle("Ungültige Eingabe") dialog.setWindowTitle("Ungültige Eingabe")
dialog.setIcon(QtWidgets.QMessageBox.Icon.Warning) dialog.setIcon(QtWidgets.QMessageBox.Icon.Warning)
dialog.setWindowIcon(Icon("warning").overwriteColor("#EA3323")) dialog.setWindowIcon(Icon("warning").overwriteColor("#EA3323"))
dialog.setText("Eingabe ist nicht in der Datenbank\nBitte prüfen und erneut eingeben") dialog.setText(
"Eingabe ist nicht in der Datenbank\nBitte prüfen und erneut eingeben"
)
dialog.exec() dialog.exec()
self.input_file_ident.setFocus() self.input_file_ident.setFocus()
self.input_file_ident.clear() self.input_file_ident.clear()
return return
else: else:
if not " " in value: if " " not in value:
# create warning dialog # create warning dialog
log.info("Invalid Input") log.info("Invalid Input")
dialog = QtWidgets.QMessageBox() dialog = QtWidgets.QMessageBox()
@@ -374,18 +409,19 @@ class MainUI(QtWidgets.QMainWindow, Ui_MainWindow):
return return
self.mediaAdd(value) self.mediaAdd(value)
self.input_file_ident.setFocus() self.input_file_ident.setFocus()
def mediaAdd(self, identifier): def mediaAdd(self, identifier):
dbg("Adding Media", identifier = identifier) log.info("Adding Media", identifier=identifier)
self.input_file_ident.clear() self.input_file_ident.clear()
self.input_file_ident.setEnabled(False) self.input_file_ident.setEnabled(False)
user_id = self.activeUser.id user_id = self.activeUser.id
media = Book(signature=identifier) media = Book(signature=identifier)
book_id = self.db.checkMediaExists(media) book_id = self.db.checkMediaExists(media)
dbg(f"Book ID: {book_id}, User ID: {user_id}", media=media) log.debug(f"Book ID: {book_id}, User ID: {user_id}", media=media)
if not book_id: if not book_id:
dbg("Book not found, searching catalogue") log.info("Book not found, searching catalogue")
if config.catalogue == True: if config.catalogue:
media = cat.get_book(identifier) media = cat.get_book(identifier)
if not media: if not media:
self.setStatusTipMessage("Buch nicht gefunden") self.setStatusTipMessage("Buch nicht gefunden")
@@ -402,8 +438,8 @@ class MainUI(QtWidgets.QMainWindow, Ui_MainWindow):
elif book_id: elif book_id:
if isinstance(book_id, list) and len(book_id) > 1: if isinstance(book_id, list) and len(book_id) > 1:
#print("Multiple Books found")
# TODO: implement book selection dialog # TODO: implement book selection dialog
raise NotImplementedError("Multiple books found")
return return
else: else:
if isinstance(book_id, int): if isinstance(book_id, int):
@@ -411,7 +447,7 @@ class MainUI(QtWidgets.QMainWindow, Ui_MainWindow):
# check if book is already loaned # check if book is already loaned
loaned = self.db.checkLoanState(book_id[0]) loaned = self.db.checkLoanState(book_id[0])
if loaned: if loaned:
#print("Book already loaned") # print("Book already loaned")
self.setStatusTipMessage("Buch bereits entliehen") self.setStatusTipMessage("Buch bereits entliehen")
# dialog with yes no to create new entry # dialog with yes no to create new entry
dialog = QtWidgets.QMessageBox() dialog = QtWidgets.QMessageBox()
@@ -432,19 +468,29 @@ class MainUI(QtWidgets.QMainWindow, Ui_MainWindow):
return return
newentry = NewEntry([book_id[0]]) newentry = NewEntry([book_id[0]])
newentry.exec() newentry.exec()
if newentry.result() == 1: # only create dialog if new entry was created if (
newentry.result() == 1
): # only create dialog if new entry was created
self.setStatusTipMessage("Neues Exemplar hinzugefügt") self.setStatusTipMessage("Neues Exemplar hinzugefügt")
#print(created_ids) # print(created_ids)
self.input_file_ident.setEnabled(True) self.input_file_ident.setEnabled(True)
newentries = newentry.newIds newentries = newentry.newIds
if newentries: if newentries:
for entry in newentries: for entry in newentries:
book = self.db.getMedia(entry) book = self.db.getMedia(entry)
self.loanMedia(user_id, [entry], book) log.debug(
dbg("inserted duplicated book into database") "Inserting duplicated book {} with id {} to user {}".format(
book, entry, user_id
)
)
self.loanMedia(user_id, [entry])
log.info("inserted duplicated book into database")
else:
log.info("No new entry created")
self.input_file_ident.setEnabled(True)
return return
else: else:
#print("Book not loaned, loaning now") # print("Book not loaned, loaning now")
self.loanMedia(user_id, book_id) self.loanMedia(user_id, book_id)
def loanMedia(self, user_id, book_id): def loanMedia(self, user_id, book_id):
@@ -455,7 +501,7 @@ class MainUI(QtWidgets.QMainWindow, Ui_MainWindow):
self.duedate.date().toString("yyyy-MM-dd"), self.duedate.date().toString("yyyy-MM-dd"),
) )
media = self.db.getMedia(book_id[0]) media = self.db.getMedia(book_id[0])
#print(media) # print(media)
self.mediaOverview.insertRow(0) self.mediaOverview.insertRow(0)
self.mediaOverview.setItem(0, 0, QtWidgets.QTableWidgetItem(media.signature)) self.mediaOverview.setItem(0, 0, QtWidgets.QTableWidgetItem(media.signature))
self.mediaOverview.setItem(0, 1, QtWidgets.QTableWidgetItem(media.title)) self.mediaOverview.setItem(0, 1, QtWidgets.QTableWidgetItem(media.title))
@@ -471,19 +517,19 @@ class MainUI(QtWidgets.QMainWindow, Ui_MainWindow):
self.input_file_ident.setEnabled(True) self.input_file_ident.setEnabled(True)
def returnMedia(self, identifier): def returnMedia(self, identifier):
#print("Returning Media", identifier) # print("Returning Media", identifier)
# get book id from database # get book id from database
# self. # self.
identifier = Book( identifier = Book(
isbn=identifier, title=identifier, signature=identifier, ppn=identifier isbn=identifier, title=identifier, signature=identifier, ppn=identifier
) )
book_id = self.db.checkMediaExists(identifier) book_id = self.db.checkMediaExists(identifier)
#print(book_id) # print(book_id)
if book_id: if book_id:
# check if book is already loaned # check if book is already loaned
loaned = self.db.checkLoanState(book_id[0]) loaned = self.db.checkLoanState(book_id[0])
if loaned: if loaned:
#print("Book already loaned, returning now") # print("Book already loaned, returning now")
user = self.db.getUserByLoan(book_id[0]) user = self.db.getUserByLoan(book_id[0])
# set userdata in lineedits # set userdata in lineedits
self.activeUser = user self.activeUser = user
@@ -492,7 +538,9 @@ class MainUI(QtWidgets.QMainWindow, Ui_MainWindow):
book_id[0], self.currentDate.toString("yyyy-MM-dd") book_id[0], self.currentDate.toString("yyyy-MM-dd")
) )
self.mediaOverview.insertRow(0) self.mediaOverview.insertRow(0)
self.mediaOverview.setItem(0, 0, QtWidgets.QTableWidgetItem(book.signature)) self.mediaOverview.setItem(
0, 0, QtWidgets.QTableWidgetItem(book.signature)
)
self.mediaOverview.setItem(0, 1, QtWidgets.QTableWidgetItem(book.title)) self.mediaOverview.setItem(0, 1, QtWidgets.QTableWidgetItem(book.title))
self.mediaOverview.setItem( self.mediaOverview.setItem(
0, 2, QtWidgets.QTableWidgetItem("Zurückgegeben") 0, 2, QtWidgets.QTableWidgetItem("Zurückgegeben")
@@ -502,15 +550,13 @@ class MainUI(QtWidgets.QMainWindow, Ui_MainWindow):
self.db.getActiveLoans(self.activeUser.id) self.db.getActiveLoans(self.activeUser.id)
) )
else: else:
#print("Book not loaned") # print("Book not loaned")
self.setStatusTipMessage("Buch nicht entliehen") self.setStatusTipMessage("Buch nicht entliehen")
self.input_file_ident.clear() self.input_file_ident.clear()
else: else:
dbg("Book not found") log.error("Book not found, identifier", identifier)
#print("Book not found") # print("Book not found")
#self.input_file_ident.setPlaceholderText(f"Buch {identifier} nicht gefunden") # self.input_file_ident.setPlaceholderText(f"Buch {identifier} nicht gefunden")
def setStatusTipMessage(self, message): def setStatusTipMessage(self, message):
dialog = QtWidgets.QMessageBox() dialog = QtWidgets.QMessageBox()
@@ -519,29 +565,40 @@ class MainUI(QtWidgets.QMainWindow, Ui_MainWindow):
dialog.setWindowIcon(Icon("error").overwriteColor("#EA3323")) dialog.setWindowIcon(Icon("error").overwriteColor("#EA3323"))
dialog.setText(message) dialog.setText(message)
dialog.exec() dialog.exec()
def exit_handler(): def exit_handler():
dbg("Exiting, creating backup") log.info(
app = QtWidgets.QApplication(sys.argv) "Exiting, creating backup, renaming inactive users, creating report if day matches"
#print(backup.backup) )
restore_config()
QtWidgets.QApplication(sys.argv)
# print(backup.backup)
# generate report if monday # generate report if monday
if datetime.datetime.now().weekday() == config.report.report_day: if datetime.datetime.now().weekday() == config.report.report_day:
log.info("Generating Report")
generate_report() generate_report()
dbg("Generated Report")
Database().renameInactiveUsers() Database().renameInactiveUsers()
if config.database.do_backup: if config.database.do_backup:
state = backup.createBackup() state = backup.createBackup()
# create dialog to show state # create dialog to show state
if state == True: if state:
return return
else: else:
dialog = QtWidgets.QMessageBox() dialog = QtWidgets.QMessageBox()
# set icon # set icon
dialog.setWindowIcon(Icon("backup").icon) dialog.setWindowIcon(Icon("backup").icon)
dialog.setWindowTitle("Backup") dialog.setWindowTitle("Backup")
dialog.setText("Backup konnte nicht erstellt werden") errormsg = "Backup konnte nicht erstellt werden\nGrund: {}"
files = os.listdir(config.database.backupLocation)
if ".backup" in files:
errormsg = errormsg.format("Normaler speicherort nicht gefunden")
else:
errormsg = errormsg.format("Backuppfad nicht gefunden")
dialog.setText(errormsg)
dialog.exec() dialog.exec()
dbg("Exiting", backupstate=state) log.info("Exiting, backup:", state)
else: else:
dialog = QtWidgets.QMessageBox() dialog = QtWidgets.QMessageBox()
# set icon # set icon
@@ -554,28 +611,55 @@ def exit_handler():
dialog.setWindowTitle("Backup nicht möglich") dialog.setWindowTitle("Backup nicht möglich")
dialog.setText("Backup konnte nicht erstellt werden\nGrund: {}".format(reason)) dialog.setText("Backup konnte nicht erstellt werden\nGrund: {}".format(reason))
dialog.exec() dialog.exec()
log.info("Exiting")
sys.exit()
def launch(*argv): def launch(*argv):
options = sys.argv options = sys.argv
if argv: if argv:
options += [arg for arg in argv] options += [arg for arg in argv]
options = [arg for arg in options if arg.startswith("--")] options += [arg for arg in options if arg.startswith("--")]
#print("Launching Main UI") # add options to sys.argv
#print(options) # print(options)
QtCore.QLocale().setDefault(QtCore.QLocale(QtCore.QLocale.Language.German, QtCore.QLocale.Country.Germany)) # print("Launching Main UI")
QtCore.QLocale().setDefault(
QtCore.QLocale(QtCore.QLocale.Language.German, QtCore.QLocale.Country.Germany)
)
SYSTEM_LANGUAGE = QtCore.QLocale().system().name() SYSTEM_LANGUAGE = QtCore.QLocale().system().name()
print(SYSTEM_LANGUAGE)
# Load base QT translations from the normal place # Load base QT translations from the normal place
app = QtWidgets.QApplication([]) app = QtWidgets.QApplication([])
main_ui = MainUI() MainUI()
#translate ui to system language # translate ui to system language
if SYSTEM_LANGUAGE: if SYSTEM_LANGUAGE:
translator = QtCore.QTranslator() translator = QtCore.QTranslator()
#do not use ascii encoding # do not use ascii encoding
translator.load(f"qt_{SYSTEM_LANGUAGE}", "translations") translator.load(f"qt_{SYSTEM_LANGUAGE}", "translations")
translator.load("app.qm", "translations") translator.load("app.qm", "translations")
app.installTranslator(translator) app.installTranslator(translator)
atexit.register(exit_handler)
sys.exit(app.exec())
# sys.exit(app.exec())
# print("Launching Main UI")
# print(options)
QtCore.QLocale().setDefault(
QtCore.QLocale(QtCore.QLocale.Language.German, QtCore.QLocale.Country.Germany)
)
SYSTEM_LANGUAGE = QtCore.QLocale().system().name()
# Load base QT translations from the normal place
app = QtWidgets.QApplication([])
MainUI()
# translate ui to system language
if SYSTEM_LANGUAGE:
translator = QtCore.QTranslator()
# do not use ascii encoding
translator.load(f"qt_{SYSTEM_LANGUAGE}", "translations")
translator.load("app.qm", "translations")
app.installTranslator(translator)
atexit.register(exit_handler) atexit.register(exit_handler)
sys.exit(app.exec()) sys.exit(app.exec())
# sys.exit(app.exec()) # sys.exit(app.exec())

View File

@@ -2,7 +2,7 @@ from .sources.Ui_dialog_multipleUserfound import Ui_Dialog
from PyQt6 import QtCore, QtGui, QtWidgets from PyQt6 import QtCore, QtGui, QtWidgets
from src.schemas import User from src.schemas import User
from src.utils import Icon from src.utils import Icon
from src import log
class MultiUserFound(QtWidgets.QDialog, Ui_Dialog): class MultiUserFound(QtWidgets.QDialog, Ui_Dialog):
def __init__(self, users: list[User]): def __init__(self, users: list[User]):
@@ -27,15 +27,20 @@ class MultiUserFound(QtWidgets.QDialog, Ui_Dialog):
self.tableWidget.cellClicked.connect(self.selectUser) self.tableWidget.cellClicked.connect(self.selectUser)
def selectUser(self, row, column): def selectUser(self, row, column):
#print(row, column) # print(row, column)
user = User( selected_user = User(
userid=self.tableWidget.item(row, 0).text(), userid=int(self.tableWidget.item(row, 0).text()),
username=self.tableWidget.item(row, 1).text(), username=self.tableWidget.item(row, 1).text(),
email=self.tableWidget.item(row, 2).text(), email=self.tableWidget.item(row, 2).text(),
) )
self.userdata = user # find the selecter in the self.users list
for user in self.users:
if user.match(selected_user):
self.userdata = user
break
log.debug("User selected: {}", self.userdata)
def displayUsers(self): def displayUsers(self):
for user in self.users: for user in self.users:
self.tableWidget.insertRow(0) self.tableWidget.insertRow(0)

View File

@@ -4,6 +4,7 @@ from src.logic import Database
from src.schemas import Book from src.schemas import Book
from src.utils import Icon from src.utils import Icon
class NewEntry(QtWidgets.QDialog, Ui_Dialog): class NewEntry(QtWidgets.QDialog, Ui_Dialog):
def __init__(self, title_id: list[int]): def __init__(self, title_id: list[int]):
super(NewEntry, self).__init__() super(NewEntry, self).__init__()
@@ -19,15 +20,15 @@ class NewEntry(QtWidgets.QDialog, Ui_Dialog):
self.populateTable() self.populateTable()
self.btn_addNewBook.clicked.connect(self.addEntry) self.btn_addNewBook.clicked.connect(self.addEntry)
self.buttonBox.accepted.connect(self.insertEntry) self.buttonBox.accepted.connect(self.insertEntry)
#disable buttonbox accepted # disable buttonbox accepted
self.buttonBox.button( self.buttonBox.button(QtWidgets.QDialogButtonBox.StandardButton.Ok).setEnabled(
QtWidgets.QDialogButtonBox.StandardButton.Ok False
).setEnabled(False) )
def addEntry(self): def addEntry(self):
self.buttonBox.button( self.buttonBox.button(QtWidgets.QDialogButtonBox.StandardButton.Ok).setEnabled(
QtWidgets.QDialogButtonBox.StandardButton.Ok True
).setEnabled(True) )
# clone last row and its data # clone last row and its data
row = self.tableWidget.rowCount() row = self.tableWidget.rowCount()
self.tableWidget.insertRow(row) self.tableWidget.insertRow(row)
@@ -35,19 +36,31 @@ class NewEntry(QtWidgets.QDialog, Ui_Dialog):
self.tableWidget.setItem( self.tableWidget.setItem(
row, i, QtWidgets.QTableWidgetItem(self.tableWidget.item(row - 1, i)) row, i, QtWidgets.QTableWidgetItem(self.tableWidget.item(row - 1, i))
) )
if i == 2 and "+" in self.tableWidget.item(row, i).text(): if i == 2:
entry = self.tableWidget.item(row, i).text().split("+")[1] if "+" in self.tableWidget.item(row, i).text():
entry = str(int(entry) + 1) entry = self.tableWidget.item(row, i).text().split("+")[1]
self.tableWidget.setItem( entry = str(int(entry) + 1)
row, self.tableWidget.setItem(
i, row,
QtWidgets.QTableWidgetItem( i,
self.tableWidget.item(row, i).text().split("+")[0] + "+" + entry QtWidgets.QTableWidgetItem(
), self.tableWidget.item(row, i).text().split("+")[0]
) + "+"
+ entry
),
)
else:
self.tableWidget.setItem(
row,
i,
QtWidgets.QTableWidgetItem(
self.tableWidget.item(row, i).text() + "+1"
),
)
def populateTable(self): def populateTable(self):
for title in self.titles: for title in self.titles:
#print(title) # print(title)
entries = self.db.getMediaSimilarSignatureByID(title) entries = self.db.getMediaSimilarSignatureByID(title)
# sort by signature # sort by signature
entries.sort(key=lambda x: x.signature, reverse=True) entries.sort(key=lambda x: x.signature, reverse=True)
@@ -59,7 +72,11 @@ class NewEntry(QtWidgets.QDialog, Ui_Dialog):
0, 2, QtWidgets.QTableWidgetItem(entry.signature) 0, 2, QtWidgets.QTableWidgetItem(entry.signature)
) )
self.tableWidget.setItem(0, 3, QtWidgets.QTableWidgetItem(entry.ppn)) self.tableWidget.setItem(0, 3, QtWidgets.QTableWidgetItem(entry.ppn))
# set row to be not editable
for i in range(4):
self.tableWidget.item(0, i).setFlags(
QtCore.Qt.ItemFlag.ItemIsEnabled
)
def insertEntry(self): def insertEntry(self):
# get all rows, convert them to Book and insert into database # get all rows, convert them to Book and insert into database
for row in range(self.tableWidget.rowCount()): for row in range(self.tableWidget.rowCount()):
@@ -73,7 +90,7 @@ class NewEntry(QtWidgets.QDialog, Ui_Dialog):
signature=signature, signature=signature,
ppn=eval(ppn), ppn=eval(ppn),
) )
#print(book) # print(book)
if not self.db.checkMediaExists(book): if not self.db.checkMediaExists(book):
newBookId = self.db.insertMedia(book) newBookId = self.db.insertMedia(book)
self.newIds.append(newBookId) self.newIds.append(newBookId)

View File

@@ -4,6 +4,7 @@ from src.utils import Icon
from src.utils.reportThread import ReportThread from src.utils.reportThread import ReportThread
from src.logic import Database from src.logic import Database
import os import os
from src import config, log
class ReportUi(QtWidgets.QDialog, Ui_Dialog): class ReportUi(QtWidgets.QDialog, Ui_Dialog):
@@ -31,14 +32,19 @@ class ReportUi(QtWidgets.QDialog, Ui_Dialog):
self.format_txt.clicked.connect(lambda: self.rthread.setFormat("txt")) self.format_txt.clicked.connect(lambda: self.rthread.setFormat("txt"))
self.format_csv.clicked.connect(lambda: self.rthread.setFormat("tsv")) self.format_csv.clicked.connect(lambda: self.rthread.setFormat("tsv"))
self.format_csv.clicked.connect(lambda: self.generateReport.setEnabled(True)) self.format_csv.clicked.connect(lambda: self.generateReport.setEnabled(True))
self.format_txt.clicked.connect(lambda: self.generateReport.setEnabled(True)) self.format_txt.clicked.connect(lambda: self.generateReport.setEnabled(True)) #
self.signature.clicked.connect(self.setSignature)
# sliders # sliders
self.dayslider.valueChanged.connect(self.set_days) self.dayslider.valueChanged.connect(self.set_days_slider)
self.show() self.show()
# labels # labels
self.label_4.hide() self.label_4.hide()
def setSignature(self):
show_signature = self.signature.isChecked()
config.report.show_signature = show_signature
def set_days_by_radio(self): def set_days_by_radio(self):
if self.radio_year.isChecked(): if self.radio_year.isChecked():
self.set_days(365) self.set_days(365)
@@ -50,15 +56,26 @@ class ReportUi(QtWidgets.QDialog, Ui_Dialog):
self.set_days(7) self.set_days(7)
self.dayslider.setValue(7) self.dayslider.setValue(7)
def set_days(self, value): def set_days(self, days=None):
# if value is not 7,30,365, deactivate radio buttons self.days = days
if value != 7 and value != 30 and value != 365:
self.radioButton.setChecked(True)
self.days = value self.dayValue.setText(str(self.days))
self.dayValue.setText(str(value))
def set_days_slider(self):
slider_value = self.dayslider.value()
self.set_days(slider_value)
match slider_value:
case 365:
self.radio_year.setChecked(True)
case 30:
self.radio_month.setChecked(True)
case 7:
self.radio_week.setChecked(True)
case _:
self.radioButton.setChecked(True)
def generate_report(self): def generate_report(self):
# self.set_days()
log.debug("Generating report for the last " + str(self.days) + " days")
self.rthread.setDays(self.days) self.rthread.setDays(self.days)
self.rthread.report_signal.connect(self.report_generated) self.rthread.report_signal.connect(self.report_generated)
self.rthread.report_nums_signal.connect(self.show_progress) self.rthread.report_nums_signal.connect(self.show_progress)
@@ -68,7 +85,6 @@ class ReportUi(QtWidgets.QDialog, Ui_Dialog):
self.rthread.start() self.rthread.start()
def reset(self): def reset(self):
self.days = 0
self.reportprogress.hide() self.reportprogress.hide()
self.reportprogress.setValue(0) self.reportprogress.setValue(0)
self.label_4.setText("Fortschritt:") self.label_4.setText("Fortschritt:")
@@ -90,7 +106,7 @@ class ReportUi(QtWidgets.QDialog, Ui_Dialog):
def report_generated(self): def report_generated(self):
self.reportlink.setOpenExternalLinks(True) self.reportlink.setOpenExternalLinks(True)
fileformat = self.rthread.format fileformat = self.rthread.format
#print(fileformat) # print(fileformat)
self.reportlink.setText( self.reportlink.setText(
f'<a href="file:///{os.getcwd()}/report.{fileformat}">Report</a>' f'<a href="file:///{os.getcwd()}/report.{fileformat}">Report</a>'
) )

View File

@@ -1,18 +1,18 @@
from .sources.Ui_dialog_settings import Ui_Dialog from .sources.Ui_dialog_settings import Ui_Dialog
from PyQt6 import QtWidgets, QtCore from PyQt6 import QtWidgets, QtCore
from src import config, log
from src.utils import Icon from src.utils import Icon
from src import config
from src.utils import debugMessage as dbg
from omegaconf import OmegaConf from omegaconf import OmegaConf
import os import os
class Settings(QtWidgets.QDialog, Ui_Dialog): class Settings(QtWidgets.QDialog, Ui_Dialog):
def __init__(self): def __init__(self):
super(Settings, self).__init__() super(Settings, self).__init__()
self.setupUi(self) self.setupUi(self)
self.setWindowTitle("Einstellungen") self.setWindowTitle("Einstellungen")
self.setWindowIcon(Icon("settings").icon) self.setWindowIcon(Icon("settings").icon)
#variables # variables
self.originalSettings = config.to_Omegaconf() self.originalSettings = config.to_Omegaconf()
self.changedSettings = config.to_Omegaconf() self.changedSettings = config.to_Omegaconf()
self.shortcuts = config.shortcuts self.shortcuts = config.shortcuts
@@ -20,12 +20,10 @@ class Settings(QtWidgets.QDialog, Ui_Dialog):
self.settingschanged = False self.settingschanged = False
self.restart_required = False self.restart_required = False
# buttonbox # buttonbox
self.buttonBox.accepted.connect(self.saveSettings) self.buttonBox.accepted.connect(self.saveSettings)
self.buttonBox.rejected.connect(self.close) self.buttonBox.rejected.connect(self.close)
self.loadSettings() self.loadSettings()
self.populateShortcuts() self.populateShortcuts()
# buttons # buttons
@@ -36,36 +34,39 @@ class Settings(QtWidgets.QDialog, Ui_Dialog):
self.btn_select_database_name.clicked.connect(self.selectDatabaseName) self.btn_select_database_name.clicked.connect(self.selectDatabaseName)
self.btn_select_report_path.clicked.connect(self.selectReportPath) self.btn_select_report_path.clicked.connect(self.selectReportPath)
self.returnMode.clicked.connect(self.returnModeSetting) self.returnMode.clicked.connect(self.returnModeSetting)
# other
#other # stretch columns
#stretch columns self.shortcutchanger.horizontalHeader().setSectionResizeMode(
self.shortcutchanger.horizontalHeader().setSectionResizeMode(0, QtWidgets.QHeaderView.ResizeMode.Stretch) 0, QtWidgets.QHeaderView.ResizeMode.Stretch
)
def returnModeSetting(self): def returnModeSetting(self):
currentstate = self.returnMode.isChecked() currentstate = self.returnMode.isChecked()
if self.originalSettings.advanced_refresh != currentstate: if self.originalSettings.advanced_refresh != currentstate:
self.enableButtonBox() self.enableButtonBox()
def populateShortcuts(self): def populateShortcuts(self):
for shortcut in self.shortcuts: for shortcut in self.shortcuts:
name = shortcut["name"] name = shortcut["name"]
default = shortcut["default"] default = shortcut["default"]
current = shortcut["current"] current = shortcut["current"]
self.addShortcut(name, default, current) self.addShortcut(name, default, current)
#assume the shortcuts will be changed # assume the shortcuts will be changed
self.settingschanged = True self.settingschanged = True
def addShortcut(self, name, default, current): def addShortcut(self, name, default, current):
#remove all pages from shortcutchanger # remove all pages from shortcutchanger
#add new page with name, default and current # add new page with name, default and current
self.shortcutchanger.insertRow(0) self.shortcutchanger.insertRow(0)
self.shortcutchanger.setItem(0, 0, QtWidgets.QTableWidgetItem(name)) self.shortcutchanger.setItem(0, 0, QtWidgets.QTableWidgetItem(name))
self.shortcutchanger.setItem(0, 1, QtWidgets.QTableWidgetItem(default)) self.shortcutchanger.setItem(0, 1, QtWidgets.QTableWidgetItem(default))
#add keysequenceedit # add keysequenceedit
keysequenceedit = QtWidgets.QKeySequenceEdit() keysequenceedit = QtWidgets.QKeySequenceEdit()
keysequenceedit.setKeySequence(current) keysequenceedit.setKeySequence(current)
self.shortcutchanger.setCellWidget(0, 2, keysequenceedit) self.shortcutchanger.setCellWidget(0, 2, keysequenceedit)
def selectBackupLocation(self): def selectBackupLocation(self):
backupLocation = QtWidgets.QFileDialog.getExistingDirectory( backupLocation = QtWidgets.QFileDialog.getExistingDirectory(
self, self,
@@ -93,7 +94,7 @@ class Settings(QtWidgets.QDialog, Ui_Dialog):
True True
) )
self.settingschanged = True self.settingschanged = True
def selectDatabasePath(self): def selectDatabasePath(self):
databasePath = QtWidgets.QFileDialog.getExistingDirectory( databasePath = QtWidgets.QFileDialog.getExistingDirectory(
self, "Select Database Path", self.originalSettings.database.path self, "Select Database Path", self.originalSettings.database.path
@@ -107,7 +108,7 @@ class Settings(QtWidgets.QDialog, Ui_Dialog):
) )
self.settingschanged = True self.settingschanged = True
self.restart_required = True self.restart_required = True
def selectDatabaseName(self): def selectDatabaseName(self):
# filepicker with filter to select only .db files if a file is selected, set name to the lineedit and set database_path # filepicker with filter to select only .db files if a file is selected, set name to the lineedit and set database_path
databaseName = QtWidgets.QFileDialog.getOpenFileName( databaseName = QtWidgets.QFileDialog.getOpenFileName(
@@ -125,7 +126,7 @@ class Settings(QtWidgets.QDialog, Ui_Dialog):
) )
self.settingschanged = True self.settingschanged = True
self.restart_required = True self.restart_required = True
def getShortcuts(self): def getShortcuts(self):
shortcuts = [] shortcuts = []
for row in range(self.shortcutchanger.rowCount()): for row in range(self.shortcutchanger.rowCount()):
@@ -140,7 +141,7 @@ class Settings(QtWidgets.QDialog, Ui_Dialog):
} }
) )
return shortcuts return shortcuts
def sortShortcuts(self, shortcuts): def sortShortcuts(self, shortcuts):
short = [] short = []
for shortcut in shortcuts: for shortcut in shortcuts:
@@ -161,16 +162,14 @@ class Settings(QtWidgets.QDialog, Ui_Dialog):
report_path = self.report_path.text() report_path = self.report_path.text()
refresh_state = self.returnMode.isChecked() refresh_state = self.returnMode.isChecked()
shortcuts = self.getShortcuts() shortcuts = self.getShortcuts()
#shortcuts to omegaconf.DictConfig # shortcuts to omegaconf.DictConfig
shortcuts = OmegaConf.create(shortcuts) shortcuts = OmegaConf.create(shortcuts)
signature = self.signature.isChecked()
if database_path != self.originalSettings.database.path : if database_path != self.originalSettings.database.path:
os.makedirs(database_path, exist_ok=True) os.makedirs(database_path, exist_ok=True)
self.restart_required = True self.restart_required = True
# create new Settings # create new Settings
self.changedSettings.institution_name = institution_name self.changedSettings.institution_name = institution_name
self.changedSettings.loan_duration = default_loan_duration self.changedSettings.loan_duration = default_loan_duration
@@ -178,85 +177,85 @@ class Settings(QtWidgets.QDialog, Ui_Dialog):
self.changedSettings.database.path = database_path self.changedSettings.database.path = database_path
self.changedSettings.database.name = database_name self.changedSettings.database.name = database_name
self.changedSettings.delete_inactive_user_duration = delete_inactive_users self.changedSettings.delete_inactive_user_duration = delete_inactive_users
self.changedSettings.report.report_day = report_day self.changedSettings.report.report_day = report_day
self.changedSettings.report.path = report_path self.changedSettings.report.path = report_path
self.changedSettings.report.generate_report = report_generate self.changedSettings.report.generate_report = report_generate
self.changedSettings.report.show_signature = signature
self.changedSettings.advanced_refresh = refresh_state self.changedSettings.advanced_refresh = refresh_state
self.changedSettings.shortcuts = shortcuts self.changedSettings.shortcuts = shortcuts
changed = self.changedSettings
changed = self.changedSettings
original = self.originalSettings original = self.originalSettings
if changed == original: if changed == original:
self.settingschanged = False self.settingschanged = False
self.restart_required = False self.restart_required = False
dbg("Settings not changed") log.info("Settings not changed")
else: else:
self.settingschanged = True self.settingschanged = True
#compare if database or shortcuts were changed # compare if database or shortcuts were changed
database = original.database == changed.database database = original.database == changed.database
shortcuts = self.shortcuts == self.sortShortcuts(changed.shortcuts) shortcuts = self.shortcuts == self.sortShortcuts(changed.shortcuts)
if not database or not shortcuts: if not database or not shortcuts:
self.restart_required = True self.restart_required = True
dbg(f"Settings changed, restart required: {self.restart_required}",database=database,shortcuts=shortcuts) log.info(
f"Settings changed, restart required: {self.restart_required}",
)
# save the new settings # save the new settings
if self.settingschanged: if self.settingschanged:
# save the settings # save the settings
config.updateValue("institution_name", self.changedSettings.institution_name) config.updateValue(
config.updateValue("default_loan_duration", self.changedSettings.loan_duration) "institution_name", self.changedSettings.institution_name
config.updateValue("database.backupLocation", self.changedSettings.database.backupLocation) )
config.updateValue(
"default_loan_duration", self.changedSettings.loan_duration
)
config.updateValue(
"database.backupLocation", self.changedSettings.database.backupLocation
)
config.updateValue("database.path", self.changedSettings.database.path) config.updateValue("database.path", self.changedSettings.database.path)
config.updateValue("database.name", self.changedSettings.database.name) config.updateValue("database.name", self.changedSettings.database.name)
config.updateValue("inactive_user_deletion", self.changedSettings.inactive_user_deletion) config.updateValue(
config.updateValue("report.report_day", self.changedSettings.report.report_day) "inactive_user_deletion", self.changedSettings.inactive_user_deletion
config.updateValue("report.generate_report", self.changedSettings.report.generate_report) )
config.updateValue(
"report.report_day", self.changedSettings.report.report_day
)
config.updateValue(
"report.generate_report", self.changedSettings.report.generate_report
)
config.updateValue("report.path", self.changedSettings.report.path) config.updateValue("report.path", self.changedSettings.report.path)
config.updateValue("advanced_refresh", self.changedSettings.advanced_refresh) config.updateValue(
"advanced_refresh", self.changedSettings.advanced_refresh
)
config.updateValue("shortcuts", self.changedSettings.shortcuts) config.updateValue("shortcuts", self.changedSettings.shortcuts)
config.updateValue(
"report.show_signature", self.changedSettings.report.show_signature
)
self.originalSettings = self.changedSettings self.originalSettings = self.changedSettings
config.save() config.save()
if self.restart_required:
self.restart()
self.close() self.close()
def restart(self):
dialog = QtWidgets.QMessageBox()
dialog.setIcon(QtWidgets.QMessageBox.Icon.Information)
dialog.setText("Neustart erforderlich")
dialog.setInformativeText(
"Das Programm muss neu gestartet werden, um die Änderungen zu übernehmen."
)
dialog.setStandardButtons(QtWidgets.QMessageBox.StandardButton.Ok)
dialog.setDefaultButton(QtWidgets.QMessageBox.StandardButton.Ok)
dialog.setWindowTitle("Neustart erforderlich")
dialog.setWindowIcon(Icon("restart").icon)
dialog.exec()
def DiscardSettings(self): def DiscardSettings(self):
self.loadSettings() self.loadSettings()
self.restart_required = False self.restart_required = False
self.settingschanged = False self.settingschanged = False
def loadSettings(self): def loadSettings(self):
self.institution_name.setText(config.institution_name) self.institution_name.setText(config.institution_name)
self.default_loan_duration.setValue( self.default_loan_duration.setValue(int(config.loan_duration))
int(config.loan_duration)
)
self.delete_inactive_user_duration.setValue( self.delete_inactive_user_duration.setValue(
int(config.delete_inactive_user_duration) int(config.delete_inactive_user_duration)
) )
self.database_backupLocation.setText( self.database_backupLocation.setText(config.database.backupLocation)
config.database.backupLocation
)
self.database_path.setText(config.database.path) self.database_path.setText(config.database.path)
self.database_name.setText(config.database.name) self.database_name.setText(config.database.name)
self.report_day.setCurrentIndex(config.report.report_day) self.report_day.setCurrentIndex(config.report.report_day)
self.check_generate_report.setChecked(config.report.generate_report) self.check_generate_report.setChecked(config.report.generate_report)
self.report_path.setText(config.report.path) self.report_path.setText(config.report.path)
self.returnMode.setChecked(config.advanced_refresh) self.returnMode.setChecked(config.advanced_refresh)
self.signature.setChecked(config.report.show_signature)
pass pass

View File

@@ -17,7 +17,12 @@ class Ui_Dialog(object):
self.verticalLayout.setObjectName("verticalLayout") self.verticalLayout.setObjectName("verticalLayout")
self.horizontalLayout = QtWidgets.QHBoxLayout() self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout") self.horizontalLayout.setObjectName("horizontalLayout")
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum) spacerItem = QtWidgets.QSpacerItem(
40,
20,
QtWidgets.QSizePolicy.Policy.Expanding,
QtWidgets.QSizePolicy.Policy.Minimum,
)
self.horizontalLayout.addItem(spacerItem) self.horizontalLayout.addItem(spacerItem)
self.btn_addNewBook = QtWidgets.QToolButton(parent=Dialog) self.btn_addNewBook = QtWidgets.QToolButton(parent=Dialog)
self.btn_addNewBook.setObjectName("btn_addNewBook") self.btn_addNewBook.setObjectName("btn_addNewBook")
@@ -38,13 +43,16 @@ class Ui_Dialog(object):
self.verticalLayout.addWidget(self.tableWidget) self.verticalLayout.addWidget(self.tableWidget)
self.buttonBox = QtWidgets.QDialogButtonBox(parent=Dialog) self.buttonBox = QtWidgets.QDialogButtonBox(parent=Dialog)
self.buttonBox.setOrientation(QtCore.Qt.Orientation.Horizontal) self.buttonBox.setOrientation(QtCore.Qt.Orientation.Horizontal)
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.StandardButton.Cancel|QtWidgets.QDialogButtonBox.StandardButton.Ok) self.buttonBox.setStandardButtons(
QtWidgets.QDialogButtonBox.StandardButton.Cancel
| QtWidgets.QDialogButtonBox.StandardButton.Ok
)
self.buttonBox.setObjectName("buttonBox") self.buttonBox.setObjectName("buttonBox")
self.verticalLayout.addWidget(self.buttonBox) self.verticalLayout.addWidget(self.buttonBox)
self.retranslateUi(Dialog) self.retranslateUi(Dialog)
self.buttonBox.accepted.connect(Dialog.accept) # type: ignore self.buttonBox.accepted.connect(Dialog.accept) # type: ignore
self.buttonBox.rejected.connect(Dialog.reject) # type: ignore self.buttonBox.rejected.connect(Dialog.reject) # type: ignore
QtCore.QMetaObject.connectSlotsByName(Dialog) QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog): def retranslateUi(self, Dialog):

View File

@@ -37,15 +37,23 @@ class Ui_Dialog(object):
self.gridLayout.addWidget(self.username, 0, 1, 1, 1) self.gridLayout.addWidget(self.username, 0, 1, 1, 1)
self.buttonBox = QtWidgets.QDialogButtonBox(parent=Dialog) self.buttonBox = QtWidgets.QDialogButtonBox(parent=Dialog)
self.buttonBox.setOrientation(QtCore.Qt.Orientation.Horizontal) self.buttonBox.setOrientation(QtCore.Qt.Orientation.Horizontal)
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.StandardButton.Cancel|QtWidgets.QDialogButtonBox.StandardButton.Save) self.buttonBox.setStandardButtons(
QtWidgets.QDialogButtonBox.StandardButton.Cancel
| QtWidgets.QDialogButtonBox.StandardButton.Save
)
self.buttonBox.setObjectName("buttonBox") self.buttonBox.setObjectName("buttonBox")
self.gridLayout.addWidget(self.buttonBox, 4, 1, 1, 1) self.gridLayout.addWidget(self.buttonBox, 4, 1, 1, 1)
spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Expanding) spacerItem = QtWidgets.QSpacerItem(
20,
40,
QtWidgets.QSizePolicy.Policy.Minimum,
QtWidgets.QSizePolicy.Policy.Expanding,
)
self.gridLayout.addItem(spacerItem, 3, 0, 1, 1) self.gridLayout.addItem(spacerItem, 3, 0, 1, 1)
self.retranslateUi(Dialog) self.retranslateUi(Dialog)
self.buttonBox.accepted.connect(Dialog.accept) # type: ignore self.buttonBox.accepted.connect(Dialog.accept) # type: ignore
self.buttonBox.rejected.connect(Dialog.reject) # type: ignore self.buttonBox.rejected.connect(Dialog.reject) # type: ignore
QtCore.QMetaObject.connectSlotsByName(Dialog) QtCore.QMetaObject.connectSlotsByName(Dialog)
Dialog.setTabOrder(self.username, self.userno) Dialog.setTabOrder(self.username, self.userno)
Dialog.setTabOrder(self.userno, self.user_mail) Dialog.setTabOrder(self.userno, self.user_mail)

View File

@@ -21,7 +21,10 @@ class Ui_Dialog(object):
self.gridLayout.addWidget(self.extenduntil, 1, 2, 1, 1) self.gridLayout.addWidget(self.extenduntil, 1, 2, 1, 1)
self.buttonBox = QtWidgets.QDialogButtonBox(parent=Dialog) self.buttonBox = QtWidgets.QDialogButtonBox(parent=Dialog)
self.buttonBox.setOrientation(QtCore.Qt.Orientation.Horizontal) self.buttonBox.setOrientation(QtCore.Qt.Orientation.Horizontal)
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.StandardButton.Cancel|QtWidgets.QDialogButtonBox.StandardButton.Ok) self.buttonBox.setStandardButtons(
QtWidgets.QDialogButtonBox.StandardButton.Cancel
| QtWidgets.QDialogButtonBox.StandardButton.Ok
)
self.buttonBox.setObjectName("buttonBox") self.buttonBox.setObjectName("buttonBox")
self.gridLayout.addWidget(self.buttonBox, 2, 2, 1, 1) self.gridLayout.addWidget(self.buttonBox, 2, 2, 1, 1)
self.label = QtWidgets.QLabel(parent=Dialog) self.label = QtWidgets.QLabel(parent=Dialog)
@@ -33,11 +36,13 @@ class Ui_Dialog(object):
self.gridLayout.addWidget(self.label, 0, 2, 1, 1) self.gridLayout.addWidget(self.label, 0, 2, 1, 1)
self.retranslateUi(Dialog) self.retranslateUi(Dialog)
self.buttonBox.accepted.connect(Dialog.accept) # type: ignore self.buttonBox.accepted.connect(Dialog.accept) # type: ignore
self.buttonBox.rejected.connect(Dialog.reject) # type: ignore self.buttonBox.rejected.connect(Dialog.reject) # type: ignore
QtCore.QMetaObject.connectSlotsByName(Dialog) QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog): def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate _translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Dialog")) Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
self.label.setText(_translate("Dialog", "Bitte das Verlängerungsdatum auswählen")) self.label.setText(
_translate("Dialog", "Bitte das Verlängerungsdatum auswählen")
)

View File

@@ -1,6 +1,6 @@
# Form implementation generated from reading ui file 'c:\Users\aky547\GitHub\LibrarySystem\src\ui\sources\dialog_generateReport.ui' # Form implementation generated from reading ui file 'c:\Users\aky547\GitHub\LibrarySystem\src\ui\sources\dialog_generateReport.ui'
# #
# Created by: PyQt6 UI code generator 6.6.1 # Created by: PyQt6 UI code generator 6.7.1
# #
# WARNING: Any manual changes made to this file will be lost when pyuic6 is # WARNING: Any manual changes made to this file will be lost when pyuic6 is
# run again. Do not edit this file unless you know what you are doing. # run again. Do not edit this file unless you know what you are doing.
@@ -12,6 +12,7 @@ from PyQt6 import QtCore, QtGui, QtWidgets
class Ui_Dialog(object): class Ui_Dialog(object):
def setupUi(self, Dialog): def setupUi(self, Dialog):
Dialog.setObjectName("Dialog") Dialog.setObjectName("Dialog")
Dialog.setWindowModality(QtCore.Qt.WindowModality.NonModal)
Dialog.resize(375, 245) Dialog.resize(375, 245)
Dialog.setMinimumSize(QtCore.QSize(40, 0)) Dialog.setMinimumSize(QtCore.QSize(40, 0))
self.verticalLayout = QtWidgets.QVBoxLayout(Dialog) self.verticalLayout = QtWidgets.QVBoxLayout(Dialog)
@@ -21,9 +22,11 @@ class Ui_Dialog(object):
self.verticalLayout.addWidget(self.label) self.verticalLayout.addWidget(self.label)
self.gridLayout = QtWidgets.QGridLayout() self.gridLayout = QtWidgets.QGridLayout()
self.gridLayout.setObjectName("gridLayout") self.gridLayout.setObjectName("gridLayout")
self.label_2 = QtWidgets.QLabel(parent=Dialog) self.radioButton = QtWidgets.QRadioButton(parent=Dialog)
self.label_2.setObjectName("label_2") self.radioButton.setText("")
self.gridLayout.addWidget(self.label_2, 0, 0, 1, 1) self.radioButton.setCheckable(True)
self.radioButton.setObjectName("radioButton")
self.gridLayout.addWidget(self.radioButton, 4, 2, 1, 1)
self.horizontalLayout = QtWidgets.QHBoxLayout() self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout") self.horizontalLayout.setObjectName("horizontalLayout")
self.radio_week = QtWidgets.QRadioButton(parent=Dialog) self.radio_week = QtWidgets.QRadioButton(parent=Dialog)
@@ -36,6 +39,9 @@ class Ui_Dialog(object):
self.radio_year.setObjectName("radio_year") self.radio_year.setObjectName("radio_year")
self.horizontalLayout.addWidget(self.radio_year) self.horizontalLayout.addWidget(self.radio_year)
self.gridLayout.addLayout(self.horizontalLayout, 1, 1, 1, 1) self.gridLayout.addLayout(self.horizontalLayout, 1, 1, 1, 1)
self.label_3 = QtWidgets.QLabel(parent=Dialog)
self.label_3.setObjectName("label_3")
self.gridLayout.addWidget(self.label_3, 2, 0, 1, 1)
self.dayValue = QtWidgets.QLineEdit(parent=Dialog) self.dayValue = QtWidgets.QLineEdit(parent=Dialog)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Fixed, QtWidgets.QSizePolicy.Policy.Fixed) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Fixed, QtWidgets.QSizePolicy.Policy.Fixed)
sizePolicy.setHorizontalStretch(0) sizePolicy.setHorizontalStretch(0)
@@ -48,15 +54,24 @@ class Ui_Dialog(object):
self.dayValue.setReadOnly(True) self.dayValue.setReadOnly(True)
self.dayValue.setObjectName("dayValue") self.dayValue.setObjectName("dayValue")
self.gridLayout.addWidget(self.dayValue, 0, 2, 1, 1) self.gridLayout.addWidget(self.dayValue, 0, 2, 1, 1)
self.radioButton = QtWidgets.QRadioButton(parent=Dialog)
self.radioButton.setText("")
self.radioButton.setCheckable(True)
self.radioButton.setObjectName("radioButton")
self.gridLayout.addWidget(self.radioButton, 3, 2, 1, 1)
self.reportlink = QtWidgets.QLabel(parent=Dialog) self.reportlink = QtWidgets.QLabel(parent=Dialog)
self.reportlink.setText("") self.reportlink.setText("")
self.reportlink.setObjectName("reportlink") self.reportlink.setObjectName("reportlink")
self.gridLayout.addWidget(self.reportlink, 3, 1, 1, 1) self.gridLayout.addWidget(self.reportlink, 4, 1, 1, 1)
self.frame = QtWidgets.QFrame(parent=Dialog)
self.frame.setFrameShape(QtWidgets.QFrame.Shape.NoFrame)
self.frame.setFrameShadow(QtWidgets.QFrame.Shadow.Plain)
self.frame.setLineWidth(0)
self.frame.setObjectName("frame")
self.gridLayout_2 = QtWidgets.QGridLayout(self.frame)
self.gridLayout_2.setObjectName("gridLayout_2")
self.format_csv = QtWidgets.QRadioButton(parent=self.frame)
self.format_csv.setObjectName("format_csv")
self.gridLayout_2.addWidget(self.format_csv, 0, 1, 1, 1)
self.format_txt = QtWidgets.QRadioButton(parent=self.frame)
self.format_txt.setObjectName("format_txt")
self.gridLayout_2.addWidget(self.format_txt, 0, 0, 1, 1)
self.gridLayout.addWidget(self.frame, 2, 1, 1, 1)
self.dayslider = QtWidgets.QSlider(parent=Dialog) self.dayslider = QtWidgets.QSlider(parent=Dialog)
self.dayslider.setFocusPolicy(QtCore.Qt.FocusPolicy.ClickFocus) self.dayslider.setFocusPolicy(QtCore.Qt.FocusPolicy.ClickFocus)
self.dayslider.setMinimum(1) self.dayslider.setMinimum(1)
@@ -67,23 +82,12 @@ class Ui_Dialog(object):
self.dayslider.setTickInterval(10) self.dayslider.setTickInterval(10)
self.dayslider.setObjectName("dayslider") self.dayslider.setObjectName("dayslider")
self.gridLayout.addWidget(self.dayslider, 0, 1, 1, 1) self.gridLayout.addWidget(self.dayslider, 0, 1, 1, 1)
self.frame = QtWidgets.QFrame(parent=Dialog) self.label_2 = QtWidgets.QLabel(parent=Dialog)
self.frame.setFrameShape(QtWidgets.QFrame.Shape.NoFrame) self.label_2.setObjectName("label_2")
self.frame.setFrameShadow(QtWidgets.QFrame.Shadow.Plain) self.gridLayout.addWidget(self.label_2, 0, 0, 1, 1)
self.frame.setLineWidth(0) self.signature = QtWidgets.QCheckBox(parent=Dialog)
self.frame.setObjectName("frame") self.signature.setObjectName("signature")
self.gridLayout_2 = QtWidgets.QGridLayout(self.frame) self.gridLayout.addWidget(self.signature, 3, 1, 1, 1)
self.gridLayout_2.setObjectName("gridLayout_2")
self.format_txt = QtWidgets.QRadioButton(parent=self.frame)
self.format_txt.setObjectName("format_txt")
self.gridLayout_2.addWidget(self.format_txt, 0, 0, 1, 1)
self.format_csv = QtWidgets.QRadioButton(parent=self.frame)
self.format_csv.setObjectName("format_csv")
self.gridLayout_2.addWidget(self.format_csv, 0, 1, 1, 1)
self.gridLayout.addWidget(self.frame, 2, 1, 1, 1)
self.label_3 = QtWidgets.QLabel(parent=Dialog)
self.label_3.setObjectName("label_3")
self.gridLayout.addWidget(self.label_3, 2, 0, 1, 1)
self.verticalLayout.addLayout(self.gridLayout) self.verticalLayout.addLayout(self.gridLayout)
self.label_4 = QtWidgets.QLabel(parent=Dialog) self.label_4 = QtWidgets.QLabel(parent=Dialog)
self.label_4.setObjectName("label_4") self.label_4.setObjectName("label_4")
@@ -108,12 +112,13 @@ class Ui_Dialog(object):
_translate = QtCore.QCoreApplication.translate _translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Dialog")) Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
self.label.setText(_translate("Dialog", "Wieviele Tage sollen im Bericht erfasst werden?")) self.label.setText(_translate("Dialog", "Wieviele Tage sollen im Bericht erfasst werden?"))
self.label_2.setText(_translate("Dialog", "Tage"))
self.radio_week.setText(_translate("Dialog", "Woche")) self.radio_week.setText(_translate("Dialog", "Woche"))
self.radio_month.setText(_translate("Dialog", "Monat")) self.radio_month.setText(_translate("Dialog", "Monat"))
self.radio_year.setText(_translate("Dialog", "Jahr")) self.radio_year.setText(_translate("Dialog", "Jahr"))
self.format_txt.setText(_translate("Dialog", "Text"))
self.format_csv.setText(_translate("Dialog", "Excel"))
self.label_3.setText(_translate("Dialog", "Dateiformat")) self.label_3.setText(_translate("Dialog", "Dateiformat"))
self.format_csv.setText(_translate("Dialog", "Excel"))
self.format_txt.setText(_translate("Dialog", "Text"))
self.label_2.setText(_translate("Dialog", "Tage"))
self.signature.setText(_translate("Dialog", "Signatur anzeigen"))
self.label_4.setText(_translate("Dialog", "Fortschritt:")) self.label_4.setText(_translate("Dialog", "Fortschritt:"))
self.generateReport.setText(_translate("Dialog", " Bericht erstellen")) self.generateReport.setText(_translate("Dialog", " Bericht erstellen"))

View File

@@ -20,13 +20,16 @@ class Ui_Dialog(object):
self.horizontalLayout.addWidget(self.textEdit) self.horizontalLayout.addWidget(self.textEdit)
self.buttonBox = QtWidgets.QDialogButtonBox(parent=Dialog) self.buttonBox = QtWidgets.QDialogButtonBox(parent=Dialog)
self.buttonBox.setOrientation(QtCore.Qt.Orientation.Vertical) self.buttonBox.setOrientation(QtCore.Qt.Orientation.Vertical)
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.StandardButton.Cancel|QtWidgets.QDialogButtonBox.StandardButton.Ok) self.buttonBox.setStandardButtons(
QtWidgets.QDialogButtonBox.StandardButton.Cancel
| QtWidgets.QDialogButtonBox.StandardButton.Ok
)
self.buttonBox.setObjectName("buttonBox") self.buttonBox.setObjectName("buttonBox")
self.horizontalLayout.addWidget(self.buttonBox) self.horizontalLayout.addWidget(self.buttonBox)
self.retranslateUi(Dialog) self.retranslateUi(Dialog)
self.buttonBox.accepted.connect(Dialog.accept) # type: ignore self.buttonBox.accepted.connect(Dialog.accept) # type: ignore
self.buttonBox.rejected.connect(Dialog.reject) # type: ignore self.buttonBox.rejected.connect(Dialog.reject) # type: ignore
QtCore.QMetaObject.connectSlotsByName(Dialog) QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog): def retranslateUi(self, Dialog):

View File

@@ -19,8 +19,12 @@ class Ui_Dialog(object):
self.label.setObjectName("label") self.label.setObjectName("label")
self.verticalLayout.addWidget(self.label) self.verticalLayout.addWidget(self.label)
self.tableWidget = QtWidgets.QTableWidget(parent=Dialog) self.tableWidget = QtWidgets.QTableWidget(parent=Dialog)
self.tableWidget.setEditTriggers(QtWidgets.QAbstractItemView.EditTrigger.NoEditTriggers) self.tableWidget.setEditTriggers(
self.tableWidget.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectionBehavior.SelectRows) QtWidgets.QAbstractItemView.EditTrigger.NoEditTriggers
)
self.tableWidget.setSelectionBehavior(
QtWidgets.QAbstractItemView.SelectionBehavior.SelectRows
)
self.tableWidget.setObjectName("tableWidget") self.tableWidget.setObjectName("tableWidget")
self.tableWidget.setColumnCount(3) self.tableWidget.setColumnCount(3)
self.tableWidget.setRowCount(0) self.tableWidget.setRowCount(0)
@@ -33,19 +37,27 @@ class Ui_Dialog(object):
self.verticalLayout.addWidget(self.tableWidget) self.verticalLayout.addWidget(self.tableWidget)
self.buttonBox = QtWidgets.QDialogButtonBox(parent=Dialog) self.buttonBox = QtWidgets.QDialogButtonBox(parent=Dialog)
self.buttonBox.setOrientation(QtCore.Qt.Orientation.Horizontal) self.buttonBox.setOrientation(QtCore.Qt.Orientation.Horizontal)
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.StandardButton.Cancel|QtWidgets.QDialogButtonBox.StandardButton.Ok) self.buttonBox.setStandardButtons(
QtWidgets.QDialogButtonBox.StandardButton.Cancel
| QtWidgets.QDialogButtonBox.StandardButton.Ok
)
self.buttonBox.setObjectName("buttonBox") self.buttonBox.setObjectName("buttonBox")
self.verticalLayout.addWidget(self.buttonBox) self.verticalLayout.addWidget(self.buttonBox)
self.retranslateUi(Dialog) self.retranslateUi(Dialog)
self.buttonBox.accepted.connect(Dialog.accept) # type: ignore self.buttonBox.accepted.connect(Dialog.accept) # type: ignore
self.buttonBox.rejected.connect(Dialog.reject) # type: ignore self.buttonBox.rejected.connect(Dialog.reject) # type: ignore
QtCore.QMetaObject.connectSlotsByName(Dialog) QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog): def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate _translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Dialog")) Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
self.label.setText(_translate("Dialog", "Es wurden mehrere passende Personen gefunden. Bitte die richtige Person auswählen.")) self.label.setText(
_translate(
"Dialog",
"Es wurden mehrere passende Personen gefunden. Bitte die richtige Person auswählen.",
)
)
item = self.tableWidget.horizontalHeaderItem(0) item = self.tableWidget.horizontalHeaderItem(0)
item.setText(_translate("Dialog", "Matrikelnr.")) item.setText(_translate("Dialog", "Matrikelnr."))
item = self.tableWidget.horizontalHeaderItem(1) item = self.tableWidget.horizontalHeaderItem(1)

View File

@@ -1,6 +1,6 @@
# Form implementation generated from reading ui file 'c:\Users\aky547\GitHub\LibrarySystem\src\ui\sources\dialog_settings.ui' # Form implementation generated from reading ui file 'c:\Users\aky547\GitHub\LibrarySystem\src\ui\sources\dialog_settings.ui'
# #
# Created by: PyQt6 UI code generator 6.6.1 # Created by: PyQt6 UI code generator 6.7.1
# #
# WARNING: Any manual changes made to this file will be lost when pyuic6 is # WARNING: Any manual changes made to this file will be lost when pyuic6 is
# run again. Do not edit this file unless you know what you are doing. # run again. Do not edit this file unless you know what you are doing.
@@ -92,25 +92,22 @@ class Ui_Dialog(object):
self.formLayout.setWidget(6, QtWidgets.QFormLayout.ItemRole.LabelRole, self.label_9) self.formLayout.setWidget(6, QtWidgets.QFormLayout.ItemRole.LabelRole, self.label_9)
self.gridLayout = QtWidgets.QGridLayout() self.gridLayout = QtWidgets.QGridLayout()
self.gridLayout.setObjectName("gridLayout") self.gridLayout.setObjectName("gridLayout")
self.btn_select_report_path = QtWidgets.QToolButton(parent=Dialog) self.label_8 = QtWidgets.QLabel(parent=Dialog)
self.btn_select_report_path.setObjectName("btn_select_report_path") self.label_8.setObjectName("label_8")
self.gridLayout.addWidget(self.btn_select_report_path, 2, 2, 1, 1) self.gridLayout.addWidget(self.label_8, 3, 0, 1, 1)
self.label_10 = QtWidgets.QLabel(parent=Dialog) self.label_11 = QtWidgets.QLabel(parent=Dialog)
self.label_10.setText("") self.label_11.setObjectName("label_11")
self.label_10.setObjectName("label_10") self.gridLayout.addWidget(self.label_11, 0, 0, 1, 1)
self.gridLayout.addWidget(self.label_10, 1, 0, 1, 1)
self.check_generate_report = QtWidgets.QCheckBox(parent=Dialog) self.check_generate_report = QtWidgets.QCheckBox(parent=Dialog)
self.check_generate_report.setObjectName("check_generate_report") self.check_generate_report.setObjectName("check_generate_report")
self.gridLayout.addWidget(self.check_generate_report, 1, 1, 1, 1) self.gridLayout.addWidget(self.check_generate_report, 1, 1, 1, 1)
self.report_path = QtWidgets.QLineEdit(parent=Dialog) self.report_path = QtWidgets.QLineEdit(parent=Dialog)
self.report_path.setObjectName("report_path") self.report_path.setObjectName("report_path")
self.gridLayout.addWidget(self.report_path, 2, 1, 1, 1) self.gridLayout.addWidget(self.report_path, 3, 1, 1, 1)
self.label_8 = QtWidgets.QLabel(parent=Dialog) self.label_10 = QtWidgets.QLabel(parent=Dialog)
self.label_8.setObjectName("label_8") self.label_10.setText("")
self.gridLayout.addWidget(self.label_8, 2, 0, 1, 1) self.label_10.setObjectName("label_10")
self.label_11 = QtWidgets.QLabel(parent=Dialog) self.gridLayout.addWidget(self.label_10, 1, 0, 1, 1)
self.label_11.setObjectName("label_11")
self.gridLayout.addWidget(self.label_11, 0, 0, 1, 1)
self.report_day = QtWidgets.QComboBox(parent=Dialog) self.report_day = QtWidgets.QComboBox(parent=Dialog)
self.report_day.setObjectName("report_day") self.report_day.setObjectName("report_day")
self.report_day.addItem("") self.report_day.addItem("")
@@ -119,6 +116,12 @@ class Ui_Dialog(object):
self.report_day.addItem("") self.report_day.addItem("")
self.report_day.addItem("") self.report_day.addItem("")
self.gridLayout.addWidget(self.report_day, 0, 1, 1, 1) self.gridLayout.addWidget(self.report_day, 0, 1, 1, 1)
self.btn_select_report_path = QtWidgets.QToolButton(parent=Dialog)
self.btn_select_report_path.setObjectName("btn_select_report_path")
self.gridLayout.addWidget(self.btn_select_report_path, 3, 2, 1, 1)
self.signature = QtWidgets.QCheckBox(parent=Dialog)
self.signature.setObjectName("signature")
self.gridLayout.addWidget(self.signature, 2, 1, 1, 1)
self.formLayout.setLayout(6, QtWidgets.QFormLayout.ItemRole.FieldRole, self.gridLayout) self.formLayout.setLayout(6, QtWidgets.QFormLayout.ItemRole.FieldRole, self.gridLayout)
self.buttonBox = QtWidgets.QDialogButtonBox(parent=Dialog) self.buttonBox = QtWidgets.QDialogButtonBox(parent=Dialog)
self.buttonBox.setOrientation(QtCore.Qt.Orientation.Horizontal) self.buttonBox.setOrientation(QtCore.Qt.Orientation.Horizontal)
@@ -162,7 +165,7 @@ class Ui_Dialog(object):
Dialog.setWindowTitle(_translate("Dialog", "Dialog")) Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
self.label.setText(_translate("Dialog", "Name der Einrichtung")) self.label.setText(_translate("Dialog", "Name der Einrichtung"))
self.label_2.setText(_translate("Dialog", "Leihdauer")) self.label_2.setText(_translate("Dialog", "Leihdauer"))
self.label_13.setText(_translate("Dialog", "Tage(n)")) self.label_13.setText(_translate("Dialog", "Tage"))
self.label_7.setText(_translate("Dialog", "Inaktive Nutzer\n" self.label_7.setText(_translate("Dialog", "Inaktive Nutzer\n"
"Löschen nach")) "Löschen nach"))
self.label_12.setText(_translate("Dialog", "Tage(n)")) self.label_12.setText(_translate("Dialog", "Tage(n)"))
@@ -176,15 +179,16 @@ class Ui_Dialog(object):
self.btn_select_database_name.setText(_translate("Dialog", "...")) self.btn_select_database_name.setText(_translate("Dialog", "..."))
self.btn_select_database_backupLocation.setText(_translate("Dialog", "...")) self.btn_select_database_backupLocation.setText(_translate("Dialog", "..."))
self.label_9.setText(_translate("Dialog", "Bericht")) self.label_9.setText(_translate("Dialog", "Bericht"))
self.btn_select_report_path.setText(_translate("Dialog", "..."))
self.check_generate_report.setText(_translate("Dialog", "Bericht erstellen"))
self.label_8.setText(_translate("Dialog", "Speicherpfad")) self.label_8.setText(_translate("Dialog", "Speicherpfad"))
self.label_11.setText(_translate("Dialog", "Tag")) self.label_11.setText(_translate("Dialog", "Tag"))
self.check_generate_report.setText(_translate("Dialog", "Bericht erstellen"))
self.report_day.setItemText(0, _translate("Dialog", "Montag")) self.report_day.setItemText(0, _translate("Dialog", "Montag"))
self.report_day.setItemText(1, _translate("Dialog", "Dienstag")) self.report_day.setItemText(1, _translate("Dialog", "Dienstag"))
self.report_day.setItemText(2, _translate("Dialog", "Mittwoch")) self.report_day.setItemText(2, _translate("Dialog", "Mittwoch"))
self.report_day.setItemText(3, _translate("Dialog", "Donnerstag")) self.report_day.setItemText(3, _translate("Dialog", "Donnerstag"))
self.report_day.setItemText(4, _translate("Dialog", "Freitag")) self.report_day.setItemText(4, _translate("Dialog", "Freitag"))
self.btn_select_report_path.setText(_translate("Dialog", "..."))
self.signature.setText(_translate("Dialog", "Signatur anzeigen"))
item = self.shortcutchanger.horizontalHeaderItem(0) item = self.shortcutchanger.horizontalHeaderItem(0)
item.setText(_translate("Dialog", "Name")) item.setText(_translate("Dialog", "Name"))
item = self.shortcutchanger.horizontalHeaderItem(1) item = self.shortcutchanger.horizontalHeaderItem(1)

View File

@@ -1,6 +1,6 @@
# Form implementation generated from reading ui file 'c:\Users\aky547\GitHub\LibrarySystem\src\ui\sources\main_Loans.ui' # Form implementation generated from reading ui file 'c:\Users\aky547\GitHub\LibrarySystem\src\ui\sources\main_Loans.ui'
# #
# Created by: PyQt6 UI code generator 6.6.1 # Created by: PyQt6 UI code generator 6.7.1
# #
# WARNING: Any manual changes made to this file will be lost when pyuic6 is # WARNING: Any manual changes made to this file will be lost when pyuic6 is
# run again. Do not edit this file unless you know what you are doing. # run again. Do not edit this file unless you know what you are doing.
@@ -67,16 +67,8 @@ class Ui_MainWindow(object):
self.loanTable.setHorizontalHeaderItem(6, item) self.loanTable.setHorizontalHeaderItem(6, item)
self.verticalLayout.addWidget(self.loanTable) self.verticalLayout.addWidget(self.loanTable)
MainWindow.setCentralWidget(self.centralwidget) MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(parent=MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 899, 22))
self.menubar.setObjectName("menubar")
self.menuDatei = QtWidgets.QMenu(parent=self.menubar)
self.menuDatei.setObjectName("menuDatei")
MainWindow.setMenuBar(self.menubar)
self.actionBeenden = QtGui.QAction(parent=MainWindow) self.actionBeenden = QtGui.QAction(parent=MainWindow)
self.actionBeenden.setObjectName("actionBeenden") self.actionBeenden.setObjectName("actionBeenden")
self.menuDatei.addAction(self.actionBeenden)
self.menubar.addAction(self.menuDatei.menuAction())
self.retranslateUi(MainWindow) self.retranslateUi(MainWindow)
self.actionBeenden.triggered.connect(MainWindow.close) # type: ignore self.actionBeenden.triggered.connect(MainWindow.close) # type: ignore
@@ -105,6 +97,5 @@ class Ui_MainWindow(object):
item.setText(_translate("MainWindow", "entliehen bis")) item.setText(_translate("MainWindow", "entliehen bis"))
item = self.loanTable.horizontalHeaderItem(6) item = self.loanTable.horizontalHeaderItem(6)
item.setText(_translate("MainWindow", "Zurückgegeben am")) item.setText(_translate("MainWindow", "Zurückgegeben am"))
self.menuDatei.setTitle(_translate("MainWindow", "Datei"))
self.actionBeenden.setText(_translate("MainWindow", "Beenden")) self.actionBeenden.setText(_translate("MainWindow", "Beenden"))
self.actionBeenden.setShortcut(_translate("MainWindow", "Q")) self.actionBeenden.setShortcut(_translate("MainWindow", "Q"))

View File

@@ -19,6 +19,38 @@ class Ui_MainWindow(object):
self.verticalLayout.setObjectName("verticalLayout") self.verticalLayout.setObjectName("verticalLayout")
self.gridLayout = QtWidgets.QGridLayout() self.gridLayout = QtWidgets.QGridLayout()
self.gridLayout.setObjectName("gridLayout") self.gridLayout.setObjectName("gridLayout")
self.label_2 = QtWidgets.QLabel(parent=self.centralwidget)
self.label_2.setObjectName("label_2")
self.gridLayout.addWidget(self.label_2, 2, 0, 1, 1)
self.input_username = QtWidgets.QLineEdit(parent=self.centralwidget)
self.input_username.setObjectName("input_username")
self.gridLayout.addWidget(self.input_username, 2, 1, 1, 1)
self.input_userno = QtWidgets.QLineEdit(parent=self.centralwidget)
self.input_userno.setObjectName("input_userno")
self.gridLayout.addWidget(self.input_userno, 1, 1, 1, 1)
self.label = QtWidgets.QLabel(parent=self.centralwidget)
self.label.setObjectName("label")
self.gridLayout.addWidget(self.label, 1, 0, 1, 1)
self.input_file_ident = QtWidgets.QLineEdit(parent=self.centralwidget)
self.input_file_ident.setObjectName("input_file_ident")
self.gridLayout.addWidget(self.input_file_ident, 3, 1, 1, 1)
self.label_6 = QtWidgets.QLabel(parent=self.centralwidget)
self.label_6.setAlignment(QtCore.Qt.AlignmentFlag.AlignLeading|QtCore.Qt.AlignmentFlag.AlignLeft|QtCore.Qt.AlignmentFlag.AlignVCenter)
self.label_6.setObjectName("label_6")
self.gridLayout.addWidget(self.label_6, 5, 0, 1, 1)
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.label_5 = QtWidgets.QLabel(parent=self.centralwidget)
font = QtGui.QFont()
font.setPointSize(14)
font.setBold(True)
self.label_5.setFont(font)
self.label_5.setObjectName("label_5")
self.horizontalLayout.addWidget(self.label_5)
self.mode = QtWidgets.QPushButton(parent=self.centralwidget)
self.mode.setObjectName("mode")
self.horizontalLayout.addWidget(self.mode)
self.gridLayout.addLayout(self.horizontalLayout, 0, 0, 1, 1)
self.horizontalLayout_4 = QtWidgets.QHBoxLayout() self.horizontalLayout_4 = QtWidgets.QHBoxLayout()
self.horizontalLayout_4.setObjectName("horizontalLayout_4") self.horizontalLayout_4.setObjectName("horizontalLayout_4")
self.duedate = QtWidgets.QDateEdit(parent=self.centralwidget) self.duedate = QtWidgets.QDateEdit(parent=self.centralwidget)
@@ -38,32 +70,6 @@ class Ui_MainWindow(object):
self.label_3 = QtWidgets.QLabel(parent=self.centralwidget) self.label_3 = QtWidgets.QLabel(parent=self.centralwidget)
self.label_3.setObjectName("label_3") self.label_3.setObjectName("label_3")
self.gridLayout.addWidget(self.label_3, 3, 0, 1, 1) self.gridLayout.addWidget(self.label_3, 3, 0, 1, 1)
self.label_6 = QtWidgets.QLabel(parent=self.centralwidget)
self.label_6.setAlignment(QtCore.Qt.AlignmentFlag.AlignLeading|QtCore.Qt.AlignmentFlag.AlignLeft|QtCore.Qt.AlignmentFlag.AlignVCenter)
self.label_6.setObjectName("label_6")
self.gridLayout.addWidget(self.label_6, 5, 0, 1, 1)
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.label_5 = QtWidgets.QLabel(parent=self.centralwidget)
font = QtGui.QFont()
font.setPointSize(14)
font.setBold(True)
self.label_5.setFont(font)
self.label_5.setObjectName("label_5")
self.horizontalLayout.addWidget(self.label_5)
self.mode = QtWidgets.QPushButton(parent=self.centralwidget)
self.mode.setObjectName("mode")
self.horizontalLayout.addWidget(self.mode)
self.gridLayout.addLayout(self.horizontalLayout, 0, 0, 1, 1)
self.label = QtWidgets.QLabel(parent=self.centralwidget)
self.label.setObjectName("label")
self.gridLayout.addWidget(self.label, 1, 0, 1, 1)
self.input_username = QtWidgets.QLineEdit(parent=self.centralwidget)
self.input_username.setObjectName("input_username")
self.gridLayout.addWidget(self.input_username, 2, 1, 1, 1)
self.input_file_ident = QtWidgets.QLineEdit(parent=self.centralwidget)
self.input_file_ident.setObjectName("input_file_ident")
self.gridLayout.addWidget(self.input_file_ident, 3, 1, 1, 1)
self.horizontalLayout_3 = QtWidgets.QHBoxLayout() self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
self.horizontalLayout_3.setObjectName("horizontalLayout_3") self.horizontalLayout_3.setObjectName("horizontalLayout_3")
spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum) spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
@@ -72,12 +78,10 @@ class Ui_MainWindow(object):
self.btn_createNewUser.setObjectName("btn_createNewUser") self.btn_createNewUser.setObjectName("btn_createNewUser")
self.horizontalLayout_3.addWidget(self.btn_createNewUser) self.horizontalLayout_3.addWidget(self.btn_createNewUser)
self.gridLayout.addLayout(self.horizontalLayout_3, 0, 1, 1, 1) self.gridLayout.addLayout(self.horizontalLayout_3, 0, 1, 1, 1)
self.label_2 = QtWidgets.QLabel(parent=self.centralwidget) self.addBook = QtWidgets.QToolButton(parent=self.centralwidget)
self.label_2.setObjectName("label_2") self.addBook.setText("")
self.gridLayout.addWidget(self.label_2, 2, 0, 1, 1) self.addBook.setObjectName("addBook")
self.input_userno = QtWidgets.QLineEdit(parent=self.centralwidget) self.gridLayout.addWidget(self.addBook, 3, 2, 1, 1)
self.input_userno.setObjectName("input_userno")
self.gridLayout.addWidget(self.input_userno, 1, 1, 1, 1)
self.verticalLayout.addLayout(self.gridLayout) self.verticalLayout.addLayout(self.gridLayout)
self.groupBox = QtWidgets.QGroupBox(parent=self.centralwidget) self.groupBox = QtWidgets.QGroupBox(parent=self.centralwidget)
self.groupBox.setFocusPolicy(QtCore.Qt.FocusPolicy.NoFocus) self.groupBox.setFocusPolicy(QtCore.Qt.FocusPolicy.NoFocus)
@@ -143,7 +147,7 @@ class Ui_MainWindow(object):
self.menuFenster = QtWidgets.QMenu(parent=self.menubar) self.menuFenster = QtWidgets.QMenu(parent=self.menubar)
self.menuFenster.setObjectName("menuFenster") self.menuFenster.setObjectName("menuFenster")
self.menuHilfe = QtWidgets.QMenu(parent=self.menubar) self.menuHilfe = QtWidgets.QMenu(parent=self.menubar)
self.menuHilfe.setGeometry(QtCore.QRect(2484, 209, 181, 94)) self.menuHilfe.setGeometry(QtCore.QRect(2347, 134, 181, 94))
self.menuHilfe.setObjectName("menuHilfe") self.menuHilfe.setObjectName("menuHilfe")
MainWindow.setMenuBar(self.menubar) MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(parent=MainWindow) self.statusbar = QtWidgets.QStatusBar(parent=MainWindow)
@@ -188,13 +192,13 @@ class Ui_MainWindow(object):
def retranslateUi(self, MainWindow): def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate _translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.label_3.setText(_translate("MainWindow", "Signatur")) self.label_2.setText(_translate("MainWindow", "Benutzername"))
self.label.setText(_translate("MainWindow", "Matrikelnummer"))
self.label_6.setText(_translate("MainWindow", "Ausleihe bis")) self.label_6.setText(_translate("MainWindow", "Ausleihe bis"))
self.label_5.setText(_translate("MainWindow", "Modus")) self.label_5.setText(_translate("MainWindow", "Modus"))
self.mode.setText(_translate("MainWindow", "Rückgabe")) self.mode.setText(_translate("MainWindow", "Rückgabe"))
self.label.setText(_translate("MainWindow", "Matrikelnummer")) self.label_3.setText(_translate("MainWindow", "Signatur"))
self.btn_createNewUser.setText(_translate("MainWindow", "Neuen Nutzer anlegen")) self.btn_createNewUser.setText(_translate("MainWindow", "Neuen Nutzer anlegen"))
self.label_2.setText(_translate("MainWindow", "Benutzername"))
self.groupBox.setTitle(_translate("MainWindow", "Nutzerdaten")) self.groupBox.setTitle(_translate("MainWindow", "Nutzerdaten"))
self.groupBox_2.setTitle(_translate("MainWindow", "Ausleihdaten")) self.groupBox_2.setTitle(_translate("MainWindow", "Ausleihdaten"))
self.label_4.setText(_translate("MainWindow", "Anzahl Ausleihen")) self.label_4.setText(_translate("MainWindow", "Anzahl Ausleihen"))
@@ -210,7 +214,9 @@ class Ui_MainWindow(object):
self.menuFenster.setTitle(_translate("MainWindow", "Fenster")) self.menuFenster.setTitle(_translate("MainWindow", "Fenster"))
self.menuHilfe.setTitle(_translate("MainWindow", "Hilfe")) self.menuHilfe.setTitle(_translate("MainWindow", "Hilfe"))
self.actionEinstellungen.setText(_translate("MainWindow", "Einstellungen")) self.actionEinstellungen.setText(_translate("MainWindow", "Einstellungen"))
self.actionEinstellungen.setShortcut(_translate("MainWindow", "Alt+S"))
self.actionBeenden.setText(_translate("MainWindow", "Beenden")) self.actionBeenden.setText(_translate("MainWindow", "Beenden"))
self.actionBeenden.setShortcut(_translate("MainWindow", "Alt+Q"))
self.actionRueckgabemodus.setText(_translate("MainWindow", "Rückgabemodus")) self.actionRueckgabemodus.setText(_translate("MainWindow", "Rückgabemodus"))
self.actionRueckgabemodus.setShortcut(_translate("MainWindow", "F5")) self.actionRueckgabemodus.setShortcut(_translate("MainWindow", "F5"))
self.actionNutzer.setText(_translate("MainWindow", "Nutzer")) self.actionNutzer.setText(_translate("MainWindow", "Nutzer"))

View File

@@ -26,7 +26,12 @@ class Ui_MainWindow(object):
self.frame.setObjectName("frame") self.frame.setObjectName("frame")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.frame) self.horizontalLayout = QtWidgets.QHBoxLayout(self.frame)
self.horizontalLayout.setObjectName("horizontalLayout") self.horizontalLayout.setObjectName("horizontalLayout")
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum) spacerItem = QtWidgets.QSpacerItem(
40,
20,
QtWidgets.QSizePolicy.Policy.Expanding,
QtWidgets.QSizePolicy.Policy.Minimum,
)
self.horizontalLayout.addItem(spacerItem) self.horizontalLayout.addItem(spacerItem)
self.btn_userChange_save = QtWidgets.QPushButton(parent=self.frame) self.btn_userChange_save = QtWidgets.QPushButton(parent=self.frame)
self.btn_userChange_save.setStatusTip("") self.btn_userChange_save.setStatusTip("")
@@ -35,7 +40,12 @@ class Ui_MainWindow(object):
self.btn_userchange_cancel = QtWidgets.QPushButton(parent=self.frame) self.btn_userchange_cancel = QtWidgets.QPushButton(parent=self.frame)
self.btn_userchange_cancel.setObjectName("btn_userchange_cancel") self.btn_userchange_cancel.setObjectName("btn_userchange_cancel")
self.horizontalLayout.addWidget(self.btn_userchange_cancel) self.horizontalLayout.addWidget(self.btn_userchange_cancel)
spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum) spacerItem1 = QtWidgets.QSpacerItem(
40,
20,
QtWidgets.QSizePolicy.Policy.Expanding,
QtWidgets.QSizePolicy.Policy.Minimum,
)
self.horizontalLayout.addItem(spacerItem1) self.horizontalLayout.addItem(spacerItem1)
self.gridLayout.addWidget(self.frame, 3, 1, 1, 1) self.gridLayout.addWidget(self.frame, 3, 1, 1, 1)
self.label = QtWidgets.QLabel(parent=self.centralwidget) self.label = QtWidgets.QLabel(parent=self.centralwidget)
@@ -94,7 +104,12 @@ class Ui_MainWindow(object):
self.radio_overdueLoans = QtWidgets.QRadioButton(parent=self.centralwidget) self.radio_overdueLoans = QtWidgets.QRadioButton(parent=self.centralwidget)
self.radio_overdueLoans.setObjectName("radio_overdueLoans") self.radio_overdueLoans.setObjectName("radio_overdueLoans")
self.horizontalLayout_2.addWidget(self.radio_overdueLoans) self.horizontalLayout_2.addWidget(self.radio_overdueLoans)
spacerItem2 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum) spacerItem2 = QtWidgets.QSpacerItem(
40,
20,
QtWidgets.QSizePolicy.Policy.Expanding,
QtWidgets.QSizePolicy.Policy.Minimum,
)
self.horizontalLayout_2.addItem(spacerItem2) self.horizontalLayout_2.addItem(spacerItem2)
self.verticalLayout.addLayout(self.horizontalLayout_2) self.verticalLayout.addLayout(self.horizontalLayout_2)
self.horizontalLayout_3 = QtWidgets.QHBoxLayout() self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
@@ -107,7 +122,12 @@ class Ui_MainWindow(object):
self.searchfilter.addItem("") self.searchfilter.addItem("")
self.searchfilter.addItem("") self.searchfilter.addItem("")
self.horizontalLayout_3.addWidget(self.searchfilter) self.horizontalLayout_3.addWidget(self.searchfilter)
spacerItem3 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum) spacerItem3 = QtWidgets.QSpacerItem(
40,
20,
QtWidgets.QSizePolicy.Policy.Expanding,
QtWidgets.QSizePolicy.Policy.Minimum,
)
self.horizontalLayout_3.addItem(spacerItem3) self.horizontalLayout_3.addItem(spacerItem3)
self.btn_extendSelectedMedia = QtWidgets.QPushButton(parent=self.centralwidget) self.btn_extendSelectedMedia = QtWidgets.QPushButton(parent=self.centralwidget)
self.btn_extendSelectedMedia.setEnabled(False) self.btn_extendSelectedMedia.setEnabled(False)
@@ -117,10 +137,16 @@ class Ui_MainWindow(object):
self.UserMediaTable = QtWidgets.QTableWidget(parent=self.centralwidget) self.UserMediaTable = QtWidgets.QTableWidget(parent=self.centralwidget)
self.UserMediaTable.setMouseTracking(True) self.UserMediaTable.setMouseTracking(True)
self.UserMediaTable.setFocusPolicy(QtCore.Qt.FocusPolicy.NoFocus) self.UserMediaTable.setFocusPolicy(QtCore.Qt.FocusPolicy.NoFocus)
self.UserMediaTable.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarPolicy.ScrollBarAlwaysOff) self.UserMediaTable.setHorizontalScrollBarPolicy(
self.UserMediaTable.setEditTriggers(QtWidgets.QAbstractItemView.EditTrigger.NoEditTriggers) QtCore.Qt.ScrollBarPolicy.ScrollBarAlwaysOff
)
self.UserMediaTable.setEditTriggers(
QtWidgets.QAbstractItemView.EditTrigger.NoEditTriggers
)
self.UserMediaTable.setAlternatingRowColors(True) self.UserMediaTable.setAlternatingRowColors(True)
self.UserMediaTable.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectionBehavior.SelectRows) self.UserMediaTable.setSelectionBehavior(
QtWidgets.QAbstractItemView.SelectionBehavior.SelectRows
)
self.UserMediaTable.setObjectName("UserMediaTable") self.UserMediaTable.setObjectName("UserMediaTable")
self.UserMediaTable.setColumnCount(6) self.UserMediaTable.setColumnCount(6)
self.UserMediaTable.setRowCount(0) self.UserMediaTable.setRowCount(0)
@@ -177,11 +203,15 @@ class Ui_MainWindow(object):
self.label_5.setText(_translate("MainWindow", "Nutzer Löschen")) self.label_5.setText(_translate("MainWindow", "Nutzer Löschen"))
self.label_4.setText(_translate("MainWindow", "Medien")) self.label_4.setText(_translate("MainWindow", "Medien"))
self.radio_allLoanedMedia.setText(_translate("MainWindow", "Alle Ausleihen")) self.radio_allLoanedMedia.setText(_translate("MainWindow", "Alle Ausleihen"))
self.radio_currentlyLoaned.setText(_translate("MainWindow", "Aktuell entliehen")) self.radio_currentlyLoaned.setText(
_translate("MainWindow", "Aktuell entliehen")
)
self.radio_overdueLoans.setText(_translate("MainWindow", "Überzogen")) self.radio_overdueLoans.setText(_translate("MainWindow", "Überzogen"))
self.searchfilter.setItemText(0, _translate("MainWindow", "Titel")) self.searchfilter.setItemText(0, _translate("MainWindow", "Titel"))
self.searchfilter.setItemText(1, _translate("MainWindow", "Signatur")) self.searchfilter.setItemText(1, _translate("MainWindow", "Signatur"))
self.btn_extendSelectedMedia.setText(_translate("MainWindow", "Ausgewählte Verlängern")) self.btn_extendSelectedMedia.setText(
_translate("MainWindow", "Ausgewählte Verlängern")
)
self.UserMediaTable.setSortingEnabled(True) self.UserMediaTable.setSortingEnabled(True)
item = self.UserMediaTable.horizontalHeaderItem(0) item = self.UserMediaTable.horizontalHeaderItem(0)
item.setText(_translate("MainWindow", "ISBN")) item.setText(_translate("MainWindow", "ISBN"))

View File

@@ -2,6 +2,9 @@
<ui version="4.0"> <ui version="4.0">
<class>Dialog</class> <class>Dialog</class>
<widget class="QDialog" name="Dialog"> <widget class="QDialog" name="Dialog">
<property name="windowModality">
<enum>Qt::NonModal</enum>
</property>
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>

View File

@@ -0,0 +1,54 @@
# Form implementation generated from reading ui file '/home/alexander/GitHub/LibrarySystem/src/ui/sources/dialog_addBook.ui'
#
# Created by: PyQt6 UI code generator 6.7.1
#
# WARNING: Any manual changes made to this file will be lost when pyuic6 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt6 import QtCore, QtGui, QtWidgets
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(262, 100)
self.gridLayout = QtWidgets.QGridLayout(Dialog)
self.gridLayout.setObjectName("gridLayout")
self.book_signature = QtWidgets.QLineEdit(parent=Dialog)
self.book_signature.setObjectName("book_signature")
self.gridLayout.addWidget(self.book_signature, 1, 1, 1, 1)
self.label_2 = QtWidgets.QLabel(parent=Dialog)
self.label_2.setObjectName("label_2")
self.gridLayout.addWidget(self.label_2, 1, 0, 1, 1)
self.label = QtWidgets.QLabel(parent=Dialog)
self.label.setObjectName("label")
self.gridLayout.addWidget(self.label, 0, 0, 1, 1)
self.book_title = QtWidgets.QLineEdit(parent=Dialog)
self.book_title.setObjectName("book_title")
self.gridLayout.addWidget(self.book_title, 0, 1, 1, 1)
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.btn_save = QtWidgets.QPushButton(parent=Dialog)
self.btn_save.setFocusPolicy(QtCore.Qt.FocusPolicy.ClickFocus)
self.btn_save.setObjectName("btn_save")
self.horizontalLayout.addWidget(self.btn_save)
self.btn_cancel = QtWidgets.QPushButton(parent=Dialog)
self.btn_cancel.setFocusPolicy(QtCore.Qt.FocusPolicy.ClickFocus)
self.btn_cancel.setObjectName("btn_cancel")
self.horizontalLayout.addWidget(self.btn_cancel)
self.gridLayout.addLayout(self.horizontalLayout, 2, 1, 1, 1)
self.retranslateUi(Dialog)
QtCore.QMetaObject.connectSlotsByName(Dialog)
Dialog.setTabOrder(self.book_title, self.book_signature)
Dialog.setTabOrder(self.book_signature, self.btn_save)
Dialog.setTabOrder(self.btn_save, self.btn_cancel)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
self.label_2.setText(_translate("Dialog", "Signatur"))
self.label.setText(_translate("Dialog", "Titel"))
self.btn_save.setText(_translate("Dialog", "Speichern"))
self.btn_cancel.setText(_translate("Dialog", "Abbrechen"))

View File

@@ -0,0 +1,61 @@
# Form implementation generated from reading ui file '/home/alexander/GitHub/LibrarySystem/src/ui/sources/dialog_createUser.ui'
#
# Created by: PyQt6 UI code generator 6.7.1
#
# WARNING: Any manual changes made to this file will be lost when pyuic6 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt6 import QtCore, QtGui, QtWidgets
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.setWindowModality(QtCore.Qt.WindowModality.WindowModal)
Dialog.resize(400, 132)
self.gridLayout = QtWidgets.QGridLayout(Dialog)
self.gridLayout.setObjectName("gridLayout")
self.userno = QtWidgets.QLineEdit(parent=Dialog)
self.userno.setInputMethodHints(QtCore.Qt.InputMethodHint.ImhDigitsOnly)
self.userno.setObjectName("userno")
self.gridLayout.addWidget(self.userno, 1, 1, 1, 1)
self.label_2 = QtWidgets.QLabel(parent=Dialog)
self.label_2.setObjectName("label_2")
self.gridLayout.addWidget(self.label_2, 1, 0, 1, 1)
self.label_3 = QtWidgets.QLabel(parent=Dialog)
self.label_3.setObjectName("label_3")
self.gridLayout.addWidget(self.label_3, 2, 0, 1, 1)
self.user_mail = QtWidgets.QLineEdit(parent=Dialog)
self.user_mail.setObjectName("user_mail")
self.gridLayout.addWidget(self.user_mail, 2, 1, 1, 1)
self.label = QtWidgets.QLabel(parent=Dialog)
self.label.setObjectName("label")
self.gridLayout.addWidget(self.label, 0, 0, 1, 1)
self.username = QtWidgets.QLineEdit(parent=Dialog)
self.username.setObjectName("username")
self.gridLayout.addWidget(self.username, 0, 1, 1, 1)
self.buttonBox = QtWidgets.QDialogButtonBox(parent=Dialog)
self.buttonBox.setOrientation(QtCore.Qt.Orientation.Horizontal)
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.StandardButton.Cancel|QtWidgets.QDialogButtonBox.StandardButton.Save)
self.buttonBox.setObjectName("buttonBox")
self.gridLayout.addWidget(self.buttonBox, 4, 1, 1, 1)
spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Expanding)
self.gridLayout.addItem(spacerItem, 3, 0, 1, 1)
self.retranslateUi(Dialog)
self.buttonBox.accepted.connect(Dialog.accept) # type: ignore
self.buttonBox.rejected.connect(Dialog.reject) # type: ignore
QtCore.QMetaObject.connectSlotsByName(Dialog)
Dialog.setTabOrder(self.username, self.userno)
Dialog.setTabOrder(self.userno, self.user_mail)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Nutzer anlegen"))
self.userno.setPlaceholderText(_translate("Dialog", "102888557"))
self.label_2.setText(_translate("Dialog", "Matrikelnummer"))
self.label_3.setText(_translate("Dialog", "Mail"))
self.user_mail.setPlaceholderText(_translate("Dialog", "email@ph-freiburg.de"))
self.label.setText(_translate("Dialog", "Name, Vorname"))
self.username.setPlaceholderText(_translate("Dialog", "Nachname, Vorname"))

View File

@@ -0,0 +1,43 @@
# Form implementation generated from reading ui file '/home/alexander/GitHub/LibrarySystem/src/ui/sources/dialog_extendLoanDuration.ui'
#
# Created by: PyQt6 UI code generator 6.7.1
#
# WARNING: Any manual changes made to this file will be lost when pyuic6 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt6 import QtCore, QtGui, QtWidgets
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.setWindowModality(QtCore.Qt.WindowModality.ApplicationModal)
Dialog.resize(400, 300)
self.gridLayout = QtWidgets.QGridLayout(Dialog)
self.gridLayout.setObjectName("gridLayout")
self.extenduntil = QtWidgets.QCalendarWidget(parent=Dialog)
self.extenduntil.setObjectName("extenduntil")
self.gridLayout.addWidget(self.extenduntil, 1, 2, 1, 1)
self.buttonBox = QtWidgets.QDialogButtonBox(parent=Dialog)
self.buttonBox.setOrientation(QtCore.Qt.Orientation.Horizontal)
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.StandardButton.Cancel|QtWidgets.QDialogButtonBox.StandardButton.Ok)
self.buttonBox.setObjectName("buttonBox")
self.gridLayout.addWidget(self.buttonBox, 2, 2, 1, 1)
self.label = QtWidgets.QLabel(parent=Dialog)
font = QtGui.QFont()
font.setPointSize(11)
font.setBold(True)
self.label.setFont(font)
self.label.setObjectName("label")
self.gridLayout.addWidget(self.label, 0, 2, 1, 1)
self.retranslateUi(Dialog)
self.buttonBox.accepted.connect(Dialog.accept) # type: ignore
self.buttonBox.rejected.connect(Dialog.reject) # type: ignore
QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
self.label.setText(_translate("Dialog", "Bitte das Verlängerungsdatum auswählen"))

View File

@@ -2,6 +2,9 @@
<ui version="4.0"> <ui version="4.0">
<class>Dialog</class> <class>Dialog</class>
<widget class="QDialog" name="Dialog"> <widget class="QDialog" name="Dialog">
<property name="windowModality">
<enum>Qt::NonModal</enum>
</property>
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>
@@ -29,10 +32,13 @@
</item> </item>
<item> <item>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<item row="0" column="0"> <item row="4" column="2">
<widget class="QLabel" name="label_2"> <widget class="QRadioButton" name="radioButton">
<property name="text"> <property name="text">
<string>Tage</string> <string/>
</property>
<property name="checkable">
<bool>true</bool>
</property> </property>
</widget> </widget>
</item> </item>
@@ -61,6 +67,13 @@
</item> </item>
</layout> </layout>
</item> </item>
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Dateiformat</string>
</property>
</widget>
</item>
<item row="0" column="2"> <item row="0" column="2">
<widget class="QLineEdit" name="dayValue"> <widget class="QLineEdit" name="dayValue">
<property name="sizePolicy"> <property name="sizePolicy">
@@ -89,23 +102,42 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="2"> <item row="4" column="1">
<widget class="QRadioButton" name="radioButton">
<property name="text">
<string/>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="reportlink"> <widget class="QLabel" name="reportlink">
<property name="text"> <property name="text">
<string/> <string/>
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="1">
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="1">
<widget class="QRadioButton" name="format_csv">
<property name="text">
<string>Excel</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QRadioButton" name="format_txt">
<property name="text">
<string>Text</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="1"> <item row="0" column="1">
<widget class="QSlider" name="dayslider"> <widget class="QSlider" name="dayslider">
<property name="focusPolicy"> <property name="focusPolicy">
@@ -131,39 +163,17 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="1"> <item row="0" column="0">
<widget class="QFrame" name="frame"> <widget class="QLabel" name="label_2">
<property name="frameShape"> <property name="text">
<enum>QFrame::NoFrame</enum> <string>Tage</string>
</property> </property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QRadioButton" name="format_txt">
<property name="text">
<string>Text</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QRadioButton" name="format_csv">
<property name="text">
<string>Excel</string>
</property>
</widget>
</item>
</layout>
</widget> </widget>
</item> </item>
<item row="2" column="0"> <item row="3" column="1">
<widget class="QLabel" name="label_3"> <widget class="QCheckBox" name="signature">
<property name="text"> <property name="text">
<string>Dateiformat</string> <string>Signatur anzeigen</string>
</property> </property>
</widget> </widget>
</item> </item>

View File

@@ -0,0 +1,119 @@
# Form implementation generated from reading ui file '/home/alexander/GitHub/LibrarySystem/src/ui/sources/dialog_generateReport.ui'
#
# Created by: PyQt6 UI code generator 6.7.1
#
# WARNING: Any manual changes made to this file will be lost when pyuic6 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt6 import QtCore, QtGui, QtWidgets
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(375, 247)
Dialog.setMinimumSize(QtCore.QSize(40, 0))
self.verticalLayout = QtWidgets.QVBoxLayout(Dialog)
self.verticalLayout.setObjectName("verticalLayout")
self.label = QtWidgets.QLabel(parent=Dialog)
self.label.setObjectName("label")
self.verticalLayout.addWidget(self.label)
self.gridLayout = QtWidgets.QGridLayout()
self.gridLayout.setObjectName("gridLayout")
self.label_2 = QtWidgets.QLabel(parent=Dialog)
self.label_2.setObjectName("label_2")
self.gridLayout.addWidget(self.label_2, 0, 0, 1, 1)
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.radio_week = QtWidgets.QRadioButton(parent=Dialog)
self.radio_week.setObjectName("radio_week")
self.horizontalLayout.addWidget(self.radio_week)
self.radio_month = QtWidgets.QRadioButton(parent=Dialog)
self.radio_month.setObjectName("radio_month")
self.horizontalLayout.addWidget(self.radio_month)
self.radio_year = QtWidgets.QRadioButton(parent=Dialog)
self.radio_year.setObjectName("radio_year")
self.horizontalLayout.addWidget(self.radio_year)
self.gridLayout.addLayout(self.horizontalLayout, 1, 1, 1, 1)
self.dayValue = QtWidgets.QLineEdit(parent=Dialog)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Fixed, QtWidgets.QSizePolicy.Policy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.dayValue.sizePolicy().hasHeightForWidth())
self.dayValue.setSizePolicy(sizePolicy)
self.dayValue.setMinimumSize(QtCore.QSize(0, 0))
self.dayValue.setMaximumSize(QtCore.QSize(40, 16777215))
self.dayValue.setFocusPolicy(QtCore.Qt.FocusPolicy.NoFocus)
self.dayValue.setReadOnly(True)
self.dayValue.setObjectName("dayValue")
self.gridLayout.addWidget(self.dayValue, 0, 2, 1, 1)
self.radioButton = QtWidgets.QRadioButton(parent=Dialog)
self.radioButton.setText("")
self.radioButton.setCheckable(True)
self.radioButton.setObjectName("radioButton")
self.gridLayout.addWidget(self.radioButton, 3, 2, 1, 1)
self.reportlink = QtWidgets.QLabel(parent=Dialog)
self.reportlink.setText("")
self.reportlink.setObjectName("reportlink")
self.gridLayout.addWidget(self.reportlink, 3, 1, 1, 1)
self.dayslider = QtWidgets.QSlider(parent=Dialog)
self.dayslider.setFocusPolicy(QtCore.Qt.FocusPolicy.ClickFocus)
self.dayslider.setMinimum(1)
self.dayslider.setMaximum(365)
self.dayslider.setOrientation(QtCore.Qt.Orientation.Horizontal)
self.dayslider.setInvertedControls(True)
self.dayslider.setTickPosition(QtWidgets.QSlider.TickPosition.TicksAbove)
self.dayslider.setTickInterval(10)
self.dayslider.setObjectName("dayslider")
self.gridLayout.addWidget(self.dayslider, 0, 1, 1, 1)
self.frame = QtWidgets.QFrame(parent=Dialog)
self.frame.setFrameShape(QtWidgets.QFrame.Shape.NoFrame)
self.frame.setFrameShadow(QtWidgets.QFrame.Shadow.Plain)
self.frame.setLineWidth(0)
self.frame.setObjectName("frame")
self.gridLayout_2 = QtWidgets.QGridLayout(self.frame)
self.gridLayout_2.setObjectName("gridLayout_2")
self.format_txt = QtWidgets.QRadioButton(parent=self.frame)
self.format_txt.setObjectName("format_txt")
self.gridLayout_2.addWidget(self.format_txt, 0, 0, 1, 1)
self.format_csv = QtWidgets.QRadioButton(parent=self.frame)
self.format_csv.setObjectName("format_csv")
self.gridLayout_2.addWidget(self.format_csv, 0, 1, 1, 1)
self.gridLayout.addWidget(self.frame, 2, 1, 1, 1)
self.label_3 = QtWidgets.QLabel(parent=Dialog)
self.label_3.setObjectName("label_3")
self.gridLayout.addWidget(self.label_3, 2, 0, 1, 1)
self.verticalLayout.addLayout(self.gridLayout)
self.label_4 = QtWidgets.QLabel(parent=Dialog)
self.label_4.setObjectName("label_4")
self.verticalLayout.addWidget(self.label_4)
self.reportprogress = QtWidgets.QProgressBar(parent=Dialog)
self.reportprogress.setProperty("value", 24)
self.reportprogress.setTextVisible(True)
self.reportprogress.setInvertedAppearance(False)
self.reportprogress.setObjectName("reportprogress")
self.verticalLayout.addWidget(self.reportprogress)
self.generateReport = QtWidgets.QPushButton(parent=Dialog)
self.generateReport.setObjectName("generateReport")
self.verticalLayout.addWidget(self.generateReport)
self.retranslateUi(Dialog)
QtCore.QMetaObject.connectSlotsByName(Dialog)
Dialog.setTabOrder(self.radio_week, self.radio_month)
Dialog.setTabOrder(self.radio_month, self.radio_year)
Dialog.setTabOrder(self.radio_year, self.generateReport)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
self.label.setText(_translate("Dialog", "Wieviele Tage sollen im Bericht erfasst werden?"))
self.label_2.setText(_translate("Dialog", "Tage"))
self.radio_week.setText(_translate("Dialog", "Woche"))
self.radio_month.setText(_translate("Dialog", "Monat"))
self.radio_year.setText(_translate("Dialog", "Jahr"))
self.format_txt.setText(_translate("Dialog", "Text"))
self.format_csv.setText(_translate("Dialog", "Excel"))
self.label_3.setText(_translate("Dialog", "Dateiformat"))
self.label_4.setText(_translate("Dialog", "Fortschritt:"))
self.generateReport.setText(_translate("Dialog", " Bericht erstellen"))

View File

@@ -49,7 +49,7 @@
</size> </size>
</property> </property>
<property name="text"> <property name="text">
<string>Tage(n)</string> <string>Tage</string>
</property> </property>
</widget> </widget>
</item> </item>
@@ -174,31 +174,7 @@ Löschen nach</string>
</item> </item>
<item row="6" column="1"> <item row="6" column="1">
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<item row="2" column="2"> <item row="3" column="0">
<widget class="QToolButton" name="btn_select_report_path">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_10">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="check_generate_report">
<property name="text">
<string>Bericht erstellen</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="report_path"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_8"> <widget class="QLabel" name="label_8">
<property name="text"> <property name="text">
<string>Speicherpfad</string> <string>Speicherpfad</string>
@@ -212,6 +188,23 @@ Löschen nach</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="1">
<widget class="QCheckBox" name="check_generate_report">
<property name="text">
<string>Bericht erstellen</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="report_path"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_10">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="0" column="1"> <item row="0" column="1">
<widget class="QComboBox" name="report_day"> <widget class="QComboBox" name="report_day">
<item> <item>
@@ -241,6 +234,20 @@ Löschen nach</string>
</item> </item>
</widget> </widget>
</item> </item>
<item row="3" column="2">
<widget class="QToolButton" name="btn_select_report_path">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="signature">
<property name="text">
<string>Signatur anzeigen</string>
</property>
</widget>
</item>
</layout> </layout>
</item> </item>
<item row="9" column="1"> <item row="9" column="1">

View File

@@ -0,0 +1,161 @@
# Form implementation generated from reading ui file '/home/alexander/GitHub/LibrarySystem/src/ui/sources/dialog_settings.ui'
#
# Created by: PyQt6 UI code generator 6.7.1
#
# WARNING: Any manual changes made to this file will be lost when pyuic6 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt6 import QtCore, QtGui, QtWidgets
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(492, 306)
self.formLayout = QtWidgets.QFormLayout(Dialog)
self.formLayout.setObjectName("formLayout")
self.label = QtWidgets.QLabel(parent=Dialog)
self.label.setObjectName("label")
self.formLayout.setWidget(0, QtWidgets.QFormLayout.ItemRole.LabelRole, self.label)
self.institution_name = QtWidgets.QLineEdit(parent=Dialog)
self.institution_name.setObjectName("institution_name")
self.formLayout.setWidget(0, QtWidgets.QFormLayout.ItemRole.FieldRole, self.institution_name)
self.label_3 = QtWidgets.QLabel(parent=Dialog)
self.label_3.setObjectName("label_3")
self.formLayout.setWidget(5, QtWidgets.QFormLayout.ItemRole.LabelRole, self.label_3)
self.databasesettings = QtWidgets.QGridLayout()
self.databasesettings.setObjectName("databasesettings")
self.database_name = QtWidgets.QLineEdit(parent=Dialog)
self.database_name.setObjectName("database_name")
self.databasesettings.addWidget(self.database_name, 1, 1, 1, 1)
self.label_4 = QtWidgets.QLabel(parent=Dialog)
self.label_4.setObjectName("label_4")
self.databasesettings.addWidget(self.label_4, 0, 0, 1, 1)
self.label_6 = QtWidgets.QLabel(parent=Dialog)
self.label_6.setObjectName("label_6")
self.databasesettings.addWidget(self.label_6, 2, 0, 1, 1)
self.database_path = QtWidgets.QLineEdit(parent=Dialog)
self.database_path.setObjectName("database_path")
self.databasesettings.addWidget(self.database_path, 0, 1, 1, 1)
self.database_backupLocation = QtWidgets.QLineEdit(parent=Dialog)
self.database_backupLocation.setObjectName("database_backupLocation")
self.databasesettings.addWidget(self.database_backupLocation, 2, 1, 1, 1)
self.label_5 = QtWidgets.QLabel(parent=Dialog)
self.label_5.setObjectName("label_5")
self.databasesettings.addWidget(self.label_5, 1, 0, 1, 1)
self.btn_select_database_path = QtWidgets.QToolButton(parent=Dialog)
self.btn_select_database_path.setObjectName("btn_select_database_path")
self.databasesettings.addWidget(self.btn_select_database_path, 0, 2, 1, 1)
self.btn_select_database_name = QtWidgets.QToolButton(parent=Dialog)
self.btn_select_database_name.setObjectName("btn_select_database_name")
self.databasesettings.addWidget(self.btn_select_database_name, 1, 2, 1, 1)
self.btn_select_database_backupLocation = QtWidgets.QToolButton(parent=Dialog)
self.btn_select_database_backupLocation.setObjectName("btn_select_database_backupLocation")
self.databasesettings.addWidget(self.btn_select_database_backupLocation, 2, 2, 1, 1)
self.formLayout.setLayout(5, QtWidgets.QFormLayout.ItemRole.FieldRole, self.databasesettings)
self.buttonBox = QtWidgets.QDialogButtonBox(parent=Dialog)
self.buttonBox.setOrientation(QtCore.Qt.Orientation.Horizontal)
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.StandardButton.Cancel|QtWidgets.QDialogButtonBox.StandardButton.Discard|QtWidgets.QDialogButtonBox.StandardButton.Ok)
self.buttonBox.setObjectName("buttonBox")
self.formLayout.setWidget(7, QtWidgets.QFormLayout.ItemRole.FieldRole, self.buttonBox)
self.label_9 = QtWidgets.QLabel(parent=Dialog)
self.label_9.setObjectName("label_9")
self.formLayout.setWidget(6, QtWidgets.QFormLayout.ItemRole.LabelRole, self.label_9)
self.gridLayout = QtWidgets.QGridLayout()
self.gridLayout.setObjectName("gridLayout")
self.btn_select_report_path = QtWidgets.QToolButton(parent=Dialog)
self.btn_select_report_path.setObjectName("btn_select_report_path")
self.gridLayout.addWidget(self.btn_select_report_path, 2, 2, 1, 1)
self.label_10 = QtWidgets.QLabel(parent=Dialog)
self.label_10.setText("")
self.label_10.setObjectName("label_10")
self.gridLayout.addWidget(self.label_10, 1, 0, 1, 1)
self.check_generate_report = QtWidgets.QCheckBox(parent=Dialog)
self.check_generate_report.setObjectName("check_generate_report")
self.gridLayout.addWidget(self.check_generate_report, 1, 1, 1, 1)
self.report_path = QtWidgets.QLineEdit(parent=Dialog)
self.report_path.setObjectName("report_path")
self.gridLayout.addWidget(self.report_path, 2, 1, 1, 1)
self.label_8 = QtWidgets.QLabel(parent=Dialog)
self.label_8.setObjectName("label_8")
self.gridLayout.addWidget(self.label_8, 2, 0, 1, 1)
self.label_11 = QtWidgets.QLabel(parent=Dialog)
self.label_11.setObjectName("label_11")
self.gridLayout.addWidget(self.label_11, 0, 0, 1, 1)
self.report_day = QtWidgets.QComboBox(parent=Dialog)
self.report_day.setObjectName("report_day")
self.report_day.addItem("")
self.report_day.addItem("")
self.report_day.addItem("")
self.report_day.addItem("")
self.report_day.addItem("")
self.gridLayout.addWidget(self.report_day, 0, 1, 1, 1)
self.formLayout.setLayout(6, QtWidgets.QFormLayout.ItemRole.FieldRole, self.gridLayout)
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.delete_inactive_user_duration = QtWidgets.QSpinBox(parent=Dialog)
self.delete_inactive_user_duration.setMaximum(9999)
self.delete_inactive_user_duration.setProperty("value", 365)
self.delete_inactive_user_duration.setObjectName("delete_inactive_user_duration")
self.horizontalLayout.addWidget(self.delete_inactive_user_duration)
self.label_12 = QtWidgets.QLabel(parent=Dialog)
self.label_12.setMaximumSize(QtCore.QSize(43, 16777215))
self.label_12.setObjectName("label_12")
self.horizontalLayout.addWidget(self.label_12)
self.formLayout.setLayout(3, QtWidgets.QFormLayout.ItemRole.FieldRole, self.horizontalLayout)
self.label_7 = QtWidgets.QLabel(parent=Dialog)
self.label_7.setObjectName("label_7")
self.formLayout.setWidget(3, QtWidgets.QFormLayout.ItemRole.LabelRole, self.label_7)
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.default_loan_duration = QtWidgets.QSpinBox(parent=Dialog)
self.default_loan_duration.setProperty("value", 7)
self.default_loan_duration.setObjectName("default_loan_duration")
self.horizontalLayout_2.addWidget(self.default_loan_duration)
self.label_13 = QtWidgets.QLabel(parent=Dialog)
self.label_13.setMaximumSize(QtCore.QSize(43, 16777215))
self.label_13.setObjectName("label_13")
self.horizontalLayout_2.addWidget(self.label_13)
self.formLayout.setLayout(1, QtWidgets.QFormLayout.ItemRole.FieldRole, self.horizontalLayout_2)
self.label_2 = QtWidgets.QLabel(parent=Dialog)
self.label_2.setObjectName("label_2")
self.formLayout.setWidget(1, QtWidgets.QFormLayout.ItemRole.LabelRole, self.label_2)
self.retranslateUi(Dialog)
self.buttonBox.accepted.connect(Dialog.accept) # type: ignore
self.buttonBox.rejected.connect(Dialog.reject) # type: ignore
QtCore.QMetaObject.connectSlotsByName(Dialog)
Dialog.setTabOrder(self.institution_name, self.database_path)
Dialog.setTabOrder(self.database_path, self.database_name)
Dialog.setTabOrder(self.database_name, self.database_backupLocation)
Dialog.setTabOrder(self.database_backupLocation, self.btn_select_database_path)
Dialog.setTabOrder(self.btn_select_database_path, self.btn_select_database_name)
Dialog.setTabOrder(self.btn_select_database_name, self.btn_select_database_backupLocation)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
self.label.setText(_translate("Dialog", "Name der Einrichtung"))
self.label_3.setText(_translate("Dialog", "Datenbank"))
self.label_4.setText(_translate("Dialog", "Speicherort"))
self.label_6.setText(_translate("Dialog", "Sicherungspfad"))
self.label_5.setText(_translate("Dialog", "Datenbankname"))
self.btn_select_database_path.setText(_translate("Dialog", "..."))
self.btn_select_database_name.setText(_translate("Dialog", "..."))
self.btn_select_database_backupLocation.setText(_translate("Dialog", "..."))
self.label_9.setText(_translate("Dialog", "Bericht"))
self.btn_select_report_path.setText(_translate("Dialog", "..."))
self.check_generate_report.setText(_translate("Dialog", "Bericht erstellen"))
self.label_8.setText(_translate("Dialog", "Speicherpfad"))
self.label_11.setText(_translate("Dialog", "Tag"))
self.report_day.setItemText(0, _translate("Dialog", "Montag"))
self.report_day.setItemText(1, _translate("Dialog", "Dienstag"))
self.report_day.setItemText(2, _translate("Dialog", "Mittwoch"))
self.report_day.setItemText(3, _translate("Dialog", "Donnerstag"))
self.report_day.setItemText(4, _translate("Dialog", "Freitag"))
self.label_12.setText(_translate("Dialog", "Tage(n)"))
self.label_7.setText(_translate("Dialog", "Inaktive Nutzer\n"
"Löschen nach"))
self.label_13.setText(_translate("Dialog", "Tage(n)"))
self.label_2.setText(_translate("Dialog", "Leihdauer"))

View File

@@ -132,23 +132,6 @@
</item> </item>
</layout> </layout>
</widget> </widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>899</width>
<height>22</height>
</rect>
</property>
<widget class="QMenu" name="menuDatei">
<property name="title">
<string>Datei</string>
</property>
<addaction name="actionBeenden"/>
</widget>
<addaction name="menuDatei"/>
</widget>
<action name="actionBeenden"> <action name="actionBeenden">
<property name="text"> <property name="text">
<string>Beenden</string> <string>Beenden</string>

View File

@@ -0,0 +1,110 @@
# Form implementation generated from reading ui file '/home/alexander/GitHub/LibrarySystem/src/ui/sources/main_Loans.ui'
#
# Created by: PyQt6 UI code generator 6.7.1
#
# WARNING: Any manual changes made to this file will be lost when pyuic6 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt6 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(899, 658)
self.centralwidget = QtWidgets.QWidget(parent=MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
self.verticalLayout.setObjectName("verticalLayout")
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.radio_all = QtWidgets.QRadioButton(parent=self.centralwidget)
self.radio_all.setChecked(True)
self.radio_all.setObjectName("radio_all")
self.horizontalLayout.addWidget(self.radio_all)
self.radio_current = QtWidgets.QRadioButton(parent=self.centralwidget)
self.radio_current.setObjectName("radio_current")
self.horizontalLayout.addWidget(self.radio_current)
self.radio_overdue = QtWidgets.QRadioButton(parent=self.centralwidget)
self.radio_overdue.setObjectName("radio_overdue")
self.horizontalLayout.addWidget(self.radio_overdue)
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
self.horizontalLayout.addItem(spacerItem)
self.verticalLayout.addLayout(self.horizontalLayout)
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.searchbar = QtWidgets.QLineEdit(parent=self.centralwidget)
self.searchbar.setObjectName("searchbar")
self.horizontalLayout_2.addWidget(self.searchbar)
self.searchFields = QtWidgets.QComboBox(parent=self.centralwidget)
self.searchFields.setObjectName("searchFields")
self.searchFields.addItem("")
self.searchFields.addItem("")
self.searchFields.addItem("")
self.horizontalLayout_2.addWidget(self.searchFields)
self.verticalLayout.addLayout(self.horizontalLayout_2)
self.loanTable = QtWidgets.QTableWidget(parent=self.centralwidget)
self.loanTable.setEditTriggers(QtWidgets.QAbstractItemView.EditTrigger.NoEditTriggers)
self.loanTable.setSelectionMode(QtWidgets.QAbstractItemView.SelectionMode.SingleSelection)
self.loanTable.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectionBehavior.SelectRows)
self.loanTable.setObjectName("loanTable")
self.loanTable.setColumnCount(7)
self.loanTable.setRowCount(0)
item = QtWidgets.QTableWidgetItem()
self.loanTable.setHorizontalHeaderItem(0, item)
item = QtWidgets.QTableWidgetItem()
self.loanTable.setHorizontalHeaderItem(1, item)
item = QtWidgets.QTableWidgetItem()
self.loanTable.setHorizontalHeaderItem(2, item)
item = QtWidgets.QTableWidgetItem()
self.loanTable.setHorizontalHeaderItem(3, item)
item = QtWidgets.QTableWidgetItem()
self.loanTable.setHorizontalHeaderItem(4, item)
item = QtWidgets.QTableWidgetItem()
self.loanTable.setHorizontalHeaderItem(5, item)
item = QtWidgets.QTableWidgetItem()
self.loanTable.setHorizontalHeaderItem(6, item)
self.verticalLayout.addWidget(self.loanTable)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(parent=MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 899, 22))
self.menubar.setObjectName("menubar")
self.menuDatei = QtWidgets.QMenu(parent=self.menubar)
self.menuDatei.setObjectName("menuDatei")
MainWindow.setMenuBar(self.menubar)
self.actionBeenden = QtGui.QAction(parent=MainWindow)
self.actionBeenden.setObjectName("actionBeenden")
self.menuDatei.addAction(self.actionBeenden)
self.menubar.addAction(self.menuDatei.menuAction())
self.retranslateUi(MainWindow)
self.actionBeenden.triggered.connect(MainWindow.close) # type: ignore
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.radio_all.setText(_translate("MainWindow", "Alle Ausleihen"))
self.radio_current.setText(_translate("MainWindow", "Aktuell Entliehene Medien"))
self.radio_overdue.setText(_translate("MainWindow", "Überzogene Medien"))
self.searchFields.setItemText(0, _translate("MainWindow", "Titel"))
self.searchFields.setItemText(1, _translate("MainWindow", "Signatur"))
self.searchFields.setItemText(2, _translate("MainWindow", "Nutzer"))
item = self.loanTable.horizontalHeaderItem(0)
item.setText(_translate("MainWindow", "ISBN"))
item = self.loanTable.horizontalHeaderItem(1)
item.setText(_translate("MainWindow", "Signatur"))
item = self.loanTable.horizontalHeaderItem(2)
item.setText(_translate("MainWindow", "Titel"))
item = self.loanTable.horizontalHeaderItem(3)
item.setText(_translate("MainWindow", "Nutzerkonto"))
item = self.loanTable.horizontalHeaderItem(4)
item.setText(_translate("MainWindow", "entliehen am"))
item = self.loanTable.horizontalHeaderItem(5)
item.setText(_translate("MainWindow", "entliehen bis"))
item = self.loanTable.horizontalHeaderItem(6)
item.setText(_translate("MainWindow", "Zurückgegeben am"))
self.menuDatei.setTitle(_translate("MainWindow", "Datei"))
self.actionBeenden.setText(_translate("MainWindow", "Beenden"))
self.actionBeenden.setShortcut(_translate("MainWindow", "Q"))

View File

@@ -17,6 +17,63 @@
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,10,20"> <layout class="QVBoxLayout" name="verticalLayout" stretch="0,10,20">
<item> <item>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Benutzername</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="input_username"/>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="input_userno"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Matrikelnummer</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="input_file_ident"/>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Ausleihe bis</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label_5">
<property name="font">
<font>
<pointsize>14</pointsize>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Modus</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="mode">
<property name="text">
<string>Rückgabe</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="5" column="1"> <item row="5" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_4"> <layout class="QHBoxLayout" name="horizontalLayout_4">
<item> <item>
@@ -69,53 +126,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="5" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Ausleihe bis</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label_5">
<property name="font">
<font>
<pointsize>14</pointsize>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Modus</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="mode">
<property name="text">
<string>Rückgabe</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Matrikelnummer</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="input_username"/>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="input_file_ident"/>
</item>
<item row="0" column="1"> <item row="0" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_3"> <layout class="QHBoxLayout" name="horizontalLayout_3">
<item> <item>
@@ -140,16 +150,13 @@
</item> </item>
</layout> </layout>
</item> </item>
<item row="2" column="0"> <item row="3" column="2">
<widget class="QLabel" name="label_2"> <widget class="QToolButton" name="addBook">
<property name="text"> <property name="text">
<string>Benutzername</string> <string/>
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="1">
<widget class="QLineEdit" name="input_userno"/>
</item>
</layout> </layout>
</item> </item>
<item> <item>
@@ -281,8 +288,8 @@
<widget class="QMenu" name="menuHilfe"> <widget class="QMenu" name="menuHilfe">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>2484</x> <x>2347</x>
<y>209</y> <y>134</y>
<width>181</width> <width>181</width>
<height>94</height> <height>94</height>
</rect> </rect>
@@ -303,11 +310,17 @@
<property name="text"> <property name="text">
<string>Einstellungen</string> <string>Einstellungen</string>
</property> </property>
<property name="shortcut">
<string>Alt+S</string>
</property>
</action> </action>
<action name="actionBeenden"> <action name="actionBeenden">
<property name="text"> <property name="text">
<string>Beenden</string> <string>Beenden</string>
</property> </property>
<property name="shortcut">
<string>Alt+Q</string>
</property>
</action> </action>
<action name="actionRueckgabemodus"> <action name="actionRueckgabemodus">
<property name="text"> <property name="text">

View File

@@ -0,0 +1,229 @@
# Form implementation generated from reading ui file '/home/alexander/GitHub/LibrarySystem/src/ui/sources/main_UserInterface.ui'
#
# Created by: PyQt6 UI code generator 6.7.1
#
# WARNING: Any manual changes made to this file will be lost when pyuic6 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt6 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 602)
self.centralwidget = QtWidgets.QWidget(parent=MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
self.verticalLayout.setObjectName("verticalLayout")
self.gridLayout = QtWidgets.QGridLayout()
self.gridLayout.setObjectName("gridLayout")
self.horizontalLayout_4 = QtWidgets.QHBoxLayout()
self.horizontalLayout_4.setObjectName("horizontalLayout_4")
self.duedate = QtWidgets.QDateEdit(parent=self.centralwidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.duedate.sizePolicy().hasHeightForWidth())
self.duedate.setSizePolicy(sizePolicy)
self.duedate.setMinimumSize(QtCore.QSize(130, 0))
self.duedate.setMaximumSize(QtCore.QSize(100, 16777215))
self.duedate.setBaseSize(QtCore.QSize(70, 0))
self.duedate.setObjectName("duedate")
self.horizontalLayout_4.addWidget(self.duedate)
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
self.horizontalLayout_4.addItem(spacerItem)
self.gridLayout.addLayout(self.horizontalLayout_4, 5, 1, 1, 1)
self.label_3 = QtWidgets.QLabel(parent=self.centralwidget)
self.label_3.setObjectName("label_3")
self.gridLayout.addWidget(self.label_3, 3, 0, 1, 1)
self.label_6 = QtWidgets.QLabel(parent=self.centralwidget)
self.label_6.setAlignment(QtCore.Qt.AlignmentFlag.AlignLeading|QtCore.Qt.AlignmentFlag.AlignLeft|QtCore.Qt.AlignmentFlag.AlignVCenter)
self.label_6.setObjectName("label_6")
self.gridLayout.addWidget(self.label_6, 5, 0, 1, 1)
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.label_5 = QtWidgets.QLabel(parent=self.centralwidget)
font = QtGui.QFont()
font.setPointSize(14)
font.setBold(True)
self.label_5.setFont(font)
self.label_5.setObjectName("label_5")
self.horizontalLayout.addWidget(self.label_5)
self.mode = QtWidgets.QLabel(parent=self.centralwidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Fixed, QtWidgets.QSizePolicy.Policy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.mode.sizePolicy().hasHeightForWidth())
self.mode.setSizePolicy(sizePolicy)
self.mode.setMinimumSize(QtCore.QSize(62, 0))
self.mode.setMaximumSize(QtCore.QSize(62, 16777215))
self.mode.setBaseSize(QtCore.QSize(62, 0))
self.mode.setAutoFillBackground(False)
self.mode.setFrameShape(QtWidgets.QFrame.Shape.StyledPanel)
self.mode.setFrameShadow(QtWidgets.QFrame.Shadow.Sunken)
self.mode.setLineWidth(2)
self.mode.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
self.mode.setObjectName("mode")
self.horizontalLayout.addWidget(self.mode)
self.gridLayout.addLayout(self.horizontalLayout, 0, 0, 1, 1)
self.label = QtWidgets.QLabel(parent=self.centralwidget)
self.label.setObjectName("label")
self.gridLayout.addWidget(self.label, 1, 0, 1, 1)
self.input_username = QtWidgets.QLineEdit(parent=self.centralwidget)
self.input_username.setObjectName("input_username")
self.gridLayout.addWidget(self.input_username, 2, 1, 1, 1)
self.input_file_ident = QtWidgets.QLineEdit(parent=self.centralwidget)
self.input_file_ident.setObjectName("input_file_ident")
self.gridLayout.addWidget(self.input_file_ident, 3, 1, 1, 1)
self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
self.horizontalLayout_3.setObjectName("horizontalLayout_3")
spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
self.horizontalLayout_3.addItem(spacerItem1)
self.btn_createNewUser = QtWidgets.QPushButton(parent=self.centralwidget)
self.btn_createNewUser.setObjectName("btn_createNewUser")
self.horizontalLayout_3.addWidget(self.btn_createNewUser)
self.gridLayout.addLayout(self.horizontalLayout_3, 0, 1, 1, 1)
self.label_2 = QtWidgets.QLabel(parent=self.centralwidget)
self.label_2.setObjectName("label_2")
self.gridLayout.addWidget(self.label_2, 2, 0, 1, 1)
self.input_userno = QtWidgets.QLineEdit(parent=self.centralwidget)
self.input_userno.setObjectName("input_userno")
self.gridLayout.addWidget(self.input_userno, 1, 1, 1, 1)
self.verticalLayout.addLayout(self.gridLayout)
self.groupBox = QtWidgets.QGroupBox(parent=self.centralwidget)
self.groupBox.setFocusPolicy(QtCore.Qt.FocusPolicy.NoFocus)
self.groupBox.setObjectName("groupBox")
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.groupBox)
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.userdata = QtWidgets.QTextEdit(parent=self.groupBox)
font = QtGui.QFont()
font.setFamily("Arial")
font.setPointSize(11)
font.setBold(True)
self.userdata.setFont(font)
self.userdata.setFocusPolicy(QtCore.Qt.FocusPolicy.NoFocus)
self.userdata.setReadOnly(True)
self.userdata.setObjectName("userdata")
self.horizontalLayout_2.addWidget(self.userdata)
self.groupBox_2 = QtWidgets.QGroupBox(parent=self.groupBox)
self.groupBox_2.setObjectName("groupBox_2")
self.gridLayout_2 = QtWidgets.QGridLayout(self.groupBox_2)
self.gridLayout_2.setObjectName("gridLayout_2")
self.btn_show_lentmedia = QtWidgets.QPushButton(parent=self.groupBox_2)
self.btn_show_lentmedia.setFocusPolicy(QtCore.Qt.FocusPolicy.ClickFocus)
self.btn_show_lentmedia.setText("")
self.btn_show_lentmedia.setObjectName("btn_show_lentmedia")
self.gridLayout_2.addWidget(self.btn_show_lentmedia, 0, 1, 1, 1)
self.label_4 = QtWidgets.QLabel(parent=self.groupBox_2)
self.label_4.setAlignment(QtCore.Qt.AlignmentFlag.AlignRight|QtCore.Qt.AlignmentFlag.AlignTrailing|QtCore.Qt.AlignmentFlag.AlignVCenter)
self.label_4.setObjectName("label_4")
self.gridLayout_2.addWidget(self.label_4, 0, 0, 1, 1)
self.label_7 = QtWidgets.QLabel(parent=self.groupBox_2)
self.label_7.setObjectName("label_7")
self.gridLayout_2.addWidget(self.label_7, 1, 0, 1, 1)
self.nextReturnDate = QtWidgets.QLabel(parent=self.groupBox_2)
self.nextReturnDate.setText("")
self.nextReturnDate.setObjectName("nextReturnDate")
self.gridLayout_2.addWidget(self.nextReturnDate, 1, 1, 1, 1)
self.horizontalLayout_2.addWidget(self.groupBox_2)
self.horizontalLayout_2.setStretch(0, 3)
self.horizontalLayout_2.setStretch(1, 1)
self.verticalLayout.addWidget(self.groupBox)
self.mediaOverview = QtWidgets.QTableWidget(parent=self.centralwidget)
self.mediaOverview.setFocusPolicy(QtCore.Qt.FocusPolicy.NoFocus)
self.mediaOverview.setObjectName("mediaOverview")
self.mediaOverview.setColumnCount(3)
self.mediaOverview.setRowCount(0)
item = QtWidgets.QTableWidgetItem()
self.mediaOverview.setHorizontalHeaderItem(0, item)
item = QtWidgets.QTableWidgetItem()
self.mediaOverview.setHorizontalHeaderItem(1, item)
item = QtWidgets.QTableWidgetItem()
self.mediaOverview.setHorizontalHeaderItem(2, item)
self.verticalLayout.addWidget(self.mediaOverview)
self.verticalLayout.setStretch(1, 10)
self.verticalLayout.setStretch(2, 20)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(parent=MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 22))
self.menubar.setObjectName("menubar")
self.menuDatei = QtWidgets.QMenu(parent=self.menubar)
self.menuDatei.setObjectName("menuDatei")
self.menuHotkeys = QtWidgets.QMenu(parent=self.menubar)
self.menuHotkeys.setObjectName("menuHotkeys")
self.menuFenster = QtWidgets.QMenu(parent=self.menubar)
self.menuFenster.setObjectName("menuFenster")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(parent=MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.actionEinstellungen = QtGui.QAction(parent=MainWindow)
self.actionEinstellungen.setObjectName("actionEinstellungen")
self.actionBeenden = QtGui.QAction(parent=MainWindow)
self.actionBeenden.setObjectName("actionBeenden")
self.actionRueckgabemodus = QtGui.QAction(parent=MainWindow)
self.actionRueckgabemodus.setObjectName("actionRueckgabemodus")
self.actionNutzer = QtGui.QAction(parent=MainWindow)
self.actionNutzer.setObjectName("actionNutzer")
self.actionNutzer_2 = QtGui.QAction(parent=MainWindow)
self.actionNutzer_2.setObjectName("actionNutzer_2")
self.actionAusleihistorie = QtGui.QAction(parent=MainWindow)
self.actionAusleihistorie.setObjectName("actionAusleihistorie")
self.actionBericht_erstellen = QtGui.QAction(parent=MainWindow)
self.actionBericht_erstellen.setObjectName("actionBericht_erstellen")
self.actionNutzer_3 = QtGui.QAction(parent=MainWindow)
self.actionNutzer_3.setObjectName("actionNutzer_3")
self.menuDatei.addAction(self.actionEinstellungen)
self.menuDatei.addAction(self.actionBeenden)
self.menuHotkeys.addAction(self.actionRueckgabemodus)
self.menuFenster.addAction(self.actionNutzer)
self.menuFenster.addAction(self.actionAusleihistorie)
self.menuFenster.addAction(self.actionBericht_erstellen)
self.menubar.addAction(self.menuDatei.menuAction())
self.menubar.addAction(self.menuHotkeys.menuAction())
self.menubar.addAction(self.menuFenster.menuAction())
self.retranslateUi(MainWindow)
self.actionBeenden.triggered.connect(MainWindow.close) # type: ignore
QtCore.QMetaObject.connectSlotsByName(MainWindow)
MainWindow.setTabOrder(self.btn_createNewUser, self.input_userno)
MainWindow.setTabOrder(self.input_userno, self.input_username)
MainWindow.setTabOrder(self.input_username, self.input_file_ident)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.label_3.setText(_translate("MainWindow", "Signatur"))
self.label_6.setText(_translate("MainWindow", "Ausleihe bis"))
self.label_5.setText(_translate("MainWindow", "Modus"))
self.mode.setText(_translate("MainWindow", "Rückgabe"))
self.label.setText(_translate("MainWindow", "Matrikelnummer"))
self.btn_createNewUser.setText(_translate("MainWindow", "Neuen Nutzer anlegen"))
self.label_2.setText(_translate("MainWindow", "Benutzername"))
self.groupBox.setTitle(_translate("MainWindow", "Nutzerdaten"))
self.groupBox_2.setTitle(_translate("MainWindow", "Ausleihdaten"))
self.label_4.setText(_translate("MainWindow", "Anzahl Ausleihen"))
self.label_7.setText(_translate("MainWindow", "Nächstes Rückgabedatum"))
item = self.mediaOverview.horizontalHeaderItem(0)
item.setText(_translate("MainWindow", "Signatur"))
item = self.mediaOverview.horizontalHeaderItem(1)
item.setText(_translate("MainWindow", "Titel"))
item = self.mediaOverview.horizontalHeaderItem(2)
item.setText(_translate("MainWindow", "Status"))
self.menuDatei.setTitle(_translate("MainWindow", "Datei"))
self.menuHotkeys.setTitle(_translate("MainWindow", "Hotkeys"))
self.menuFenster.setTitle(_translate("MainWindow", "Fenster"))
self.actionEinstellungen.setText(_translate("MainWindow", "Einstellungen"))
self.actionBeenden.setText(_translate("MainWindow", "Beenden"))
self.actionRueckgabemodus.setText(_translate("MainWindow", "Rückgabemodus"))
self.actionRueckgabemodus.setShortcut(_translate("MainWindow", "F5"))
self.actionNutzer.setText(_translate("MainWindow", "Nutzer"))
self.actionNutzer.setShortcut(_translate("MainWindow", "F6"))
self.actionNutzer_2.setText(_translate("MainWindow", "Nutzer"))
self.actionAusleihistorie.setText(_translate("MainWindow", "Ausleihhistorie"))
self.actionAusleihistorie.setShortcut(_translate("MainWindow", "F8"))
self.actionBericht_erstellen.setText(_translate("MainWindow", "Bericht erstellen"))
self.actionBericht_erstellen.setShortcut(_translate("MainWindow", "F7"))
self.actionNutzer_3.setText(_translate("MainWindow", "Nutzer"))

View File

@@ -0,0 +1,197 @@
# Form implementation generated from reading ui file '/home/alexander/GitHub/LibrarySystem/src/ui/sources/main_userData.ui'
#
# Created by: PyQt6 UI code generator 6.7.1
#
# WARNING: Any manual changes made to this file will be lost when pyuic6 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt6 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.setWindowModality(QtCore.Qt.WindowModality.WindowModal)
MainWindow.resize(800, 600)
self.centralwidget = QtWidgets.QWidget(parent=MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
self.verticalLayout.setObjectName("verticalLayout")
self.gridLayout = QtWidgets.QGridLayout()
self.gridLayout.setObjectName("gridLayout")
self.frame = QtWidgets.QFrame(parent=self.centralwidget)
self.frame.setFrameShape(QtWidgets.QFrame.Shape.StyledPanel)
self.frame.setFrameShadow(QtWidgets.QFrame.Shadow.Raised)
self.frame.setObjectName("frame")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.frame)
self.horizontalLayout.setObjectName("horizontalLayout")
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
self.horizontalLayout.addItem(spacerItem)
self.btn_userChange_save = QtWidgets.QPushButton(parent=self.frame)
self.btn_userChange_save.setStatusTip("")
self.btn_userChange_save.setObjectName("btn_userChange_save")
self.horizontalLayout.addWidget(self.btn_userChange_save)
self.btn_userchange_cancel = QtWidgets.QPushButton(parent=self.frame)
self.btn_userchange_cancel.setObjectName("btn_userchange_cancel")
self.horizontalLayout.addWidget(self.btn_userchange_cancel)
spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
self.horizontalLayout.addItem(spacerItem1)
self.gridLayout.addWidget(self.frame, 3, 1, 1, 1)
self.label = QtWidgets.QLabel(parent=self.centralwidget)
self.label.setObjectName("label")
self.gridLayout.addWidget(self.label, 0, 0, 1, 1)
self.user_no = QtWidgets.QLineEdit(parent=self.centralwidget)
self.user_no.setFocusPolicy(QtCore.Qt.FocusPolicy.NoFocus)
self.user_no.setReadOnly(True)
self.user_no.setObjectName("user_no")
self.gridLayout.addWidget(self.user_no, 1, 1, 1, 1)
self.label_3 = QtWidgets.QLabel(parent=self.centralwidget)
self.label_3.setObjectName("label_3")
self.gridLayout.addWidget(self.label_3, 2, 0, 1, 1)
self.name = QtWidgets.QLineEdit(parent=self.centralwidget)
self.name.setObjectName("name")
self.gridLayout.addWidget(self.name, 0, 1, 1, 1)
self.label_2 = QtWidgets.QLabel(parent=self.centralwidget)
self.label_2.setObjectName("label_2")
self.gridLayout.addWidget(self.label_2, 1, 0, 1, 1)
self.mail = QtWidgets.QLineEdit(parent=self.centralwidget)
self.mail.setObjectName("mail")
self.gridLayout.addWidget(self.mail, 2, 1, 1, 1)
self.horizontalLayout_4 = QtWidgets.QHBoxLayout()
self.horizontalLayout_4.setObjectName("horizontalLayout_4")
self.label_5 = QtWidgets.QLabel(parent=self.centralwidget)
self.label_5.setObjectName("label_5")
self.horizontalLayout_4.addWidget(self.label_5)
self.deleteUser = QtWidgets.QToolButton(parent=self.centralwidget)
self.deleteUser.setMinimumSize(QtCore.QSize(30, 30))
self.deleteUser.setText("")
self.deleteUser.setObjectName("deleteUser")
self.horizontalLayout_4.addWidget(self.deleteUser)
self.gridLayout.addLayout(self.horizontalLayout_4, 3, 0, 1, 1)
self.verticalLayout.addLayout(self.gridLayout)
self.line = QtWidgets.QFrame(parent=self.centralwidget)
self.line.setFrameShape(QtWidgets.QFrame.Shape.HLine)
self.line.setFrameShadow(QtWidgets.QFrame.Shadow.Sunken)
self.line.setObjectName("line")
self.verticalLayout.addWidget(self.line)
self.label_4 = QtWidgets.QLabel(parent=self.centralwidget)
font = QtGui.QFont()
font.setPointSize(12)
self.label_4.setFont(font)
self.label_4.setObjectName("label_4")
self.verticalLayout.addWidget(self.label_4)
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.radio_allLoanedMedia = QtWidgets.QRadioButton(parent=self.centralwidget)
self.radio_allLoanedMedia.setChecked(False)
self.radio_allLoanedMedia.setObjectName("radio_allLoanedMedia")
self.horizontalLayout_2.addWidget(self.radio_allLoanedMedia)
self.radio_currentlyLoaned = QtWidgets.QRadioButton(parent=self.centralwidget)
self.radio_currentlyLoaned.setChecked(True)
self.radio_currentlyLoaned.setObjectName("radio_currentlyLoaned")
self.horizontalLayout_2.addWidget(self.radio_currentlyLoaned)
self.radio_overdueLoans = QtWidgets.QRadioButton(parent=self.centralwidget)
self.radio_overdueLoans.setObjectName("radio_overdueLoans")
self.horizontalLayout_2.addWidget(self.radio_overdueLoans)
spacerItem2 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
self.horizontalLayout_2.addItem(spacerItem2)
self.verticalLayout.addLayout(self.horizontalLayout_2)
self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
self.horizontalLayout_3.setObjectName("horizontalLayout_3")
self.searchbox = QtWidgets.QLineEdit(parent=self.centralwidget)
self.searchbox.setObjectName("searchbox")
self.horizontalLayout_3.addWidget(self.searchbox)
self.searchfilter = QtWidgets.QComboBox(parent=self.centralwidget)
self.searchfilter.setObjectName("searchfilter")
self.searchfilter.addItem("")
self.searchfilter.addItem("")
self.horizontalLayout_3.addWidget(self.searchfilter)
spacerItem3 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
self.horizontalLayout_3.addItem(spacerItem3)
self.btn_extendSelectedMedia = QtWidgets.QPushButton(parent=self.centralwidget)
self.btn_extendSelectedMedia.setEnabled(False)
self.btn_extendSelectedMedia.setObjectName("btn_extendSelectedMedia")
self.horizontalLayout_3.addWidget(self.btn_extendSelectedMedia)
self.verticalLayout.addLayout(self.horizontalLayout_3)
self.UserMediaTable = QtWidgets.QTableWidget(parent=self.centralwidget)
self.UserMediaTable.setMouseTracking(True)
self.UserMediaTable.setFocusPolicy(QtCore.Qt.FocusPolicy.NoFocus)
self.UserMediaTable.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
self.UserMediaTable.setEditTriggers(QtWidgets.QAbstractItemView.EditTrigger.NoEditTriggers)
self.UserMediaTable.setAlternatingRowColors(True)
self.UserMediaTable.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectionBehavior.SelectRows)
self.UserMediaTable.setObjectName("UserMediaTable")
self.UserMediaTable.setColumnCount(6)
self.UserMediaTable.setRowCount(0)
item = QtWidgets.QTableWidgetItem()
self.UserMediaTable.setHorizontalHeaderItem(0, item)
item = QtWidgets.QTableWidgetItem()
self.UserMediaTable.setHorizontalHeaderItem(1, item)
item = QtWidgets.QTableWidgetItem()
self.UserMediaTable.setHorizontalHeaderItem(2, item)
item = QtWidgets.QTableWidgetItem()
self.UserMediaTable.setHorizontalHeaderItem(3, item)
item = QtWidgets.QTableWidgetItem()
self.UserMediaTable.setHorizontalHeaderItem(4, item)
item = QtWidgets.QTableWidgetItem()
self.UserMediaTable.setHorizontalHeaderItem(5, item)
self.UserMediaTable.horizontalHeader().setDefaultSectionSize(156)
self.UserMediaTable.horizontalHeader().setMinimumSectionSize(43)
self.UserMediaTable.horizontalHeader().setSortIndicatorShown(True)
self.UserMediaTable.verticalHeader().setDefaultSectionSize(31)
self.UserMediaTable.verticalHeader().setMinimumSectionSize(25)
self.verticalLayout.addWidget(self.UserMediaTable)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(parent=MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 22))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(parent=MainWindow)
self.statusbar.setSizeGripEnabled(True)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
MainWindow.setTabOrder(self.name, self.mail)
MainWindow.setTabOrder(self.mail, self.btn_userChange_save)
MainWindow.setTabOrder(self.btn_userChange_save, self.btn_userchange_cancel)
MainWindow.setTabOrder(self.btn_userchange_cancel, self.radio_allLoanedMedia)
MainWindow.setTabOrder(self.radio_allLoanedMedia, self.radio_currentlyLoaned)
MainWindow.setTabOrder(self.radio_currentlyLoaned, self.radio_overdueLoans)
MainWindow.setTabOrder(self.radio_overdueLoans, self.searchbox)
MainWindow.setTabOrder(self.searchbox, self.searchfilter)
MainWindow.setTabOrder(self.searchfilter, self.btn_extendSelectedMedia)
MainWindow.setTabOrder(self.btn_extendSelectedMedia, self.UserMediaTable)
MainWindow.setTabOrder(self.UserMediaTable, self.user_no)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.btn_userChange_save.setText(_translate("MainWindow", "Speichern"))
self.btn_userchange_cancel.setText(_translate("MainWindow", "Abbrechen"))
self.label.setText(_translate("MainWindow", "Name, Vorname"))
self.label_3.setText(_translate("MainWindow", "Mail"))
self.label_2.setText(_translate("MainWindow", "Matrikelnummer"))
self.label_5.setText(_translate("MainWindow", "Nutzer Löschen"))
self.label_4.setText(_translate("MainWindow", "Medien"))
self.radio_allLoanedMedia.setText(_translate("MainWindow", "Alle Ausleihen"))
self.radio_currentlyLoaned.setText(_translate("MainWindow", "Aktuell entliehen"))
self.radio_overdueLoans.setText(_translate("MainWindow", "Überzogen"))
self.searchfilter.setItemText(0, _translate("MainWindow", "Titel"))
self.searchfilter.setItemText(1, _translate("MainWindow", "Signatur"))
self.btn_extendSelectedMedia.setText(_translate("MainWindow", "Ausgewählte Verlängern"))
self.UserMediaTable.setSortingEnabled(True)
item = self.UserMediaTable.horizontalHeaderItem(0)
item.setText(_translate("MainWindow", "ISBN"))
item = self.UserMediaTable.horizontalHeaderItem(1)
item.setText(_translate("MainWindow", "Signatur"))
item = self.UserMediaTable.horizontalHeaderItem(2)
item.setText(_translate("MainWindow", "Titel"))
item = self.UserMediaTable.horizontalHeaderItem(3)
item.setText(_translate("MainWindow", "entliehen am"))
item = self.UserMediaTable.horizontalHeaderItem(4)
item.setText(_translate("MainWindow", "entliehen bis"))
item = self.UserMediaTable.horizontalHeaderItem(5)
item.setText(_translate("MainWindow", "Rückgabe am"))

View File

@@ -1,10 +1,11 @@
from .sources.Ui_main_userData import Ui_MainWindow from .sources.Ui_main_userData import Ui_MainWindow
from PyQt6 import QtCore, QtGui, QtWidgets from PyQt6 import QtCore, QtGui, QtWidgets
from src import log
from src.logic import Database from src.logic import Database
from src.schemas import User from src.schemas import User, Book
from .extendLoan import ExtendLoan from .extendLoan import ExtendLoan
from src.utils import stringToDate, Icon from src.utils import stringToDate, Icon
from src.utils import debugMessage as dbg import datetime
TABLETOFIELDTRANSLATE = { TABLETOFIELDTRANSLATE = {
"Titel": "title", "Titel": "title",
@@ -33,7 +34,9 @@ class UserUI(QtWidgets.QMainWindow, Ui_MainWindow):
self.deleteUser.clicked.connect(self.userDelete) self.deleteUser.clicked.connect(self.userDelete)
self.deleteUser.setIcon(Icon("delete").overwriteColor("red")) self.deleteUser.setIcon(Icon("delete").overwriteColor("red"))
self.deleteUser.setEnabled(False) self.deleteUser.setEnabled(False)
self.deleteUser.setToolTip("Nutzer löschen nicht möglich, solange Medien ausgeliehen sind") self.deleteUser.setToolTip(
"Nutzer löschen nicht möglich, solange Medien ausgeliehen sind"
)
self.btn_extendSelectedMedia.setEnabled(False) self.btn_extendSelectedMedia.setEnabled(False)
# radioButtons # radioButtons
@@ -45,8 +48,9 @@ class UserUI(QtWidgets.QMainWindow, Ui_MainWindow):
self.frame.hide() self.frame.hide()
if self.UserMediaTable.rowCount() == 0: if self.UserMediaTable.rowCount() == 0:
self.btn_extendSelectedMedia.setEnabled(False) self.btn_extendSelectedMedia.setEnabled(False)
self.deleteUser.setEnabled( True) self.deleteUser.setEnabled(True)
else: self.btn_extendSelectedMedia.setEnabled(True) else:
self.btn_extendSelectedMedia.setEnabled(True)
# table # table
self.UserMediaTable.horizontalHeader().setSectionResizeMode( self.UserMediaTable.horizontalHeader().setSectionResizeMode(
@@ -61,10 +65,21 @@ class UserUI(QtWidgets.QMainWindow, Ui_MainWindow):
self.name.textChanged.connect(self.showFrame) self.name.textChanged.connect(self.showFrame)
self.user_no.textChanged.connect(self.showFrame) self.user_no.textChanged.connect(self.showFrame)
self.mail.textChanged.connect(self.showFrame) self.mail.textChanged.connect(self.showFrame)
self.show() self.show()
def check_book(self, book: Book):
today = QtCore.QDate.currentDate().toString("yyyy-MM-dd")
returnDate = stringToDate(book.loan_to).toString("yyyy-MM-dd")
returned = book.returned
if returned == 1:
return "returned"
else:
if returnDate < today:
return "overdue"
else:
return "ok"
def userDelete(self): def userDelete(self):
self.db.deleteUser(self.user_id) self.db.deleteUser(self.user_id)
dialog = QtWidgets.QMessageBox() dialog = QtWidgets.QMessageBox()
@@ -84,7 +99,7 @@ class UserUI(QtWidgets.QMainWindow, Ui_MainWindow):
for item in self.UserMediaTable.selectedItems(): for item in self.UserMediaTable.selectedItems():
if item.column() == 1: if item.column() == 1:
signature = item.text() signature = item.text()
#print(signature) # print(signature)
self.db.extendLoanDuration(signature, extendDate) self.db.extendLoanDuration(signature, extendDate)
self.userMedia = [] self.userMedia = []
self.UserMediaTable.setRowCount(0) self.UserMediaTable.setRowCount(0)
@@ -95,11 +110,10 @@ class UserUI(QtWidgets.QMainWindow, Ui_MainWindow):
limiter = self.searchbox.text().lower() limiter = self.searchbox.text().lower()
searchfield = self.searchfilter.currentText() searchfield = self.searchfilter.currentText()
searchfield = TABLETOFIELDTRANSLATE[searchfield] searchfield = TABLETOFIELDTRANSLATE[searchfield]
# dbg(limiter=limiter, search=searchfield)
self.UserMediaTable.setRowCount(0) self.UserMediaTable.setRowCount(0)
for loan in self.userMedia: for loan in self.userMedia:
#print("looping loans") # print("looping loans")
fielddata = eval(f"loan.{searchfield}") fielddata = eval(f"loan.{searchfield}")
if isinstance(fielddata, str): if isinstance(fielddata, str):
fielddata = fielddata.lower() fielddata = fielddata.lower()
@@ -149,12 +163,12 @@ class UserUI(QtWidgets.QMainWindow, Ui_MainWindow):
if self.radio_currentlyLoaned.isChecked() if self.radio_currentlyLoaned.isChecked()
else "overdue" else "overdue"
) )
#print(mode) # print(mode)
if self.userMedia == []: if self.userMedia == []:
books = self.db.getAllMedia(self.user_id) books = self.db.getAllMedia(self.user_id)
for book in books: for book in books:
self.userMedia.append(book) self.userMedia.append(book)
#print(self.userMedia) # print(self.userMedia)
self.UserMediaTable.setRowCount(0) self.UserMediaTable.setRowCount(0)
for book in self.userMedia: for book in self.userMedia:
@@ -166,7 +180,7 @@ class UserUI(QtWidgets.QMainWindow, Ui_MainWindow):
continue continue
elif mode == "overdue": elif mode == "overdue":
# book not returned and todays date is greater than todate # book not returned and todays date is greater than todate
dbg(book=book) log.debug("Book: {}".format(book))
if book.returned_date is not None: if book.returned_date is not None:
continue continue
# if todate is greater than current date, continue # if todate is greater than current date, continue
@@ -174,7 +188,8 @@ class UserUI(QtWidgets.QMainWindow, Ui_MainWindow):
continue continue
self.addBookToTable(book) self.addBookToTable(book)
#print(book.title) # print(book.title)
def addBookToTable(self, book): def addBookToTable(self, book):
self.UserMediaTable.insertRow(0) self.UserMediaTable.insertRow(0)
# item0 = isbn # item0 = isbn
@@ -213,6 +228,22 @@ class UserUI(QtWidgets.QMainWindow, Ui_MainWindow):
else stringToDate(book.returned_date).toString("dd.MM.yyyy") else stringToDate(book.returned_date).toString("dd.MM.yyyy")
), ),
) )
match self.check_book(book):
case "overdue":
for i in range(6):
self.UserMediaTable.item(0, i).setBackground(
QtGui.QColor(255, 0, 0, 100)
)
case "ok":
for i in range(6):
self.UserMediaTable.item(0, i).setBackground(
QtGui.QColor(105, 255, 51, 100)
)
case "returned":
for i in range(6):
self.UserMediaTable.item(0, i).setBackground(
QtGui.QColor(102, 153, 153, 100)
)
def launch(): def launch():
@@ -222,4 +253,4 @@ def launch():
window = UserUI("Test", "3613899476", "sdf@f.de") window = UserUI("Test", "3613899476", "sdf@f.de")
window.show() window.show()
sys.exit(app.exec()) sys.exit(app.exec())

View File

@@ -1,5 +1,2 @@
from .log import Log
from .icon import Icon from .icon import Icon
from .debug import debugMessage
from .stringtodate import stringToDate from .stringtodate import stringToDate
from .documentation import launch_documentation

View File

@@ -7,13 +7,14 @@ from PyQt6.QtCore import QDate
from src import config from src import config
import datetime import datetime
# query all loans that happened in the last 7 days # query all loans that happened in the last 7 days
def generate_report(): def generate_report():
'''Generate an excel report for all actions that happened in the last seven days """Generate an excel report for all actions that happened in the last seven days
Returns: Returns:
str: a string represeting the generated table str: a string represeting the generated table
''' """
db = Database() db = Database()
path = db.db_path path = db.db_path
year = datetime.datetime.now().year year = datetime.datetime.now().year
@@ -23,9 +24,12 @@ def generate_report():
report_path = os.path.join(config.report.path, f"report_{year}_{week}.tsv") report_path = os.path.join(config.report.path, f"report_{year}_{week}.tsv")
day = QDate.currentDate().addDays(-7).toString("yyyy-MM-dd") day = QDate.currentDate().addDays(-7).toString("yyyy-MM-dd")
query = f"""SELECT * FROM loans WHERE loan_date >= '{day}';""" query = f"""SELECT * FROM loans WHERE loan_date >= '{day}';"""
#print(query) # print(query)
colnames = ["UserId", "Title", "Action", "Datum"] colnames = ["UserId", "Title", "Action", "Datum"]
if config.report.show_signature:
# insert the signature column at the second position
colnames.insert(2, "Signature")
table = PrettyTable(colnames) table = PrettyTable(colnames)
table.align[colnames[0]] = "l" table.align[colnames[0]] = "l"
table.align[colnames[1]] = "l" table.align[colnames[1]] = "l"
@@ -41,19 +45,15 @@ def generate_report():
loan_action_date = stringToDate( loan_action_date = stringToDate(
loan[3] if loan[5] == 0 else loan[6] loan[3] if loan[5] == 0 else loan[6]
).toString("dd.MM.yyyy") ).toString("dd.MM.yyyy")
table.add_row( row = [
[ loan[1],
loan[1], db.getMedia(loan[2]).title,
db.getMedia(loan[2]).title, loan_action,
loan_action, loan_action_date,
loan_action_date, ]
] if config.report.show_signature:
) row.insert(2, db.getMedia(loan[2]).signature)
# #print(table) table.add_row(row)
# # wruitng the table to a file
# with open("report.txt", "w", encoding="utf-8") as f:
# f.write(str(table))
tsv_table = table.get_csv_string().replace(",", "\t") tsv_table = table.get_csv_string().replace(",", "\t")
# write the file # write the file
with open(report_path, "w", encoding="utf-8") as f: with open(report_path, "w", encoding="utf-8") as f:

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