Skip to content

Commit

Permalink
Mise à jour du fichier README.md, correction de la liste des dépendan…
Browse files Browse the repository at this point in the history
…ces (et donc du fichier requirements.txt). Correction du bug qui empêchait l'application de démarrer grâce au débugger python de VScode - c'était dû à un oublie après un test pour ajouter une icône à une entrée du menu 'Source'. Ajout d'un système de vérification des mises à jour dans la fenêtre 'A propos' (fichier FenetreInfo.py)
  • Loading branch information
pandaroux007 committed Sep 8, 2024
1 parent 5d2c063 commit 24f3763
Show file tree
Hide file tree
Showing 8 changed files with 93 additions and 56 deletions.
4 changes: 1 addition & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,4 @@ runApp.onefile-build
# dossier contenant des éléments de développement
dev
# dossier d'environnement python au cas où
gotimeEnv
# fichier contenant les screenshots de l'appli
screenshots/
gotimeEnv
64 changes: 37 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ ___
5. Merci à ma professeur d'anglais, qui a lancer l'idée et qui m'a fait confiance pour réaliser ce projet;
6. Merci à tous les développeurs des modules utilisés ici pour leurs travaux et leurs contributions à la communauté open-source;
7. Enfin, merci à tous les créateurs de contenus techniques sur internet qui m'ont permis de trouver de la documentation pour chaque éléments des modules.

___
# Apparence globale
## Interface
### Barre de Menu
Expand Down Expand Up @@ -146,7 +146,7 @@ Comme indiqué plus haut, sur la fenêtre se trouve un bouton permettant de "dé
une nouvelle fenêtre avec affiché seulement le temps restant, sur un fond de couleur. Cette fenêtre à l'avantage d'être beaucoup plus
visible que l'affichage de l'application, mais aussi le fait qu'elle reste toujours au premier plan (même si vous cliquez à côté, elle
restera apparente).

___
# Développement
## Fonctionnement des versions
> **Base : *x.y.z***
Expand Down Expand Up @@ -175,7 +175,7 @@ Voici une petite liste non exhaustive des futurs améliorations.

- [ ] Si un jour, une fois l'application terminée completement avec toutes les améliorations présentées ci-haut, j'ai envie de perdre mon temps, je passerai probablement sur une version 4 cross-platform, avec wxWidgets (**wxPython**) ou Toga (?). Mais comme cela nécessite de refaire toute l'interface, je ne le ferai probablement pas avant longtemps (j'en profiterai pour changer quelques détails pour rendre l'application plus conviviale).

- [ ] Terminer la section "À propos" du menu "Source"
- [x] Terminer la section "À propos" du menu "Source"

