Style Buttons, re-layout Login

This commit is contained in:
Yuri Becker
2025-03-13 17:23:36 +01:00
parent 343e15c873
commit 7099102e13
21 changed files with 278 additions and 251 deletions

17
.idea/QtSettings.xml generated Normal file
View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="QtSettings">
<option name="mySettingsPerProfile">
<map>
<entry key="">
<value>
<PerProfileState>
<option name="myCustomQmlPath" value="/opt/homebrew/share/qt/qml" />
<option name="myCustomQtBinPath" value="/opt/homebrew/bin" />
</PerProfileState>
</value>
</entry>
</map>
</option>
</component>
</project>

17
.idea/qmlSettings.xml generated Normal file
View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="QmlSettings">
<option name="mySettingsPerProfile">
<map>
<entry key="">
<value>
<PerProfileState>
<option name="myLSPEnabled" value="true" />
<option name="myQmlFormatEnabled" value="true" />
</PerProfileState>
</value>
</entry>
</map>
</option>
</component>
</project>

View File

@@ -0,0 +1,17 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Compile pyqcrm.qrc" type="ShConfigurationType">
<option name="SCRIPT_TEXT" value=".venv/bin/pyside6-rcc -o rc_pyqcrm.py pyqcrm.qrc" />
<option name="INDEPENDENT_SCRIPT_PATH" value="true" />
<option name="SCRIPT_PATH" value=".venv/bin/pyside6-rcc" />
<option name="SCRIPT_OPTIONS" value="-o rc_qml.py qml.qrc" />
<option name="INDEPENDENT_SCRIPT_WORKING_DIRECTORY" value="true" />
<option name="SCRIPT_WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="INDEPENDENT_INTERPRETER_PATH" value="true" />
<option name="INTERPRETER_PATH" value="/bin/zsh" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="EXECUTE_IN_TERMINAL" value="false" />
<option name="EXECUTE_SCRIPT_FILE" value="false" />
<envs />
<method v="2" />
</configuration>
</component>

View File

@@ -0,0 +1,17 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Compile qml.qrc" type="ShConfigurationType">
<option name="SCRIPT_TEXT" value=".venv/bin/pyside6-rcc -o rc_qml.py qml.qrc" />
<option name="INDEPENDENT_SCRIPT_PATH" value="true" />
<option name="SCRIPT_PATH" value=".venv/bin/pyside6-rcc" />
<option name="SCRIPT_OPTIONS" value="-o rc_qml.py qml.qrc" />
<option name="INDEPENDENT_SCRIPT_WORKING_DIRECTORY" value="true" />
<option name="SCRIPT_WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="INDEPENDENT_INTERPRETER_PATH" value="true" />
<option name="INTERPRETER_PATH" value="/bin/zsh" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="EXECUTE_IN_TERMINAL" value="false" />
<option name="EXECUTE_SCRIPT_FILE" value="false" />
<envs />
<method v="2" />
</configuration>
</component>

31
.idea/runConfigurations/main.xml generated Normal file
View File

@@ -0,0 +1,31 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="main" type="PythonConfigurationType" factoryName="Python" nameIsGenerated="true">
<module name="pyqcrm" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs>
<env name="PYTHONUNBUFFERED" value="1" />
<env name="QT_LOGGING_RULES" value="*.debug=true; qt.*.debug=false" />
<env name="QT_LOGGING_TO_CONSOLE" value="1" />
<env name="QT_QML_DEBUG" value="1" />
</envs>
<option name="SDK_HOME" value="" />
<option name="SDK_NAME" value="Python 3.12 (pyqcrm)" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="IS_MODULE_SDK" value="false" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/main.py" />
<option name="PARAMETERS" value="" />
<option name="SHOW_COMMAND_LINE" value="false" />
<option name="EMULATE_TERMINAL" value="false" />
<option name="MODULE_MODE" value="false" />
<option name="REDIRECT_INPUT" value="false" />
<option name="INPUT_FILE" value="" />
<method v="2">
<option name="RunConfigurationTask" enabled="true" run_configuration_name="Compile qml.qrc" run_configuration_type="ShConfigurationType" />
<option name="RunConfigurationTask" enabled="true" run_configuration_name="Compile pyqcrm.qrc" run_configuration_type="ShConfigurationType" />
</method>
</configuration>
</component>

45
.idea/watcherTasks.xml generated
View File

@@ -1,45 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectTasksOptions">
<TaskOptions isEnabled="true">
<option name="arguments" value="-o rc_qml.py qml.qrc" />
<option name="checkSyntaxErrors" value="true" />
<option name="description" />
<option name="exitCodeBehavior" value="ERROR" />
<option name="fileExtension" value="qml" />
<option name="immediateSync" value="true" />
<option name="name" value="qml.qrc" />
<option name="output" value="" />
<option name="outputFilters">
<array />
</option>
<option name="outputFromStdout" value="false" />
<option name="program" value="$PROJECT_DIR$/.venv/bin/pyside6-rcc" />
<option name="runOnExternalChanges" value="true" />
<option name="scopeName" value="Project Files" />
<option name="trackOnlyRoot" value="false" />
<option name="workingDir" value="$PROJECT_DIR$" />
<envs />
</TaskOptions>
<TaskOptions isEnabled="true">
<option name="arguments" value="-o rc_pyqcrm.py pyqcrm.qrc" />
<option name="checkSyntaxErrors" value="true" />
<option name="description" />
<option name="exitCodeBehavior" value="ERROR" />
<option name="fileExtension" value="qml" />
<option name="immediateSync" value="true" />
<option name="name" value="pyqcrm.qrc" />
<option name="output" value="" />
<option name="outputFilters">
<array />
</option>
<option name="outputFromStdout" value="false" />
<option name="program" value="$PROJECT_DIR$/.venv/bin/pyside6-rcc" />
<option name="runOnExternalChanges" value="true" />
<option name="scopeName" value="Project Files" />
<option name="trackOnlyRoot" value="false" />
<option name="workingDir" value="$PROJECT_DIR$" />
<envs />
</TaskOptions>
</component>
</project>

