diff --git a/Gui/LoginScreen.qml b/Gui/LoginScreen.qml
new file mode 100644
index 0000000..4b99d22
--- /dev/null
+++ b/Gui/LoginScreen.qml
@@ -0,0 +1,96 @@
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Layouts
+
+
+Item
+{
+ anchors.fill: parent
+ ColumnLayout
+ {
+
+ anchors.fill: parent
+ Item
+ {
+ height: 150
+ }
+ Label
+ {
+ text: qsTr ("Login")
+ font.pixelSize: 49
+ Layout.alignment: Qt.AlignHCenter
+ }
+ RowLayout
+ {
+ Layout.alignment: Qt.AlignHCenter
+ spacing: 15
+ Label
+ {
+ text: qsTr ("Benutzername")
+ minimumPixelSize: 20
+ Layout.preferredWidth: 150
+ horizontalAlignment: Text.AlignRight
+
+ }
+
+ TextField
+ {
+ id: benutzerName
+ placeholderText: qsTr ("Benutzernamen eingeben")
+ implicitWidth: 300
+ }
+ }
+
+ RowLayout
+ {
+ Layout.alignment: Qt.AlignHCenter
+ spacing: 15
+ Label
+ {
+ minimumPixelSize: 20
+ Layout.preferredWidth: 150
+ text: qsTr ("Passwort")
+
+ horizontalAlignment: Text.AlignRight
+ }
+
+ TextField
+ {
+ id: passwort
+ placeholderText: qsTr ("Passwort eingeben")
+ implicitWidth: 300
+ echoMode: TextInput.Password
+ }
+ }
+ RowLayout
+ {
+ Layout.preferredWidth: 465
+ Layout.alignment: Qt.AlignHCenter
+ Button
+ {
+ text: qsTr ("Feierabend für heute!")
+ Layout.alignment: Qt.AlignRight
+ onClicked:
+ {
+ if (benutzerName.text.trim() && passwort.text.trim())
+ loggedin_user.login(benutzerName.text.trim(), passwort.text)
+ }
+ }
+ }
+
+ Item
+ {
+ Layout.fillHeight: true
+
+ }
+ }
+ Component.onCompleted:
+ {
+ loggedin_user.loginOkay.connect(loggedin)
+ }
+ function loggedin()
+ {
+ appLoader.source = "Dashboard.qml"
+ }
+
+}
diff --git a/Gui/firststart.qml b/Gui/firststart.qml
index fe75225..47fc5a2 100644
--- a/Gui/firststart.qml
+++ b/Gui/firststart.qml
@@ -6,21 +6,6 @@ import QtQuick.Dialogs
import "../js/qmldict.js" as Qmldict
-
-// Item {
-
-// benutzername
-// passwort
-// server
-// port
-// benutzername(db)
-// passwort(db)
-// DbName
-// type
-
-
-// }
-
Item
{
Component.onCompleted:
diff --git a/Gui/main.qml b/Gui/main.qml
index 42c14b8..2bb20c0 100644
--- a/Gui/main.qml
+++ b/Gui/main.qml
@@ -54,7 +54,7 @@ ApplicationWindow
{
importDialog.open()
}
- else appLoader.source= "Dashboard.qml"
+ else appLoader.source= "LoginScreen.qml"
}
Dialog
diff --git a/doc/.$Programmstart Diagramm.drawio.dtmp b/doc/.$Programmstart Diagramm.drawio.dtmp
new file mode 100644
index 0000000..2e2067a
--- /dev/null
+++ b/doc/.$Programmstart Diagramm.drawio.dtmp
@@ -0,0 +1,288 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lib/ConfigLoader.py b/lib/ConfigLoader.py
index 99fd28b..8705c9c 100644
--- a/lib/ConfigLoader.py
+++ b/lib/ConfigLoader.py
@@ -48,7 +48,7 @@ class ConfigLoader(QObject):
@Slot(dict, result= bool)
def addAdminUser(self, user_config):
admin = UserManager(user_config["user"], PyqcrmFlags.ADMIN).createUser()
- print (admin)
+
if not admin:
self.usernameNotAvailable.emit()
return admin
@@ -112,7 +112,6 @@ class ConfigLoader(QObject):
@Slot(str)
def setEncyrptKey(self, key):
self.__config['pyqcrm']['ENCRYPTION_KEY'] = key
- print(self.__config)
self.__saveConfig()
def __saveConfig(self):
diff --git a/lib/DB/DbManager.py b/lib/DB/DbManager.py
index c0980e7..a9587f6 100644
--- a/lib/DB/DbManager.py
+++ b/lib/DB/DbManager.py
@@ -7,20 +7,25 @@ class DbManager(object):
__dbmanager = None
def __new__(cls, dbconf = None):
+
if cls.__dbmanager is None:
cls.__dbmanager = super(DbManager, cls).__new__(cls)
cls.__dbmanager.__initializeConfig(dbconf)
return cls.__dbmanager
- def getConnection(cls):
- if not cls.__connection:
- try:
- cls.__connection = mariadb.connect(**cls.__con_param)
+ def getConnection(cls):
+ try:
+ if not cls.__connection or not cls.__connection.ping():
+ cls.__connection = mariadb.connect(**cls.__con_param)
+ except mariadb.InterfaceError as e:
+ cls.__connection = mariadb.connect(**cls.__con_param)
+ print(f"INTERFACE ERROR: {e}")
except mariadb.Error as e:
- print("Connection parameters are wrong: {e}")
- return cls.__connection
+ print(f"Connection parameters are wrong: {e}")
+
+ return cls.__connection
def __initializeConfig(cls, dbconf):
cls.__con_param = { 'user': dbconf['DB_USER'], 'password': dbconf['DB_PASS'],
@@ -30,3 +35,5 @@ class DbManager(object):
+
+
diff --git a/lib/DB/UserDAO.py b/lib/DB/UserDAO.py
new file mode 100644
index 0000000..30e7f53
--- /dev/null
+++ b/lib/DB/UserDAO.py
@@ -0,0 +1,32 @@
+# This Python file uses the following encoding: utf-8
+from .DbManager import DbManager
+from ..PyqcrmFlags import PyqcrmFlags
+import mariadb
+
+class UserDAO:
+ def __init__(self):
+ self.__con = DbManager().getConnection()
+ self.__cur = self.__con.cursor()
+
+ def createUser(self, username, password, info, role= PyqcrmFlags.USER):
+ user_created = True
+ try:
+ self.__cur.callproc("createUser", (username, password, info, role))
+ self.__con.commit()
+ except mariadb.Error as e:
+ print(f"Error: {e}")
+ print(e.errno)
+ user_created = False
+ finally:
+ self.__closeConnection()
+ return user_created
+
+ def getUser(self, username):
+ self.__cur.callproc("getUser", (username,))
+ return self.__cur.fetchone()
+
+ def __closeConnection(self):
+ self.__cur.close()
+ self.__con.close()
+
+
diff --git a/lib/DB/UserManager.py b/lib/DB/UserManager.py
index f09ad3b..0f65700 100644
--- a/lib/DB/UserManager.py
+++ b/lib/DB/UserManager.py
@@ -2,38 +2,35 @@ from .DbManager import DbManager
from ..PyqcrmFlags import PyqcrmFlags
from ..Vermasseln import Vermasseln
import mariadb
+from .UserDAO import UserDAO
+from PySide6.QtCore import Slot, QObject, Signal
-class UserManager():
+class UserManager(QObject):
- def __init__(self, user_config, role):
+ loginOkay = Signal()
+
+ def __init__(self, user_config = None, role = None):
+ super().__init__()
self.__con = DbManager().getConnection()
self.__cur = self.__con.cursor()
- self.__username = user_config["PYQCRM_USER"]
- self.__password = user_config["PYQCRM_USER_PASS"]
- self.__info = user_config["PYQCRM_USER_INFO"]
- self.__role = role if role == PyqcrmFlags.ADMIN else 0
+ if user_config and role:
+
+ self.__username = user_config["PYQCRM_USER"]
+ self.__password = user_config["PYQCRM_USER_PASS"]
+ self.__info = user_config["PYQCRM_USER_INFO"]
+ self.__role = role if role == PyqcrmFlags.ADMIN else 0
def createUser(self):
self.__hashPassword()
- user_created = True
- try:
- self.__cur.callproc("createUser", (self.__username, self.__password, self.__info, self.__role))
- self.__con.commit()
- except mariadb.Error as e:
- print(f"Error: {e}")
- print(e.errno)
- user_created = False
- finally:
- self.__cur.close()
- #self.__closeConnection()
- return user_created
+ user_created = UserDAO().createUser(self.__username, self.__password, self.__info, self.__role)
+
+ return user_created
def __hashPassword(self):
self.__password = Vermasseln.userPasswordHash(self.__password)
- print (self.__password)
def getUser(self):
@@ -51,7 +48,16 @@ class UserManager():
def disableUser(self):
self.__closeConnection()
- def __closeConnection(self):
- self.__cur.close()
- self.__con.close()
+ @Slot(str, str)
+ def login(self, username, password):
+ user = UserDAO().getUser(username)
+ if user:
+ self.__checkPassword(password, user[2])
+
+ def __checkPassword(self, password, hash_password):
+ pwList = hash_password.split("$")
+
+ hash_Pw = Vermasseln.userPasswordHash(password, pwList[0])
+ if hash_password == hash_Pw:
+ self.loginOkay.emit()
diff --git a/lib/Vermasseln.py b/lib/Vermasseln.py
index 04ca19f..6aca97a 100644
--- a/lib/Vermasseln.py
+++ b/lib/Vermasseln.py
@@ -47,9 +47,9 @@ class Vermasseln:
return cipher
@classmethod
- def userPasswordHash(self, password):
-
- salt = "".join(random.choice(string.ascii_letters + string.digits) for i in range (32))
+ def userPasswordHash(self, password, salt = None):
+ if not salt:
+ salt = "".join(random.choice(string.ascii_letters + string.digits) for i in range (32))
hash_pw = (salt + password).encode("utf-8")
h_obj = SHA3_512.new(hash_pw)
password = salt + "$" + h_obj.hexdigest()
diff --git a/main.py b/main.py
index f671983..d292a95 100644
--- a/main.py
+++ b/main.py
@@ -9,6 +9,8 @@ from lib.DB.BusinessModel import BusinessModel
import rc_pyqcrm
import rc_qml
from lib.DB.DbManager import DbManager
+from lib.DB.UserManager import UserManager
+
# [pyqcrm]
# program-name=""
@@ -43,6 +45,7 @@ if __name__ == "__main__":
config = ConfigLoader()
+
if not config.getConfig():
bad_config = True
bm = False
@@ -50,12 +53,14 @@ if __name__ == "__main__":
dbconf = config.getConfig()['database']
DbManager(dbconf)
bm = BusinessModel(DbManager().getConnection(), ["roleid", "username", "gecos"])
+ user = UserManager()
#print(con is con2)
engine.rootContext().setContextProperty("bm", bm)
engine.rootContext().setContextProperty("bad_config", bad_config) # print(f"Fehler: {i}")
engine.rootContext().setContextProperty("config", config)
+ engine.rootContext().setContextProperty("loggedin_user", user)
engine.load(qml_file)
diff --git a/pyqcrm.pyproject b/pyqcrm.pyproject
index 9ecf4df..f9564c9 100644
--- a/pyqcrm.pyproject
+++ b/pyqcrm.pyproject
@@ -28,6 +28,7 @@
"lib/DB/DbManager.py",
"Gui/DbConfiguration.qml",
"lib/DB/UserManager.py",
- "lib/PyqcrmFlags.py"
+ "lib/PyqcrmFlags.py",
+ "lib/DB/UserDAO.py"
]
}
diff --git a/qml.qrc b/qml.qrc
index 92d05d0..d5f8b2d 100644
--- a/qml.qrc
+++ b/qml.qrc
@@ -5,5 +5,6 @@
Gui/AdminUserConfig.qml
Gui/EncryptionKey.qml
Gui/DbConfiguration.qml
+ Gui/LoginScreen.qml
diff --git a/rc_qml.py b/rc_qml.py
new file mode 100644
index 0000000..12fc612
--- /dev/null
+++ b/rc_qml.py
@@ -0,0 +1,334 @@
+# Resource object code (Python 3)
+# Created by: object code
+# Created by: The Resource Compiler for Qt version 6.8.0
+# WARNING! All changes made in this file will be lost!
+
+from PySide6 import QtCore
+
+qt_resource_data = b"\
+\x00\x00\x01\xd8\
+\x00\
+\x00\x06lx\xda\xb5TM\x8f\xd30\x10\xbdW\xea\x7f\
+\xb0r\x02!\xa5\x8b\x10\x07\x22q\xa0]\x0e\x88]U\
+\x8b*qv\xeci\xe2\xad\xe3I\xc7\x13\xca\x0a\xed\x7f\
+\xc7\x89\xbbM\xd8\xa2lV\x0b>Dy\xf3\xf1\xfc\xe6\
+\xd9\xb2\xa9j$\x167|\xd3\x18\xb5\x9b\xcf\xcc\x1f8\
+]\xa1cB\xeb\xcf\x12W\xf2\x0e\x1b\x0e\xf1\xf9\xec\x1b\
+\x1e\x22\x9a\xcf~\xcdg\x22,\xa33\xc1X/%E\
+\xeck\xa9\x8c+2q\x11q\x09\xa6(9\x13\xef\xde\
+G|0\x9a\xcbL\xd4\x92\xc0q\xda\xa1\x98\x90N\x95\
+H>\x82#y\xbb\x02\xf9\xa9<\xfc\xf7\x09\x0b[>\
+eZ\xd0\x0a\x8c\xe9\xfb\x87\x9fe\xc3\x8c\xee\x8c\xb3\x15\
+\xad\xa5/\x97(I\xf7\xe1\xad\x95\x81\x91\xa9\x81\xc1\xf6\
+\xf03\xc4\xf6~C\xaf\x92\xcb\xd0\x92\xb7-\xc9\xeb\x01\
+WU[\xa3\x0c\x7f\x8f\x83\x9dh\xd3\x87D\xebk\x90\
+\xd8\xe5\xc5\x1b\xf1\xf6\xa2\xefE\xb7\x0a%;\xd0Y\x1f\
+\x1b\xc8\xecl\xa9\xeb+\x94\x1a(\xf5\xd8\x90\x02\xf1Q\
+\xf4:\xd2}e\x93\xbe\xfe\xfe9\xf3\xef\x1a\xa7\xc1M\
+\x1f\xfekW?2y$\xfcGc/\x16b\xb3\xbe\
+\x5cg\xe1\xfe\x10\x88\x03\x08_bc\xb5P\xd2Z\xc1\
+%\x88\x0a5\xd8\xa7\xadZ5\x9e\xb1\x02\xda\xc8\xdc\x82\
+?\xf7k\xaa[\x98\xdf\xc2\x8e\xa7\xbb\xb5\xee\xeaG\xdc\
+\x8a\x84cnM\x17W\x19\x96\x94\x83a\xa0\xe9\x0a\xaf\
+\xfb\xa6\x11\x99\x03\xea\xffx\xa1?\x07f\xbc\x83\x97\x1e\
+\x92\xcc\x09T\xe9\x1aWL\xb7\xe1\xd3\xa9g\xc4\x85\x9e\
+\xf8)\x13N2\xbf0T\x7f\x15Y\xb6/\xe4\xf0\xa0\
+\xe2\x83\x9an\x8d\xb5\xc7\xedz\xb5\x93\xa6fy\x8b~\
+\x10S\xe8\x8e\xdef\x22\xd9\x93\xca\x16\xa6\x92\x05\xf8E\
+\x05\xaeI\xfd\x8f\x22yT\xac\xd0\x22\x85Z\x02\x9d\x8c\
+;w\xd4J\xed\x9b~-\xa90.\x13\x1f\x1e\xbd\xbb\
+\xdd\xe77x;\xb3\xff\
+\x00\x00\x03Y\
+i\
+mport QtQuick\x0d\x0ai\
+mport QtQuick.Co\
+ntrols\x0d\x0aimport Q\
+tQuick.Layouts\x0d\x0a\
+\x0d\x0aGridLayout\x0d\x0a{\x0d\
+\x0a id: passEnc\
+ryptKeyGrid\x0d\x0a \
+ columns: 2\x0d\x0a \
+ columnSpacing: \
+5\x0d\x0a rowSpacin\
+g: 9\x0d\x0a // anc\
+hors.fill: paren\
+t\x0d\x0a\x0d\x0a propert\
+y string name: \x22\
+pyqcrm\x22\x0d\x0a\x0d\x0a L\
+abel\x0d\x0a {\x0d\x0a \
+ text: qsTr(\
+\x22Encryption Key \
+eingeben\x22)\x0d\x0a \
+ font.pixelSi\
+ze: 40\x0d\x0a \
+Layout.columnSpa\
+n: 2\x0d\x0a La\
+yout.alignment: \
+Qt.AlignHCenter\x0d\
+\x0a padding\
+: 15\x0d\x0a }\x0d\x0a\x0d\x0a\x0d\
+\x0a Label\x0d\x0a \
+{\x0d\x0a text:\
+ qsTr(\x22Encryptio\
+n Key:\x22)\x0d\x0a \
+ Layout.alignme\
+nt: Qt.AlignRigh\
+t\x0d\x0a }\x0d\x0a\x0d\x0a \
+TextField\x0d\x0a {\
+\x0d\x0a id: pa\
+ssEncryptKey\x0d\x0a \
+ placeholde\
+rText: qsTr(\x22Hie\
+r Encryption Key\
+ eingeben\x22)\x0d\x0a \
+ Layout.fill\
+Width: true\x0d\x0a \
+ height: 3\x0d\x0a\
+ echoMode\
+: TextInput.Pass\
+word\x0d\x0a pr\
+operty string na\
+me: \x22ENCRYPT_KEY\
+\x22\x0d\x0a }\x0d\x0a\x0d\x0a \
+Item\x0d\x0a {\x0d\x0a \
+ Layout.fill\
+Height: true\x0d\x0a \
+ }\x0d\x0a}\x0d\x0a\
+\x00\x00\x01&\
+i\
+mport QtQuick\x0d\x0ai\
+mport QtQuick.Co\
+ntrols\x0d\x0a\x0d\x0aItem\x0d\x0a\
+{\x0d\x0a anchors.f\
+ill: parent\x0d\x0a \
+ Label\x0d\x0a {\x0d\x0a \
+ text: qsT\
+r (\x22Login\x22)\x0d\x0a \
+ font.pixelS\
+ize: 49\x0d\x0a }\x0d\x0a\
+ TextField\x0d\x0a \
+ {\x0d\x0a te\
+xt: qsTr (\x22Benu\
+tzername\x22)\x0d\x0a \
+}\x0d\x0a TextField\
+\x0d\x0a {\x0d\x0a \
+ text: qsTr (\x22P\
+asswort\x22)\x0d\x0a }\
+\x0d\x0a}\x0d\x0a\
+\x00\x00\x00#\
+m\
+odule gui\x0d\x0aTopBa\
+r 1.0 TopBar.qml\
+\x0d\x0a\
+\x00\x00\x02\x06\
+\x00\
+\x00\x07\xf8x\xda\xb5\x94Ms\xda0\x10\x86\xef\xcc\xf0\
+\x1f4>\xb5\x87\x924\xad3S\xe7\x04\x09\xad\x99\xc9\
+\x07`\x92\x1e;\xb2\xb5\x80&\xb2\xe4J\xeb\xe6k\xf8\
+\xef\x95b\x83\x9d\xba\x9d\x1a\x06l\x1f\xb4\xab\xd5\xee\xbb\
+\x8f%\xf14S\x1a\xc9\x04'9O\xee\xbb\x1d\xfe\xc6\
+\xee\x9d+\x89Z\x09\xd3\x98\xb8\xa4O*G\xebw\xef\
+7\xcdY\xe1\xe8v^\xba\x1db\x9f\xa3#\x92i\x95\
+\x81\xc6'B\x05\xa7\x86\xcc\xb96\x18!\xd5\x18\xd4\xc6\
+ni\xb1\x82\xb3\x80\xb0\xb8\xb2\x13%\xf2T\x9a\x80\x9c\
+\xd4\xed(\xa3\x09\x97\x8b\x80\xf8\x85W\xab\x87\x8d\xeb\x8b\
+\xd3\xe2\x9c\x9b\xca\x06\xb5\x9d!\x92\xa6\x10\x10\x8fQ\xa4\
+15\xe0\xad\xe3.i\x0c\xa2\x18\x96\xb2\xdd\x83\xf0h\
+%\xfe43\xfd\xce\xbb\xa0\x082\xa6\xf2\x9e\x0c\xb94\
+\x08B\xe4r\x01\xd2{_\x85\xcf-\xa2^\xc6\x1fA\
+D\xfc\xd9\x96\xf9|\x5c\xcd\x15Pz\x1b\xe9r\xd3M\
+m\xd6\xe2Y\xc8\x14\xa4-:\xc1^\xdfY\xe1\xb95\
+AW\xa1\x19e\xec\xb5\xc7\x8fe\xdf\xab\x82|\xcb.\
+\x06\x1fBe0\xa8\xcb\xfew\xf1)_,q\x9d|\
+\xb5\x1e\xccl\xbe\xaf\x1c\x04kT*~\x9c+P\xd3\
++h\x02K%\x18\xe8YMH\xc8A\x13\x17I\xc0\
+v\x03\xf1[\x92\xa5\xa49\x17\xe2;g\xb8\x0c\x08\xea\
+\x1cjI\xff\xfe[/\x06?\xc2\x9bh\xe6\xfd!\xb8\
+\x15\x96\xb1\xdd\xd3\xdba\xd9\x0a\x8aK\xdf\x0eJ\xa9e\
+'.\xbf\xacZ\xbb\xb7\x95\x0e\xc8H\xe2\xdd\xdaz\x89\
+\x15\xa2J\xed\x9e9>\xf1\xcf\x08\xaa, \xa7\xbe\xff\
+\xc9?[\xb5a:\xbe\x99\xee\xc6\xf4\xda\xa58\x1cS\
+\x97\xbe5S\x17\xbc\xe7\xbdv\xdd\xbf\x1a\xee\xc4e\x00\
+2\xc7g\xd0\xf2\xb0|n\x0d\xe8\xad\x18\xd5u\xed\x99\
+\xd5m4\x9cz\x8d\xab\xa4\xdd\xc9\xa4\xc6<\x1c\xf8t\
+\x16%X\xe5\x87d\xa9\xae\x14\xb3\xea\xdd\xda\x91\xccl\
+\xb1f\xd4\xff\xceq\xa9|\xcf,\xc7\xfd(\xf2\x1a\x97\
+\xff\x08!m\xb4W+\x12\x82\x03S\xafb\x17\xdb\xef\
+7h\x023#\
+\x00\x00\x07\x0f\
+i\
+mport QtQuick\x0d\x0ai\
+mport QtQuick.Co\
+ntrols\x0d\x0aimport Q\
+tQuick.Layouts\x0d\x0a\
+\x0d\x0aGridLayout\x0d\x0a{\x0d\
+\x0a id: createU\
+serGrid\x0d\x0a col\
+umns: 2\x0d\x0a col\
+umnSpacing: 5\x0d\x0a \
+ rowSpacing: 9\
+\x0d\x0a // anchors\
+.fill: parent\x0d\x0a\x0d\
+\x0a property st\
+ring name: \x22user\
+\x22\x0d\x0a\x0d\x0a Label\x0d\x0a\
+ {\x0d\x0a t\
+ext: qsTr(\x22Admin\
+ User erstellen\x22\
+)\x0d\x0a font.\
+pixelSize: 40\x0d\x0a \
+ Layout.co\
+lumnSpan: 2\x0d\x0a \
+ Layout.alig\
+nment: Qt.AlignH\
+Center\x0d\x0a \
+padding: 15\x0d\x0a \
+ }\x0d\x0a\x0d\x0a\x0d\x0a Labe\
+l\x0d\x0a {\x0d\x0a \
+ id: benutzerNa\
+melabel\x0d\x0a \
+ text: qsTr(\x22Ben\
+utzername:\x22)\x0d\x0a \
+ Layout.ali\
+gnment: Qt.Align\
+Right\x0d\x0a }\x0d\x0a\x0d\x0a\
+ TextField\x0d\x0a \
+ {\x0d\x0a id\
+: benutzerName\x0d\x0a\
+ placehol\
+derText: qsTr(\x22H\
+ier Benutzername\
+ eingeben\x22)\x0d\x0a \
+ Layout.fill\
+Width: true\x0d\x0a \
+ height: 3\x0d\x0a\
+ property\
+ string name: \x22P\
+YQCRM_USER\x22\x0d\x0a \
+ }\x0d\x0a\x0d\x0a Label\x0d\
+\x0a {\x0d\x0a \
+text: qsTr(\x22Pass\
+wort:\x22)\x0d\x0a \
+ Layout.alignmen\
+t: Qt.AlignRight\
+\x0d\x0a }\x0d\x0a\x0d\x0a T\
+extField\x0d\x0a {\x0d\
+\x0a id: pas\
+sword\x0d\x0a e\
+choMode: TextInp\
+ut.Password\x0d\x0a \
+ placeholder\
+Text: qsTr(\x22Hier\
+ Passwort eingeb\
+en\x22)\x0d\x0a La\
+yout.fillWidth: \
+true\x0d\x0a pr\
+operty string na\
+me: \x22PYQCRM_USER\
+_PASS\x22\x0d\x0a }\x0d\x0a \
+ Label\x0d\x0a {\x0d\
+\x0a text: q\
+sTr(\x22Info:\x22)\x0d\x0a \
+ Layout.ali\
+gnment: Qt.Align\
+Right\x0d\x0a }\x0d\x0a\x0d\x0a\
+ TextField\x0d\x0a \
+ {\x0d\x0a id\
+: gecos\x0d\x0a \
+ placeholderText\
+: qsTr(\x22Zus\xc3\xa4tzl\
+iche Info\x22)\x0d\x0a \
+ Layout.fill\
+Width: true\x0d\x0a \
+ property st\
+ring name: \x22PYQC\
+RM_USER_INFO\x22\x0d\x0a \
+ }\x0d\x0a\x0d\x0a Item\
+\x0d\x0a {\x0d\x0a \
+ Layout.fillHeig\
+ht: true\x0d\x0a }\x0d\
+\x0a Component.o\
+nCompleted:\x0d\x0a \
+ {\x0d\x0a conf\
+ig.usernameNotAv\
+ailable.connect(\
+usernameNotAvail\
+able)\x0d\x0a }\x0d\x0a \
+ function usern\
+ameNotAvailable(\
+)\x0d\x0a {\x0d\x0a \
+ benutzerName.p\
+laceholderText =\
+ qsTr (\x22Benutzer\
+name ist bereits\
+ vergeben\x22)\x0d\x0a \
+ benutzerNam\
+e.clear()\x0d\x0a \
+ benutzerNamel\
+abel.color = \x22re\
+d\x22\x0d\x0a benu\
+tzerNamelabel.fo\
+nt.bold = true\x0d\x0a\
+ }\x0d\x0a}\x0d\x0a\x0d\x0a\x0d\x0a\
+"
+
+qt_resource_name = b"\
+\x00\x03\
+\x00\x00N\xb9\
+\x00G\
+\x00u\x00i\
+\x00\x0a\
+\x08\x8e<\xbc\
+\x00T\
+\x00o\x00p\x00B\x00a\x00r\x00.\x00q\x00m\x00l\
+\x00\x11\
+\x00\x11r\xdc\
+\x00E\
+\x00n\x00c\x00r\x00y\x00p\x00t\x00i\x00o\x00n\x00K\x00e\x00y\x00.\x00q\x00m\x00l\
+\
+\x00\x0f\
+\x07\xc70\x5c\
+\x00L\
+\x00o\x00g\x00i\x00n\x00S\x00c\x00r\x00e\x00e\x00n\x00.\x00q\x00m\x00l\
+\x00\x06\
+\x07\x84+\x02\
+\x00q\
+\x00m\x00l\x00d\x00i\x00r\
+\x00\x13\
+\x0aQ\xd8\x1c\
+\x00D\
+\x00b\x00C\x00o\x00n\x00f\x00i\x00g\x00u\x00r\x00a\x00t\x00i\x00o\x00n\x00.\x00q\
+\x00m\x00l\
+\x00\x13\
+\x01\xa7!\xbc\
+\x00A\
+\x00d\x00m\x00i\x00n\x00U\x00s\x00e\x00r\x00C\x00o\x00n\x00f\x00i\x00g\x00.\x00q\
+\x00m\x00l\
+"
+
+qt_resource_struct = b"\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
+\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x06\x00\x00\x00\x02\
+\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00&\x00\x00\x00\x00\x00\x01\x00\x00\x01\xdc\
+\x00\x00\x01\x93q\xc1B\xf5\
+\x00\x00\x00\xb0\x00\x00\x00\x00\x00\x01\x00\x00\x08\x94\
+\x00\x00\x01\x93\x87\xd8o\x8c\
+\x00\x00\x00r\x00\x00\x00\x00\x00\x01\x00\x00\x06c\
+\x00\x00\x01\x93>1\xe8\xfe\
+\x00\x00\x00N\x00\x00\x00\x00\x00\x01\x00\x00\x059\
+\x00\x00\x01\x93\x8b\xaf\xbcY\
+\x00\x00\x00\x0c\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\
+\x00\x00\x01\x93\x87$\x0bw\
+\x00\x00\x00\x84\x00\x01\x00\x00\x00\x01\x00\x00\x06\x8a\
+\x00\x00\x01\x93q\xc1B\xf4\
+"
+
+def qInitResources():
+ QtCore.qRegisterResourceData(0x03, qt_resource_struct, qt_resource_name, qt_resource_data)
+
+def qCleanupResources():
+ QtCore.qUnregisterResourceData(0x03, qt_resource_struct, qt_resource_name, qt_resource_data)
+
+qInitResources()