import QtQuick 2.12 import qt.koriolan.shipheart 1.0 Shipheart_page { id: page_protection // Mis en forme : readonly property double pourcentage_largeur_colonne_gauche: 0.5 readonly property double espace_colonnes_principales: 20 readonly property double pourcentage_hauteur_ligne_haut: 0.15 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 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 // Affichage : property int niveau_page: 0 property bool bouton_bandeau_bas_zone_retour_actif: false property int protection_mode: 0 // Données : property string code: "" property string code_admin: "" property string code_saisi: "" property string code_saisi_pattern: "" // Contient une suite de '*' dont le nombre correspond à la taille du code entré (avec un maxi) property int type_code: shipheart_type_code_normal // 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(); } if (stackView.depth === (niveau_page + 1)) // Désactive le raffraichissement quand la page n'est pas activée dans la pile { mise_a_jour_periodique(); } } } // Titre de la page : Shipheart_titre_1 {titre:qsTr("Accès protégé"); 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 / 2); color: "transparent" border.width: 1 border.color: couleur_gris_moyen radius: shipheart_rayon_bouton Text { anchors { verticalCenter: parent.verticalCenter verticalCenterOffset: 12 // Les '*' sont naturellement décalées vers le haut de la ligne... horizontalCenter: parent.horizontalCenter } font.pixelSize: 80 font.letterSpacing: 10 text: code_saisi_pattern; color: couleur_blanc_casse } } //------------------------------------------------------- // Ecran Bas - Gauche : //------------------------------------------------------- Rectangle { id: zone_affichage_bas_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 / 2); color: "transparent" Grid { id: grille_clavier width: parent.width * 0.6 height: parent.height * 0.8 columns: 3 rows: 4 spacing: 10 anchors { verticalCenter: parent.verticalCenter horizontalCenter: parent.horizontalCenter } Repeater { model: modele_clavier Rectangle { width: (grille_clavier.width - ((grille_clavier.columns - 1) * grille_clavier.spacing)) / grille_clavier.columns height: (grille_clavier.height - ((grille_clavier.rows - 1) * grille_clavier.spacing)) / grille_clavier.rows color: shipheart_couleur_fond_bouton radius: shipheart_rayon_bouton Text { anchors { verticalCenter: parent.verticalCenter horizontalCenter: parent.horizontalCenter } font.pixelSize: 50 text: libelle; color: couleur_blanc_casse visible: (libelle === "") ? false : true } Image { source: icone sourceSize.height: 30 anchors { verticalCenter: parent.verticalCenter horizontalCenter: parent.horizontalCenter } visible: (libelle === "") ? true : false } MouseArea { anchors.fill: parent onClicked: { shipheart_clic(); switch(action) { case "backspace": code_saisi = code_saisi.slice(0, code_saisi.length - 1); type_code = shipheart_type_code_normal; // Par défaut, si on clique sur Backspace, on retourne en mode normal break; case "clear": code_saisi = ""; type_code = shipheart_type_code_normal; // Par défaut, si on clique sur Clear, on retourne en mode normal break; default: code_saisi += libelle; break; } if (check_code() === 0) deverrouillage(); mise_a_jour_pattern(); } onPressAndHold: { if (libelle === "0") // Appui long sur le '0' pour passer en accès administrateur { if (type_code === shipheart_type_code_normal) type_code = shipheart_type_code_admin; else type_code = shipheart_type_code_normal; } } } } } ListModel { id: modele_clavier ListElement { libelle: "7"; action: ""; icone: "" } ListElement { libelle: "8"; action: ""; icone: "" } ListElement { libelle: "9"; action: ""; icone: "" } ListElement { libelle: "4"; action: ""; icone: "" } ListElement { libelle: "5"; action: ""; icone: "" } ListElement { libelle: "6"; action: ""; icone: "" } ListElement { libelle: "1"; action: ""; icone: "" } ListElement { libelle: "2"; action: ""; icone: "" } ListElement { libelle: "3"; action: ""; icone: "" } ListElement { libelle: ""; action: "backspace"; icone: "/images/backspace.png" } ListElement { libelle: "0"; action: ""; icone: "" } ListElement { libelle: ""; action: "clear"; icone: "/images/double_fleche_gauche.png" } } } } //------------------------------------------------------- // 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; color: "transparent" Text { id: texte_protection_mode_access_parametres_avances anchors { verticalCenter: parent.verticalCenter horizontalCenter: parent.horizontalCenter } padding: 20 font.pixelSize: 20 horizontalAlignment: Text.AlignHCenter text: qsTr("L'accès aux paramètres avancés est protégé.\nMerci d'entrer le code de déverrouillage pour y accéder...") color: couleur_blanc_casse visible: (protection_mode === protection_mode_access_parametres_avances) ? true : false } Text { id: texte_protection_mode_access_parametres_avances_admin anchors { top: texte_protection_mode_access_parametres_avances.bottom horizontalCenter: parent.horizontalCenter } padding: 20 font.pixelSize: 20 horizontalAlignment: Text.AlignHCenter text: qsTr("Mode administrateur validé
Entrer votre code dédié") color: couleur_bleu_koriolan visible: (protection_mode === protection_mode_access_parametres_avances) ? ((type_code === shipheart_type_code_admin) ? true : false) : false } } //------------------------------------------------------- // 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 } } Image { id: image_alarme_paramètres // Affichage du coin inférieur-droit en rouge si une erreur de paramètres est détectée source: "/images/coin_bas_droite_rouge.png" sourceSize.height: 20 anchors { bottom: parent.bottom right: parent.right } visible: shipheart_defaut_config_k_bus } Image { id: image_info_paramètres // Affichage du coin inférieur-droit en bleu si une nouvelle version est dispo source: "/images/coin_bas_droite_bleu_koriolan.png" sourceSize.height: 20 anchors { bottom: parent.bottom right: parent.right } visible: !image_alarme_paramètres.visible && ((shipheart_fichier_a_charger !== "") || (shipheart_fichier_a_valider !== "")) } 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() } } } } //=========================================================== // Economiseur : Doit être placé en fin de page pour fonctionner //=========================================================== MouseArea { anchors.fill: parent preventStealing: true // Permet que cela fonctionne même si un élément flickable (notamment) soit derrière et "vole" le click enabled: flag_economiseur_actif onClicked: { mise_en_veille(0); } } //============================================================================================================= // Init de la page //============================================================================================================= function init_page() { var req, res; //console.log("Mode actuel : " + protection_mode); mise_en_veille(0); niveau_page = stackView.depth - 1; // Permet de stocker le niveau de la page dans la Stackview req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Code" '; res = bdd.requete_unique(req); code = res[0]; req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Code_admin" '; res = bdd.requete_unique(req); code_admin = res[0]; req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Max_taille_code" '; res = bdd.requete_unique(req); if (Number(res[0]) >= max_taille_code_pattern) max_taille_code_pattern = Number(res[0]) + 2; } //============================================================================================================= // Déverrouillage //============================================================================================================= function deverrouillage() { var req, res; //console.log("Le code est valide. La page est déverrouillée....") code_saisi = ""; switch(protection_mode) { case protection_mode_access_parametres_avances: if (shipheart_time_out_niveau_acces === 0) shipheart_niveau_acces_en_cours = shipheart_niveau_acces_aucun; else if (shipheart_time_out_niveau_acces === -1)shipheart_compteur_time_out_niveau_acces = 0; shipheart_compteur_time_out_niveau_acces = shipheart_time_out_niveau_acces; stackView.push("parametres_avances.qml"); break; case protection_mode_verrouillage: break; case protection_mode_deverrouillage: break; default: ; } } //============================================================================================================= // Vérification du code_saisi vs le code //============================================================================================================= function check_code() { var code_saisi_encrypte; code_saisi_encrypte = bdd.sha256(code_saisi); //console.debug("Le code saisi est [" + code_saisi + "] et le code saisi encrypté est [" + code_saisi_encrypte + "]"); //console.debug("Le hash du code user est [" + code + "]"); //console.debug("Le hash du code admin est [" + code_admin + "]"); //console.debug("Le hash du code Koriolan est [" + code_koriolan + "]"); switch(type_code) { case shipheart_type_code_normal: default : if (code.localeCompare(code_saisi_encrypte) === 0) { shipheart_niveau_acces_en_cours = shipheart_niveau_acces_user; // Vérification du code saisi vs code user //console.debug("Code User validé"); return (0); } break; case shipheart_type_code_admin: if (code_admin.localeCompare(code_saisi_encrypte) === 0) { shipheart_niveau_acces_en_cours = shipheart_niveau_acces_admin; // Vérification du code saisi vs code administrateur //console.debug("Code Admin validé"); return (0); } else if (code_koriolan.localeCompare(code_saisi_encrypte) === 0) { shipheart_niveau_acces_en_cours = shipheart_niveau_acces_koriolan; // Vérification du code saisi vs code Koriolan //console.debug("Code Koriolan validé"); return (0); } break; } return(-1); // Autres cas.... } //============================================================================================================= // Mise à jour du pattern //============================================================================================================= function mise_a_jour_pattern() { var longueur; var i; longueur = code_saisi.length; if (longueur > max_taille_code_pattern) longueur = max_taille_code_pattern; code_saisi_pattern = ""; for (i=0; i