diff options
| author | Debulois <quentin@debulois.fr> | 2022-05-05 16:17:58 +0200 |
|---|---|---|
| committer | Debulois <quentin@debulois.fr> | 2022-05-05 16:17:58 +0200 |
| commit | d12ff4871844043e7a9e06a63a79c6e415ade936 (patch) | |
| tree | 490625d179de9b754b5056d29b8726143098e61c | |
| parent | 809f5c2c7ce0bdf05287c6f1b5ec1330efb0c469 (diff) | |
Tous les fichiers sont commentés
| -rw-r--r-- | main.spec | 51 | ||||
| -rw-r--r-- | src/app/mainHome.py | 77 | ||||
| -rw-r--r-- | src/app/mainLogin.py | 65 | ||||
| -rw-r--r-- | src/app/mainLogout.py | 15 | ||||
| -rw-r--r-- | src/app/mainMenuBar.py | 38 | ||||
| -rw-r--r-- | src/app/mainRegister.py | 71 | ||||
| -rw-r--r-- | src/app/windowAPropos.py | 11 | ||||
| -rw-r--r-- | src/app/windowAdmin.py | 142 | ||||
| -rw-r--r-- | src/app/windowMissions.py | 129 | ||||
| -rw-r--r-- | src/app/windowRecherche.py | 106 | ||||
| -rw-r--r-- | src/app/windowUserInfo.py | 118 | ||||
| -rw-r--r-- | src/database/dbadmin.py | 34 | ||||
| -rw-r--r-- | src/database/dbmain.py | 10 | ||||
| -rw-r--r-- | src/database/dbmission.py | 8 | ||||
| -rw-r--r-- | src/database/dbsearch.py | 9 | ||||
| -rw-r--r-- | src/database/dbuser.py | 6 | ||||
| -rw-r--r-- | src/main.py | 44 | ||||
| -rw-r--r-- | src/main.spec | 2 | ||||
| -rw-r--r-- | src/setup.iss | 58 | ||||
| -rw-r--r-- | src/setup.py | 22 |
20 files changed, 767 insertions, 249 deletions
diff --git a/main.spec b/main.spec new file mode 100644 index 0000000..05ce173 --- /dev/null +++ b/main.spec @@ -0,0 +1,51 @@ +# -*- mode: python ; coding: utf-8 -*- + + +block_cipher = None + + +a = Analysis( + ['main.py'], + pathex=[], + binaries=[], + datas=[], + hiddenimports=[], + hookspath=[], + hooksconfig={}, + runtime_hooks=[], + excludes=[], + win_no_prefer_redirects=False, + win_private_assemblies=False, + cipher=block_cipher, + noarchive=False, +) +pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher) + +exe = EXE( + pyz, + a.scripts, + [], + exclude_binaries=True, + name='main', + debug=False, + bootloader_ignore_signals=False, + strip=False, + upx=True, + console=False, + disable_windowed_traceback=False, + argv_emulation=False, + target_arch=None, + codesign_identity=None, + entitlements_file=None, + icon='app\\ressources\\icon.ico', +) +coll = COLLECT( + exe, + a.binaries, + a.zipfiles, + a.datas, + strip=False, + upx=True, + upx_exclude=[], + name='main', +) diff --git a/src/app/mainHome.py b/src/app/mainHome.py index a366c66..39a9863 100644 --- a/src/app/mainHome.py +++ b/src/app/mainHome.py @@ -1,4 +1,12 @@ +############################################################################ +# # +# Description: Fenêtre principale avec l'accueil et les éléments pour # +# effectuer une recherche # +# # +############################################################################ + +# Import des éléments de PyQt5 from PyQt5.QtWidgets import ( QGroupBox, QPushButton, QComboBox, QLineEdit, @@ -6,8 +14,9 @@ from PyQt5.QtWidgets import ( QVBoxLayout, QLabel, QMessageBox ) +# Import des éléments locals from src.app import ( - mainLogin, mainRegister, + mainLogin, mainRegister, mainMenuBar, windowRecherche, mainLogout ) @@ -15,9 +24,16 @@ from src.database.dbsearch import DbSearch def core_search_id(mainWindow: object, jobId: int) -> None: - """""" + """ + Recherche les professionnels ayant tel emploi par l'id de ce dernier. + Renvoie le resultat de la recherche vers core_search_main + """ + # Instanciation dbsearch: object = DbSearch(mainWindow) + # Recherche resRecherche: list = dbsearch.get_all_pro_by_jobid(jobId) + # Si résultat on renvoie vers le "wrapper" de recherche, + # sinon QMessage if resRecherche: core_search_main(mainWindow, resRecherche) else: @@ -29,9 +45,16 @@ def core_search_id(mainWindow: object, jobId: int) -> None: def core_search_name(mainWindow: object, name: str) -> None: - """""" + """ + Recherche de professionnel par leur nom. + Renvoie le resultat de la recherche vers core_search_main. + """ + # Instanciation dbsearch: object = DbSearch(mainWindow) + # Recherche resRecherche: tuple = dbsearch.get_pro_info_by_lastname(name) + # Si résultat on renvoie vers le "wrapper" de recherche, + # sinon QMessage if resRecherche: core_search_main(mainWindow, resRecherche) else: @@ -43,15 +66,29 @@ def core_search_name(mainWindow: object, name: str) -> None: def core_search_main(mainWindow: object, resRecherche: tuple) -> None: - """""" + """ + Prépare la données reçue par les fonctions core_search_id et + core_search_name en ajoutant tous les emplois des professionels + présant dans le résultat de la recherche et envoie + l'ensemble à "winwdowRecherche" + """ + # Instaciation dbsearch: object = DbSearch(mainWindow) + # Préparation du "payload", une liste pour tous les résultats results: list = [] + # Pour chaque éléments dans les résultat de la recherche for i in resRecherche: + # On initialise un dictionnaire ("Associative array" en PHP) proInfo: dict = {} + # id -> proId proInfo["id"] = i[0] + # text -> sera le texte à afficher resJobs = dbsearch.get_pro_job_by_proid(proInfo["id"]) + # Tout depuis l'entrée '1' de la liste proInfo["text"] = list(i[1:]) + # Et à '2' on ajoute le nom fr(i[2]) de chaque jobId associés au pro liée par un ", " proInfo["text"].insert(2, ", ".join([j[2] for j in resJobs])) + # On transforme la liste en texte en liant les éléments avec un " - " proInfo["text"] = " - ".join(proInfo["text"]) results.append(proInfo) @@ -59,12 +96,17 @@ def core_search_main(mainWindow: object, resRecherche: tuple) -> None: def window_main(mainWindow, reloadMenu = False) -> None: - """""" + """ + Page principale de l'app d'où l'on peut effectuer des recherches + """ + # Si l'argument reloaMenu de la fonction est vrai on recharge la menuBar if reloadMenu: mainMenuBar.menu_init(mainWindow) + # Instanciation de la classe dbsearch: object = DbSearch(mainWindow) - # + # On check si la variable userConnected de la classe principale est vrai ou pas + # pour savoir si un utilisateur est connecté, on crée le widget QLabel en conséquence if not mainWindow.userConnected: connState: object = QLabel("Non connecté.") else: @@ -72,8 +114,12 @@ def window_main(mainWindow, reloadMenu = False) -> None: f"Connecté: {mainWindow.userEmail} - {mainWindow.userStatus}" ) + # On adapte les widgets QPushButton en fonction if not mainWindow.userConnected: btnConnexion: object = QPushButton("Connexion") + # /!\ Association du bouton necessaire avec un lambda (fonction anonyme) + # sinon la fonction est executé à l'execution de la fonction et non quand + # on clique sur le bouton btnConnexion.clicked.connect(lambda: mainLogin.window_main(mainWindow)) else: btnDeconnexion: object = QPushButton("Déconnexion") @@ -85,7 +131,7 @@ def window_main(mainWindow, reloadMenu = False) -> None: btnInscription: object = QPushButton("Inscription") btnInscription.clicked.connect(lambda: mainRegister.window_main(mainWindow)) - # + # Partie layout des boutons de navigation layUser: object = QHBoxLayout() layUser.addStretch() layUser.addWidget(btnInscription) @@ -94,9 +140,10 @@ def window_main(mainWindow, reloadMenu = False) -> None: else: layUser.addWidget(btnDeconnexion) + # GroupeBox des boutons de navigation grpUser: object = QGroupBox("Gestion de l'utilisateur") grpUser.setLayout(layUser) - # + # Widgets pour une recherche par nom labRechercheNom: object = QLabel("Par nom") inputRechercheNom: object = QLineEdit(maxLength=128) btnRechercheNom: object = QPushButton("Rechercher") @@ -107,6 +154,7 @@ def window_main(mainWindow, reloadMenu = False) -> None: inputRechercheNom.text() ) ) + # Widgets pour une recherche par catégorie labRechercheCat: object = QLabel("Par emploi") cmbRechercheCat: object = QComboBox() alljobs: list = dbsearch.get_job_all() @@ -120,36 +168,39 @@ def window_main(mainWindow, reloadMenu = False) -> None: cmbRechercheCat.currentData() ) ) - # + # Layout recherche par nom layRechercheNom: object = QVBoxLayout() layRechercheNom.addWidget(labRechercheNom) layRechercheNom.addWidget(inputRechercheNom) layRechercheNom.addWidget(btnRechercheNom) + # Layout recherche par catégorie layRechercheCat: object = QVBoxLayout() layRechercheCat.addWidget(labRechercheCat) layRechercheCat.addWidget(cmbRechercheCat) layRechercheCat.addWidget(btnRechercheCat) - # + # Layout des deux types de recherche layRecherche: object = QHBoxLayout() layRecherche.addStretch() layRecherche.addLayout(layRechercheNom) layRecherche.addStretch() layRecherche.addLayout(layRechercheCat) layRecherche.addStretch() - # + # Groupe des deux recherches grpRecherche: object = QGroupBox("Recherche") grpRecherche.setLayout(layRecherche) - # + # Layout principale layMain: object = QVBoxLayout() layMain.addWidget(connState) layMain.addWidget(grpUser) layMain.addStretch() layMain.addWidget(grpRecherche) layMain.addStretch() - # + # Si la fenêtre avait deja un layout au travers du "mainWidget", + # on le supprime pour afficher les élements de cette fonction if hasattr(mainWindow, "mainWidget"): mainWindow.mainWidget.deleteLater() + # On crée le mainWidget et on défini sont layout mainWindow.mainWidget = QWidget() mainWindow.mainWidget.setLayout(layMain) mainWindow.setCentralWidget(mainWindow.mainWidget) diff --git a/src/app/mainLogin.py b/src/app/mainLogin.py index 617df73..bd3f916 100644 --- a/src/app/mainLogin.py +++ b/src/app/mainLogin.py @@ -1,4 +1,11 @@ +############################################################################ +# # +# Description: Fenêtre principale avec les éléments pour se connecter # +# # +############################################################################ + +# Import des éléments de PyQt5 from PyQt5.QtWidgets import ( QPushButton, QHBoxLayout, QGroupBox, QLabel, @@ -6,24 +13,32 @@ from PyQt5.QtWidgets import ( QVBoxLayout, QGridLayout, QMessageBox ) +# Import des éléments locals from src.app import mainHome, mainRegister from src.database.dbuser import DbUser from src.database.dbsearch import DbSearch def core_login(mainWindow: object, email: str, password: str) -> None: - """""" + """ + Fait appel aux methodes de DbUser et DbSearch pour vérifier si + les informations de connections fournies sont correctes et auquel cas + modifie les variables de la classe principale de l'app afin de + valider la connection de l'utilisateur. + """ + # Instanciation des classes permettant d'accéder à la BDD dbuser: object = DbUser(mainWindow) dbsearch: object = DbSearch(mainWindow) + # Si l'email exist if dbuser.check_exist_email(email): + # On vérifi l'assiocation email - pass userId = dbuser.check_user_credential(email, password) + # Si ça match, on a l'userId associé if userId: + # On récupère les infos de l'utilisateur userAccount = dbsearch.get_user_account_by_userid(userId)[0] - QMessageBox.information( - mainWindow, - "Connexion", - "Vous êtes connecté" - ) + # On associe ces valeur au variable de la classe principale + # pour connecter l'utilisateur mainWindow.userConnected = True mainWindow.userId = userId mainWindow.userEmail = userAccount[1] @@ -34,12 +49,19 @@ def core_login(mainWindow: object, email: str, password: str) -> None: mainWindow.userStatus = "Pro" elif userAccount[3] == 2: mainWindow.userStatus = "Client" + # Un Qmessage pour prévenir que c'est OK + QMessageBox.information( + mainWindow, + "Connexion", + "Vous êtes connecté" + ) + # On redirige à l'accueil mainHome.window_main(mainWindow, True) else: QMessageBox.warning( mainWindow, "Connexion", - "Mauvaise combinaison mail & mot de passe" + "Mauvais mot de passe" ) else: QMessageBox.warning( @@ -50,26 +72,24 @@ def core_login(mainWindow: object, email: str, password: str) -> None: def window_main(mainWindow: object) -> None: - """""" - if not mainWindow.userConnected: - connState: object = QLabel("Non connecté.") - else: - connState: object = QLabel( - f"Connecté: {mainWindow.userEmail} - {mainWindow.userStatus}" - ) - + """ + Page principale de l'app d'où l'on peut se connecter + """ + #Création du widget info sur la connection + connState: object = QLabel("Non connecté.") + # Widgets des boutons de navigation btnAccueil: object = QPushButton("Accueil") btnAccueil.clicked.connect(lambda: mainHome.window_main(mainWindow)) btnInscription: object = QPushButton("Inscription") btnInscription.clicked.connect(lambda: mainRegister.window_main(mainWindow)) - # + # Partie layout des boutons de navigation layUser: object = QHBoxLayout() layUser.addWidget(btnAccueil) layUser.addStretch() layUser.addWidget(btnInscription) grpUtilisateur: object = QGroupBox("Gestion de l'utilisateur") grpUtilisateur.setLayout(layUser) - # + # Widgets du menu de conenxion labMail: object = QLabel("Email") inpMail: object = QLineEdit(maxLength=128) labPassword: object = QLabel("Mot de passe") @@ -84,29 +104,30 @@ def window_main(mainWindow: object) -> None: inpPassword.text() ) ) - # + # Grid layout du menu de connexion layGrid: object = QGridLayout() layGrid.addWidget(labMail, 0, 0) layGrid.addWidget(inpMail, 0, 1) layGrid.addWidget(labPassword, 1, 0) layGrid.addWidget(inpPassword, 1, 1) layGrid.addWidget(btnConnexion, 2, 1) - # + # Layout du menu de connecion accueillant le QGridLayout layLogin: object = QHBoxLayout() layLogin.addStretch() layLogin.addLayout(layGrid) layLogin.addStretch() - # + # GroupBox du menu de connexion grpLogin: object = QGroupBox("Connexion") grpLogin.setLayout(layLogin) - # + # Layout du widget principal layMain: object = QVBoxLayout() layMain.addWidget(connState) layMain.addWidget(grpUtilisateur) layMain.addStretch() layMain.addWidget(grpLogin) layMain.addStretch() - # + # On supprime l'ancien QWidget et on en crée un nouveau + # avec les éléments et la lyout de cette de la fonction mainWindow.mainWidget.deleteLater() mainWindow.mainWidget = QWidget() mainWindow.mainWidget.setLayout(layMain) diff --git a/src/app/mainLogout.py b/src/app/mainLogout.py index 4df4273..00a2168 100644 --- a/src/app/mainLogout.py +++ b/src/app/mainLogout.py @@ -1,9 +1,21 @@ +############################################################################ +# # +# Description: Function pour se déconnecter # +# # +############################################################################ + +# Import de PyQt5 from PyQt5.QtWidgets import QMessageBox def core_logout(mainWindow: object) -> None: - """""" + """ + Modifie les variable de la classe principale de l'app + afin de déconnecter l'utilisateur + """ + # On réinitialise les variables de la classe + # principale pour déconnecter l'utilisateur if mainWindow.userConnected == True: mainWindow.userConnected = False mainWindow.userId = "" @@ -11,6 +23,7 @@ def core_logout(mainWindow: object) -> None: mainWindow.userInscrDate = "" mainWindow.userStatus = "" + # On avertit avec QMessage QMessageBox.information( mainWindow, "Déconnection", diff --git a/src/app/mainMenuBar.py b/src/app/mainMenuBar.py index 3ab0090..7c05529 100644 --- a/src/app/mainMenuBar.py +++ b/src/app/mainMenuBar.py @@ -1,8 +1,19 @@ +############################################################################ +# # +# Description: Gestion du "Menu bar" menu en haut de la fenêtre # +# # +############################################################################ + +# Import de join de la bibliothèque de bas OS pour joindre plusieurs +# nom en un chemin poitnant vers un dossier ou fichier from os.path import join +# Import de path pour récupérer le chemin actuel from pathlib import Path +# Import des éléments de PyQt5 from PyQt5.QtGui import QIcon from PyQt5.QtWidgets import QAction +# Import des éléments locals from src.app import ( windowAPropos, windowAdmin, windowUserInfo, windowMissions @@ -10,31 +21,46 @@ from src.app import ( def menu_init(mainWindow: object) -> None: - """""" - logo: str = join(Path(__file__).parent, "ressources", "icon.ico") + """ + Génère le 'menu bar' de l'app en fonction de si l'utilisateur + est connecté et de son status. + """ + # On défini le logo de l'application + logo: str = join("ressources", "icon.ico") mainWindow.setWindowIcon(QIcon(logo)) + # On défini le titre de la fenêtre mainWindow.setWindowTitle("Alphajob") + # On initialise le menu de la fenêtre principale, + # ou on l'"attrape" si il existe déja (pointeur vers ce dernier) menu: object = mainWindow.menuBar() - menu.clear() # Clear au cas où + # On le réinitialise si jamais il existait déja + menu.clear() + # On le repeuple avec différents menu et boutons en fonction du type de compte if mainWindow.userConnected and mainWindow.userStatus == "Admin": + # Ajout d'un menu "Admin" menuAdmin: object = menu.addMenu("Admin") + # Création de 3 boutons, pour les 3 champs modifiables par l'admin btnEmplois: object = QAction("Gestion des emplois", mainWindow) btnUsers: object = QAction("Gestion des Utilisateurs", mainWindow) btnMissions: object = QAction("Gestion des missions", mainWindow) + # On lie ces boutons a des fonctions, toujours avec un lambda pour que ces fonctions + # ne soit pas déclencher à la'appel de la fonction menu_init btnEmplois.triggered.connect(lambda: windowAdmin.window_admin_emplois(mainWindow)) btnUsers.triggered.connect(lambda: windowAdmin.window_admin_users(mainWindow)) btnMissions.triggered.connect(lambda: windowAdmin.window_admin_missions(mainWindow)) + # On ajoute ces boutons au menu "Admin" menuAdmin.addAction(btnEmplois) menuAdmin.addAction(btnUsers) menuAdmin.addAction(btnMissions) + # Si client ou pro elif mainWindow.userConnected and ( mainWindow.userStatus == "Pro" or mainWindow.userStatus == "Client"): - # Infos + # Ajout d'un menu "mes infos" avec son bouton menuUserInfos: object = menu.addMenu("Mes infos") btnMesInfos: object = QAction("Gérer ses infos", mainWindow) btnMesInfos.triggered.connect(lambda: windowUserInfo.window_main(mainWindow)) menuUserInfos.addAction(btnMesInfos) - # Missions + # Ajout d'un menu "mes misisons" avec ses boutons menuMissions: object = menu.addMenu("Mes missions") btnPendingMission: object = QAction("Missions en attente", mainWindow) btnOngoignMission: object = QAction("Missions en cours", mainWindow) @@ -46,6 +72,8 @@ def menu_init(mainWindow: object) -> None: menuMissions.addAction(btnOngoignMission) menuMissions.addAction(btnCompletedMission) + # Dans tous les cas + # Ajout d'un menu "Options" aves son bouton menuOptions: object = menu.addMenu("Options") btnApropos: object = QAction("A propos", mainWindow) btnApropos.triggered.connect(lambda: windowAPropos.window_main(mainWindow)) diff --git a/src/app/mainRegister.py b/src/app/mainRegister.py index ce9486f..568727d 100644 --- a/src/app/mainRegister.py +++ b/src/app/mainRegister.py @@ -1,5 +1,13 @@ +############################################################################ +# # +# Description: Fenêtre principale avec les éléments pour s'enregistrer # +# # +############################################################################ + +# Import pour effectuer des regex import re +# Import de PyQt5 from PyQt5.QtWidgets import ( QPushButton, QHBoxLayout, QGroupBox, QLabel, @@ -7,18 +15,23 @@ from PyQt5.QtWidgets import ( QVBoxLayout, QComboBox, QGridLayout, QMessageBox ) +# Import des éléments locals from src.app import mainLogin, mainHome, mainLogout from src.database.dbuser import DbUser def core_register(mainWindow: object, email: str, password: str, userStatus: str) -> None: - """""" + """ + Fonction vérifiant les données fournies par l'utilisateur pour une inscription, + un email valide et un mot de passe un minimum robuste et utilise si tel est le cas + utilise une fonction de DbUser pour inscrire l'utilisateur. + """ dbuser: object = DbUser(mainWindow) regNumb: str = "[0-9]" regUpper: str = "[A-Z]" regSpecial: str = "[`!@#$%^&*()_+\-=\[\]{};':\"\\|,.<>\/?~µ°€£]" regEmail: str = "^[a-z0-9._-]+@[a-z0-9-]+\.[a-z]+" - # Si vide + # Si l'email est vide if not email: QMessageBox.warning( mainWindow, @@ -27,6 +40,7 @@ def core_register(mainWindow: object, email: str, password: str, userStatus: str ) return + # Si le mot de passe est vide if not password: QMessageBox.warning( mainWindow, @@ -35,6 +49,7 @@ def core_register(mainWindow: object, email: str, password: str, userStatus: str ) return + # Si le status de l'utilisateur n'est pas défini if userStatus == None: QMessageBox.warning( mainWindow, @@ -43,7 +58,7 @@ def core_register(mainWindow: object, email: str, password: str, userStatus: str ) return - # les regex + # Si la regex pour verifier si l'email est valide if not re.fullmatch(regEmail, email): QMessageBox.warning( mainWindow, @@ -52,6 +67,7 @@ def core_register(mainWindow: object, email: str, password: str, userStatus: str ) return + # Les regex pour savoir si le mot de passe est un minimum robuste if len(password) < 8\ or not re.search(regNumb, password)\ or not re.search(regUpper, password)\ @@ -67,7 +83,7 @@ def core_register(mainWindow: object, email: str, password: str, userStatus: str ) return - # si email deja présent + # Si l'email est deja présent if dbuser.check_exist_email(email): QMessageBox.warning( mainWindow, @@ -76,6 +92,7 @@ def core_register(mainWindow: object, email: str, password: str, userStatus: str ) return + # Enregistrement du nouvel utilisateur succes: int = dbuser.register_user(email, password, userStatus) if succes: QMessageBox.information( @@ -93,7 +110,11 @@ def core_register(mainWindow: object, email: str, password: str, userStatus: str def window_main(mainWindow: object) -> None: - """""" + """ + Page principale de l'app d'où l'on peut s'inscrire + """ + # On check si la variable userConnected de la classe principale est vrai ou pas + # pour savoir si un utilisateur est connecté, on crée le widget QLabel en conséquence if not mainWindow.userConnected: connexionState: object = QLabel("Non connecté.") else: @@ -101,9 +122,10 @@ def window_main(mainWindow: object) -> None: f"Connecté: {mainWindow.userEmail} - {mainWindow.userStatus}" ) + # On rajoute les QPushBoutton pour retourner à l'accueil btnAccueil: object = QPushButton("Accueil") btnAccueil.clicked.connect(lambda: mainHome.window_main(mainWindow)) - # + # On adapte les widgets QPushButton en fonction if not mainWindow.userConnected: btnConnexion: object = QPushButton("Connexion") btnConnexion.clicked.connect(lambda: mainLogin.window_main(mainWindow)) @@ -116,6 +138,7 @@ def window_main(mainWindow: object) -> None: ] ) + # Partie layout des boutons de navigation layoutUser: object = QHBoxLayout() layoutUser.addWidget(btnAccueil) layoutUser.addStretch() @@ -124,9 +147,10 @@ def window_main(mainWindow: object) -> None: else: layoutUser.addWidget(btnDeconnexion) - grpUtilisateur: object = QGroupBox("Gestion de l'utilisateur") - grpUtilisateur.setLayout(layoutUser) - # + # GroupBox des boutons de navigation + grpUser: object = QGroupBox("Gestion de l'utilisateur") + grpUser.setLayout(layoutUser) + # Widgets pour s'inscrire labMail: object = QLabel("Email") leditMail: object = QLineEdit(maxLength=128) labPassword: object = QLabel("Mot de passe") @@ -134,10 +158,9 @@ def window_main(mainWindow: object) -> None: leditPassword.setEchoMode(QLineEdit.Password) labStatus: object = QLabel("Rôle") comboStatus: object = QComboBox() - comboStatus.addItem("Admin", 0) - comboStatus.addItem("Pro", 1) + comboStatus.addItem("Admin", 0) + comboStatus.addItem("Pro", 1) comboStatus.addItem("Client", 2) - # btnRegister: object = QPushButton("S'inscrire") btnRegister.clicked.connect( lambda: core_register( @@ -147,30 +170,32 @@ def window_main(mainWindow: object) -> None: comboStatus.currentData() ) ) - # + # GridLayout pour les champs de l'inscription LayoutInfoConnexion: object = QGridLayout() - LayoutInfoConnexion.addWidget(labMail, 0, 0) - LayoutInfoConnexion.addWidget(leditMail, 0, 1) - LayoutInfoConnexion.addWidget(labPassword, 1, 0) + LayoutInfoConnexion.addWidget(labMail, 0, 0) + LayoutInfoConnexion.addWidget(leditMail, 0, 1) + LayoutInfoConnexion.addWidget(labPassword, 1, 0) LayoutInfoConnexion.addWidget(leditPassword, 1, 1) - LayoutInfoConnexion.addWidget(labStatus, 2, 0) - LayoutInfoConnexion.addWidget(comboStatus, 2, 1) - LayoutInfoConnexion.addWidget(btnRegister, 3, 1) - # + LayoutInfoConnexion.addWidget(labStatus, 2, 0) + LayoutInfoConnexion.addWidget(comboStatus, 2, 1) + LayoutInfoConnexion.addWidget(btnRegister, 3, 1) + # Layout accueillant le GridLayout layoutGroupConnexion: object = QHBoxLayout() layoutGroupConnexion.addStretch() layoutGroupConnexion.addLayout(LayoutInfoConnexion) layoutGroupConnexion.addStretch() + # GroupBox du menu pour s'inscrire grpConnexion: object = QGroupBox("Inscription") grpConnexion.setLayout(layoutGroupConnexion) - # + # Layout du widget principal layoutMain: object = QVBoxLayout() layoutMain.addWidget(connexionState) - layoutMain.addWidget(grpUtilisateur) + layoutMain.addWidget(grpUser) layoutMain.addStretch() layoutMain.addWidget(grpConnexion) layoutMain.addStretch() - # + # On supprime l'ancien QWidget et on en crée un nouveau + # avec les éléments et la lyout de cette de la fonction mainWindow.mainWidget.deleteLater() mainWindow.mainWidget = QWidget() mainWindow.mainWidget.setLayout(layoutMain) diff --git a/src/app/windowAPropos.py b/src/app/windowAPropos.py index 2450e03..bf6116e 100644 --- a/src/app/windowAPropos.py +++ b/src/app/windowAPropos.py @@ -1,9 +1,18 @@ +############################################################################ +# # +# Description: Fenêtre à propos # +# # +############################################################################ + +# Import de PyQt5 from PyQt5.QtWidgets import QMessageBox def window_main(mainWindow: object) -> None: - """""" + """ + Simple QMessageBox avec des infos 'A propos' + """ QMessageBox.information( mainWindow, "A propos", diff --git a/src/app/windowAdmin.py b/src/app/windowAdmin.py index af27e54..c09dea4 100644 --- a/src/app/windowAdmin.py +++ b/src/app/windowAdmin.py @@ -1,4 +1,11 @@ +############################################################################ +# # +# Description: Fenêtres et functions permettant d'administrer la BDD # +# # +############################################################################ + +# Import des éléments de PyQt5 from PyQt5.QtWidgets import ( QDialog, QGroupBox, QLabel, QLineEdit, QVBoxLayout, @@ -6,14 +13,20 @@ from PyQt5.QtWidgets import ( QPushButton, QComboBox, QMessageBox ) +# Import des éléments locals from src.database.dbadmin import DbAdmin from src.database.dbsearch import DbSearch from src.database.dbmission import DbMission def core_ajout_emploi(mainWindow: object, nomEn: str, nomFr: str) -> int: - """""" + """ + Fonction permettant d'ajouter un emploi dans la BDD + avec une fonction de DbAdmin + """ + # Instanciation des méthodes permettant de gérer la BDD en tant qu'admin dbadmin: object = DbAdmin(mainWindow) + # Tentative d'enregistrement du nouveau job avec son nom EN et FR success: int = dbadmin.register_job_category(nomEn, nomFr) if success: QMessageBox.information( @@ -32,8 +45,13 @@ def core_ajout_emploi(mainWindow: object, nomEn: str, nomFr: str) -> int: def core_suppr_emploi(mainWindow: object, jobId: int) -> int: - """""" + """ + Fonction permettant de supprimer un emploi de la BDD + avec une fonction de DbAdmin + """ + # Instanciation des méthodes permettant de gérer la BDD en tant qu'admin dbadmin: object = DbAdmin(mainWindow) + # Tentative de suppression d'un emploi avec son ID success: int = dbadmin.del_job_category_by_jobid(jobId) if success: QMessageBox.information( @@ -52,8 +70,13 @@ def core_suppr_emploi(mainWindow: object, jobId: int) -> int: def core_suppr_user(mainWindow: object, userId: int) -> int: - """""" + """ + Fonction permettant de supprimer un utilisateur de la BDD + avec une fonction de DbAdmin + """ + # Instanciation des méthodes permettant de gérer la BDD en tant qu'admin dbadmin: object = DbAdmin(mainWindow) + # Tentative de suppression d'un emploi avec son ID success: int = dbadmin.del_user_by_userid(userId) if success: QMessageBox.information( @@ -72,8 +95,13 @@ def core_suppr_user(mainWindow: object, userId: int) -> int: def core_suppr_mission(mainWindow: object, missionId: int) -> int: - """""" + """ + Fonction permettant de supprimer une mission de la BDD + avec une fonction de DbAdmin + """ + # Instanciation des méthodes permettant de gérer la BDD en tant qu'admin dbadmin: object = DbAdmin(mainWindow) + # Tentative de suppression d'un emploi avec son ID success: int = dbadmin.del_mission_by_missionid(missionId) if success: QMessageBox.information( @@ -92,24 +120,34 @@ def core_suppr_mission(mainWindow: object, missionId: int) -> int: class window_admin_emplois(): - """""" + """ + Fenêtre permettant de gérer les emplois de la BDD, + permet de pouvoir en ajouter ou en supprimer + """ def cmb_populate(self, mainWindow: object , cmb: object) -> None: - """""" - # Instanciation DB + """ + Méthode permettant de peupler le combobox avec + tous les emplois de la BDD + """ + # Instanciation des méthodes de recherche dans la BDD dbsearch: object = DbSearch(mainWindow) allJobs: object = dbsearch.get_job_all() + # On éfface les éléments présent dans le ComboBox cmb.clear() + # On repeuple avec les nouveaux éléments for i in allJobs: cmb.addItem(f"{i[2]}", i[0]) def __init__(self, mainWindow: object) -> None: - """""" - # Fenêtre + """ + Affichage de la fenêtre + """ + # Instanciation d'une nouvealle fenêtre simple dial: object = QDialog(parent=mainWindow) + # Attribution du titre de cette fenêtre dial.setWindowTitle("Admin - Emplois") - - # Widgets Ajout + # Widgets pour ajouter un nouveau job labAjoutEn: object = QLabel("Nom en Anglais") inpAjoutEn: object = QLineEdit(maxLength=128) labAjoutFr: object = QLabel("Nom en Français") @@ -125,18 +163,17 @@ class window_admin_emplois(): self.cmb_populate(mainWindow, cmbSuppr) ] ) - # Layout Ajout + # GridLayout pour l'ajout d'un nouveau job layAjout: object = QGridLayout() layAjout.addWidget(labAjoutEn, 0, 0) layAjout.addWidget(inpAjoutEn, 0, 1) layAjout.addWidget(labAjoutFr, 1, 0) layAjout.addWidget(inpAjoutFr, 1, 1) layAjout.addWidget(btnAjout, 2, 1) - # Grp Ajout + # GroupBox pour ce GridLayout grpAjout: object = QGroupBox("Ajout d'un emploi") grpAjout.setLayout(layAjout) - - # Widgets Suppr + # Widgets pour supprimer un job labSuppr: object = QLabel("Emploi à supprimmer") cmbSuppr: object = QComboBox() self.cmb_populate(mainWindow, cmbSuppr) @@ -147,35 +184,38 @@ class window_admin_emplois(): mainWindow, cmbSuppr.currentData() ), + # self. = this. = faire appel à une méthode ou une var qui appartient à notre classe self.cmb_populate(mainWindow, cmbSuppr) ] ) - # Layouts Suppr + # GridLayouts pour supprimer un job laySuppr: object = QGridLayout() laySuppr.addWidget(labSuppr, 0, 0) laySuppr.addWidget(cmbSuppr, 0, 1) laySuppr.addWidget(btnSuppr, 1, 1) - # Grp Suppr + # GroupBox pour ce GridLayout grpSuppr: object = QGroupBox("Suppression d'un emploi") grpSuppr.setLayout(laySuppr) - - # Layout Main & show + # Layout principal auquel on donne les deux GroupBox layMain: object = QVBoxLayout() layMain.addWidget(grpAjout) layMain.addWidget(grpSuppr) dial.setLayout(layMain) + # On affiche la fenêtre dial.show() def window_admin_users(mainWindow: object) -> None: - """""" - # Instanciation DB + """ + Fenêtre permettant de supprimer un utilisateur de la BDD + """ + # Instanciation des méthodes permettant de gérer la BDD en tant qu'admin dbadmin: object = DbAdmin(mainWindow) - allUsers: object = dbadmin.get_all_users_account() - # Fenêtre + # Instanciation d'une nouvealle fenêtre simple dial: object = QDialog(parent=mainWindow) + # Attribution du titre de cette fenêtre dial.setWindowTitle("Admin - Utilisateurs") - # Widgets Users + # Widgets pour supprimer un utilisateur labCmdUser: object = QLabel("Id à supprimer") inpCmdUser: object = QLineEdit(maxLength=128) btnSuppr: object = QPushButton("Supprimer") @@ -188,41 +228,60 @@ def window_admin_users(mainWindow: object) -> None: dial.close() ] ) + # Création d'une liste qui stockera tous les QLabel pour chaque utilisateur labUsers: list = [] + # Récupération de tous les utilisateurs + allUsers: object = dbadmin.get_all_users_account() for i in allUsers: - labUsers.append(QLabel(f"ID:{i[0]} Mail:{i[1]} Inscr.{i[4]} Status:{i[5]}")) - # Layouts Users + if i[5] == 0: + status = "Admin" + elif i[5] == 1: + status = "Pro" + elif i[5] == 2: + status = "Client" + + # On formate une ligne avec les infos utiles + labUsers.append(QLabel(f"ID:{i[0]} Mail:{i[1]} Inscr.{i[4]} Status:{status}")) + # Layout pour la partie "commande" (Qlabel + QlineEdit + QPushButon) layCmd: object = QHBoxLayout() layCmd.addStretch() layCmd.addWidget(labCmdUser) layCmd.addWidget(inpCmdUser) layCmd.addWidget(btnSuppr) layCmd.addStretch() + # Layout pour tous les utilisateurs layUsers: object = QVBoxLayout() for i in range(len(labUsers)): layUsers.addWidget(labUsers[i]) + + # Layout pour accueillir le layout des commandes et des utilisateurs laySuppr: object = QVBoxLayout() laySuppr.addLayout(layCmd) laySuppr.addLayout(layUsers) - # Grp Users + # GroupeBox principal grpUser: object = QGroupBox("Suppression d'un utilisateur") grpUser.setLayout(laySuppr) - # Layout Main & Show + # Layout principal layMain: object = QVBoxLayout() layMain.addWidget(grpUser) dial.setLayout(layMain) + # Affichage de la fenêtre dial.show() def window_admin_missions(mainWindow: object): - """""" - # Instanciation DB + """ + Fenêtre permettant de supprimer une mission de la BDD + """ + # Instanciation des méthodes pour faire des + # recherches dans la BDD dbmission: object = DbMission(mainWindow) dbsearch: object = DbSearch(mainWindow) - # Fenêtre + # Instanciation d'une nouvealle fenêtre simple dial: object = QDialog(parent=mainWindow) + # Attribution du titre de cette fenêtre dial.setWindowTitle("Admin - Missions") - # Widgets Users + # Widgets pour supprimer un mission labCmdMission: object = QLabel("Id à supprimer") inpCmdMission: object = QLineEdit() btnSuppr: object = QPushButton("Supprimer") @@ -232,37 +291,46 @@ def window_admin_missions(mainWindow: object): mainWindow, inpCmdMission.text() ), + # On ferme la fenêtre une fois la mission supprimer + # pour ne pas avoir à la rafraichir dial.close() ] ) - allMissions: object = dbmission.get_all_missions() + # Création d'une liste qui stockera tous les QLabel pour chaque mission labMissions: list = [] + # Récupération de toutes les missions + allMissions: object = dbmission.get_all_missions() for i in allMissions: + # On récupère le nom FR ([2]), du job de la mission (i[10]) du premier resultat renvoyé par MySQL ([0]) jobName = dbsearch.get_job_by_jobid(i[10])[0][2] + # On formate une ligne avec les infos utiles et en formatant les dates avec strftime labMissions.append( QLabel( - f"ID:{i[0]} date:{i[1].strftime('%m/%d/%Y')} Emploi:{jobName} sujet:{i[2]} clientId:{i[8]} proId:{i[9]}" + f"ID:{i[0]} Emise le:{i[1].strftime('%m/%d/%Y')} Job:{jobName} Sujet:{i[2]} IdClient:{i[8]} IdPro:{i[9]}" ) ) - # Layouts Missions + # Layout pour la partie "commande" (Qlabel + QlineEdit + QPushButon) layCmd: object = QHBoxLayout() layCmd.addStretch() layCmd.addWidget(labCmdMission) layCmd.addWidget(inpCmdMission) layCmd.addWidget(btnSuppr) layCmd.addStretch() + # Layout pour toutes les missions layMissions: object = QVBoxLayout() for i in range(len(labMissions)): layMissions.addWidget(labMissions[i]) + # Layout pour accueillir le layout des commandes et des missions laySuppr: object = QVBoxLayout() laySuppr.addLayout(layCmd) laySuppr.addLayout(layMissions) - # Grp Missions + # GroupeBox principal grpMission: object = QGroupBox("Suppression d'une mission") grpMission.setLayout(laySuppr) - # Layout Main & Show + # Layout principal layMain: object = QVBoxLayout() layMain.addWidget(grpMission) dial.setLayout(layMain) + # Affichage de la fenêtre dial.show() diff --git a/src/app/windowMissions.py b/src/app/windowMissions.py index 5878c8a..c3d225c 100644 --- a/src/app/windowMissions.py +++ b/src/app/windowMissions.py @@ -1,34 +1,37 @@ +############################################################################ +# # +# Description: Fenêtres et fonctions permettant de gérer ses missions # +# # +############################################################################ + +# Import de PyQt5 from PyQt5.QtWidgets import ( QDialog, QGroupBox, QLabel, QVBoxLayout, QHBoxLayout, QPushButton, QMessageBox, QLineEdit, QComboBox ) +# Import des éléments locaux from src.database.dbmission import DbMission +from src.database.dbsearch import DbSearch def core_review(dial: object, dbmission: object, missionId: int) -> None: - """""" + """ + Fenêtre permettant de donner un avis et une note à une mission + en tant que Client. + """ + # Instanciation d'une nouvealle fenêtre simple dialReview: object = QDialog(parent=dial) - # - lineNote: object = QHBoxLayout() + # Widgets pour pouvoir laisser un commentaire labNote: object = QLabel("Note: ") cmbNote: object = QComboBox() for i in range(6): cmbNote.addItem(str(i), i) - lineNote.addWidget(labNote) - lineNote.addStretch() - lineNote.addWidget(cmbNote) - # - lineReview: object = QHBoxLayout() + labReview: object = QLabel("Avis: ") inpReview: object = QLineEdit(maxLength=256) - lineReview.addWidget(labReview) - lineReview.addStretch() - lineReview.addWidget(inpReview) - # - lineBtn: object = QHBoxLayout() btnValider: object = QPushButton("Valider") btnValider.clicked.connect( lambda: [ @@ -42,27 +45,44 @@ def core_review(dial: object, dbmission: object, missionId: int) -> None: dialReview.close() ] ) + # Layout des lignes avec leurs widgets + lineNote: object = QHBoxLayout() + lineNote.addWidget(labNote) + lineNote.addStretch() + lineNote.addWidget(cmbNote) + lineReview: object = QHBoxLayout() + lineReview.addWidget(labReview) + lineReview.addStretch() + lineReview.addWidget(inpReview) + lineBtn: object = QHBoxLayout() lineBtn.addStretch() lineBtn.addWidget(btnValider) lineBtn.addStretch() - # + # Layout accueillant les lignes layReview: object = QVBoxLayout() layReview.addLayout(lineNote) layReview.addLayout(lineReview) layReview.addLayout(lineBtn) - # + # GroupBox principal grpMain: object = QGroupBox("Donnez votre avis") grpMain.setLayout(layReview) + # Layout principal layMain: object = QVBoxLayout() layMain.addWidget(grpMain) - # dialReview.setLayout(layMain) + # Affichage de la fenêtre dialReview.show() def core_validate(mainWindow: object, dial: object, missionId: int, status: str) -> None: - """""" + """ + Valide une mission et en fonction du statut de l'utilisateur + et de l'etat de la mission, renvoie vers le bon message ou + la possibilitée de laisser un commentaire + """ + # Instanciation des méthodes pour pouvoir gérer les missions dans la BDD dbmission: object = DbMission(mainWindow) + # Validation en fonction de l'étape à laquelle se trouve actuellement la mission if status == "acceptedByPro": dbmission.accept_mission_by_missionid(missionId) QMessageBox.information( @@ -80,17 +100,27 @@ def core_validate(mainWindow: object, dial: object, missionId: int, status: str) elif status == "validatedByClient": core_review(dial, dbmission, missionId) + # On ferme la fenetre pour éviter d'avoir à la rafraichir dial.close() def core_get_missions_by_status(mainWindow: object, status: str) -> list: - """""" + """ + Récupération des missions liées à l'utilisateur et sélection + des missions ayant le statut demandé + """ + # Instanciation des méthodes pour pouvoir gérer les missions dans la BDD dbmission: object = DbMission(mainWindow) + # Récupération des missions en fonction du status et selon l'ID + # de l'utilisateur actuellement connecté if mainWindow.userStatus == "Pro": missionsAll: list = dbmission.get_mission_by_proid(mainWindow.userId) elif mainWindow.userStatus == "Client": missionsAll: list = dbmission.get_mission_by_clientid(mainWindow.userId) + # Selon la fenêtre appelée dans le menu bar, on sélectionne les missions ayant ce status + # en regardant si les champs de validation sont vide ou non, on converti aussi les tuple des resultats + # que renvoi la BDD en list if status == "pending": missionsPending: list = [list(i) for i in missionsAll if i[5] == None] return missionsPending @@ -103,34 +133,71 @@ def core_get_missions_by_status(mainWindow: object, status: str) -> list: def window_main(mainWindow: object, status: str) -> None: - """""" - dial: object = QDialog(parent=mainWindow) - missions: list = core_get_missions_by_status(mainWindow, status) + """ + Fenêtre permettant de gérer ses missions + """ + dbsearch: object = DbSearch(mainWindow) + # Instanciation d'une nouvealle fenêtre simple + dial: object = QDialog(parent=mainWindow) + # Récupération des missions en fonction su status sélectionné + missions: list = core_get_missions_by_status(mainWindow, status) + # Liste qui va accueillir les lignes linesMission: list = [] - for mission in missions: - line: object = QHBoxLayout() - labMission: object = QLabel(" - ".join([str(i) for i in mission[1:] if i != None])) + # Mission à la place de "i" pour eviter d'avoir un "j" par la suite + for i in missions: + # Widgets de la ligne + line: object = QHBoxLayout() + # On récupère le nom FR de l'emploi + job = dbsearch.get_job_by_jobid(i[8])[0][2] + # On formate la ligne avec les infos intéréssantes selon le status de la mission + if status == "pending": + labMission: object = QLabel( + f"Emise le: {i[1].strftime('%m/%d/%Y')} Pro: {i[10]} Job: {job} Sujet: {i[2]}" + ) + elif status == "ongoing": + if i[6] != None: + valClient = i[6].strftime('%m/%d/%Y') + else: + valClient = "N/A" + + if i[7] != None: + valPro = i[7].strftime('%m/%d/%Y') + else: + valPro = "N/A" + + labMission: object = QLabel( + f"Emise le: {i[1].strftime('%m/%d/%Y')} Pro: {i[10]} Job: {job} Sujet: {i[2]} Validé Client: {valClient} Validé Pro: {valPro}" + ) + elif status == "completed": + labMission: object = QLabel( + f"Emise le: {i[1].strftime('%m/%d/%Y')} Pro: {i[10]} Job: {job} Sujet: {i[2]} Validé Client: {i[6].strftime('%m/%d/%Y')} Validé Pro: {i[7].strftime('%m/%d/%Y')} Note: {i[3]} Avis: {i[4]}" + ) + line.addWidget(labMission) + # On vérifie si le status de la mission peut étre validé par l'utilisateur actuel + # Si c'est une mission en attente et que l'on est le Pro if status == "pending" and mainWindow.userStatus == "Pro": btnValidate: object = QPushButton("Valider") btnValidate.clicked.connect( - lambda checked, missionId=mission[0]: + lambda checked, missionId=i[0]: core_validate(mainWindow, dial, missionId, "acceptedByPro") ) line.addStretch() line.addWidget(btnValidate) - elif status == "ongoing" and mainWindow.userStatus == "Pro" and mission[7] == None: + # Si la mission est en cours et qu'elle n'est pas encore validé par le pro et que l'on est ce dernier + elif status == "ongoing" and mainWindow.userStatus == "Pro" and i[7] == None: btnValidate: object = QPushButton("Valider") btnValidate.clicked.connect( - lambda checked, missionId=mission[0]: + lambda checked, missionId=i[0]: core_validate(mainWindow, dial, missionId, "validatedByPro") ) line.addStretch() line.addWidget(btnValidate) - elif status == "ongoing" and mainWindow.userStatus == "Client" and mission[6] == None: + # Si la mission est en cours et que l'on est le client + elif status == "ongoing" and mainWindow.userStatus == "Client" and i[6] == None: btnValidate: object = QPushButton("Valider") btnValidate.clicked.connect( - lambda checked, missionId=mission[0]: + lambda checked, missionId=i[0]: core_validate(mainWindow, dial, missionId, "validatedByClient") ) line.addStretch() @@ -138,10 +205,12 @@ def window_main(mainWindow: object, status: str) -> None: linesMission.append(line) + # On ajoute chaque lignes au layout des missions layMission: object = QVBoxLayout() for i in linesMission: layMission.addLayout(i) + # On crée un GroupBox en le nommant en fonction du status des missions if status == "pending": grpMain: object = QGroupBox("Missions en attente") elif status == "ongoing": @@ -150,7 +219,9 @@ def window_main(mainWindow: object, status: str) -> None: grpMain: object = QGroupBox("Missions terminées") grpMain.setLayout(layMission) + # On ajout le GroupBox au layout principal layMain: object = QVBoxLayout() layMain.addWidget(grpMain) dial.setLayout(layMain) + # On affiche la fenêtre dial.show() diff --git a/src/app/windowRecherche.py b/src/app/windowRecherche.py index b2305e1..941e770 100644 --- a/src/app/windowRecherche.py +++ b/src/app/windowRecherche.py @@ -1,7 +1,15 @@ +############################################################################ +# # +# Description: Fenêtre de resultat d'une recherche et fenêtre permettant # +# de mandater un professionnel # +# # +############################################################################ + # https://docs.python.org/3/faq/programming.html#why-do-lambdas-defined-in-a-loop-with-different-values-all-return-the-same-result # https://stackoverflow.com/questions/53751106/create-lambda-functions-in-a-loop-for-pyqt5-signals?noredirect=1 +# Import de PyQt5 from PyQt5.QtWidgets import ( QDialog, QVBoxLayout, QHBoxLayout, QLabel, @@ -9,33 +17,29 @@ from PyQt5.QtWidgets import ( QComboBox, QLineEdit, QMessageBox ) +# Import des éléments locaux from src.database.dbsearch import DbSearch from src.database.dbmission import DbMission def core_mandater(mainWindow: object, dial: object, proId: int) -> None: - """""" + """ + Fenêtre permettant de mandater un professionnel + """ + # Instaciation des méthodes pour rechercher et gérer les missions dans la BDD dbmission: object = DbMission(mainWindow) dbsearch: object = DbSearch(mainWindow) + # Récupération des emplois du Pro avec son ID proJobs: list = dbsearch.get_pro_job_by_proid(proId) - + # Instanciation d'une fenêtre simple dial: object = QDialog(dial) - + # Widgets pour pouvoir mandater le pro labInpMandate: object = QLabel("Sujet de la mission:") inpMandate: object = QLineEdit(maxLength=128) - layInpMandate: object = QHBoxLayout() - layInpMandate.addWidget(labInpMandate) - layInpMandate.addStretch() - layInpMandate.addWidget(inpMandate) - labCmbMandate: object = QLabel("Profession concernée:") cmbMandate: object = QComboBox() - layCmbMandate: object = QHBoxLayout() for i in proJobs: cmbMandate.addItem(f"{i[2]}", i[0]) - layCmbMandate.addWidget(labCmbMandate) - layCmbMandate.addStretch() - layCmbMandate.addWidget(cmbMandate) btnMandate = QPushButton("Mandater") btnMandate.clicked.connect( @@ -54,31 +58,46 @@ def core_mandater(mainWindow: object, dial: object, proId: int) -> None: dial.close() ] ) + # Layout pour les lignes + layInpMandate: object = QHBoxLayout() + layInpMandate.addWidget(labInpMandate) + layInpMandate.addStretch() + layInpMandate.addWidget(inpMandate) + layCmbMandate: object = QHBoxLayout() + layCmbMandate.addWidget(labCmbMandate) + layCmbMandate.addStretch() + layCmbMandate.addWidget(cmbMandate) layBtnMandate: object = QHBoxLayout() layBtnMandate.addStretch() layBtnMandate.addWidget(btnMandate) layBtnMandate.addStretch() - + # Layout du formulaire pour mandater layGrp: object = QVBoxLayout() layGrp.addLayout(layInpMandate) layGrp.addLayout(layCmbMandate) layGrp.addLayout(layBtnMandate) - + # GroupBox du formulaire grpMandate: object = QGroupBox() grpMandate.setLayout(layGrp) - + # Layout principal auquel on donne le GroupBox layMain: object = QVBoxLayout() layMain.addWidget(grpMandate) - dial.setLayout(layMain) + # Affichage de la fenêtre dial.show() def core_more_infos(mainWindow: object, dial: object, proId: int) -> None: - """""" + """ + Fenêtre permettant de voir toutes les infos d'un professionnel + """ + # Instanciation d'une fenètre simple dial: object = QDialog(dial) + # Instanciation des méthode de recherche dans la BDD search: object = DbSearch(mainWindow) + # Récupération des infos de l'utilisateur en se passant de son id (champ 1) resRecherche: list = search.get_user_info_by_userid(proId)[0][1:] + # Liste comprenant le text des labels labelsText: list = [ "Nom", "Prénom", @@ -90,13 +109,15 @@ def core_more_infos(mainWindow: object, dial: object, proId: int) -> None: "Code postale", "Ville", ] - + # Pour chaque élément dans la liste des textes de label on crée + # une ligne avec le resultat de la recherche qui lui est lié layProInfo = QVBoxLayout() for i in range(len(resRecherche)): line: object = QHBoxLayout() line.addWidget(QLabel(f"{labelsText[i]}: {resRecherche[i]}")) layProInfo.addLayout(line) + # Si on est connecté en tant que client on rajoute le bouton pour mandater if mainWindow.userStatus == "Client": layBtnMandate: object = QHBoxLayout() btnMandate: object = QPushButton("Mandater") @@ -109,42 +130,51 @@ def core_more_infos(mainWindow: object, dial: object, proId: int) -> None: layBtnMandate.addStretch() layProInfo.addLayout(layBtnMandate) + # Enfin le GroupBox qui va recevoir l'ensemble grpProInfo: object = QGroupBox() grpProInfo.setLayout(layProInfo) - - layMain: object = QVBoxLayout() + # Le layout principal + layMain: object = QVBoxLayout() layMain.addWidget(grpProInfo) - dial.setLayout(layMain) + # On affiche la fenêtre dial.show() def window_main(mainWindow: object, results: list) -> None: - """""" + """ + Fenêtre affichant le résultat d'une recherche + """ + # Instanciation d'une fenêtre simple dial: object = QDialog(parent=mainWindow) - dial.setWindowTitle("Recherche") - layoutsResult: list = [] + # On défini le titre de cette fenêtre + dial.setWindowTitle("Résulta de la Recherche") + # On crée une liste qui va recevoir les lignes qui possède + # les widgets définis avec le payload des résultats + linesResult: list = [] for i in results: layoutLine = QHBoxLayout() - color = results.index(i) % 2 - if color: - colored = QLabel(i["text"]) - colored.setStyleSheet("background-color: rgb(230,200,200); border-radius: 3px") - layoutLine.addWidget(colored) - else: - layoutLine.addWidget(QLabel(i["text"])) - btnInfos = QPushButton("Infos") + layoutLine.addWidget(QLabel(i["text"])) + btnInfos: object = QPushButton("Infos") btnInfos.clicked.connect( lambda checked, proId=i["id"]: core_more_infos(mainWindow, dial, proId) ) layoutLine.addStretch() layoutLine.addWidget(btnInfos) - layoutsResult.append(layoutLine) - - layoutMain = QVBoxLayout() - for layout in layoutsResult: - layoutMain.addLayout(layout) - + linesResult.append(layoutLine) + + # Layout qui va recvoir les lignes + layRecherche: object = QVBoxLayout() + for i in linesResult: + layRecherche.addLayout(i) + + # GroupBox de la recherche + grpRecherche: object = QGroupBox("Recherche") + grpRecherche.setLayout(layRecherche) + # Layout principal a qui on donne le GroupBox + layoutMain: object = QVBoxLayout() + layoutMain.addWidget(grpRecherche) dial.setLayout(layoutMain) + # On afficha la fenêtre dial.show() diff --git a/src/app/windowUserInfo.py b/src/app/windowUserInfo.py index 4455dde..181925d 100644 --- a/src/app/windowUserInfo.py +++ b/src/app/windowUserInfo.py @@ -1,6 +1,14 @@ +############################################################################ +# # +# Description: Fenêtre et fonctions permettant de gérer ses infos # +# # +############################################################################ + # https://stackoverflow.com/questions/3077192/get-a-layouts-widgets-in-pyqt +# Import de PyQt5 +from tkinter import Widget from PyQt5.QtWidgets import ( QDialog, QGroupBox, QLabel, QLineEdit, @@ -8,14 +16,21 @@ from PyQt5.QtWidgets import ( QPushButton, QComboBox, QMessageBox ) +# Import des fichiers locaux from src.database.dbuser import DbUser from src.database.dbsearch import DbSearch def core_add_job(jobName: str, jobId: int, listMyJobs: list, layMyJobs: object) -> None: - """""" + """ + Fonction permettant d'ajouter l'id de l'emploi sélectionné et + la ligne avec un bouton pour le retirer. + """ + # Uniquement si le job n'était pas deja sélectionné if jobId not in listMyJobs: + # On le rajoute à la liste des emplois sélectionnés listMyJobs.append(jobId) + # On crée le layout avec ses widgets pour pouvoir le supprimer si on le souhaite lineMyJobs: object = QHBoxLayout() labJob: object = QLabel(jobName) btnRemoveJob: object = QPushButton("Supprimer") @@ -32,29 +47,37 @@ def core_add_job(jobName: str, jobId: int, listMyJobs: list, layMyJobs: object) def core_delete_job(layLineJob: object) -> None: - """""" - lab: object = layLineJob.itemAt(0).widget() - lab.deleteLater() - btn: object = layLineJob.itemAt(2).widget() - btn.deleteLater() + """ + Fonction permettant de supprimer une ligne de la fenêtre + """ + # On loop a travers chaque item dans le layout et on le supprime + for i in range(layLineJob.count()): + widget: object = layLineJob.itemAt(i).widget() + if widget != None: # Stretch renvoi None + widget.deleteLater() + + # Enfin on supprime le layout layLineJob.deleteLater() def core_validate(mainWindow: object, dial: object, - layLines: list, oldJobs: list = None, newJobs: list = None) -> None: - """""" - user: object = DbUser(mainWindow = mainWindow) + layLines: dict, oldJobs: list = None, newJobs: list = None) -> None: + """ + Fonction validant les informations renseignées et modification + de ses dernières dans la BDD avec un méthode de BdUser. + """ + # Instanciation des méthodes pour gérer les utilisateurs + user: object = DbUser(mainWindow = mainWindow) + # On crée une liste qui vas recevoir les informations renseignées userInfos: list = [] + # Pour chaque ligne si cette ligne n'est pas sélectionenr un emploi ou + # mes emplois, on ajoute la valeur de l'input à la liste for i in layLines: if i != "selectJobs" and i != "myJobs": lineInput: object = layLines[i].itemAt(2).widget() userInfos.append(lineInput.text()) - if mainWindow.userStatus == "Pro": - isPro: bool = True - else: - isPro: bool = False - + # Si un champs est vide, on "return" pour arreter la fonction if "" in userInfos: QMessageBox.warning( dial, @@ -63,6 +86,13 @@ def core_validate(mainWindow: object, dial: object, ) return + # On regarde si l'utilisateur est un Pro ou un Client + if mainWindow.userStatus == "Pro": + isPro: bool = True + else: + isPro: bool = False + + # On met à jour les informations de l'utilisateur connecté user.update_user_infos(userInfos, mainWindow.userId, isPro, oldJobs, newJobs) QMessageBox.information( dial, @@ -72,10 +102,19 @@ def core_validate(mainWindow: object, dial: object, def window_main(mainWindow: object) -> None: + """ + Fenêtre permettant de modifier ses informations d'utilisateur + """ + # Instanciation des méthodes pour effectuer des recherches search: object = DbSearch(mainWindow) - dial: object = QDialog(parent=mainWindow) + # Instaciation d'une fenêtre simple + dial: object = QDialog(parent=mainWindow) + # On défini le titre de cette fenêtre dial.setWindowTitle("Mes infos") + # On récupère les infos de l'utilisateur infos: list = search.get_user_info_by_userid(mainWindow.userId) + # Si il y a déja des infos enregistrées, on les récupère dans deux dictionnaires + # en séparants les champs spécifiques aux pros if infos: champsClients: dict = { "Nom": infos[0][1], @@ -105,11 +144,17 @@ def window_main(mainWindow: object) -> None: "Description" ] - layLines: list = {} + # On crée un dict qui va recevoir les lignes + layLines: dict = {} + # Pour chaque élément dans champsClient, que ce soit une liste ou un dict for i in champsClients: + # On crée une ligne avec son QLabel défini selon l'index si c'est un dict, + # ou la valeur de l'élément si c'est une liste, et cette index ou cette valeur + # sera également l'index du dict des lignes layLines[i] = QHBoxLayout() layLines[i].addWidget(QLabel(i)) layLines[i].addStretch() + # Si il y a deja des infos, on attribut cette info au QLineEdit, sinon on laisse le champ vierge if infos: if i == "Téléphone": layLines[i].addWidget(QLineEdit(champsClients[i], maxLength=10)) @@ -125,9 +170,11 @@ def window_main(mainWindow: object) -> None: else: layLines[i].addWidget(QLineEdit(maxLength=128)) + # Si l'utilisateur est un pro, on rajoute les champs réservés à ces derniers if mainWindow.userStatus == "Pro": + # On récupère tous les emplois et rajoute les widgets + # pour pouvoir ajouter ces derniers allJobs: object = search.get_job_all() - laySelectJobs: object = QHBoxLayout() labSelectJobs: object = QLabel("Les emplois:") cmbAllJobs: object = QComboBox() for i in allJobs: @@ -143,20 +190,32 @@ def window_main(mainWindow: object) -> None: layMyJobs ) ) + # On définie le layout de cette ligne et on le rajoute au dictionnaire des lignes + laySelectJobs: object = QHBoxLayout() laySelectJobs.addWidget(labSelectJobs) laySelectJobs.addStretch() laySelectJobs.addWidget(cmbAllJobs) laySelectJobs.addStretch() laySelectJobs.addWidget(btnSelectJobs) layLines["selectJobs"] = laySelectJobs - # + # On récupère les jobs déja sélectionnés pour le pro myJobs: object = search.get_pro_job_by_proid(mainWindow.userId) - layMyJobs: object = QVBoxLayout() + # On initie une nouvelle liste pour les jobs qui vont étre sélectionnés newJobs: list = [] + # On Crée la partie qui recevra les lignes des emplois + layMyJobs: object = QVBoxLayout() + # Pour chaque job qui avait déja été sélectionné for i in myJobs: + # On crée une une ligne en passant le nom FR, l'id, + # la liste des nouveaux jobs et le layout qui recoit ces lignes core_add_job(i[2], i[0], newJobs, layMyJobs) - oldJobs: list = newJobs.copy() # Sinon pointer !!! + + # On duplique tout de suite la liste des nouveaux jobs + # pour pouvoir faire la diff avant après + oldJobs: list = newJobs.copy() # Obligé de "copy" sinon pointer !!! + # On donne au dictionnaire des lignes le layout qui recoit les jobs sélectionnés layLines["myJobs"] = layMyJobs + # On ajoute les autres champs réservés aux pros for i in champsPro: layLines[i] = QHBoxLayout() layLines[i].addWidget(QLabel(i)) @@ -166,34 +225,39 @@ def window_main(mainWindow: object) -> None: else: layLines[i].addWidget(QLineEdit(maxLength=256)) - layModif: object = QVBoxLayout() - for i in layLines: - layModif.addLayout(layLines[i]) - + # On crée le bouton pour valider les modifications btnModif: object = QPushButton("modifer") btnModif.clicked.connect( lambda: - core_validate( + core_validate( # Si c'est un pro mainWindow, dial, layLines, oldJobs, newJobs ) if mainWindow.userStatus == "Pro" - else core_validate( + else core_validate( # Sinon mainWindow, dial, layLines ) ) + # On crée et peuple le layout qui recoit toutes les lignes + layModif: object = QVBoxLayout() + for i in layLines: + layModif.addLayout(layLines[i]) + + # On ajoute le bouton layBtn: object = QHBoxLayout() layBtn.addStretch() layBtn.addWidget(btnModif) layModif.addLayout(layBtn) - # + # On crée et donne au GroupBox le layout des lignes grpMain: object = QGroupBox("Mes infos") grpMain.setLayout(layModif) + # On crée le layout principal auquel on donne le GroupBox mainLayout: object = QVBoxLayout() mainLayout.addWidget(grpMain) dial.setLayout(mainLayout) + # On affiche la fenêtre dial.show() diff --git a/src/database/dbadmin.py b/src/database/dbadmin.py index 76e31b4..f63caf5 100644 --- a/src/database/dbadmin.py +++ b/src/database/dbadmin.py @@ -5,6 +5,8 @@ # afin de gérer l'administration du site # # # ############################################################################ +# https:#stackoverflow.com/questions/1361340/how-can-i-do-insert-if-not-exists-in-mysql +# https:#stackoverflow.com/questions/1676551/best-way-to-test-if-a-row-exists-in-a-mysql-table # Import de dbmain from src.database.dbmain import DbMain @@ -12,12 +14,14 @@ from src.database.dbmain import DbMain # Extension de cette classe avec dbmain class DbAdmin(DbMain): - - # **************************************************************************** + """ + Classe contenant les méthodes pour gérer la BDD réservées à l'admin + """ # GESTION DES UTILISATEURS DANS L'ADMIN - # **************************************************************************** - # Récupérer toutes les infos de la table userAccount def get_all_users_account(self) -> list: + """ + Récupération de tous les utilsiateur + """ reqGetAll: str = """ SELECT * @@ -28,11 +32,11 @@ class DbAdmin(DbMain): return result - # https:#stackoverflow.com/questions/1361340/how-can-i-do-insert-if-not-exists-in-mysql - # Suppresion d'un utilisateur def del_user_by_userid(self, userId: int) -> int: + """ + Méthode pour la suppression d'un utilisateur + """ # Préparation de la requète pour voir si l'utilisateur existe - # https:#stackoverflow.com/questions/1676551/best-way-to-test-if-a-row-exists-in-a-mysql-table reqCheckExistId: str = """ SELECT EXISTS( SELECT 1 FROM @@ -56,11 +60,11 @@ class DbAdmin(DbMain): return 0 - # **************************************************************************** # GESTION DES EMPLOIS DANS L'ADMIN - # **************************************************************************** - # Ajout d'une categorie def register_job_category(self, jobNameEn: str, jobNameFr: str) -> int: + """ + Méthode pour l'ajout d'une categorie + """ # Préparation et execution de la requète pour voir si la categorie existe en anglais reqCheckjobCategoryNameEn: str = """ SELECT EXISTS( @@ -106,8 +110,10 @@ class DbAdmin(DbMain): return 0 - # Suppresion d'un utilisateur def del_job_category_by_jobid(self, jobId: int) -> int: + """ + Méthode pour la suppression d'une catégorie d'emploi + """ # Préparation de la requète pour voir si l'utilisateur existe reqCheckExistId: str = """ SELECT EXISTS( @@ -137,11 +143,11 @@ class DbAdmin(DbMain): return 0 - # **************************************************************************** # GESTION DES MISSIONS DANS L'ADMIN - # **************************************************************************** - # Suppresion d'une mission def del_mission_by_missionid(self, missionId: int) -> int: + """ + Méthode pour la suppression d'une mission + """ # Préparation de la requète pour voir si l'utilisateur existe reqCheckExistId: str = """ SELECT EXISTS( diff --git a/src/database/dbmain.py b/src/database/dbmain.py index 4344e23..af62364 100644 --- a/src/database/dbmain.py +++ b/src/database/dbmain.py @@ -18,9 +18,11 @@ from PyQt5.QtWidgets import QMessageBox class DbMain(): - # **************************************************************************** + """ + Classe principale pour gérer la BDD avec les méthode pour se connecter, + créer les tables, exéctuer une requête SQL, etc ... + """ # INFOS GLOBAL ET DE CONNEXION - # **************************************************************************** # Pour gérer si "en production" DEBUG = False # Configuration du serveur MYSQL / MARIADB @@ -29,9 +31,7 @@ class DbMain(): PASSWORD = "" DATABASE = "alphajob" - # **************************************************************************** # DECLARATION DES TABLES - # **************************************************************************** # UserAccount, infos du compte nécessaire à la connection CREATETABLEUSERACCOUNT = """CREATE TABLE IF NOT EXISTS `alphajob`.`userAccount` ( `userId` INT UNSIGNED NOT NULL AUTO_INCREMENT, @@ -142,9 +142,7 @@ class DbMain(): TABLEMISSION = "mission" - # **************************************************************************** # FONCTIONS PRINCIPALES - # **************************************************************************** # Création de la DB si elle n'existe pas def create_db(self) -> None: reqInitDb = "CREATE DATABASE IF NOT EXISTS " + self.DATABASE diff --git a/src/database/dbmission.py b/src/database/dbmission.py index 0bb73e0..c97b9ad 100644 --- a/src/database/dbmission.py +++ b/src/database/dbmission.py @@ -16,10 +16,10 @@ from datetime import datetime # Extension de cette classe avec dbmain class DbMission(DbMain): - - # **************************************************************************** + """ + Classe avec des méthodes pour gérer les missions + """ # ENREGISTREMENT ET VALIDATION DES MISSIONS - # **************************************************************************** # Enregistrement d'une mission def register_mission(self, subject: str, clientId: int, proId: int, jobId: int) -> int: # Préparation de la requète pour enregistrement de la mission @@ -106,9 +106,7 @@ class DbMission(DbMain): self.exec_cmd(reqAddMission, [review, note, missionId], True) - # **************************************************************************** # RECUPERATION DES INFORMATIONS RELATIVES AUX MISSIONS - # **************************************************************************** # Récupérations des missions d'un pro par son id def get_mission_by_proid(self, proId: int) -> list: reqGetMissionsProId = """ diff --git a/src/database/dbsearch.py b/src/database/dbsearch.py index 62316f4..a489d84 100644 --- a/src/database/dbsearch.py +++ b/src/database/dbsearch.py @@ -14,9 +14,10 @@ from src.database.dbmain import DbMain # Extension de cette classe avec dbmain class DbSearch(DbMain): - # **************************************************************************** + """ + Classes avec les méthodes pour effectuer des recherches + """ # RECUPERATION DES INFORMATIONS RELATIVES AUX UTILISATEURS - # **************************************************************************** # Récupération des infos d'un compte par son id def get_user_account_by_userid(self, userId: int) -> list: reqSearchUser = """ @@ -44,9 +45,7 @@ class DbSearch(DbMain): return self.cur.fetchall() - # **************************************************************************** # RECUPERATION DES INFORMATIONS RELATIVES AUX PROS - # **************************************************************************** def get_all_pro_by_jobid(self, jobId: int) -> list: reqSearchConsultant = """ SELECT @@ -119,9 +118,7 @@ class DbSearch(DbMain): return self.cur.fetchall() - # **************************************************************************** # RECUPERATION DES INFORMATIONS RELATIVES AUX EMPLOIS - # **************************************************************************** # Récupérer toutes les infos de la table jobCategory def get_job_all(self) -> list: reqGetAllJobs = """ diff --git a/src/database/dbuser.py b/src/database/dbuser.py index bc89f8a..e93f82e 100644 --- a/src/database/dbuser.py +++ b/src/database/dbuser.py @@ -15,10 +15,10 @@ from src.database.dbmain import DbMain # Extension de cette classe avec dbmain class DbUser(DbMain): - - # **************************************************************************** + """ + Classe avec les méthodes pour gérer les utilisateurs + """ # GESTION DES UTILISATEURS - # **************************************************************************** # Enregistrement d'un nouvel utilisateur def register_user(self, email: str, password: str, userStatus: int) -> int: # On vérifie si l'email existe deja dans la bdd diff --git a/src/main.py b/src/main.py index 24fc1e1..ac1a46d 100644 --- a/src/main.py +++ b/src/main.py @@ -1,17 +1,29 @@ +############################################################################ +# # +# Description: Fichier main pour lancer l'application avec sa classe # +# principale # +# # +############################################################################ + +# Import de sys pour avoir accès aux arguments si il y en a +# et pour pouvoir quitter l'application import sys +# Import de PyQt5 from PyQt5.QtWidgets import QMainWindow, QApplication -from src.app import mainHome -from src.app import mainMenuBar +# Import des éléments locaux +from src.app import mainHome, mainMenuBar class mainWindow(QMainWindow): - """""" - # + """ + Classe principale de l'app + """ + # Versiond de l'app VERSION = 0.1 - # + # Var pour savoir si on peut accéder à la BDD mysqlReachable: bool = False - # + # Variables concernant l'état de connexion userConnected: bool = False userId: str = "" userEmail: str = "" @@ -24,14 +36,16 @@ class mainWindow(QMainWindow): mainHome.window_main(self) -if __name__ == "__main__": - def main(): - """ - Démarrage de l'app - """ - APP = QApplication(sys.argv) - GUI = mainWindow() - GUI.show() - sys.exit(APP.exec_()) +def main(): + """ + Démarrage de l'app + """ + APP = QApplication(sys.argv) + GUI = mainWindow() + GUI.show() + sys.exit(APP.exec_()) + +# Si ce fichier est bien directement lancé avec python et non importé +if __name__ == "__main__": main() diff --git a/src/main.spec b/src/main.spec index 47ce1af..05ce173 100644 --- a/src/main.spec +++ b/src/main.spec @@ -37,7 +37,7 @@ exe = EXE( target_arch=None, codesign_identity=None, entitlements_file=None, - icon='gui\\ressources\\icon.ico', + icon='app\\ressources\\icon.ico', ) coll = COLLECT( exe, diff --git a/src/setup.iss b/src/setup.iss new file mode 100644 index 0000000..054d6db --- /dev/null +++ b/src/setup.iss @@ -0,0 +1,58 @@ +; Script generated by the Inno Setup Script Wizard. +; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! + +#define MyAppName "AlphaJob" +#define MyAppVersion "0.1" +#define MyAppPublisher "Debulois Quentin" +#define MyAppURL "https://git.debulois.fr/alphajob_app/" +#define MyAppExeName "alphajob.exe" +#define MyAppAssocName MyAppName + " File" +#define MyAppAssocExt ".myp" +#define MyAppAssocKey StringChange(MyAppAssocName, " ", "") + MyAppAssocExt + +[Setup] +; NOTE: The value of AppId uniquely identifies this application. Do not use the same AppId value in installers for other applications. +; (To generate a new GUID, click Tools | Generate GUID inside the IDE.) +AppId={{896464EE-4CF7-4C5A-BF3B-DA87AB8215F5} +AppName={#MyAppName} +AppVersion={#MyAppVersion} +;AppVerName={#MyAppName} {#MyAppVersion} +AppPublisher={#MyAppPublisher} +AppPublisherURL={#MyAppURL} +AppSupportURL={#MyAppURL} +AppUpdatesURL={#MyAppURL} +DefaultDirName={autopf}\{#MyAppName} +ChangesAssociations=yes +DisableProgramGroupPage=yes +; Uncomment the following line to run in non administrative install mode (install for current user only.) +;PrivilegesRequired=lowest +OutputBaseFilename=mysetup +Compression=lzma +SolidCompression=yes +WizardStyle=modern + +[Languages] +Name: "french"; MessagesFile: "compiler:Languages\French.isl" + +[Tasks] +Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked + +[Files] +Source: "C:\Users\Quentin\Desktop\app_alphajob\src\dist\main\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion +Source: "C:\Users\Quentin\Desktop\app_alphajob\src\dist\main\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs +; NOTE: Don't use "Flags: ignoreversion" on any shared system files + +[Registry] +Root: HKA; Subkey: "Software\Classes\{#MyAppAssocExt}\OpenWithProgids"; ValueType: string; ValueName: "{#MyAppAssocKey}"; ValueData: ""; Flags: uninsdeletevalue +Root: HKA; Subkey: "Software\Classes\{#MyAppAssocKey}"; ValueType: string; ValueName: ""; ValueData: "{#MyAppAssocName}"; Flags: uninsdeletekey +Root: HKA; Subkey: "Software\Classes\{#MyAppAssocKey}\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\{#MyAppExeName},0" +Root: HKA; Subkey: "Software\Classes\{#MyAppAssocKey}\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\{#MyAppExeName}"" ""%1""" +Root: HKA; Subkey: "Software\Classes\Applications\{#MyAppExeName}\SupportedTypes"; ValueType: string; ValueName: ".myp"; ValueData: "" + +[Icons] +Name: "{autoprograms}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}" +Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon + +[Run] +Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent + diff --git a/src/setup.py b/src/setup.py index db06109..6a55325 100644 --- a/src/setup.py +++ b/src/setup.py @@ -1,7 +1,23 @@ -from os import system +############################################################################ +# # +# Description: Fichier setup pour empaqueter l'app # +# # +############################################################################ +# https://github.com/jrsoftware/issrc + +from os import system, mkdir +from os.path import join, isdir +from shutil import copy + +icon: str = join("app", "ressources", "icon.ico") +exePath: str = join("dist", "main", "main.exe") +dirRess: str = join("dist", "main", "ressources") +res: int = system(f"pyinstaller -w -i {icon} main.py") -res = system("pyinstaller -w -i .\\gui\\ressources\\icon.ico main.py") if res == 0: - system(".\\dist\\main\\main.exe") + if not isdir(dirRess): + mkdir(dirRess) + copy(icon, dirRess) + system(exePath) |
