From 7157176b5b5f607bfab1ebc5567d505887523ae5c0ed72a9545a202b577d59ce Mon Sep 17 00:00:00 2001 From: Marco Gatzen Date: Tue, 3 Dec 2024 16:30:56 +0100 Subject: [PATCH] Einloggen funktioniert --- Gui/LoginScreen.qml | 96 +++++++ Gui/firststart.qml | 15 - Gui/main.qml | 2 +- doc/.$Programmstart Diagramm.drawio.dtmp | 288 +++++++++++++++++++ lib/ConfigLoader.py | 3 +- lib/DB/DbManager.py | 19 +- lib/DB/UserDAO.py | 32 +++ lib/DB/UserManager.py | 50 ++-- lib/Vermasseln.py | 6 +- main.py | 5 + pyqcrm.pyproject | 3 +- qml.qrc | 1 + rc_qml.py | 334 +++++++++++++++++++++++ 13 files changed, 804 insertions(+), 50 deletions(-) create mode 100644 Gui/LoginScreen.qml create mode 100644 doc/.$Programmstart Diagramm.drawio.dtmp create mode 100644 lib/DB/UserDAO.py create mode 100644 rc_qml.py 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()