Import initial du projet shipheart_cm5

This commit is contained in:
2026-08-13 09:19:38 +02:00
commit 53e47729fb
533 changed files with 127946 additions and 0 deletions
+518
View File
@@ -0,0 +1,518 @@
//========================================================================================================================================================================
// CONFIG_SHIPRS.QML
// La page est appelée depuis la page 'parametres_avances'home_attente.qml' lorsque la connexion a la BDD n'a pu être effectuée
//========================================================================================================================================================================
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQml.Models
import qt.koriolan.shipheart 1.0
import"fonctions.js" as Fonctions
Shipheart_page {
id: page_config_shiprs
// Mis en forme :
readonly property double pourcentage_largeur_colonne_gauche: 0.75
readonly property double espace_colonnes_principales: 20
readonly property double pourcentage_hauteur_message_alerte: 0.45
readonly property double espace_lignes_principales: 20
readonly property double affichage_hauteur_utile: shipheart_hauteur_page - shipheart_hauteur_bandeau_haut - shipheart_hauteur_bandeau_bas
readonly property int hauteur_ligne_formulaire: 60
readonly property double pourcentage_largeur_labels_formulaire: 0.45
readonly property int hauteur_bouton_droit: 80
readonly property double pourcentage_bandeau_bas_largeur_zone_retour: 1
readonly property int periode_init_raffraichissement_parametres: 1 // En ms
readonly property int periode_raffraichissement_parametres: 1000 // En ms
readonly property int step_timer_sortie: 10 // en ms
// Affichage :
property bool bouton_bandeau_bas_zone_retour_actif: false
property bool flag_init: true // Permet de bloquer certains affichage tant que l'init n'est pas terminée
// Données :
property bool connexion_impossible: false
property string adresse_ip_shipbase: "inconnue<br /><i>unknown</i>"
property int taille_ecran_shiprs: 10
property bool configuration_modifiee: false
property string message_erreur: ""
property string message_info: ""
property int valeur_timer_sortie: 0
// Modèles :
// Note : les modèles chargés dans 'main.qml' n'ont pas à être rechargés dans les pages suivantes
//===========================================================
// Timer periode raffraichissement parametres :
//===========================================================
Timer {
id: timer_raffraichissement_parametres
interval: periode_init_raffraichissement_parametres
triggeredOnStart: false
running: true
repeat: true
onTriggered: {
if (interval == periode_init_raffraichissement_parametres) { // Premier passage, 1ms après le premier chargement
interval = periode_raffraichissement_parametres;
init_page();
}
else if (!bouton_bandeau_bas_zone_retour_actif)
{
// mise_a_jour();
}
}
}
//===========================================================
// Timer pour gérer l'appui long du reboot :
//===========================================================
Timer {
id: timer_sortie
interval: step_timer_sortie
triggeredOnStart: false
repeat: true
onTriggered: {
if (valeur_timer_sortie < shipheart_mouse_press_and_hold_interval_tres_long) valeur_timer_sortie+= step_timer_sortie;
else // Le fait de ne pas utilise le OnPressandHold permet d'être sût que la sortie se fait au même moment que la fin du comptage (sinon, on peut avoir de petits décalages)
{
timer_sortie.running = false;
valeur_timer_sortie = 0;
// Demande de Reset (via linux si on est sur un ShipRS !) :
let commande = "sudo sh -c \"sudo reboot now\" ";
//console.log("Commande shell : [" + commande + "]");
systeme.commande_shell(commande, "");
}
}
}
// Titre de la p"/images/ak14.png"age :
Shipheart_titre_1 {titre:"ShipRS"; hauteur: shipheart_hauteur_bandeau_haut}
//-------------------------------------------------------
// Ecran Haut :
//-------------------------------------------------------
Rectangle {
id: zone_affichage_message_alerte
x: 0
y: shipheart_hauteur_bandeau_haut;
width: shipheart_largeur_page;
height: visible ? (shipheart_hauteur_page - shipheart_hauteur_bandeau_haut) * pourcentage_hauteur_message_alerte : 0;
color: "transparent"
border.width: 3
border.color: couleur_rouge
radius: shipheart_rayon_bouton
visible: connexion_impossible
Image {
id: picto_alerte
source: "/images/ak14.png"
sourceSize.height: 100;
anchors {
left: parent.left
leftMargin: 20
verticalCenter: parent.verticalCenter
}
}
Text { // Affiche parfaitement 1, 2 ou 3 lignes de texte. A partir de 4 et 5, ça mort sur le contour du rectangle mais c'est encore lisible.
id: message_alerte
width: parent.width - picto_alerte.width - picto_alerte.anchors.leftMargin - anchors.leftMargin;
wrapMode: Text.Wrap
horizontalAlignment: Text.AlignHCenter
leftPadding: 10 // Dégage le pictogramme sur la gauche
rightPadding: 10 // Evite de se caler sur le bord droit du rectangle
text: "La connexion à ShipBase a échoué.<br />\
Vérifiez avant tout que ShipBase est bien sous tension et qu'il est bien connecté au réseau local.<br />\
Vérifiez ensuite que ShipRS est également connecté au réseau local via son port Ethernet.<br />\
Enfin, assurez-vous que l'adresse IP de ShipBase sur le réseau local est bien celle renseignée ci-dessous.<br />\
Dans le cas contraire, vous pouvez la mettre à jour puis cliquer sur [Enregistrer].<br />\
<b>Attention : La prise en compte de cette nouvelle adresse ne sera prise en compte qu'après un redémarrage de ShipRS.</b><br /><br />
<i>The connection to ShipBase has failed.<br />
First of all, check that ShipBase is switched on and connected to the local network.<br />
Then check that ShipRS is also connected to the local network via its Ethernet port.<br />
Finally, make sure that the IP address of ShipBase on the local network is the one given below.<br />
If not, you can update it and click on [Save].<br />
<b>Please note: The new address will only be taken into account after a restart of ShipRS.</b></i>";
anchors {
left: picto_alerte.right
verticalCenter: parent.verticalCenter
}
font.pixelSize: 18
color: couleur_blanc_casse
}
}
//-------------------------------------------------------
// Ecran Bas - Gauche :
//-------------------------------------------------------
Rectangle {
id: zone_affichage_saisie_parametres
x: 0
y: shipheart_hauteur_bandeau_haut + zone_affichage_message_alerte.height + espace_lignes_principales;
width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2);
height: ((shipheart_hauteur_page - shipheart_hauteur_bandeau_haut) * (1 - pourcentage_hauteur_message_alerte)) - espace_lignes_principales;
color: "transparent"
ListView {
id: grille_principale
width: parent.width
height: parent.height
snapMode: GridView.SnapToRow // L'arret de l'affichage se fera sur une rangée entière
clip: true // Nécessaire pour que les Delegates s'arretent à l'intérieur de la GridView
model: modele_grille_principale
footer: Rectangle { // Permet de dégager la place suffisante en fin de GridView pour accéder même au dernier élément lorsque que clavier est déplié
height: shipheart_hauteur_clavier
color: "transparent"
}
ObjectModel {
id: modele_grille_principale
//-------------------------------------------------------------------------------
// Ligne de formulaire : Adresse IP
Rectangle {
width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2)
height: visible ? hauteur_ligne_formulaire : 0
color: "transparent"
Shipheart_formulaire_label {
text: "Adresse IP de ShipBase sur le réseau local<br /><i>ShipBase IP address on local network</i>"
width: parent.width * pourcentage_largeur_labels_formulaire
}
Shipheart_formulaire_textfield {
id: champ_formulaire_Adresse_ip
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
x: parent.width * pourcentage_largeur_labels_formulaire
}
Shipheart_formulaire_ligne_separation {
haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse
}
}
//-------------------------------------------------------------------------------
// Ligne de formulaire : Taille écran
Rectangle {
width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2)
height: visible ? hauteur_ligne_formulaire : 0
color: "transparent"
Shipheart_formulaire_label {
text: "Taille de l'écran<br /><i>Screen size</i>"
width: parent.width * pourcentage_largeur_labels_formulaire
}
Shipheart_formulaire_combobox {
id: champ_formulaire_Taille_ecran
model: ListModel { }
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
onActivated: {
shipheart_clic();
}
}
Shipheart_formulaire_ligne_separation {
haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse
}
}
//-------------------------------------------------------------------------------
// Message d'erreur si adresse IP invalide :
Rectangle {
width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2)
height: visible ? hauteur_ligne_formulaire : 0
color: "transparent"
visible: (message_erreur !== "") || (message_info !== "")
Text {
// height: parent.height * proportion_hauteur_texte_droite
width: parent.width;
anchors.horizontalCenter: parent.horizontalCenter
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
topPadding: 20 // Cette valeur permet d'être aligné avec la version courante...
bottomPadding: 50
font.pixelSize: 18
text: (message_erreur !== "") ? message_erreur : message_info
color: (message_erreur !== "") ? couleur_rouge : couleur_blanc_casse
wrapMode: Text.Wrap
}
}
}
}
}
//-------------------------------------------------------
// Ecran Bas - Droite :
//-------------------------------------------------------
Rectangle {
id: zone_affichage_droite
x: zone_affichage_saisie_parametres.width + espace_colonnes_principales
y: shipheart_hauteur_bandeau_haut + zone_affichage_message_alerte.height + espace_lignes_principales;
width: (shipheart_largeur_page * (1 - pourcentage_largeur_colonne_gauche)) - (espace_colonnes_principales / 2);
height: ((shipheart_hauteur_page - shipheart_hauteur_bandeau_haut) * (1 - pourcentage_hauteur_message_alerte)) - espace_lignes_principales;
color: "transparent"
visible: !clavier.active
Column {
anchors.fill: parent
spacing: 10
// Bouton Enregistrer :
Rectangle {
width: parent.width
height: hauteur_bouton_droit
color: shipheart_couleur_fond_bouton
radius: shipheart_rayon_bouton
Text {
anchors {
verticalCenter: parent.verticalCenter
horizontalCenter: parent.horizontalCenter
}
font.pixelSize: 20
text: "Enregistrer<br /><i>Save</i>"
color: couleur_blanc_casse
}
MouseArea {
anchors.fill: parent
onClicked: {
enregistrement();
if ((!connexion_impossible) && (message_erreur === ""))
{
shipheart_clic();
stackView.pop()
}
}
}
}
//--------------------------------------------------------------------
// Bouton Rebooter :
Rectangle {
width: parent.width
height: hauteur_bouton_droit
color: shipheart_couleur_fond_bouton
radius: shipheart_rayon_bouton
visible: connexion_impossible && configuration_modifiee
Label {
anchors.centerIn: parent
text: "Redémarrer ShipRS<br /><i>Restart ShipRS</i>"
color: couleur_blanc_casse
font.pixelSize:20
}
// Barre grandissante pour montrer durée d'appui vs tempo nécessaire :
Rectangle {
width: (valeur_timer_sortie / shipheart_mouse_press_and_hold_interval_tres_long) * parent.width
height: parent.height
color: couleur_rouge_transparent
radius: shipheart_rayon_bouton
}
MouseArea {
anchors.fill: parent
onPressed: { // Déclenché lors de l'appui inital
valeur_timer_sortie = 0;
timer_sortie.running = true;
}
onClicked: { // Déclenché si l'appui n'a pas été suffisement long pour avoir un Press&Hold :
timer_sortie.running = false;
valeur_timer_sortie = 0;
}
onExited: { // Déclenché si le doigt sort de la zone du bouton (sinon, on continue à compter alors qu'on est sorti de la zone et même relaché le doigt !!)
timer_sortie.running = false;
valeur_timer_sortie = 0;
}
}
}
}
}
//-------------------------------------------------------
// Bandeau bas :
//-------------------------------------------------------
Row {
x: 0
y: shipheart_hauteur_page - shipheart_hauteur_bandeau_bas;
width: shipheart_largeur_page;
height: shipheart_hauteur_bandeau_bas;
spacing: 5
padding: 5
visible: !connexion_impossible
//.................................................
// Bouton retour
//.................................................
Rectangle {
id: bandeau_bas_zone_retour
width: (parent.width * pourcentage_bandeau_bas_largeur_zone_retour) - (2 * parent.padding)
height: shipheart_hauteur_bandeau_bas - parent.topPadding - parent.bottomPadding;
radius: shipheart_rayon_bouton
color: shipheart_couleur_fond_bouton
Image {
source: "/images/icone_retour.png"
sourceSize.height: 30
anchors {
verticalCenter: parent.verticalCenter
horizontalCenter: parent.horizontalCenter
}
}
MouseArea { // Zone d'interaction. On est obligé de la mettre dans la grille pour que Rectangle et MouseArea soient frères ou parent/enfant ET qu'on n'occupe qu'un espace dans la grille.
id: mouse_area_bandeau_bas_zone_retour
anchors.fill: parent
onClicked: {
shipheart_clic();
stackView.pop()
}
}
}
}
//=============================================================================================================
// Init de la page
//=============================================================================================================
function init_page()
{
var i;
var lignes;
lignes = systeme.lecture_fichier(shipheart_nom_complet_fichier_shiprs_conf);
// ATTENTION : la première ligne renvoyée par la fonction n'est PAS lue dans le fichier mais indique si la lecture s'est déroulée correctement ("Ok") ou pas ("Nok").
console.log("Résultat de la lecture de 'shiprs.conf' = " + lignes[0]);
console.log("Adresse IP de ShipBase dans 'shiprs.conf' = " + lignes[1]);
console.log("Taille écran dans 'shiprs.conf' = " + lignes[2]);
if (lignes[0] === "Ok")
{
adresse_ip_shipbase = lignes[1];
taille_ecran_shiprs = lignes[2];
}
else
{
adresse_ip_shipbase = "???.???.???.???";
taille_ecran_shiprs = 10;
message_erreur = "/!\\ La lecture du fichier 'shiprs.conf' est impossible<br /><i>/!\\ ShipRS config file can't be accessed</i>";
}
//-----------------------------------------------------------------------------------------
champ_formulaire_Adresse_ip.text = adresse_ip_shipbase;
//-----------------------------------------------------------------------------------------
champ_formulaire_Taille_ecran.model.clear();
champ_formulaire_Taille_ecran.model.append({"valeur": 7, "texte": "7\" " });
champ_formulaire_Taille_ecran.model.append({"valeur": 10, "texte": "10\" " });
champ_formulaire_Taille_ecran.model.append({"valeur": 22, "texte": "22\" " });
// Positionnement de l'index sur la valeur en cours :
i = recherche_index_valeur_modele(taille_ecran_shiprs, champ_formulaire_Taille_ecran.model, "taille_ecran_shiprs");
if (i === -1) champ_formulaire_Taille_ecran.currentIndex = recherche_index_valeur_modele(10, champ_formulaire_Taille_ecran.model, "taille_ecran_shiprs");
else champ_formulaire_Taille_ecran.currentIndex = i;
flag_init = false;
}
//=============================================================================================================
// Enregistrement des valeurs saisies
//=============================================================================================================
function enregistrement()
{
var lignes = [];
message_erreur = ""; // Nécessaire si une erreur était présente au préalable.
message_info = ""; // Nécessaire si un message était présent au préalable.
// Vérification de la validité du format de l'adresse IP saisie :
if (Fonctions.test_format_adresse_ip_v4(champ_formulaire_Adresse_ip.text))
//-----------------------------------------------------------
// Cas où le format est valide :
{
if(champ_formulaire_Adresse_ip.text !== "192.168.4.1")
{
adresse_ip_shipbase = champ_formulaire_Adresse_ip.text;
taille_ecran_shiprs = champ_formulaire_Taille_ecran.model.get(champ_formulaire_Taille_ecran.currentIndex).valeur;
lignes.push(adresse_ip_shipbase);
lignes.push(taille_ecran_shiprs);
if (systeme.ecriture_fichier(shipheart_nom_complet_fichier_shiprs_conf, lignes) === -1)
{
message_erreur = "/!\\ L'écriture du fichier 'shiprs.conf' est impossible.<br /><i>/!\\ 'shiprs.conf' file cannot be written to</i>";
}
else
{
configuration_modifiee = true;
message_info = "Les nouveaux paramètres ont été enregistrés.<br />Vous pouvez maintenant maintenir appuyé le bouton [Redémarrer ShipRS] jusqu'au redémarrage pour que ces nouveaux paramètres soient pris en compte.<br /><i>The new settings have been saved.<br />You can now press and hold the [Restart ShipRS] button until the system restarts to take these new settings into account.</i>";
}
//console.log("Format d'adresse IP valide...")
}
else message_erreur = "L'adresse IP [192.168.4.1] n'est pas autorisée. Merci d'entrer une adresse différente...<br /><i>The [192.168.4.1] IP address is not authorized. Please enter a different address...</i>";
}
//-----------------------------------------------------------
// Cas où le format est invalide :
else
{
message_erreur = "L'adresse IP saisie n'est pas valide et ne peut pas être enregistrée. Merci d'entrer une chaine valide...<br /><i>The IP address entered is invalid and cannot be saved. Please enter a valid string...</i>";
// champ_formulaire_Adresse_ip.text = adresse_ip_shipbase; // Retour à la valeur précédente
//console.log("Format d'adresse IP invalide !")
}
}
//=============================================================================================================
// Recherche de l'index d'une certaine valeur dans un modele
//=============================================================================================================
function recherche_index_valeur_modele(cible, modele, nom_modele)
{
var i;
for (i=0; i<modele.count; i ++)
{
if (modele.get(i).valeur === cible) break; // Cas où la valeur cible a été trouvée parmi les valeurs du modèle
}
if (i === modele.count)
{
console.log("Aucune valeur trouvée pour cible = [" + cible + "] du modèle = " + nom_modele);
i = -1; // Cas où la valeur n'a pas été trouvée parmi les valeurs du modèle
}
//else console.log("Valeur trouvée : [" + i + "] pour cible = [" + cible + "] soit texte = [" + modele.get(i).texte + "]");
return(i);
}
}