//======================================================================================================================================================================== // CONFIG_MODULE.QML // Ce fichier traite la configuration d'un module (à la fois sur l'aspect physique et config) // La page est appelée depuis la page config_reseau_j_bus.qml, en cliquant sur un module dans la colonne 'config' //======================================================================================================================================================================== 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_module // Mis en forme : readonly property double pourcentage_largeur_colonne_gauche: 0.75 readonly property double espace_colonnes_principales: 20 readonly property double pourcentage_hauteur_ligne_haut: 0 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: 50 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_appui_long: 30 // en ms // Données : property bool flag_init: true // Permet de bloquer certains affichage tant que l'init n'est pas terminée property int valeur_timer_appui_long: 0 property int adresse_module; property int type_carte: 0 property string titre_page: "" property int consigne_en_cours: 0 // Contient la commande en cours sur le module property int index_courant_masses: -1 // SDIR #321 // 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 { mise_a_jour(); } } } //=========================================================== // Lorsque la page est sur le point d'être affichée dans la pile : //=========================================================== StackView.onActivating: { init_page(); // Permet un rafraichissement des champs qui ont pu être modifiés dans les pages en-dessous (Emplacement du module, Commentaires,...) } //=========================================================== // Titre de la page : //=========================================================== Shipheart_titre_1 {titre:titre_page; hauteur: shipheart_hauteur_bandeau_haut} //------------------------------------------------------- // Ecran Haut - Gauche : //------------------------------------------------------- Rectangle { id: zone_affichage_haut_gauche x: 0 y: shipheart_hauteur_bandeau_haut; width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2) height: (affichage_hauteur_utile * pourcentage_hauteur_ligne_haut) - 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 // Cf Ship2net.qml pour ajouter ici des champs de saisie... } } } //------------------------------------------------------- // Ecran Milieu - Gauche : //------------------------------------------------------- Rectangle { id: zone_affichage_milieu_gauche x: 0 y: shipheart_hauteur_bandeau_haut + zone_affichage_haut_gauche.height + espace_lignes_principales; width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2) height: (affichage_hauteur_utile * (1 - pourcentage_hauteur_ligne_haut)) - espace_lignes_principales; color: "transparent" //------------------------------------------------------------------- // Grille pour afficher les valeurs des paramètres non configurables : ListView { id: grille_informations width: parent.width height: parent.height spacing: 5 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_informations delegate: ligne_champ Component { id: ligne_champ Rectangle { width: grille_informations.width height: undefined // Permet de faire fonctionner le 'implicitHeight' qui suit implicitHeight: (texte_valeur_champ.implicitHeight > hauteur_ligne_formulaire) ? texte_valeur_champ.implicitHeight : hauteur_ligne_formulaire color: "transparent" // visible: !flag_init Shipheart_formulaire_label { text: nom_champ width: parent.width * pourcentage_largeur_labels_formulaire } Shipheart_formulaire_valeur_fixe { id: texte_valeur_champ text: valeur_champ width: parent.width * (1 - pourcentage_largeur_labels_formulaire) x: parent.width * pourcentage_largeur_labels_formulaire padding: 10 } Shipheart_formulaire_ligne_separation { haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse } } } ListModel { id: modele_grille_informations } } } //------------------------------------------------------- // Ecran Droite : //------------------------------------------------------- Rectangle { id: zone_affichage_droite x: zone_affichage_haut_gauche.width + espace_colonnes_principales y: shipheart_hauteur_bandeau_haut; width: (shipheart_largeur_page * (1 - pourcentage_largeur_colonne_gauche)) - (espace_colonnes_principales / 2) height: (affichage_hauteur_utile * pourcentage_hauteur_ligne_haut) - (espace_lignes_principales / 2); color: "transparent" Column { anchors.fill: parent spacing: 10 //------------------------------------------------ // Bouton localiser le module : Rectangle { width: parent.width height: hauteur_bouton_droit color: (consigne_en_cours !== 0) ? shipheart_couleur_fond_bouton_actif : shipheart_couleur_fond_bouton radius: shipheart_rayon_bouton visible: !clavier.active && (type_carte !== shipheart_type_module_shipbase) Text { anchors { verticalCenter: parent.verticalCenter horizontalCenter: parent.horizontalCenter } font.pixelSize: 20 text: qsTr("Localiser le module") color: couleur_blanc_casse } MouseArea { anchors.fill: parent onClicked: { shipheart_clic(); if (consigne_en_cours === 0) consigne_en_cours = 1; else consigne_en_cours = 0; commande_localisation_module(adresse_module, consigne_en_cours); } } } } } //------------------------------------------------------- // 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 //................................................. // 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(); if (consigne_en_cours !== 0) commande_localisation_module(adresse_module, 0); // Coupure de la localisation du module si on quitte la page et que la localisation est en cours stackView.pop() } } } } // Note : il est inutile de prévoir un Mousearea pour sortir de l'économiseur sur cette page puisqu'il // est systématiquement bloqué pour toutes les pages lancées depuis 'Paramètres Avancés'. //============================================================================================================= // Init de la page //============================================================================================================= function init_page() { mise_a_jour(); flag_init = false; } //============================================================================================================= // Mise à jour des informations variables // NB : le choix est fait de relancer une init complète chaque seconde. Un peu lourd mais permet de raffraichir // automatiquement toutes les infos chaque seconde (utile en tests de cartes...) [SDIR #309] //============================================================================================================= function mise_a_jour() { var req, res; var i; var nom_champ, valeur_champ, flag_valide; var index = 0; var nom_champ_emplacement, valeur_champ_emplacement; var nom_champ_commentaires, valeur_champ_commentaires; modele_grille_informations.clear(); // RAZ des valeurs existantes // La liste ci-dessous permet de définir les champs qui seront affichés ainsi que leur ordre d'affichage : // Attention : 'Type' est traité hors boucle et doit donc rester en première position !! var param = ["Type", "Adresse_k_bus", "Adresse_mac", // "Software_type", "Software_version", "Software_crc", "Hardware_version", "Flag_r_term", // "Cpu_unique_id", // "Cpu_flash_size", // "Cpu_package", "Date_maj"]; // Laissé actif en dernière position pour gérer les ',' lors de commentaires... Mais supprimé dans le switch... req = 'SELECT '; req += param[0]; for (i=1; i<(param.length - 1); i++) req += ', ' + param[i]; req += ' FROM TB_Modules_physiques WHERE Adresse_k_bus=' + adresse_module + ' '; //console.log("req =[" + req + "]"); res = bdd.requete_unique(req); //======================================================= // Cas particulier du 'Type' qui est traité hors boucle : // NB : il doit donc rester en première position de la liste des paramètres !! type_carte = Number(res[0]); //================================================== // Traitement de tous les autres paramètres : for (i=1; i<(param.length - 1); i++) { flag_valide = true; switch(param[i]) // NB : l'ordre de traitement dans le switch n'a aucun impact sur l'affichage.... { case "Adresse_k_bus" : if (type_carte === shipheart_type_module_shipbase) titre_page = qsTr("Paramètres du module [%1]").arg(Fonctions.nom_type_module(type_carte)) else titre_page = qsTr("Paramètres du module [%1] à l'adresse [%2]").arg(Fonctions.nom_type_module(type_carte)).arg(Number(res[i])); continue; case "Adresse_mac" : nom_champ = qsTr("N° de série"); valeur_champ = res[i]; break; case "Software_type" : nom_champ = qsTr("Nom du firmware"); valeur_champ = res[i]; break; case "Software_version" : nom_champ = qsTr("Version du firmware"); valeur_champ = res[i]; break; case "Hardware_version": nom_champ = qsTr("Version matérielle"); valeur_champ = res[i]; break; case "Flag_r_term" : if (adresse_module === 0) continue; nom_champ = qsTr("Résistance de terminaison"); valeur_champ = Number(res[i]) ? qsTr("Oui") : qsTr("Non"); break; // case "Cpu_unique_id": nom_champ = qsTr("ID unique du processeur"); valeur_champ = res[i]; break; // case "Cpu_flash_size": nom_champ = qsTr("Taille mémoire flash"); valeur_champ = res[i] + " kB"; break; // case "Cpu_package": nom_champ = qsTr("Code package processeur"); valeur_champ = res[i]; break; case "Software_crc": nom_champ = qsTr("CRC du firmware"); valeur_champ = res[i]; break; case "Date_maj": flag_valide = false; break; default: nom_champ = param[i]; valeur_champ = res[i]; break; } if (flag_valide) { valeur_champ = valeur_champ.replace(/\n/g, "
"); // Remplace les '\n' par '
'. Sinon, les '\n' ne sont pas pris en compte par le RichText d'affichage. modele_grille_informations.append({"nom_champ": nom_champ, "valeur_champ": valeur_champ}); } } //================================================== // Cas particulier des SP8DC avec leur courant de masse : if (type_carte === shipheart_type_module_shippower8DC) { // Ajout de l'entrée dans le modèle : modele_grille_informations.append({"nom_champ": qsTr("Courant de masses sur réseau"), "valeur_champ": "0"}); index_courant_masses = modele_grille_informations.count - 1; // Permet d'accéder ensuite à ce champ particulier pour mettre sa valeur à jour. Le '-1' permet d'avoir une valeur entre 0 et N car l'append précédent a positionné le COUNT à >= 1. } //========================================================= // Cas particulier du champ Version Processeur de ShipBase : if (adresse_module === 0) // Pour ShipBase, la version de Compute Module n'est pas dans TB_Modules_physiques mais dans TB_Systeme... { res = bdd.requete_unique('SELECT Valeur FROM TB_Systeme WHERE Nom="Version_cm" '); modele_grille_informations.append({"nom_champ": qsTr("Version processeur"), "valeur_champ": res[0]}); } //========================================================= // Courant de masse des SP8DC : if (index_courant_masses >= 0) // SDIR #321 : si l'index est toujours égal à -1, c'est que le champ n'est pas utilisé sur ce module et on ne fait pas de mises à jour. { req = 'SELECT Courant_masses FROM TB_Modules_config WHERE Adresse_k_bus=' + adresse_module + ' '; //console.log("req = [" + req + "]"); res = bdd.requete_unique(req); modele_grille_informations.setProperty(index_courant_masses, "valeur_champ", Number(res[0]).toFixed(3).toString() + " A"); } } //============================================================================================================= // Emission d'une commande à destination d'une carte //============================================================================================================= function commande_localisation_module(id, consigne) { var req; consigne_en_cours = consigne; req = "UPDATE TB_Modules_config SET New_cde='" + shipheart_commande_module_localisation + "/" + consigne + "' WHERE Adresse_k_bus=" + adresse_module + " "; bdd.requete_unique(req); } }