diff --git a/.idea/QtSettings.xml b/.idea/QtSettings.xml new file mode 100644 index 0000000..a6b7798 --- /dev/null +++ b/.idea/QtSettings.xml @@ -0,0 +1,17 @@ + + + + + + \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..244a3c0 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/qmlSettings.xml b/.idea/qmlSettings.xml new file mode 100644 index 0000000..55ca8a9 --- /dev/null +++ b/.idea/qmlSettings.xml @@ -0,0 +1,17 @@ + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations/Compile_pyqcrm_qrc.xml b/.idea/runConfigurations/Compile_pyqcrm_qrc.xml new file mode 100644 index 0000000..85533b5 --- /dev/null +++ b/.idea/runConfigurations/Compile_pyqcrm_qrc.xml @@ -0,0 +1,17 @@ + + + + \ No newline at end of file diff --git a/.idea/runConfigurations/Compile_qml_qrc.xml b/.idea/runConfigurations/Compile_qml_qrc.xml new file mode 100644 index 0000000..080cbbe --- /dev/null +++ b/.idea/runConfigurations/Compile_qml_qrc.xml @@ -0,0 +1,17 @@ + + + + \ No newline at end of file diff --git a/.idea/runConfigurations/main.xml b/.idea/runConfigurations/main.xml new file mode 100644 index 0000000..e41afc4 --- /dev/null +++ b/.idea/runConfigurations/main.xml @@ -0,0 +1,31 @@ + + + + + \ No newline at end of file diff --git a/.idea/watcherTasks.xml b/.idea/watcherTasks.xml deleted file mode 100644 index 887bd74..0000000 --- a/.idea/watcherTasks.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/Gui/CompanyConf.qml b/Gui/CompanyConf.qml index ff60813..d76f9af 100644 --- a/Gui/CompanyConf.qml +++ b/Gui/CompanyConf.qml @@ -66,8 +66,6 @@ ColumnLayout Label { text: qsTr("PLZ") - // font.pixelSize: 57 - // font.bold: true } ComboBox diff --git a/Gui/LoginScreen.qml b/Gui/LoginScreen.qml index 7fbe4d6..c3cc942 100644 --- a/Gui/LoginScreen.qml +++ b/Gui/LoginScreen.qml @@ -3,226 +3,138 @@ import QtQuick import QtQuick.Controls import QtQuick.Dialogs import QtQuick.Layouts +import TeroStyle - -Item -{ +Item { property string recpass: "" + + function dbConnectionFailed(msg) { + oschkar.notificationBox.informativeText = msg; + oschkar.notificationBox.text = "Verbindung zum Datenbankserver verloren"; + oschkar.notificationBox.open(); + } + function getEncryptionKey() { + recoveryPaswordDialog.open(); + } + function loggedin() { + appLoader.source = "Dashboard.qml"; + } + anchors.fill: parent + anchors.topMargin: Dimensions.l - ColumnLayout - { + Component.onCompleted: { + loggedin_user.loginOkay.connect(loggedin); + config.invalidEncryptionKey.connect(getEncryptionKey); + config.checkEncryptionKey(); + loggedin_user.noDbConnection.connect(dbConnectionFailed); + benutzerName.forceActiveFocus(); + } - anchors.fill: parent + ColumnLayout { + spacing: Dimensions.m + anchors.centerIn: parent - FontLoader - { - id: helloStranger - source: "qrc:/fonts/HelloStranger.otf" - } - - FontLoader - { - id: damarWulan - source: "qrc:/fonts/Damarwulan.ttf" - } - - FontLoader - { - id: hussarPrint - source: "qrc:/fonts/HussarPrintA.otf" - } - - FontLoader - { - id: reginaldScript - source: "qrc:/fonts/ReginaldScript.ttf" - } - - Item - { - height: 65 - } - - Label - { - text: qsTr ("Login*****") - font.family: helloStranger.font.family - font.weight: helloStranger.font.weight - font.styleName: helloStranger.font.styleName - font.pixelSize: 89 - font.bold: true + Label { + font: Typography.h1 + text: qsTr("Login") Layout.alignment: Qt.AlignHCenter - color: "yellow" + Layout.bottomMargin: Dimensions.l } - Item - { - height: 25 - } + Field { + label: qsTr("Benutzername") - RowLayout - { - Layout.alignment: Qt.AlignHCenter - spacing: 15 - - Label - { - text: qsTr ("Benutzername") - minimumPixelSize: 20 - Layout.preferredWidth: 150 - horizontalAlignment: Text.AlignRight - font.family: damarWulan.font.family - font.weight: damarWulan.font.weight - font.styleName: damarWulan.font.styleName - font.pixelSize: 21 - } - - TextField - { + TextField { id: benutzerName - placeholderText: qsTr ("Benutzernamen eingeben") - implicitWidth: 300 - font: hussarPrint.font + focus: true - onAccepted: - { - if (benutzerName.text.trim() && passwort.text.trim()) - loggedin_user.login(benutzerName.text.trim(), passwort.text) - else if(benutzerName.text.trim()) passwort.forceActiveFocus() - } - } - } - - RowLayout - { - Layout.alignment: Qt.AlignHCenter - spacing: 15 - - Label - { - minimumPixelSize: 20 - Layout.preferredWidth: 150 - text: qsTr ("Passwort") - font.family: damarWulan.font.family - font.weight: damarWulan.font.weight - font.styleName: damarWulan.font.styleName - font.pixelSize: 21 - horizontalAlignment: Text.AlignRight - } - - TextField - { - id: passwort - placeholderText: qsTr ("Passwort eingeben") implicitWidth: 300 - font: hussarPrint.font + placeholderText: qsTr("Benutzernamen eingeben") + + onAccepted: { + if (benutzerName.text.trim() && passwort.text.trim()) + loggedin_user.login(benutzerName.text.trim(), passwort.text); + else if (benutzerName.text.trim()) + passwort.forceActiveFocus(); + } + } + } + Field { + label: qsTr("Passwort") + + TextField { + id: passwort + echoMode: TextInput.Password - onAccepted: - { + implicitWidth: 300 + placeholderText: qsTr("Passwort eingeben") + + onAccepted: { if (benutzerName.text.trim() && passwort.text.trim()) - loggedin_user.login(benutzerName.text.trim(), passwort.text) - else if(passwort.text.trim()) benutzerName.forceActiveFocus() + loggedin_user.login(benutzerName.text.trim(), passwort.text); + else if (passwort.text.trim()) + benutzerName.forceActiveFocus(); } } } - RowLayout - { - Layout.preferredWidth: 465 - Layout.alignment: Qt.AlignHCenter + Button { + Layout.topMargin: Dimensions.m + text: qsTr("Login") + width: parent.width - Button - { - text: qsTr ("Feierabend für heute!") - Layout.alignment: Qt.AlignRight - font: reginaldScript.font - onClicked: - { - if (benutzerName.text.trim() && passwort.text.trim()) - loggedin_user.login(benutzerName.text.trim(), passwort.text) - } + onClicked: { + if (benutzerName.text.trim() && passwort.text.trim()) + loggedin_user.login(benutzerName.text.trim(), passwort.text); } } - - Item - { + Item { Layout.fillHeight: true - } - - Dialog - { + Dialog { id: recoveryPaswordDialog - modal: true - title: qsTr("Wiederherstellung") + anchors.centerIn: parent + modal: true standardButtons: Dialog.Ok | Dialog.Cancel - onAccepted: - { - recpass = recoveryPaswordInput.text - getRecoveryDialog.open() + title: qsTr("Wiederherstellung") + + onAccepted: { + recpass = recoveryPaswordInput.text; + getRecoveryDialog.open(); } - ColumnLayout - { - RowLayout - { - Label - { + ColumnLayout { + RowLayout { + Label { text: qsTr("Wiederherstellungspasswort eingeben: ") } - - TextField - { + TextField { id: recoveryPaswordInput - text: "" + echoMode: TextInput.Password implicitWidth: 300 placeholderText: qsTr("Hier Wiederherstellungspasswort eingeben") + text: "" } } } } - - FileDialog - { + FileDialog { id: getRecoveryDialog - title: qsTr("Wiederherstellungsdatei") + + currentFolder: StandardPaths.standardLocations(StandardPaths.DocumentsLocation)[0] fileMode: FileDialog.OpenFile nameFilters: ["PYQCRM Recovery files (*.pyqrec)"] - currentFolder: StandardPaths.standardLocations(StandardPaths.DocumentsLocation)[0] + title: qsTr("Wiederherstellungsdatei") + onAccepted: config.getRecoveryKey(getRecoveryDialog.currentFile, recpass) onRejected: quit() } - Notifications - { + Notifications { id: oschkar + } } - - Component.onCompleted: - { - loggedin_user.loginOkay.connect(loggedin) - config.invalidEncryptionKey.connect(getEncryptionKey) - config.checkEncryptionKey() - loggedin_user.noDbConnection.connect(dbConnectionFailed) - benutzerName.forceActiveFocus() - } - - function loggedin() - { - appLoader.source = "Dashboard.qml" - } - - function getEncryptionKey() - { - recoveryPaswordDialog.open() - } - function dbConnectionFailed(msg) - { - oschkar.notificationBox.informativeText = msg - oschkar.notificationBox.text = "Verbindung zum Datenbankserver verloren" - oschkar.notificationBox.open() - } } diff --git a/Gui/main.qml b/Gui/main.qml index cb21ac1..e912e50 100644 --- a/Gui/main.qml +++ b/Gui/main.qml @@ -6,12 +6,13 @@ import QtCore ApplicationWindow { - //property alias appLoader: appLoader id: appWindow width: Screen.width * .75 height: Screen.height * .85 visible: true - title: "PYQCRM" + title: "TERO Personal" + font: Typography.body + color: Colors.mantle property string confile: "" property alias settingsFileDialog: settingsFiledialog diff --git a/TeroStyle/Button.qml b/TeroStyle/Button.qml new file mode 100644 index 0000000..d7e5a3b --- /dev/null +++ b/TeroStyle/Button.qml @@ -0,0 +1,30 @@ +import QtQuick +import QtQuick.Templates as T + +T.Button { + id: control + + implicitHeight: implicitContentHeight + implicitWidth: contentItem.width + + background: Rectangle { + color: Colors.primary + radius: Dimensions.radius + } + contentItem: Text { + color: Colors.foreground + font: control.font + padding: Dimensions.s + 2 + text: control.text + // Make sure the button is at least wide enough to be comfortably clickable + width: Math.max(implicitWidth, 120) + horizontalAlignment: Text.AlignHCenter + } + + MouseArea { + id: mouseArea + anchors.fill: parent + cursorShape: Qt.PointingHandCursor + onPressed: (mouse) => mouse.accepted = false + } +} diff --git a/TeroStyle/Colors.qml b/TeroStyle/Colors.qml new file mode 100644 index 0000000..c5844a7 --- /dev/null +++ b/TeroStyle/Colors.qml @@ -0,0 +1,19 @@ +pragma Singleton + +import QtQuick + +QtObject { + readonly property int dark: 0 + readonly property int light: 1 + + property int theme: dark + + readonly property color primary: "#b81a34" + readonly property color foreground: theme === dark ? "#fdfdfd" : "#110b0c" + readonly property color background: theme === dark ? "#303136" : "#eff1f5" + readonly property color mantle: theme === dark ? "#1e1f22" : "#e7e9ef" + readonly property color interactive: theme === dark ? "#878b97" : "#d9d9da" + readonly property color error: theme === dark ? "#ff2264" : "#ff004b" + + readonly property double highlightOpacity: .3 +} \ No newline at end of file diff --git a/TeroStyle/ComboBox.qml b/TeroStyle/ComboBox.qml new file mode 100644 index 0000000..b97e813 --- /dev/null +++ b/TeroStyle/ComboBox.qml @@ -0,0 +1,75 @@ +import QtQuick +import QtQuick.Templates as T +import QtQuick.Controls + +T.ComboBox { + id: control + + font: Typography.body + implicitHeight: background.height + padding: Dimensions.m + + background: Rectangle { + border.color: Colors.interactive + border.width: 1 + color: Colors.mantle + height: 47 + radius: Dimensions.radius + } + + delegate: T.ItemDelegate { + width: control.width + height: implicitContentHeight + topPadding + bottomPadding + padding: Dimensions.s + leftPadding: control.leftPadding + contentItem: Label { + text: control.textRole ? model[control.textRole] : modelData + color: Colors.foreground + elide: Text.ElideRight + verticalAlignment: Text.AlignVCenter + } + highlighted: control.highlightedIndex === index + } + indicator: Label { + x: control.width - width + height: control.height + width: contentWidth + Dimensions.s * 2 + text: "▼" + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + padding: Dimensions.s + + background: Rectangle { + anchors.fill: parent + color: Colors.primary + topRightRadius: Dimensions.radius + bottomRightRadius: Dimensions.radius + border.color: Colors.interactive + } + } + + popup: T.Popup { + y: control.height + z: 2 + width: control.width + contentItem: ListView { + clip: true + implicitHeight: contentHeight + model: control.popup.visible ? control.delegateModel : null + currentIndex: control.highlightedIndex + + highlight: Rectangle { + color: Colors.primary + opacity: Colors.highlightOpacity + } + + ScrollIndicator.vertical: ScrollIndicator {} + } + + background: Rectangle { + color: Colors.mantle + border.color: Colors.interactive + radius: Dimensions.radius + } + } +} \ No newline at end of file diff --git a/TeroStyle/Dimensions.qml b/TeroStyle/Dimensions.qml new file mode 100644 index 0000000..0b15c64 --- /dev/null +++ b/TeroStyle/Dimensions.qml @@ -0,0 +1,25 @@ +pragma Singleton + +import QtQuick + +QtObject { + /** + * Distance for objects that are tied to each other, + * e.g. a field and its label. + */ + readonly property int s: 9 + + /** + * Distance for objects that are grouped together, e.g. radio buttons of the + * same radio group. + */ + readonly property int m: 15 + + /** + * Distance for objects that are not related to each other, or to objects + * and their container. + */ + readonly property int l: 30 + + readonly property int radius: 4 +} \ No newline at end of file diff --git a/TeroStyle/Field.qml b/TeroStyle/Field.qml new file mode 100644 index 0000000..4a3a3dd --- /dev/null +++ b/TeroStyle/Field.qml @@ -0,0 +1,13 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts + +ColumnLayout { + required property string label + spacing: Dimensions.s + + Label { + text: label + font: Typography.body + } +} \ No newline at end of file diff --git a/TeroStyle/TextField.qml b/TeroStyle/TextField.qml new file mode 100644 index 0000000..b5f8da9 --- /dev/null +++ b/TeroStyle/TextField.qml @@ -0,0 +1,20 @@ +import QtQuick +import QtQuick.Templates as T + +T.TextField { + id: control + background: Rectangle { + id: background + color: Colors.mantle + radius: Dimensions.radius + border.width: !control.focus ? 1 : 2 + border.color: Colors.interactive + height: 47 + } + + color: Colors.foreground + implicitHeight: background.height + placeholderTextColor: Colors.interactive + font: Typography.body + padding: Dimensions.m +} \ No newline at end of file diff --git a/TeroStyle/Typography.qml b/TeroStyle/Typography.qml new file mode 100644 index 0000000..ec5e21f --- /dev/null +++ b/TeroStyle/Typography.qml @@ -0,0 +1,26 @@ +pragma Singleton + +import QtCore +import QtQuick + +Item { + readonly property FontLoader robotoCondensed: FontLoader { + source: "qrc:/fonts/RobotoCondensed.otf" + } + + readonly property font body: ({ + family: robotoCondensed.font, + pointSize: 16, + weight: Font.Medium, + letterSpacing: 0, + kerning: true, + }) + + readonly property font h1: ({ + family: body.family, + pointSize: 38, + weight: body.weight, + letterSpacing: body.letterSpacing, + kerning: body.kerning, + }) +} \ No newline at end of file diff --git a/TeroStyle/qmldir b/TeroStyle/qmldir new file mode 100644 index 0000000..e95abc1 --- /dev/null +++ b/TeroStyle/qmldir @@ -0,0 +1,8 @@ +module TeroStyle +singleton Colors Colors.qml +singleton Dimensions Dimensions.qml +singleton Typography Typography.qml +Button Button.qml +ComboBox ComboBox.qml +Field Field.qml +TextField TextField.qml \ No newline at end of file diff --git a/fonts/BeautifulPeople.ttf b/fonts/BeautifulPeople.ttf deleted file mode 100644 index f699e7e..0000000 Binary files a/fonts/BeautifulPeople.ttf and /dev/null differ diff --git a/fonts/Damarwulan.ttf b/fonts/Damarwulan.ttf deleted file mode 100644 index 20d9fac..0000000 Binary files a/fonts/Damarwulan.ttf and /dev/null differ diff --git a/fonts/HelloStranger.otf b/fonts/HelloStranger.otf deleted file mode 100644 index 61cdd2e..0000000 Binary files a/fonts/HelloStranger.otf and /dev/null differ diff --git a/fonts/HussarPrintA.otf b/fonts/HussarPrintA.otf deleted file mode 100644 index cab9d2f..0000000 Binary files a/fonts/HussarPrintA.otf and /dev/null differ diff --git a/fonts/LittleBirdsRegular.ttf b/fonts/LittleBirdsRegular.ttf deleted file mode 100644 index 942ec04..0000000 Binary files a/fonts/LittleBirdsRegular.ttf and /dev/null differ diff --git a/fonts/ReginaldScript.ttf b/fonts/ReginaldScript.ttf deleted file mode 100644 index eabce3d..0000000 Binary files a/fonts/ReginaldScript.ttf and /dev/null differ diff --git a/fonts/RobotoCondensed.otf b/fonts/RobotoCondensed.otf new file mode 100644 index 0000000..1bb498a Binary files /dev/null and b/fonts/RobotoCondensed.otf differ diff --git a/main.py b/main.py index a522bd0..6336235 100644 --- a/main.py +++ b/main.py @@ -6,7 +6,7 @@ from PySide6.QtNetwork import QLocalServer, QLocalSocket from PySide6.QtWidgets import QSystemTrayIcon from PySide6.QtGui import QGuiApplication, QIcon from PySide6.QtQml import QQmlApplicationEngine -from PySide6.QtCore import QIODevice #, QResource +from PySide6.QtCore import QIODevice from lib.ConfigLoader import ConfigLoader from lib.DB.BusinessModel import BusinessModel import rc_pyqcrm @@ -20,7 +20,6 @@ from lib.DB.EmployeeModel import EmployeeModel from lib.DB.ObjectModel import ObjectModel from lib.Printers import Printers - os.environ['QML_XHR_ALLOW_FILE_READ'] = '1' # [pyqcrm] @@ -47,6 +46,7 @@ object_model = None printers = None user = None + def initializeProgram(): print(f"In {__file__} file, initializeProgram()") global address_model, bad_config, business_model, user, business_type, contact_model, employee_model, object_model, db_con, printers @@ -65,6 +65,7 @@ def initializeProgram(): object_model = ObjectModel() publishContext() + def configReady(): global bad_config bad_config = False @@ -82,12 +83,11 @@ def publishContext(): engine.rootContext().setContextProperty("employee_model", employee_model) engine.rootContext().setContextProperty("object_model", object_model) + if __name__ == "__main__": - #QResource.registerResource("rc_qml.py") app = QGuiApplication(sys.argv) engine = QQmlApplicationEngine() - pyq_sok = QLocalSocket() pyq_sok.connectToServer("PYQCRM_INSTANCE", QIODevice.ReadOnly) @@ -100,9 +100,7 @@ if __name__ == "__main__": pyq_server = QLocalServer() pyq_server.listen("PYQCRM_INSTANCE") - engine.addImportPath("qrc:/"); - - # qml_file = Path(__file__).resolve().parent / "Gui/main.qml" + engine.addImportPath("qrc:/") qml_file = "qrc:/Gui/main.qml" @@ -123,13 +121,12 @@ if __name__ == "__main__": engine.rootContext().setContextProperty("config", config) engine.rootContext().setContextProperty("sys_printers", printers) - engine.rootContext().setContextProperty("bad_config", bad_config) # print(f"Fehler: {i}") + engine.rootContext().setContextProperty("bad_config", bad_config) engine.rootContext().setContextProperty("db_con", db_con) engine.rootContext().setContextProperty("systray", tray) engine.load(qml_file) - if not engine.rootObjects(): sys.exit(-1) sys.exit(app.exec()) diff --git a/pyqcrm.qrc b/pyqcrm.qrc index cc9b28b..5fb0d1b 100644 --- a/pyqcrm.qrc +++ b/pyqcrm.qrc @@ -12,11 +12,7 @@ sounds/puzzerr.ogg sounds/sysnotify.ogg sounds/wrong.ogg - fonts/Damarwulan.ttf - fonts/HelloStranger.otf - fonts/HussarPrintA.otf - fonts/LittleBirdsRegular.ttf - fonts/ReginaldScript.ttf + fonts/RobotoCondensed.otf images/account.svg README LICENSE diff --git a/qml.qrc b/qml.qrc index 83f2403..bd61e1b 100644 --- a/qml.qrc +++ b/qml.qrc @@ -49,5 +49,15 @@ Gui/UtilityDialogs.qml Gui/OffersTable.qml Gui/OfferTable.qml + TeroStyle/Button.qml + TeroStyle/Colors.qml + TeroStyle/ComboBox.qml + TeroStyle/Field.qml + TeroStyle/Dimensions.qml + TeroStyle/qmldir + TeroStyle/TextField.qml + TeroStyle/Typography.qml + + diff --git a/qtquickcontrols2.conf b/qtquickcontrols2.conf index f0d0a6e..ad97e39 100644 --- a/qtquickcontrols2.conf +++ b/qtquickcontrols2.conf @@ -1,2 +1,2 @@ [Controls] -Style=Fusion +Style=TeroStyle