## Installation des dépendances
Attention, **certains des modules utilisés par le projet ne sont pas inclus par défauts dans python**. Pour les installer, il vous suffit de
Expand All @@ -184,24 +184,30 @@ lancer la commande suivante (après vous être déplacé dans le répertoire du
pip install -r requirements.txt
```
Cette commande installera les modules listés dans le fichier *requirements.txt*, utilisés par l'application mais qui ne sont pas inclue par défaut dans python3. Tous les modules utilisés par l'application sont listé ci-dessous :
1. tkinter
2. datetime
3. webbrowser
4. sys
5. subprocess
6. **darkdetect**
7. **PIL (pillow)**
8. os
9. json
10. platform
11. getpass
12. socket
13. **pygame**
1. `tkinter`, `ttk`, `messagebox`
2. `datetime`
3. `webbrowser`
4. `sys`
5. `subprocess`
6. **`darkdetect`**
7. `os`
8. `json`
9. `platform`
10. `getpass`
11. `socket`
12. **`pygame`**
13. `packaging`
14. `re`
15. `urllib`
16. `threading`

> [!CAUTION]
> Notez qu'il peut y avoir des problème lors de l'utilisation de `darkdetect` sous Windows avec le fichier `setup.py`. Je réfléchie à placer directement le code du module dans [src](src/), je dois encore regarder les permissions accordées par la licence *BSD License*.
## Fonctionnement
GoTime fonctionne avec la fonction `after` de `tkinter`. L'affichage de l'heure fonctionne de cette manière et le minuteur également.
Cette méthode permet d'appeller une fonction un certain temps plus tard, temps défini en ms. Pour modifier chaque seconde l'heure, par exemple,
on utilise cette commande (l.130)
on utilise cette commande (l.138)
```py
self.after(1000, self.update_time) # Met à jour toutes les secondes
```
Expand All @@ -210,16 +216,11 @@ Pour ce qui est des paramètres, l'application fonctionne grâce à une lecture/
Tout le reste de l'application n'est qu'une question d'apparence et de widgets, la base fonctionne comme ceci.

## Bugs
Il y a deux bug actuellement découverts.
1. Bien entendu, le bug des antivirus sur Windows persiste et c'est l'un des plus gros problèmes de l'application. Cependant il est aussi très simple à contourner : il suffit de désactiver son antivirus le temps d'installer le logiciel et le réactiver ensuite (ce qui prouve leur inutilité sur ce point). Je conseille d'utiliser la fonction "disable for 10mn" pour ne pas oublier ensuite de le réactiver.
Il y a un bug actuellement découvert.
1. Le bug des antivirus sur Windows persiste et c'est l'un des plus gros problèmes de l'application. Cependant il est aussi très simple à contourner : il suffit de désactiver son antivirus le temps d'installer le logiciel et le réactiver ensuite (ce qui prouve leur inutilité sur ce point). Je conseille d'utiliser la fonction "disable for 10mn" pour ne pas oublier ensuite de le réactiver.

2. Actuellement l'application ne démarre pas (enfin la fenêtre commence à s'ouvrir - elle est juste noire, il n'y a aucun widget dedant - avec une boite de dialogue indiquant le message d'erreur). Le message d'erreur indique que le fichier [icon.png](dep/icon.png) n'existe pas (Cette erreur n'était jamais apparue avant que je change le système de paramètres dans la branche git "correctionParam"). Voici le message :
```txt
Hmm...Quelque chose semble s'être mal passé...
L'erreur est : image "/home/pandaroux007/Bureau/Programmation/Projets python/gui/GoTime/dep/icon.png" doesn't exist
```

## Compilation
## Compilation & distribution
### Compilation avec Nuitka
Pour compiler et distribuer l'application, j'utilise [`nuitka`](https://github.com/Nuitka/Nuitka), avec cette commande :
```sh
python3 -m nuitka --run --onefile --output-filename="GoTime" --windows-console-mode=disable --follow-imports --enable-plugin=tk-inter --nofollow-import-to=pygame.tests --linux-icon="dep/icon.ico" --macos-app-icon="dep/icon.ico" --windows-icon-from-ico="dep/icon.ico" runApp.py
Expand All @@ -232,4 +233,13 @@ python3 -m nuitka --run --onefile --output-filename="GoTime" --windows-console-m
**EDIT** : Après tests, il se trouve que l'ajout de `--mingw64` lors de la compilation sous Windows ne change rien, l'application et son installation se font toujours flaguer. Je conseille donc à ceux qui installent l'application ou qui la compile **de désactiver pour quelques minutes leurs antivirus**.

> [!NOTE]
> Installez nuitka avec `pip install nuitka`, puis installez l'utilitaire de compression d'exécutables si il n'est pas installé (`pip install zstandard`), configurez le cache des fichiers `C` (ccache), puis lancez la commande indiquez plus haut.
> Installez nuitka avec `pip install nuitka`, puis installez l'utilitaire de compression d'exécutables si il n'est pas installé (`pip install zstandard`), configurez le cache des fichiers `C` (ccache), puis lancez la commande indiquez plus haut.
### Distribution du logiciel
Comme indiqué dans [le chapitre installation](#installation), l'application est distribuée de trois façon:
#### Sous Linux
- Utilisation de scripts shell bash ([install.sh](install.sh) et [uninstall.sh](#désinstallation))
#### Sous Microsoft Windows
- Utilisation d'un installateur créé *via* `Inno Setup`
#### Sous MacOS-X
- Pas de programme compilé ni de script d'installation : les utilisateurs de machines Apple devrons utiliser la version python directement pendant une durée indéterminée.
1 change: 0 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
pillow
darkdetect
pygame
12 changes: 5 additions & 7 deletions src/Application.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
from tkinter import messagebox # pour les erreur et les validations
import darkdetect # pour la détection du thème de l'OS
# ------------------------ fichiers de l'application
from Definitions import * # fichier contenant toutes les variables
from Definitions import *
from FenetreLicence import FenetreLicence
from FenetreParametres import FenetreParametres # fichier contenant la fenêtre d'affichage des paramètres
from FenetreInfo import FenetreInfo # fichier contenant la fenêtre d'affichage du lien du dépôt GitHub
from FenetreParametres import FenetreParametres
from FenetreInfo import FenetreInfo

class Application(tk.Tk):
def __init__(self):
Expand All @@ -32,7 +32,7 @@ def __init__(self):
barre_de_menu = tk.Menu(self)
# ------------------------ Création d'un menu 'Fenêtre'
fenetre_menu = tk.Menu(barre_de_menu, tearoff=0)
fenetre_menu.add_command(label="Paramètres", command=lambda: FenetreParametres())
fenetre_menu.add_command(label="Paramètres", command=lambda: FenetreParametres(callback_theme=self.gestion_theme_par_defaut))
fenetre_menu.add_separator()
fenetre_menu.add_command(label="Quitter", command=self.quit)
barre_de_menu.add_cascade(label="Fenêtre", menu=fenetre_menu)
Expand All @@ -43,11 +43,9 @@ def __init__(self):
barre_de_menu.add_cascade(label="Commandes", menu=commandes_menu)
# ------------------------ Création d'un troisième menu 'Source'
source_menu = tk.Menu(barre_de_menu, tearoff=0)
# source_menu.add_command(label="Ouvrir GitHub", command=lambda: webbrowser.open_new_tab(lien_du_github))
# source_menu.add_command(label="Afficher GitHub", command=lambda: FenetreInfoAffichageLienGitHub())
source_menu.add_command(label="Afficher LICENCE", command=lambda: FenetreLicence())
source_menu.add_command(label="Signaler un bug", command=lambda: webbrowser.open_new_tab(lien_du_github + "/issues"))
source_menu.add_command(label="À propos", image=chemin_image_application, command=lambda: FenetreInfo())
source_menu.add_command(label="À propos", command=lambda: FenetreInfo())
barre_de_menu.add_cascade(label="Source", menu=source_menu)
# ------------------------ Ajout de la barre de menu à la fenêtre
self.config(menu=barre_de_menu)
Expand Down
11 changes: 5 additions & 6 deletions src/Definitions.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
# https://github.com/Nuitka/Nuitka/issues/1737#issuecomment-1224488673
# https://stackoverflow.com/questions/59427353/how-to-get-the-current-path-of-compiled-binary-from-python-using-nuitka
repertoire_courant = os.path.dirname(os.path.abspath(os.path.realpath(sys.argv[0])))
""" # variables définie par nuitka lors de la compilation (UNIQUEMENT Nuitka, pas un autre compilateur!)
""" # chemins lors de la compilation
chemin_fichier_parametres = os.path.join(repertoire_courant, "dep", "settings.json")
chemin_fichier_logs = os.path.join(repertoire_courant, 'log', "error_log.csv")
chemin_image_application = os.path.join(repertoire_courant, 'dep', 'icon.png')
Expand All @@ -18,7 +18,6 @@
chemin_fichier_parametres = os.path.join(os.path.dirname(repertoire_courant), "dep", "settings.json")
chemin_fichier_logs = os.path.join(os.path.dirname(repertoire_courant), 'log', "error_log.csv")
chemin_image_application = os.path.join(os.path.dirname(repertoire_courant), 'dep', 'icon.png')
chemin_image_checkmark = os.path.join(os.path.dirname(repertoire_courant), 'dep', 'checkmark.png')
chemin_fichier_wav_fin_temps = os.path.join(os.path.dirname(repertoire_courant), 'sons', 'digital-clock-alarm.wav')
chemin_fichier_licence = os.path.join(os.path.dirname(repertoire_courant), "LICENCE.txt")

Expand Down Expand Up @@ -77,7 +76,7 @@ def jouer_sonnerie(etat_jouer_son):
sonnerie_actuelle = mixer.Sound(chemin_fichier_wav_fin_temps)
if etat_jouer_son: sonnerie_actuelle.play()
else: sonnerie_actuelle.stop()
except Exception as e: log_error(f"Exception dans la fonction jouer_sonnerie : {e}"); pass
except Exception as e: log_error(f"Exception dans la fonction jouer_sonnerie : {str(e)}"); pass

# ------------------------ Variables utiles
systeme_exploitation = system()
Expand All @@ -89,7 +88,7 @@ def jouer_sonnerie(etat_jouer_son):
temps_max = 10800 # 3 heures en secondes

# ------------------------ Infos App
lien_du_github = "https://github.com/pandaroux007/GoTime"
nom_application = "GoTime"
version_application = "1.0.3-bêta"
developpeur_application = "Pandaroux007"
version_application = "1.1.0-bêta"
developpeur_application = "pandaroux007"
lien_du_github = "https://github.com/" + developpeur_application + "/" + nom_application
52 changes: 42 additions & 10 deletions src/FenetreInfo.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import tkinter as tk
from tkinter import messagebox
import webbrowser
from threading import Thread
from urllib import request
from packaging import version
import re
# ------------------------ fichiers de l'application
from Definitions import *

Expand All @@ -13,8 +17,9 @@ def __init__(self, master, text, url, *args, **kwargs):
self.bind("<Leave>", lambda action: self.config(font=("TkDefaultFont", 10)))

class FenetreInfo(tk.Toplevel):
def __init__(self, parent):
super().__init__(parent)
def __init__(self):
super().__init__()
# ------------------------ Parametrge fenêtre
self.title(f"À propos de {nom_application}")
self.geometry("400x300")
self.resizable(False, False)
Expand All @@ -29,14 +34,41 @@ def __init__(self, parent):
# ------------------------ lien du GitHub
LienHypertexte(self.frame_infos, text="GitHub du projet", url=lien_du_github).pack(pady=10)
# ------------------------ Frame pour les boutons
button_frame = tk.Frame(self.frame_infos)
button_frame.pack(side=tk.BOTTOM, fill=tk.X, pady=(20, 0))
self.frame_boutons = tk.Frame(self.frame_infos)
self.frame_boutons.pack(side=tk.BOTTOM, fill=tk.X, pady=(20, 0))
# ------------------------ Bouton verif les mises à jours
update_button = tk.Button(button_frame, text="Vérifier les mises à jour maintenant", command=self.check_updates)
update_button.pack(side=tk.LEFT, expand=True)
self.bouton_verif_mises_a_jour = tk.Button(self.frame_boutons, text="Vérifier les mises à jour maintenant", command=self.lancer_verif_mise_a_jour)
self.bouton_verif_mises_a_jour.pack(side=tk.LEFT, expand=True)
# ------------------------ Bouton "OK"
ok_button = tk.Button(button_frame, text="OK", command=self.destroy)
ok_button.pack(side=tk.RIGHT, expand=True)
self.bouton_ok = tk.Button(self.frame_boutons, text="OK", command=self.destroy)
self.bouton_ok.pack(side=tk.RIGHT, expand=True)

def check_updates(self):
messagebox.showwarning("Mise à jour", "Cette partie de l'application est encore en développement!") # "Vérification des mises à jour en cours..."
def lancer_verif_mise_a_jour(self):
self.bouton_verif_mises_a_jour.config(state="disabled")
Thread(target=self.verif_mise_a_jour, daemon=True).start()

# utilisation de self.after(0, ...) pour modifier la gui depuis le thread car tkinter n'est pas thread-safe
def verif_mise_a_jour(self):
try:
# ------------------------ Requête à l'api de github pour obtenir la dernière version
url = "https://api.github.com/repos/" + developpeur_application + "/" + nom_application + "/releases/latest"
with request.urlopen(url) as response:
data = json.loads(response.read().decode())
derniere_version_app_sur_github = data['tag_name']
# ------------------------ enlever les éléments inutiles dans le numéro de version
version_app_local = re.sub(r"[^\d.]", "", version_application)
version_app_github = re.sub(r"[^\d.]", "", derniere_version_app_sur_github)
# ------------------------ comparer les deux versions
if version.parse(version_app_local) < version.parse(version_app_github):
def afficher_message_mise_a_jour_dispo():
reponse = messagebox.askyesno(
title="Mise à jour disponible", icon="info",
message=f"Une nouvelle version {version_app_github} de {nom_application} est disponible!\n\nVoulez-vous ouvrir la page de téléchargement ?")
if reponse == tk.YES: webbrowser.open_new_tab(url=lien_du_github + "/releases/latest")
self.after(0, afficher_message_mise_a_jour_dispo)
else: self.after(0, lambda: messagebox.showinfo(title="Aucune mise à jour disponible", message=f"Aucune nouvelle version de {nom_application} n'est disponible!"))
# ------------------------ Si une erreur est levée afficher un message d'avertissement
except Exception as e:
self.after(0, lambda: messagebox.showwarning(title="Avertissement", message=f"Erreur lors de la vérification des mises à jour!\n{e}"))
# ------------------------ réactiver le bouton de verif des mises à jours
finally: self.after(0, lambda: self.bouton_verif_mises_a_jour.config(state="normal"))
1 change: 1 addition & 0 deletions src/FenetreLicence.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import tkinter as tk
from tkinter import messagebox
# ------------------------ fichiers de l'application
from Definitions import *

class FenetreLicence(tk.Toplevel):
Expand Down
4 changes: 2 additions & 2 deletions src/runApp.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@
root = Application()
root.mainloop()
except Exception as e:
messagebox.showerror(title=f"Erreur", message=f"Hmm...Quelque chose semble s'être mal passé...\nL'erreur est : {e}")
log_error(e)
messagebox.showerror(title=f"Erreur", message=f"Hmm...Quelque chose semble s'être mal passé...\nL'erreur est : {str(e)}")
log_error(str(e))
exit()

0 comments on commit 24f3763

Please sign in to comment.