View File

@@ -3,226 +3,128 @@ 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
ColumnLayout
{
Component.onCompleted: {
loggedin_user.loginOkay.connect(loggedin);
config.invalidEncryptionKey.connect(getEncryptionKey);
config.checkEncryptionKey();
loggedin_user.noDbConnection.connect(dbConnectionFailed);
benutzerName.forceActiveFocus();
}
ColumnLayout {
anchors.fill: parent
FontLoader
{
id: helloStranger
source: "qrc:/fonts/HelloStranger.otf"
spacing: Dimensions.m
Label {
font: Typography.h1
text: qsTr("Login")
}
FontLoader
{
id: damarWulan
source: "qrc:/fonts/Damarwulan.ttf"
Label {
text: qsTr("Benutzername")
}
TextField {
id: benutzerName
focus: true
implicitWidth: 300
placeholderText: qsTr("Benutzernamen eingeben")
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
Layout.alignment: Qt.AlignHCenter
color: "yellow"
}
Item
{
height: 25
}
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
onAccepted: {
if (benutzerName.text.trim() && passwort.text.trim())
loggedin_user.login(benutzerName.text.trim(), passwort.text);
else if (benutzerName.text.trim())
passwort.forceActiveFocus();
}
}
Label {
text: qsTr("Passwort")
}
TextField {
id: passwort
echoMode: TextInput.Password
implicitWidth: 300
placeholderText: qsTr("Passwort eingeben")
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()
}
onAccepted: {
if (benutzerName.text.trim() && passwort.text.trim())
loggedin_user.login(benutzerName.text.trim(), passwort.text);
else if (passwort.text.trim())
benutzerName.forceActiveFocus();
}
}
Button {
text: qsTr("Primary")
onClicked: {
if (benutzerName.text.trim() && passwort.text.trim())
loggedin_user.login(benutzerName.text.trim(), passwort.text);
}
}
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
echoMode: TextInput.Password
onAccepted:
{
if (benutzerName.text.trim() && passwort.text.trim())
loggedin_user.login(benutzerName.text.trim(), passwort.text)
else if(passwort.text.trim()) benutzerName.forceActiveFocus()
}
}
}
RowLayout
{
Layout.preferredWidth: 465
Layout.alignment: Qt.AlignHCenter
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)
}
}
}
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()
}
}

View File

@@ -1,8 +0,0 @@
import QtQuick
import QtQuick.Controls.Basic
Button {
background: Rectangle {
radius: 4003
}
}

View File

@@ -1,3 +0,0 @@
module TeroStyle
singleton Colors Colors.qml
Button Button.qml

View File

@@ -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

30
TeroStyle/Button.qml Normal file
View File

@@ -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
}
}

11
TeroStyle/Dimensions.qml Normal file
View File

@@ -0,0 +1,11 @@
pragma Singleton
import QtQuick
QtObject {
readonly property int s: 9
readonly property int m: 15
readonly property int l: 30
readonly property int radius: 4
}

33
TeroStyle/Typography.qml Normal file
View File

@@ -0,0 +1,33 @@
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
})
//
// readonly property font h2: ({
// family: regular.font,
// pointSize: 38,
// weight: Font.Normal
// })
}

5
TeroStyle/qmldir Normal file
View File

@@ -0,0 +1,5 @@
module TeroStyle
singleton Colors Colors.qml
singleton Dimensions Dimensions.qml
singleton Typography Typography.qml
Button Button.qml

Binary file not shown.

Binary file not shown.

BIN
fonts/RobotoCondensed.otf Normal file

Binary file not shown.

15
main.py
View File

@@ -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())

View File

@@ -16,7 +16,7 @@
<file>fonts/HelloStranger.otf</file>
<file>fonts/HussarPrintA.otf</file>
<file>fonts/LittleBirdsRegular.ttf</file>
<file>fonts/ReginaldScript.ttf</file>
<file>fonts/RobotoCondensed.otf</file>
<file>images/account.svg</file>
<file>README</file>
<file>LICENSE</file>

View File

@@ -49,7 +49,12 @@
<file>Gui/UtilityDialogs.qml</file>
<file>Gui/OffersTable.qml</file>
<file>Gui/OfferTable.qml</file>
<file>Gui/Style/qmldir</file>
<file>Gui/Style/Button.qml</file>
<file>TeroStyle/Button.qml</file>
<file>TeroStyle/Colors.qml</file>
<file>TeroStyle/Dimensions.qml</file>
<file>TeroStyle/qmldir</file>
<file>TeroStyle/Typography.qml</file>
</qresource>
<qresource prefix="/TeroStyle"/>
</RCC>