221 lines
7.5 KiB
Python
221 lines
7.5 KiB
Python
# # !/home/linuxero/proj/tero/pyqcrm/.qtcreator/venv-3.13.1/bin/python3
|
||
"""! @brief CRM for cleaning services written in Python, PySide6 and QtQuick."""
|
||
##
|
||
# @mainpage PYQCRM - Qt for Python CRM
|
||
#
|
||
# @section description_main Description
|
||
# A CRM program for digitally manageing the business of cleaning
|
||
# services company.
|
||
#
|
||
# @section notes_main Notes
|
||
# - The project is built using QtCreator 6.8.x
|
||
# - Minimum Python version 3.13.x
|
||
# - PySide6
|
||
#
|
||
# Copyright (c) 2025 Schnaxero. All rights reserved.
|
||
##
|
||
# @file main.py
|
||
#
|
||
# @brief Main entry point of the program
|
||
#
|
||
# @section description_pyqcrm Description
|
||
# Initialization of the program goes here. Various global functions called from the entry point.
|
||
# The GUI application is set up and started here.
|
||
#
|
||
# @section libraries_main Libraries/Modules
|
||
# - <a href="https://docs.python.org/3/library/os.html">os</a> standard library
|
||
# - Access to environ, a mapping object of keys and values to set an environment variable.
|
||
# - <a href="https://docs.python.org/3/library/sys.html">sys</a> standard library
|
||
# - Access to argv and system functions.
|
||
# - <a href="https://docs.python.org/3/library/logging.html">logging</a> standard library
|
||
# - Access to logging functions.
|
||
# - <a href="https://doc.qt.io/qtforpython-6/PySide6/QtNetwork/QLocalServer.html">QLocalServer</a> PySide6 class
|
||
# - Provides a local socket based server.
|
||
# - <a href="https://doc.qt.io/qtforpython-6/PySide6/QtNetwork/QLocalSocket.html">QLocalSocket</a> PySide6 class
|
||
# - Provides a local socket.
|
||
# - <a href="https://doc.qt.io/qtforpython-6/PySide6/QtWidgets/QSystemTrayIcon.html">QSystemTrayIcon</a> PySide6 class
|
||
# - Provides an icon for the application in the system tray.
|
||
# - <a href="https://doc.qt.io/qtforpython-6/PySide6/QtGui/QIcon.html">QIcon</a> PySide6 class
|
||
# - Provides scalable icons in different modes and states.
|
||
# - <a href="https://doc.qt.io/qtforpython-6/PySide6/QtGui/QGuiApplication.html">QGuiApplication</a> PySide6 class
|
||
# - Manages the GUI application’s control flow and main settings.
|
||
# - <a href="https://doc.qt.io/qtforpython-6/PySide6/QtQml/QQmlApplicationEngine.html">QQmlApplicationEngine</a> PySide6 class
|
||
# - Provides a convenient way to load an application from a single QML file.
|
||
# - <a href="https://doc.qt.io/qtforpython-6/PySide6/QtCore/QIODevice.html">QIODevice</a> PySide6 class
|
||
# - Base interface class of all I/O devices in Qt.
|
||
# - lib module (local)
|
||
# - Backbone classes to run the program.
|
||
#
|
||
# @section notes_pyqcrm Notes
|
||
# - Install dependencies (See requirements.txt).
|
||
#
|
||
# @section todo_pyqcrm TODO
|
||
# - A lot of nice-to-haves.
|
||
#
|
||
# @section author_pyqcrm Author(s)
|
||
# - Created by Linuxero on 03/14/2025.
|
||
# - Modified by Linuxero on 03/14/2025.
|
||
#
|
||
# Copyright (c) 2025 Schnaxero. All rights reserved.
|
||
# Imports
|
||
import os
|
||
import sys
|
||
import logging
|
||
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 lib.ConfigLoader import ConfigLoader
|
||
from lib.DB.BusinessModel import BusinessModel
|
||
import rc_pyqcrm
|
||
import rc_qml
|
||
from lib.DB.DbManager import DbManager
|
||
from lib.DB.UserManager import UserManager
|
||
from lib.DB.AddressModel import AddressModel
|
||
from lib.DB.BTypeModel import BTypeModel
|
||
from lib.DB.ContactModel import ContactModel
|
||
from lib.DB.EmployeeModel import EmployeeModel
|
||
from lib.DB.ObjectModel import ObjectModel
|
||
from lib.Printers import Printers
|
||
|
||
# Environment settings
|
||
## Allow local file read.
|
||
os.environ['QML_XHR_ALLOW_FILE_READ'] = '1'
|
||
|
||
# [pyqcrm]
|
||
# program-name=""
|
||
# version=
|
||
|
||
# [database]
|
||
# server=""
|
||
# port=
|
||
# user=""
|
||
# password=""
|
||
# name=""
|
||
# type=""
|
||
|
||
# Global Constants
|
||
## Configuration availability.
|
||
bad_config = False
|
||
|
||
## Database connection available.
|
||
db_con = False
|
||
|
||
## The model class for address manipulation.
|
||
address_model = None
|
||
|
||
## The model class for customer manipulation.
|
||
business_model = None
|
||
|
||
## The model class for customer type manipulation.
|
||
business_type = None
|
||
|
||
## The model class for contact manipulation.
|
||
contact_model = None
|
||
|
||
## The model class for employee manipulation.
|
||
employee_model = None
|
||
|
||
## The model class for object manipulation.
|
||
object_model = None
|
||
|
||
## The class of available printers on the system.
|
||
printers = None
|
||
|
||
## The logged-in user.
|
||
user = None
|
||
|
||
# Functions
|
||
def initializeProgram():
|
||
"""! Initializes the program."""
|
||
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
|
||
if not bad_config:
|
||
dbconf = config.getConfig()['database']
|
||
DbManager(dbconf)
|
||
printers = Printers()
|
||
if DbManager().getConnection():
|
||
db_con = True
|
||
user = UserManager()
|
||
business_model = BusinessModel()
|
||
address_model = AddressModel()
|
||
business_type = BTypeModel()
|
||
contact_model = ContactModel()
|
||
employee_model = EmployeeModel()
|
||
object_model = ObjectModel()
|
||
publishContext()
|
||
|
||
def configReady():
|
||
"""! Slot to respond to the validity of the configuration."""
|
||
global bad_config
|
||
bad_config = False
|
||
initializeProgram()
|
||
|
||
|
||
def publishContext():
|
||
"""! Connect necessary modules to the QML GUI."""
|
||
# print(f"In {__file__} file, publishContext()")
|
||
global engine, address_model, bad_config, business_model, user, business_type, contact_model, object_model, employee_model, printers
|
||
engine.rootContext().setContextProperty("loggedin_user", user)
|
||
engine.rootContext().setContextProperty("business_model", business_model)
|
||
engine.rootContext().setContextProperty("address_model", address_model)
|
||
engine.rootContext().setContextProperty("business_type", business_type)
|
||
engine.rootContext().setContextProperty("contact_model", contact_model)
|
||
engine.rootContext().setContextProperty("employee_model", employee_model)
|
||
engine.rootContext().setContextProperty("object_model", object_model)
|
||
|
||
# Entry point of the program
|
||
if __name__ == "__main__":
|
||
#QResource.registerResource("rc_qml.py")
|
||
app = QGuiApplication(sys.argv)
|
||
engine = QQmlApplicationEngine()
|
||
|
||
|
||
pyq_sok = QLocalSocket()
|
||
pyq_sok.connectToServer("PYQCRM_INSTANCE", QIODevice.ReadOnly)
|
||
|
||
if pyq_sok.state() == QLocalSocket.ConnectedState:
|
||
print("PYQCRM already running..")
|
||
print("Stop the running instance before running the application..")
|
||
sys.exit(-1)
|
||
else:
|
||
print("Starting PYQCRM_INSTANCE")
|
||
pyq_server = QLocalServer()
|
||
pyq_server.listen("PYQCRM_INSTANCE")
|
||
|
||
engine.addImportPath("qrc:/")
|
||
engine.addImportPath("qrc:/Style")
|
||
|
||
# qml_file = Path(__file__).resolve().parent / "Gui/main.qml"
|
||
|
||
qml_file = "qrc:/Gui/main.qml"
|
||
|
||
icon = QIcon(":/images/tero.jpg")
|
||
app.setWindowIcon(icon)
|
||
|
||
tray = QSystemTrayIcon()
|
||
tray.setIcon(icon)
|
||
tray.setToolTip("PYQCRM")
|
||
|
||
config = ConfigLoader()
|
||
|
||
if not config.getConfig():
|
||
bad_config = True
|
||
config.configurationReady.connect(configReady)
|
||
else:
|
||
initializeProgram()
|
||
|
||
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("db_con", db_con)
|
||
engine.rootContext().setContextProperty("systray", tray)
|
||
|
||
engine.load(qml_file)
|
||
|
||
|
||
if not engine.rootObjects():
|
||
sys.exit(-1)
|
||
sys.exit(app.exec())
|