//======================================================================================================================================================================== // CONFIG_FICHIER.QML // Ce fichier permet de gérer d'une part des fichier sur ShipBase, dans un répertpoire interne et, d'autre part, des fichiers sur une clé externe. // Il peut être utilisé dans plusieurs configurations différentes : // - image d'accueil ('shipheart_mode_config_fichiers_image_accueil') // - silhouette d'une page personnalisée ('shipheart_mode_config_fichiers_silhouette') // - rapports d'installation ('shipheart_mode_config_fichiers_rapports') // - Sauvegardes ('shipheart_mode_config_fichiers_sauvegardes') // Le choix de l'un de ces modes se fait en passant la propriété 'mode_config_fichiers' qui peut prendre l'une des valeurs indquées ci-dessus. //======================================================================================================================================================================== import QtQuick 2.12 import QtQuick.Controls 2.12 import Qt.labs.folderlistmodel 2.12 import qt.koriolan.shipheart 1.0 import"fonctions.js" as Fonctions Shipheart_page { id: page_config_fichiers // Mis en forme : readonly property double pourcentage_largeur_colonne_gauche: 0.40 readonly property double pourcentage_largeur_colonne_centre: (1 - pourcentage_largeur_colonne_gauche - pourcentage_largeur_colonne_droite) readonly property double pourcentage_largeur_colonne_droite: 0.40 readonly property double espace_colonnes_principales: 20 readonly property double espace_colonnes_secondaires: 10 readonly property double affichage_hauteur_utile: shipheart_hauteur_page - shipheart_hauteur_bandeau_haut - shipheart_hauteur_bandeau_bas readonly property double pourcentage_largeur_labels_formulaire: 0.4 readonly property double pourcentage_bandeau_bas_largeur_zone_retour: 1 readonly property int hauteur_ligne_formulaire: 60 readonly property int hauteur_bouton: 80 readonly property int periode_init_raffraichissement_parametres: 500 // En ms Cette durée est volontairement longue car cela permet l'affichage du fond de la page avant la première mise à jour (qui peut être "bloquante" sir la clé est déjà là est qu'un montage est demandé) readonly property int periode_raffraichissement_parametres_montage_port_usb: 1 // En ms Doit être une valeur différente des autres tempo utilisées readonly property int periode_raffraichissement_parametres: 1000 // En ms readonly property int step_timer_appui_long: 30 // en ms readonly property int etat_cle_absente: 0 readonly property int etat_cle_presente: 1 readonly property int etat_cle_presente_partition: 2 readonly property int etat_cle_presente_montee: 3 readonly property int etat_cle_presente_demontee: 4 // Données : property bool flag_init: true property int mode_config_fichiers: shipheart_mode_config_fichiers_inconnu property int id_page: 0 property int valeur_timer_appui_long: 0 property int port_usb_en_cours: -1 property int etat_initial_port_usb_avant: -1 property int etat_initial_port_usb_arrière: -1 property int etat_cle: 0 // Cf les différente svaleurs possibles ci-dessus ('etat_cle_absente', etc...) property bool flag_sortie_en_attente: false; property bool flag_new_file_en_attente: false; property string sous_repertoire_cle: "" property string sens: "" // Soit vide, soit "cle_vers_shipheart", soit "shipheart_vers_cle" property int index_fichier_local_actif: -1 property int index_fichier_cle_actif: -1 property string nom_fichier_local_selectionne: "" property string titre_page: "" property string nom_repertoire_local: "" property bool flag_selection_locale_multiple_enabled: true property string texte_bouton_action_sens_vide: "" property string texte_bouton_action_sens_non_vide: "" property int max_taille_fichier: 0 property string texte_types_fichiers_valides: "" // Modèles : // Note : les modèles chargés dans 'main.qml' n'ont pas à être rechargés dans les pages suivantes //=========================================================== // Modèles de lecture de répertoire : // Attention : pour que les modèles maintiennent à jour leur données, // il faut que le répertoire cible (le contenant) ne soient pas modifié. // Par exemple, le fait de supprimer le répertoire (pour le vider) // puis de le recréer avec le même nom fait perdre le lien au modèle // qui ne se met alors plus à jour... //=========================================================== FolderListModel { id: repertoire_local // nameFilters: ["*.png", "*.PNG", "*.jpg", "*.JPG", "*.jpeg", "*.JPEG"] // nameFilters: ["*.enc"] showDirs: false sortField: FolderListModel.Time // Tri sur l'heure du fichier folder: "file://" + nom_repertoire_local // Pour un fichier, il faut obligatoirement ajouter 'file:' devant. Ou 'qrc:' pour une URL. Le message d'alerte de QT Creator est toujours là... onStatusChanged: { if ((status === FolderListModel.Ready) && (!flag_init) && (!boite_information.opened)) mise_a_jour_modele_fichiers_locaux(); } onRowsInserted: (parent, first, last) => { // Ce sont les 3 arguments du signel : le parent n'est pas utulisé en l'occurence car FolderListModel est un modèle "à plat" mais les 2ème et 3ème sont les index des nouveaux enregistrement dans le répertoire. if ((!flag_init) && (flag_new_file_en_attente)) { var nom_fichier_cree; flag_new_file_en_attente = false; // Pour utilisation ultérieure mise_a_jour_modele_fichiers_locaux(); // Comme 'onRowsInserted' est généralement déclenché AVANT OnStatusChanged, on fait une mise à jour du modèle sinon on ne trouvera pas le nouveau fichier créé à la fin de cette fonction... busy_indicator_centre.running = false; // Arrêt du sablier var i; for (i = first; i <= last; i ++) // En pratique, si on attend un nouveau fichier en cours de cration, on ne va probablement recevoir qu'UN fichier (et si plusieurs, on ne traitera que le dernier...) { nom_fichier_cree = repertoire_local.get(i, "fileName").replace(/\s\s+/g, ''); // Le REPLACE permet la suppression de tous les espaces, TAB, etc.... } // Affichage du fichier généré dans le popup d'info : switch(mode_config_fichiers) // Le message à afficher dépend du contexte d'utilisation du fichier : { //---------------------------------------------------- case shipheart_mode_config_fichiers_rapports: { boite_information.message = qsTr("Le rapport d'installation

%1

a été généré.").arg(nom_fichier_cree); boite_information.niveau = 0; boite_information.imageTitreSource = "/images/ampoule.png" boite_information.open(); break; } //---------------------------------------------------- case shipheart_mode_config_fichiers_sauvegardes: { boite_information.message = qsTr("La sauvegarde

%1

a été générée.").arg(nom_fichier_cree.replace(".tar.gz.enc", "")); // La suppression de l'extension est juste plus facile à lire boite_information.niveau = 0; boite_information.imageTitreSource = "/images/ampoule.png" boite_information.open(); break; } //---------------------------------------------------- case shipheart_mode_config_fichiers_image_accueil: case shipheart_mode_config_fichiers_silhouette: case shipheart_mode_config_fichiers_inconnu: default: { break; } } // Activation du nouveau fichier créé (pour l'identifier simplement) : if (nom_fichier_cree !== "") { for (i = 0; i < modele_fichiers_locaux.count; i ++) { if (modele_fichiers_locaux.get(i).nom === nom_fichier_cree) { modele_fichiers_locaux.set(i, {"actif": true}); nom_fichier_local_selectionne = modele_fichiers_locaux.get(i).nom; sens = "shipheart_vers_cle"; break; } } } } } } //=========================================================== // Timer periode raffraichissement parametres : //=========================================================== Timer { id: timer_raffraichissement_parametres interval: periode_init_raffraichissement_parametres triggeredOnStart: false running: true repeat: true onTriggered: { //-------------------------------------------------------------- // Init : if (interval === periode_init_raffraichissement_parametres) { interval = periode_raffraichissement_parametres; init_page(); } //------------------------------------------------------------------------ // Demande de montage d'un port USB (permet de lancer le Busy Indicator) : else if (interval === periode_raffraichissement_parametres_montage_port_usb) { if (shipheart_type_installation === shipheart_type_installation_shipbase) // SDIR #317 { monter_port_usb(shipheart_port_usb_avant_bas); check_ports_usb(); // Permets de mettre à jour les données du port sans attendre etat_cle = etat_cle_presente_montee; busy_indicator_droite.running = false; interval = periode_raffraichissement_parametres; } } //------------------------------------------------------------------------ // Période normale : else { if (shipheart_type_installation === shipheart_type_installation_shipbase) // SDIR #317 { mise_a_jour(); } } } } //=========================================================== // Timer pour gérer les appuis longs : //=========================================================== Timer { id: timer_appui_long interval: step_timer_appui_long triggeredOnStart: false repeat: true onTriggered: { if (valeur_timer_appui_long < shipheart_mouse_press_and_hold_interval_tres_long) valeur_timer_appui_long+= step_timer_appui_long; 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_appui_long.running = false; valeur_timer_appui_long = 0; if (mousearea_bouton_supprimer.pressed) { shipheart_clic(); suppression_fichiers(); } else if (mousearea_bouton_restaurer.pressed) { shipheart_clic(); boite_validation_securisee.niveau = 2; boite_validation_securisee.boutonOk = false boite_validation_securisee.boutonAnnuler = true boite_validation_securisee.boutonSecurise = true boite_validation_securisee.boutonSecuriseTexte = qsTr("Confirmer"); boite_validation_securisee.imageTitreSource = "/images/attention.png"; boite_validation_securisee.message = qsTr("Restauration de la sauvegarde

Si vous confirmez, cette mise à jour peut nécessiter quelques minutes pendant lesquelles votre système ShipHeart ne sera pas accessible.

Vous ne devez confirmer l'installation que si vous êtes en situation sûre (au port, au mouillage, ...) et que la perte de contrôle de vos systèmes de bord pendant ce laps de temps est sans aucun danger !

Cliquez sur Annuler pour revenir en arrière et effectuer cette installation ultérieurement.") boite_validation_securisee.alignementMessage = Text.AlignLeft boite_validation_securisee.affichageAscenseur = true; boite_validation_securisee.open(); } } } } //=========================================================== // Titre de la page : //=========================================================== Shipheart_titre_1 {titre: titre_page; hauteur: shipheart_hauteur_bandeau_haut} //------------------------------------------------------- // Ecran Gauche : //------------------------------------------------------- Rectangle { id: zone_affichage_gauche x: 0 y: shipheart_hauteur_bandeau_haut; width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2) height: affichage_hauteur_utile color: "transparent" //------------------------------------------------------------------- // Grille pour afficher les fichiers locaux : GridView { id: grille_locale width: parent.width height: parent.height cellWidth: parent.width; cellHeight: hauteur_ligne_formulaire 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_fichiers_locaux delegate: Rectangle { width: grille_locale.cellWidth height: grille_locale.cellHeight - 5 color: "transparent" Rectangle { // c'est le bouton proprement dit... height: parent.height width:parent.width color: (model.actif) ? shipheart_couleur_fond_bouton_actif : shipheart_couleur_fond_bouton radius: shipheart_rayon_bouton anchors.bottom: parent.bottom // Nom du fichier : Text { anchors { top: parent.top left: parent.left } width: parent.width - 70 // Le '-70' permet de garder l'espace nécessaire à la taille du fichier à droite height: parent.height horizontalAlignment: Qt.AlignLeft verticalAlignment: Qt.AlignVCenter leftPadding: 20 text: model.nom color: couleur_blanc_casse font.pixelSize: 18 font.bold: false wrapMode: Label.Wrap } // Taille du fichier : Text { anchors.fill: parent horizontalAlignment: Qt.AlignRight verticalAlignment: Qt.AlignVCenter rightPadding: 10 text: "[" + model.taille + "]" color: couleur_gris_moyen font.pixelSize: 15 } // Triangle bleu indiquant le fichier sélectionné : Image { id: image_selectionnee source: "/images/coin_bas_droite_bleu_koriolan.png" sourceSize.height: 20 anchors { bottom: parent.bottom right: parent.right } visible: ((mode_config_fichiers === shipheart_mode_config_fichiers_image_accueil) && (nom_fichier_local_selectionne === modele_fichiers_locaux.get(index).nom)) || ((mode_config_fichiers === shipheart_mode_config_fichiers_silhouette) && (nom_fichier_local_selectionne === modele_fichiers_locaux.get(index).nom)) } MouseArea{ anchors.fill : parent onClicked: { shipheart_clic(); var i; var flag_actifs = false; // Mise à jour de l'état Actif/Inactif de l'entrée cliquée (et mise à jour des autres entrées si besoin) ! if (flag_selection_locale_multiple_enabled) // Dans ce cas, on fait juste un toggle d'activatuion du fichier cliqué : { if (modele_fichiers_locaux.get(index).actif) modele_fichiers_locaux.set(index, { "actif": false } ); else modele_fichiers_locaux.set(index, { "actif": true } ); } else // Dans ce cas, il faut passer à 1 ou 0 fichiers actifs : { if (modele_fichiers_locaux.get(index).actif) // S'il était actif, il devient inactif (et on est sûr qu'il n'y en n'a pas d'autres) { index_fichier_local_actif = -1; modele_fichiers_locaux.set(index, { "actif": false } ); } else // S'il était inactif, il faut désactiver tous les autres (a priori, un seul) puis activer celui qui vient d'être cliqué { // Désactivation de tous fichiers locaux : for (i=0; i= modele_fichiers_locaux.count) return false; let item = modele_fichiers_locaux.get(index_fichier_local_actif); if (!item) return false; return ((sens === "shipheart_vers_cle") && (nom_fichier_local_selectionne !== item.nom)) } else if (mode_config_fichiers === shipheart_mode_config_fichiers_silhouette) { if (sens === "") return true; // Permet d'accéder à "Acune image" else if (sens === "cle_vers_shipheart") return false; // Si aucune image à gauche n'est sélectionnée, on ne peut rien faire else if (sens === "shipheart_vers_cle") // Si une image est sélectionnée à gauche : { if (index_fichier_local_actif < 0 || index_fichier_local_actif >= modele_fichiers_locaux.count) return false; let item = modele_fichiers_locaux.get(index_fichier_local_actif); if (!item) return false; return (nom_fichier_local_selectionne !== item.nom) } else return false; // Ne devrait pas arriver } else if (mode_config_fichiers === shipheart_mode_config_fichiers_rapports) return true; else if (mode_config_fichiers === shipheart_mode_config_fichiers_sauvegardes) return true; } onClicked: { shipheart_clic(); action(); if ((mode_config_fichiers === shipheart_mode_config_fichiers_image_accueil) || (mode_config_fichiers === shipheart_mode_config_fichiers_silhouette) ) sortie(); } } } //--------------------------------------- // Bouton Copier : Rectangle { width: parent.width height: hauteur_bouton - parent.spacing color: shipheart_couleur_fond_bouton radius: shipheart_rayon_bouton visible: !flag_init Text { anchors.fill: parent horizontalAlignment: Qt.AlignHCenter rightPadding: 20 verticalAlignment: Qt.AlignVCenter text: qsTr("Copier") color: (mousearea_copier.enabled) ? couleur_blanc_casse : couleur_gris_moyen font.pixelSize: 18 } Image { source: "/images/right.png" visible: mousearea_copier.enabled && (sens === "shipheart_vers_cle") sourceSize.height: 25 anchors { verticalCenter: parent.verticalCenter right: parent.right rightMargin: 20 } } Image { source: "/images/left.png" visible: mousearea_copier.enabled && (sens === "cle_vers_shipheart") sourceSize.height: 25 anchors { verticalCenter: parent.verticalCenter left: parent.left leftMargin: 20 } } MouseArea { id: mousearea_copier anchors.fill: parent enabled: (sens !== "") && (etat_cle === etat_cle_presente_montee) onClicked: { shipheart_clic(); copie_fichiers(); } } } //--------------------------------------- // Bouton Supprimer : Rectangle { width: parent.width height: hauteur_bouton - parent.spacing color: shipheart_couleur_fond_bouton radius: shipheart_rayon_bouton visible: !flag_init Rectangle { // Barre grandissante pour montrer durée d'appui vs tempo nécessaire : width: (valeur_timer_appui_long / shipheart_mouse_press_and_hold_interval_tres_long) * parent.width height: parent.height color: couleur_rouge_transparent radius: shipheart_rayon_bouton visible: mousearea_bouton_supprimer.pressed } Text { anchors.fill: parent horizontalAlignment: Qt.AlignHCenter rightPadding: 20 verticalAlignment: Qt.AlignVCenter text: qsTr("Supprimer") color: (mousearea_bouton_supprimer.enabled) ? couleur_blanc_casse : couleur_gris_moyen font.pixelSize: 18 } MouseArea { id: mousearea_bouton_supprimer anchors.fill: parent enabled: { //-------------------------------------------------------------------------------- if ((mode_config_fichiers === shipheart_mode_config_fichiers_image_accueil) || (mode_config_fichiers === shipheart_mode_config_fichiers_silhouette)) { //----------------------------------- if (sens === "cle_vers_shipheart") { if (index_fichier_cle_actif < 0 || index_fichier_cle_actif >= modele_fichiers_cle.count) return false; let item = modele_fichiers_cle.get(index_fichier_cle_actif); if (!item) return false; return (item.type !== "dir"); } //----------------------------------- else if (sens === "shipheart_vers_cle") { if (index_fichier_local_actif < 0 || index_fichier_local_actif >= modele_fichiers_locaux.count) return false; let item = modele_fichiers_locaux.get(index_fichier_local_actif); if (!item) return false; return (nom_fichier_local_selectionne !== item.nom); // On n'autorise pas la suppression de l'image en cours } //----------------------------------- else return false; // Sens = "" } //-------------------------------------------------------------------------------- else if ((mode_config_fichiers === shipheart_mode_config_fichiers_rapports) || (mode_config_fichiers === shipheart_mode_config_fichiers_sauvegardes)) { let flag_actifs = false; let i; //----------------------------------- if (sens === "cle_vers_shipheart") { // Recherche de la présence d'au moins une entrée active sur la clé : for (i=0; i= modele_fichiers_locaux.count) return ""; let item = modele_fichiers_locaux.get(index_fichier_local_actif); if (!item) return ""; return "file://" + nom_repertoire_local + "/" + item.nom; } else { if (index_fichier_cle_actif < 0 || index_fichier_cle_actif >= modele_fichiers_cle.count) return ""; let item = modele_fichiers_cle.get(index_fichier_cle_actif); if (!item) return ""; return "file://" + shipheart_repertoire_cle_usb + ((sous_repertoire_cle === "") ? "" : "/" + sous_repertoire_cle) + "/" + item.nom; } } else return ""; } anchors.fill: parent fillMode: Image.PreserveAspectFit anchors { verticalCenter: parent.verticalCenter horizontalCenter: parent.horizontalCenter } } } } //--------------------------- // Busy Indicator au centre (utilisé pendant le traitement d'une commande longue (rapport, sauvegarde, ...) : Shipheart_busy_indicator { id: busy_indicator_centre anchors.verticalCenterOffset: 100 // Permet de placer le sablier en-dessous des boutons centraux } } //------------------------------------------------------- // Ecran Droite : //------------------------------------------------------- Rectangle { id: zone_affichage_droite x: zone_affichage_centre.x + zone_affichage_centre.width + espace_colonnes_principales y: 0 width: (shipheart_largeur_page * pourcentage_largeur_colonne_droite) - (espace_colonnes_principales / 2) height: affichage_hauteur_utile + shipheart_hauteur_bandeau_haut color: "transparent" visible: (shipheart_type_installation === shipheart_type_installation_shipbase) // Sur ShipRS, on n'affiche pas la partie Clé car elle n'est pas acessible physiquement // L'utilisation d'une ListView pour afficher une seule ligne peut paraitre étrange mais si on ne le fait pas, le lien entre le modèle et // l'affichage n'est pas fait et l'affichage ne prend que la valeur initiale du modèle (pas les mises à jour ultérieures). ListView { id: grille_cle width: parent.width height: parent.height model: modele_ports_usb //==================================== // Infos sur la clé : delegate: Rectangle { id: zone_port_avant_bas width: parent.width height: visible ? shipheart_hauteur_bandeau_haut : 0 color: "transparent" visible: !flag_init && (etat_cle !== etat_cle_absente) && (index === shipheart_port_usb_avant_bas) //----------------------------------- // Label de la clé : Text { anchors.fill: parent horizontalAlignment: Qt.AlignLeft verticalAlignment: Qt.AlignVCenter topPadding: -20 leftPadding: 20 text: flag_init ? "" : model.label color: couleur_blanc_casse font.pixelSize: 18 } //----------------------------------- // Taille et % d'utilisation : Text { anchors.fill: parent horizontalAlignment: Qt.AlignLeft verticalAlignment: Qt.AlignVCenter topPadding: 25 leftPadding: 20 text: flag_init ? "" : model.size + " [" + model.used + "]" color: couleur_gris_moyen font.pixelSize: 15 visible: (etat_cle === etat_cle_presente_montee) } //----------------------------------- // Bouton de démontage manuel : Rectangle { id: zone_port_avant_bas_bouton_ejection width: 200 height: shipheart_hauteur_bandeau_haut - 10 anchors { right: parent.right verticalCenter: parent.verticalCenter } color: shipheart_couleur_fond_bouton radius: shipheart_rayon_bouton visible: !flag_init && etat_cle === etat_cle_presente_montee Text { anchors.fill: parent horizontalAlignment: Qt.AlignHCenter rightPadding: 20 verticalAlignment: Qt.AlignVCenter text: qsTr("Ejection") color: couleur_blanc_casse font.pixelSize: 18 } Image { source: "/images/down.png" sourceSize.height: 15 anchors { right: parent.right verticalCenter: parent.verticalCenter rightMargin: 20 } } MouseArea { anchors.fill: parent onClicked: { shipheart_clic(); if (etat_cle === etat_cle_presente_montee) { demonter_port_usb(port_usb_en_cours); modele_fichiers_cle.clear(); // Effacement du modèle si le device est démonté etat_cle = etat_cle_presente_demontee; } } } } } //==================================================== // Affichage lorsqu'aucune clé n'est encore reconnue : // Etat 0 ou 3 : Aucune clé dans port Avant Bas : Image { source: (etat_cle === etat_cle_absente) ? "/images/right.png" : "/images/left.png" visible: texte_entree_sortie_cle.visible sourceSize.height: 30 anchors { verticalCenter: parent.verticalCenter right: parent.right verticalCenterOffset: -90 // Attention : cet offset est directement lié au montage mécanique de l'écran... rightMargin: 30 SequentialAnimation on rightMargin { loops: Animation.Infinite NumberAnimation { to: 100; duration: (etat_cle === etat_cle_absente) ? 300 : 2000; easing.type: (etat_cle === etat_cle_absente) ? Easing.Linear : Easing.OutElastic; } PauseAnimation { duration: (etat_cle === etat_cle_absente) ? 0 : 1000 } NumberAnimation { to: 30; duration: (etat_cle === etat_cle_absente) ? 2000 : 300; easing.type: (etat_cle === etat_cle_absente) ? Easing.OutElastic : Easing.Linear; } PauseAnimation { duration: (etat_cle === etat_cle_absente) ? 1000 : 0 } } } } Text { id: texte_entree_sortie_cle anchors.fill: parent horizontalAlignment: Qt.AlignHCenter verticalAlignment: Qt.AlignVCenter text: (etat_cle === etat_cle_absente) ? qsTr("Insérer une clé USB dans le port du bas, à droite") : qsTr("Vous pouvez retirer la clé en toute sécurité...") color: couleur_blanc_casse font.pixelSize: 18 visible: !flag_init && ( (etat_cle === etat_cle_absente) || (etat_cle === etat_cle_presente_demontee) ) } //--------------------------- ListModel { id: modele_ports_usb; } } //----------------------------------------------- // Grille des fichiers de la clé : GridView { id: liste_fichiers_cle y: shipheart_hauteur_bandeau_haut width: parent.width height: affichage_hauteur_utile cellWidth: parent.width; cellHeight: hauteur_ligne_formulaire 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_fichiers_cle visible: (shipheart_type_installation === shipheart_type_installation_shipbase) // Bouton d'un fichier ou répertoire : delegate: Rectangle { width: liste_fichiers_cle.cellWidth height: liste_fichiers_cle.cellHeight - 5 color: "transparent" Rectangle { // c'est le bouton proprement dit... height: parent.height width:parent.width color: (model.actif) ? shipheart_couleur_fond_bouton_actif : shipheart_couleur_fond_bouton radius: shipheart_rayon_bouton anchors.bottom: parent.bottom // Nom du fichier : Text { anchors.fill: parent horizontalAlignment: Qt.AlignLeft verticalAlignment: Qt.AlignVCenter leftPadding: 20 text: model.nom color: (model.type === "fic") ? (model.autorise ? couleur_blanc_casse : couleur_gris_moyen) : couleur_bleu_koriolan font.pixelSize: 18 font.bold: (model.type === "fic") ? false : true wrapMode: Label.Wrap visible: (model.type !== "dir") || (model.nom !== "..") } Image { source: "/images/up_bleu.png" sourceSize.height: 15 anchors { left: parent.left verticalCenter: parent.verticalCenter leftMargin: 20 } visible: (model.type === "dir") && (model.nom === "..") } // Taille du fichier : Text { anchors.fill: parent horizontalAlignment: Qt.AlignRight verticalAlignment: Qt.AlignVCenter rightPadding: 10 text: "[" + model.taille + "]" color: ((max_taille_fichier === 0) || (model.taille_octets <= max_taille_fichier)) ? couleur_gris_moyen : couleur_rouge font.pixelSize: 15 visible: (model.type === "fic") } MouseArea{ anchors.fill : parent onClicked: { shipheart_clic(); var i; var flag_actifs = false; // Si l'entrée cliquée est un répertoire : if (modele_fichiers_cle.get(index).type === "dir") { if (modele_fichiers_cle.get(index).nom === "..") { var dirs = sous_repertoire_cle.split('/'); sous_repertoire_cle = ""; for (i=0; i<(dirs.length-1); i++) { if (sous_repertoire_cle !== "") sous_repertoire_cle += "/"; sous_repertoire_cle += dirs[i]; //console.log("Repertoire cle = [ " + sous_repertoire_cle + " ]" ); } } else sous_repertoire_cle += ((sous_repertoire_cle === "") ? "" : "/") + modele_fichiers_cle.get(index).nom; // Descente dans le sous-répertoire ls(shipheart_repertoire_cle_usb + ((sous_repertoire_cle === "") ? "" : "/" + sous_repertoire_cle)); // Rechargement du modèle avec le contenu du sous-répertoire// Rechargement du modèle avec le contenu du sous-répertoire } else // Sinon, c'est que c'est un fichier : { if ((modele_fichiers_cle.get(index).autorise) && (model.taille_octets <= max_taille_fichier)) { if (modele_fichiers_cle.get(index).actif) { index_fichier_cle_actif = -1; modele_fichiers_cle.set(index, { "actif": false } ); } else { // Désactivation de tous les boutons sur la clé : for (i=0; iéjectée automatiquement.
Vous pouvez la retirer dès maintenant en toute sécurité..."); boite_information.open(); flag_sortie_en_attente = true; // Permettra de sortir de la page lors de la fermeture de la boite de dialogue } else sortie(); } } } } //=========================================================== // Boit d'information //=========================================================== Shipheart_boite_dialogue { id: boite_information onClicked: { //-------------------------------------------------------------------- // Info avant sortie : if (flag_sortie_en_attente) sortie(); } } //------------------------------------------------------- // Boite d'information : //------------------------------------------------------- Shipheart_boite_dialogue_validation_securisee { id: boite_validation_securisee onClicked: { switch(bouton) { case shipheart_boite_dialogue_bouton_4: // Confirmation sécurisée : restauration(); break; case shipheart_boite_dialogue_bouton_2: // Annuler : on revient sur la page pour que l'on puisse enregistrer. break; default: } boite_validation_securisee.close(); } } // 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() { var req, res; var nb; var i; var nom_champ, valeur_champ; //---------------------------------------------------------------- // Alimentation des ports USB : (SDIR #303) //---------------------------------------------------------------- // Récupération de la consigne actuelle de l'alim des ports USB : req = 'SELECT Cle_primaire, Consigne FROM TB_Circuits WHERE Adresse_module=0 AND No_circuit=1 '; //console.log("Requête = [ " + req + "; ]"); res = bdd.requete_unique(req); etat_initial_port_usb_avant = Number(res[1]); if (etat_initial_port_usb_avant === 0) { req = 'UPDATE TB_Circuits SET New_consigne=100 WHERE Adresse_module=0 AND No_circuit=1 '; //console.log("Requête = [ " + req + "; ]"); bdd.requete_unique(req); } req = 'SELECT Cle_primaire, Consigne FROM TB_Circuits WHERE Adresse_module=0 AND No_circuit=2 '; //console.log("Requête = [ " + req + "; ]"); res = bdd.requete_unique(req); etat_initial_port_usb_arrière = Number(res[1]); if (etat_initial_port_usb_arrière === 0) { req = 'UPDATE TB_Circuits SET New_consigne=100 WHERE Adresse_module=0 AND No_circuit=2 '; //console.log("Requête = [ " + req + "; ]"); bdd.requete_unique(req); } //---------------------------------------------------------------- // Préparation des paramètres généraux, selon le contecte d'usage : //---------------------------------------------------------------- switch(mode_config_fichiers) { //---------------------------------------------------- case shipheart_mode_config_fichiers_image_accueil: { titre_page = qsTr("Image d'accueil"); nom_repertoire_local = shipheart_repertoire_config + shipheart_sous_repertoire_images_accueil; flag_selection_locale_multiple_enabled = false; texte_bouton_action_sens_vide = qsTr("Sélectionner cette image"); texte_bouton_action_sens_non_vide = texte_bouton_action_sens_vide; max_taille_fichier = shipheart_taille_maxi_image_accueil; texte_types_fichiers_valides = ".PNG | .png | .JPG | .jpg"; // Récupération du nom de fichier configuré : req = 'SELECT Valeur '; req += ' FROM TB_Configuration '; req += ' WHERE Nom="Fichier_image_accueil" '; //console.log("req = [ " + req + "; ]"); res = bdd.requete_unique(req); nom_fichier_local_selectionne = res[0]; break; } //---------------------------------------------------- case shipheart_mode_config_fichiers_silhouette: { if (id_page === 0) sortie(); titre_page = qsTr("Silhouette de la page"); nom_repertoire_local = shipheart_repertoire_config + shipheart_sous_repertoire_images_silhouette; flag_selection_locale_multiple_enabled = false; texte_bouton_action_sens_vide = qsTr("Aucune image"); texte_bouton_action_sens_non_vide = qsTr("Sélectionner cette image"); max_taille_fichier = shipheart_taille_maxi_silhouette; texte_types_fichiers_valides = ".PNG | .png | .JPG | .jpg"; // Récupération du nom de fichier configuré : req = 'SELECT Fichier '; req += ' FROM TB_Pages '; req += ' WHERE Cle_primaire=' + id_page + ' '; //console.log("req = [ " + req + "; ]"); res = bdd.requete_unique(req); nom_fichier_local_selectionne = res[0]; break; } //---------------------------------------------------- case shipheart_mode_config_fichiers_rapports: { titre_page = qsTr("Rapports d'installation"); nom_repertoire_local = shipheart_repertoire_config + shipheart_sous_repertoire_rapports; flag_selection_locale_multiple_enabled = true; texte_bouton_action_sens_vide = qsTr("Nouveau rapport d'installation"); texte_bouton_action_sens_non_vide = texte_bouton_action_sens_vide; max_taille_fichier = shipheart_taille_maxi_rapport; texte_types_fichiers_valides = ".PDF | .pdf"; break; } //---------------------------------------------------- case shipheart_mode_config_fichiers_sauvegardes: { titre_page = qsTr("Sauvegardes"); nom_repertoire_local = shipheart_repertoire_config + shipheart_sous_repertoire_sauvegardes; flag_selection_locale_multiple_enabled = true; texte_bouton_action_sens_vide = qsTr("Nouvelle sauvegarde"); texte_bouton_action_sens_non_vide = texte_bouton_action_sens_vide; max_taille_fichier = shipheart_taille_maxi_sauvegarde; texte_types_fichiers_valides = ".ENC | .enc"; break; } //---------------------------------------------------- case shipheart_mode_config_fichiers_inconnu: default: { sortie(); break; } } //---------------------------------------------------- // Pour ShipRS : mise à jour des fichiers locaux à partir de ShipBase if (shipheart_type_installation !== shipheart_type_installation_shipbase) synchro_repertoires_shiprs(); // Permet d'avoir les derniers fichiers mis à jour dans ShipBase... //---------------------------------------------------- // Valeurs par défait du répertoire local : // mise_a_jour_modele_fichiers_locaux(); sens = "shipheart_vers_cle"; // Permet que le fichier sélectionné à l'init soit affiché avec les boutons dans les bonnes positions. //---------------------------------------------------- // Mise à jour de la liste des ports USB : etat_cle = etat_cle_absente; modele_ports_usb.clear(); modele_ports_usb.append({ "nom": qsTr("USB Arrière"), "presence": false, "disk": "", "partition": "", "monte": false, "size": "", "used": "", "label": "", "manufacturer": "", "product": "", "serial_number": "" } ); modele_ports_usb.append({ "nom": qsTr("Spare"), "presence": false, "disk": "", "partition": "", "monte": false, "size": "", "used": "", "label": "", "manufacturer": "", "product": "", "serial_number": "" } ); modele_ports_usb.append({ "nom": qsTr("USB Avant"), "presence": false, "disk": "", "partition": "", "monte": false, "size": "", "used": "", "label": "", "manufacturer": "", "product": "", "serial_number": "" } ); modele_ports_usb.append({ "nom": qsTr("Touch pad"), "presence": false, "disk": "", "partition": "", "monte": false, "size": "", "used": "", "label": "", "manufacturer": "", "product": "", "serial_number": "" } ); //---------------------------------------------------- // Note : A ce stade, on considère que seul le port Avant Bas est utilisé. // Si besoin détendre au port arrière par exemple, il faut 'juste' gérer ce paramètre dynamiquement. // Les données des 4 ports présents sur ShipBase sont d'ores et déjà mises à jour. port_usb_en_cours = shipheart_port_usb_avant_bas; //---------------------------------------------------- // Mise à jour initiale : if (shipheart_type_installation === shipheart_type_installation_shipbase) // SDIR #317 { mise_a_jour(); } flag_init = false; } //============================================================================================================= // Mise à jour toutes les secondes : //============================================================================================================= function mise_a_jour_modele_fichiers_locaux() { var i; var nom; var actif; modele_fichiers_locaux.clear(); index_fichier_local_actif = -1; for (i = 0; i < repertoire_local.count; i ++) { nom = repertoire_local.get(i, "fileName"); if ((sens === "shipheart_vers_cle") && (nom === nom_fichier_local_selectionne)) // on cherche le fichier qui correspond à la config en cours { actif = true; index_fichier_local_actif = i; } else actif = false; modele_fichiers_locaux.append({ "nom": nom, "taille": Fonctions.taille_fichier(repertoire_local.get(i, "fileSize"), shipheart_langue), "actif": actif } ); } if ((sens === "shipheart_vers_cle") && (index_fichier_local_actif === -1)) sens = ""; } //============================================================================================================= // Mise à jour toutes les secondes : //============================================================================================================= function mise_a_jour() { var i; if (shipheart_type_installation === shipheart_type_installation_shipbase) check_ports_usb(); // SDIR #317 // Note : à ce stade, on ne prend en compte que le port Avant Bas. // Si besoin, ajouter ici une boucle pour étudier les autres ports (qui sont déjà mis à jour) switch(etat_cle) { //---------------------------- case etat_cle_absente: if (modele_ports_usb.get(shipheart_port_usb_avant_bas).presence) etat_cle = etat_cle_presente; else break; // break; // Volontairement pas de break; //---------------------------- case etat_cle_presente: if (!modele_ports_usb.get(shipheart_port_usb_avant_bas).presence) { etat_cle = etat_cle_absente; break; } if (modele_ports_usb.get(shipheart_port_usb_avant_bas).partition !== "") etat_cle = etat_cle_presente_partition; else break; // break; // Volontairement pas de break; //---------------------------- case etat_cle_presente_partition: if (!modele_ports_usb.get(shipheart_port_usb_avant_bas).presence) { etat_cle = etat_cle_absente; break; } if (modele_ports_usb.get(shipheart_port_usb_avant_bas).partition === "") { etat_cle = etat_cle_presente; break; } // Lancement du montage : busy_indicator_droite.running = true; timer_raffraichissement_parametres.interval = periode_raffraichissement_parametres_montage_port_usb; break; //---------------------------- case etat_cle_presente_montee: if (!modele_ports_usb.get(shipheart_port_usb_avant_bas).presence) { boite_information.niveau = 2; boite_information.imageTitreSource = "/images/attention.png" boite_information.message = qsTr("La clé USB a été retirée sans avoir préalablement été éjectée !
Cela peut conduire à des pertes de données sur la clé, voire sur ShipHeart.

Lors de vos prochaines utilisations, pensez à éjecter la clé avec le bouton en haut de page avant de la retirer... Merci !"); boite_information.open(); etat_cle = etat_cle_absente; modele_fichiers_cle.clear(); // Effacement du modèle si le device est retirée break; } if (modele_ports_usb.get(shipheart_port_usb_avant_bas).partition === "") { etat_cle = etat_cle_presente; break; } if (modele_ports_usb.get(shipheart_port_usb_avant_bas).montee) { etat_cle = etat_cle_presente_partition; break; } break; //---------------------------- case etat_cle_presente_demontee: if (!modele_ports_usb.get(shipheart_port_usb_avant_bas).presence) etat_cle = etat_cle_absente; break; //---------------------------- default: console.log("Etat_clé a une valeur anormale [" + etat_cle + "] ; elle est remise à 0."); etat_cle = etat_cle_absente; break; } } //============================================================================================================= // Action demandée par le bouton du haut de la zone centrale : // - si Image_accueil : Enregistre l'image en cours de sélection comme l'image de la page d'accueil // - si Silhouette : Enregistre l'image en cours de sélection comme l'image de la silhouette // - si Rapport : Lance l'utilitaire de génération de rapport d'installation // - si Sauvegarde : Lance l'utilitaire de génération d'une sauvegarde //============================================================================================================= function action() { var req, res; var i; var commande; switch(mode_config_fichiers) { //---------------------------------------------------- case shipheart_mode_config_fichiers_image_accueil: { if (index_fichier_local_actif === -1) // Cas où aucun fichier n'est sélectionné : { nom_fichier_local_selectionne = ""; } else nom_fichier_local_selectionne = modele_fichiers_locaux.get(index_fichier_local_actif).nom; shipheart_fichier_image_accueil = nom_fichier_local_selectionne; // Enregistrement dans la BDD : req = 'UPDATE TB_Configuration '; req += ' SET Valeur="' + nom_fichier_local_selectionne + '" '; req += ' WHERE Nom="Fichier_image_accueil" '; //console.log("Requête = [ " + req + "; ]"); bdd.requete_unique(req); break; } //---------------------------------------------------- case shipheart_mode_config_fichiers_silhouette: { if (index_fichier_local_actif === -1) nom_fichier_local_selectionne = "" else nom_fichier_local_selectionne = modele_fichiers_locaux.get(index_fichier_local_actif).nom; // Enregistrement dans la BDD : req = 'UPDATE TB_Pages '; req += ' SET Fichier="' + nom_fichier_local_selectionne + '" '; req += ' WHERE Cle_primaire= ' + id_page + ' '; //console.log("Requête = [ " + req + "; ]"); bdd.requete_unique(req); break; } //---------------------------------------------------- case shipheart_mode_config_fichiers_rapports: { busy_indicator_centre.running = true; // Lance le sablier (il sera arrêté lors de l'apparition du nouveau fichier par le gestionnaire FolderListModel // Commande d'exécution du script : commande = "sudo php " + shipheart_repertoire_utils + "/" + shipheart_nom_fichier_rapport_installation; systeme.commande_shell_non_bloquante(commande); //console.log("Exécution de la commande [ " + commande + " ]"); flag_new_file_en_attente = true; // Permet de lancer un traitement spécifique lorsque le fichier de sauvegarde sera détecté dans le répertoire if (shipheart_type_installation !== shipheart_type_installation_shipbase) synchro_repertoires_shiprs(); break; } //---------------------------------------------------- case shipheart_mode_config_fichiers_sauvegardes: { busy_indicator_centre.running = true; // Lance le sablier (il sera arrêté lors de l'apparition du nouveau fichier par le gestionnaire FolderListModel // Commande d'exécution du script : commande = "sudo php " + shipheart_repertoire_utils + "/" + shipheart_nom_fichier_sauvegarde; systeme.commande_shell_non_bloquante(commande); //console.log("Exécution de la commande [ " + commande + " ]"); flag_new_file_en_attente = true; // Permet de lancer un traitement spécifique lorsque le fichier de sauvegarde sera détecté dans le répertoire if (shipheart_type_installation !== shipheart_type_installation_shipbase) synchro_repertoires_shiprs(); break; } //---------------------------------------------------- case shipheart_mode_config_fichiers_inconnu: default: { break; } } } //============================================================================================================= // Monte le port USB dont le n° est passé en paramètre //============================================================================================================= function monter_port_usb(port) { var commande, retour; commande = "sudo mount /dev/" + modele_ports_usb.get(port).partition + " " + shipheart_repertoire_cle_usb; retour = systeme.commande_shell(commande, ""); //console.log("Excution de la commande [ " + commande + " ]. Retour = [ " + retour + " ]"); sous_repertoire_cle = ""; // Par défaut, on se positionne à la racine de la clé lorsqu'elle est montée } //============================================================================================================= // Démonte le port USB dont le n° est passé en paramètre //============================================================================================================= function demonter_port_usb(port) { var commande, retour; commande = "sudo sync"; retour = systeme.commande_shell(commande, ""); //console.log("Excution de la commande [ " + commande + " ]. Retour = [ " + retour + " ]"); retour = systeme.commande_shell(commande, ""); // Il semble que la première commande SYNC retourne immédiatement, avant que la commande elle-meme soit traitée. Une seconde permet d'être sûr que la première est terminée... //console.log("Excution de la commande [ " + commande + " ]. Retour = [ " + retour + " ]"); commande = "sudo umount -l /dev/" + modele_ports_usb.get(port).partition; retour = systeme.commande_shell(commande, ""); //console.log("Excution de la commande [ " + commande + " ]. Retour = [ " + retour + " ]"); } //============================================================================================================= // Vérifie la présence d'un device sur les 4 ports USB de ShipBase et met à jour le modèle correspondant //============================================================================================================= function check_ports_usb() { var commande, retour; var i, j; var port_en_cours = shipheart_port_usb_aucun; var etat_sequenceur; var flag_devices_presents; var lignes; var params; var param_levs; var param_ports; var param_products; //------------------------------------------------------------------------------------------- // Copie du fichier des devices USB vers le répertoire temporaire (impossible à lire sinon) : commande = "sudo cp " + shipheart_repertoire_sys_usb + "/" + shipheart_nom_fichier_usb_devices + " " + shipheart_repertoire_tmp_usb + "/" + shipheart_nom_fichier_usb_devices; retour = systeme.commande_shell(commande, ""); //console.log("Exécution de la commande [ " + commande + " ]. Retour = [ " + retour + " ]"); //------------------------------------------------------------------------------------------- // RAZ des valeurs par défaut (pour prendre en compte le faitq que le device a pu être retiré) : for (i = 0; i < modele_ports_usb.count; i ++) { modele_ports_usb.set(i, { "presence": false, "disk": "", "partition": "", "monte": false, "size": "", "used": "", "label": "", "manufacturer": "", "product": "", "serial_number": "" } ); } //------------------------------------------------------------------------------------------- // Lecture du fichier des devices : // Note : on ne peut pas lire directement le fichier qui est protégé ; on en fait donc une copie dans le répertoire TMP. // Voir le contenu, qui est assez explicite, par 'sudo cat /sys/kernel/debug/usb/devices' lignes = systeme.lecture_fichier(shipheart_repertoire_tmp_usb + "/" + shipheart_nom_fichier_usb_devices); // 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 du fichier = " + lignes[0]); if (lignes[0] === "Ok") { etat_sequenceur = 0; for (i = 1; i < lignes.length; i ++) { //console.log(i + " : " + lignes[i]); if (lignes[i] !== "") { lignes[i] = lignes[i].replace(/\s\s+/g, ' '); // Remplace les espaces multiples, tabulations, etc... par un seul espace params = lignes[i].split(' '); if (params.length > 0) { switch(etat_sequenceur) { //---------------------------- // Etat de repos (attente d'un "T: ") : // Exemple : 'T: Bus=01 Lev=03 Prnt=27 Port=00 Cnt=01 Dev#= 31 Spd=12 MxCh= 0' case 0: if (params[0] === "T:") { param_levs = params[2].split('='); param_ports = params[4].split('='); // NOTE : on considère que la clé est branchée directement, sans passer par un hub. Sinon, son LEVEL sera > 2. // Si besoin de prendre en compte l'utilisation de HUB, c'est possible mais il faudra affiner l'algorithme en utilisant // les champs 'Dev#=' contenant le n° de device du HUB et le champ 'Prnt=' contenant le n° du parent. // Il faut donc attraper le 'Dev#' du Hub au 'Level=02' & 'Port=00' (arrière) ou 'Port=02' (avant) puis traiter les autres // entrées avec 'Level' > 2 et dont le 'Prnt' === le 'Dev#' du hub... // A noter qu'on peut aussi traiter tout cela de façon récusrive si on veut traiter les empilements de hub...! if (Number(param_levs[1]) === 2) { // On ne traite que les ports qui nous interressent : if ((Number(param_ports[1]) >= shipheart_port_usb_arriere) && (Number(param_ports[1]) <= shipheart_port_usb_touchpad)) { port_en_cours = Number(param_ports[1]); modele_ports_usb.set(port_en_cours, { "presence": true}); etat_sequenceur = 1; } } } break; //---------------------------- // Attente des lignes de type "S: " case 1: if (params[0] === "S:") { param_products = params[1].split('='); switch(param_products[0]) { //--------------------- case "Manufacturer": // ports_usb[port_en_cours]['manufacturer'] = lignes[i].substring(lignes[i].indexOf('=')+1); modele_ports_usb.set(port_en_cours, { "manufacturer": lignes[i].substring(lignes[i].indexOf('=')+1)}); // Récupère tout ce qui est après le '=' car il peut y avoir des espaces... break; //--------------------- case "Product": // ports_usb[port_en_cours]['product'] = lignes[i].substring(lignes[i].indexOf('=')+1); // Récupère tout ce qui est après le '=' car il peut y avoir des espaces... modele_ports_usb.set(port_en_cours, { "product": lignes[i].substring(lignes[i].indexOf('=')+1)}); // Récupère tout ce qui est après le '=' car il peut y avoir des espaces... break; //--------------------- case "SerialNumber": // ports_usb[port_en_cours]['serial_number'] = lignes[i].substring(lignes[i].indexOf('=')+1); // Récupère tout ce qui est après le '=' car il peut y avoir des espaces... modele_ports_usb.set(port_en_cours, { "serial_number": lignes[i].substring(lignes[i].indexOf('=')+1)}); // Récupère tout ce qui est après le '=' car il peut y avoir des espaces... break; } } break; //---------------------------- default: etat_sequenceur = 0; break; } } } else etat_sequenceur = 0; } } //------------------------------------------------------------------------------------------- // Synthèse des devices trouvés : flag_devices_presents = false; for (i = 0; i < modele_ports_usb.count; i ++) { if (!modele_ports_usb.get(i).presence) continue; // On ne prend en compte que les ports accessibles de l'éxtérieur : // NB : pour les V1, le port Arrière n'est pas accessible mais il ne sera donc jamais détecté... if ((i === shipheart_port_usb_arriere) || (i === shipheart_port_usb_avant_bas)) flag_devices_presents = true; } //------------------------------------------------------------------------------------------- // Recherche des disque et partitions présentes : if (flag_devices_presents) { //------------------------------------------------------------------------------------------- // génération de la commande LSBLK qui permet d'obtenir un lien entre disque/partition et n° de série du device : // La commande permet d'obtenir quelque chose comme : // disk sda 4C530001130622100112 // part sda1 Koriolan // disk sdb 4C531001530726109585 // part sdb1 KORIOLAN /home/koriolan/cle_usb 7.4G 35% // Où '-I 8' permet de n'inclure que les drivers de Major Code = 8, soit les 'sdxx' // 'TYPE,KNAME,LABEL,SERIAL,MOUNTPOINT,FSSIZE,FSUSE%' est la liste des paramètres attendus // '-n' supprime la ligne de titres de espace_colonnes_principales // '-r' donne une sortie "raw" dans laquelle les TAB sont remplacées par des espaces. commande = "sudo lsblk -I 8 -o TYPE,KNAME,LABEL,SERIAL,MOUNTPOINT,FSSIZE,FSUSE% -n -r "; retour = systeme.commande_shell(commande, shipheart_repertoire_tmp_usb + "/" + shipheart_nom_fichier_usb_lsblk); // Le second argument est la redirection de la sortie. //console.log("Excution de la commande [ " + commande + " ]. Retour = [ " + retour + " ]"); //------------------------------------------------------------------------------------------- // Lecture du fichier 'resultat_lsblk' : lignes = systeme.lecture_fichier(shipheart_repertoire_tmp_usb + "/" + shipheart_nom_fichier_usb_lsblk); // 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 du fichier = " + lignes[0]); if (lignes[0] === "Ok") { port_en_cours = -1; for (i = 1; i < lignes.length; i ++) { //console.log(i + " : " + lignes[i]); if (lignes[i] !== "") { lignes[i] = lignes[i].replace(/\s\s+/g, ' '); // Remplace les espaces multiples, tabulations, etc... par un seul espace params = lignes[i].split(' '); if (params.length > 0) { //-------------------------------------------- // Lecture de la ligne commençant par 'disk' : if (params[0] === "disk") { for (j = 0; j < modele_ports_usb.count; j ++) { if (!modele_ports_usb.get(j).presence) continue; if (modele_ports_usb.get(j).serial_number === params[2]) { modele_ports_usb.set(j, { "disk": params[1] }); port_en_cours = j; } } } //-------------------------------------------- // Lecture de la ligne commençant par 'part' : else if (params[0] === "part") { if (port_en_cours !== -1) // Ne devrait pas arriver si les lignes sont bien ordonnées : 'disk' puis 'part' { if (modele_ports_usb.get(port_en_cours).disk[2] === params[1][2]) // On compare la lettre X de 'sdX' du disk et de 'sdX1' de la partition { modele_ports_usb.set(port_en_cours, { "partition": params[1] }); modele_ports_usb.set(port_en_cours, { "label": params[2] }); if (params.length >= 4) modele_ports_usb.set(port_en_cours, { "monte": (params[3] !== "") }); if (params.length >= 5) modele_ports_usb.set(port_en_cours, { "size": params[4] }); if (params.length >= 6) modele_ports_usb.set(port_en_cours, { "used": params[5] }); port_en_cours = -1; } } } } } } } } // Boucle sur tous les ports présents : for (i = 0; i < modele_ports_usb.count; i ++) { if (!modele_ports_usb.get(i).presence) continue; if ((i !== shipheart_port_usb_arriere) && (i !== shipheart_port_usb_avant_bas)) continue; /* console.log(i+"=Port [" + modele_ports_usb.get(i).nom + "] détecté : Disk=" + modele_ports_usb.get(i).disk + ", Part=" + modele_ports_usb.get(i).partition + ", Label=" + modele_ports_usb.get(i).label + ", Monté=" + modele_ports_usb.get(i).monte + ", Size=" + modele_ports_usb.get(i).size + ", Used=" + modele_ports_usb.get(i).used + ", Manufacturer=" + modele_ports_usb.get(i).manufacturer + ", Product=" + modele_ports_usb.get(i).product + ", SerialNumber=" + modele_ports_usb.get(i).serial_number ); */ // Mise à jour du modèle de la clé si elle est montée mais n'a jamais été mise à jour : if ((modele_ports_usb.get(i).monte) && (modele_fichiers_cle.count === 0)) { ls(shipheart_repertoire_cle_usb + ((sous_repertoire_cle === "") ? "" : "/" + sous_repertoire_cle)); // Rechargement du modèle avec le contenu du sous-répertoire } } } //============================================================================================================= // Liste les fichiers et répertoires présents dans le répertoire dont le chemin complet est passé en paramètres //============================================================================================================= function ls(dir) { var commande, retour; var i; var lignes; var params; //------------------------------------------------------------------------------------------- // génération de la commande 'ls -lh' permet d'obtenir quelque chose comme : // total 1271152 // -rwxr-xr-x 1 root root 1.5K Jun 16 2023 backend.cpp // -rwxr-xr-x 1 root root 99K Apr 15 2024 batterie.qml // -rwxr-xr-x 1 root root 7.8K Apr 14 2024 bdd.cpp // -rwxr-xr-x 1 root root 651 Apr 14 2024 bdd.h // drwxr-xr-x 3 root root 4.0k Jun 21 2023 Projets_Qt // -rwxr-xr-x 1 root root 1.3G Jul 11 2023 shiprs_cm4_2023_06_17.img.gz // drwxr-xr-x 2 root root 4.0K Jul 5 2023 System Volume Information commande = "sudo ls " + dir + " -l"; retour = systeme.commande_shell(commande, shipheart_repertoire_tmp_usb + "/" + shipheart_nom_fichier_usb_ls); // Le second argument est la redirection de la sortie. //console.log("Excution de la commande [ " + commande + " ]. Retour = [ " + retour + " ]"); //------------------------------------------------------------------------------------------- // Lecture du fichier 'resultat_ls' : lignes = systeme.lecture_fichier(shipheart_repertoire_tmp_usb + "/" + shipheart_nom_fichier_usb_ls); // 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 du fichier = " + lignes[0]); if (lignes[0] === "Ok") { modele_fichiers_cle.clear(); // Ajout du bouton de remontée vers le répertoire parent si on n'est pas à la racine de la clé : if (sous_repertoire_cle !== "") { modele_fichiers_cle.append( { "type": "dir", "nom": "..", "taille": "", "taille_octets": 0, "actif": false, "autorise": false } ); } for (i = 1; i < lignes.length; i ++) { //console.log(i + " : " + lignes[i]); if (lignes[i] !== "") { lignes[i] = lignes[i].replace(/\s\s+/g, ' '); // Remplace les espaces multiples, tabulations, etc... par un seul espace params = lignes[i].split(' '); if (params.length === 9) { //-------------------------------------------- // Lecture de la ligne commençant par '-' : if (params[0][0] === '-') // Cas d'un fichier (exemple : "-rwxr-xr-x 1 root root 1536 Jun 16 2023 backend.cpp") { // Recherche de l'extensio du fichier et teste s'il est autorisé dans la liste : var pos_extension = params[8].lastIndexOf('.') var autorise = false; if (pos_extension !== -1) { autorise = texte_types_fichiers_valides.includes(params[8].slice(pos_extension)); } //console.log("Fichier "+params[8]+", taille="+params[4]+", texte_types_fichiers_valides="+texte_types_fichiers_valides+", Extension="+ params[8].slice(pos_extension)) modele_fichiers_cle.append( { "type": "fic", "nom": params[8], "taille": Fonctions.taille_fichier(Number(params[4]), shipheart_langue), "taille_octets": Number(params[4]), "actif": false, "autorise": autorise } ); } //-------------------------------------------- // Lecture de la ligne commençant par 'd' : else if (params[0][0] === 'd') // Cas d'une répertoire (exemple : "drwxr-xr-x 3 root root 4096 Jun 21 2023 Projets_Qt") { //console.log("Répertoire "+params[8]+", taille="+params[4] ) modele_fichiers_cle.append( { "type": "dir", "nom": params[8], "taille": Fonctions.taille_fichier(Number(params[4]), shipheart_langue), "taille_octets": Number(params[4]), "actif": false, "autorise": false } ); } } } } } } //============================================================================================================= // Copie les fichier sélectionnés (le 'sens' indiquant où sont situés les fichiers à copier et vers où les copier) //============================================================================================================= function copie_fichiers() { var commande, retour; var i; //console.log("Demande de copie de fichiers dans le sens : " + sens) if (sens === "shipheart_vers_cle") { for (i = 0; i < modele_fichiers_locaux.count; i ++) { if (modele_fichiers_locaux.get(i).actif) { commande = "cp " + nom_repertoire_local + "/" + modele_fichiers_locaux.get(i).nom + " " + shipheart_repertoire_cle_usb + ((sous_repertoire_cle === "") ? "" : "/" + sous_repertoire_cle) + "/" + modele_fichiers_locaux.get(i).nom; retour = systeme.commande_shell(commande, ""); //console.log("Excution de la commande [ " + commande + " ]. Retour = [ " + retour + " ]"); } } // Mise à jour du modèle du répertoire de la clé : ls(shipheart_repertoire_cle_usb + ((sous_repertoire_cle === "") ? "" : "/" + sous_repertoire_cle)); } else if (sens === "cle_vers_shipheart") { for (i = 0; i < modele_fichiers_cle.count; i ++) { if (modele_fichiers_cle.get(i).actif) { commande = "cp " + shipheart_repertoire_cle_usb + ((sous_repertoire_cle === "") ? "" : "/" + sous_repertoire_cle) + "/" + modele_fichiers_cle.get(i).nom + " " + nom_repertoire_local + "/" + modele_fichiers_cle.get(i).nom; retour = systeme.commande_shell(commande, ""); //console.log("Excution de la commande [ " + commande + " ]. Retour = [ " + retour + " ]"); } } // NB : la mise à jour du modèle local se fait automatiquement par FolderListModel } } //============================================================================================================= // Supprime les fichier sélectionnés (le 'sens' indiquant où sont situés les fichiers à supprimer //============================================================================================================= function suppression_fichiers() { var commande, retour; var i; //console.log("Demande de suppression de fichiers dans le sens : " + sens) if (sens === "shipheart_vers_cle") { for (i = 0; i < modele_fichiers_locaux.count; i ++) // NB : on pourrait utiliser 'index_fichier_local_selectionne' mais on garde le principe général qui accepte la suppression multiple... { if (modele_fichiers_locaux.get(i).actif) { commande = "rm " + nom_repertoire_local + "/" + modele_fichiers_locaux.get(i).nom; retour = systeme.commande_shell(commande, ""); //console.log("Excution de la commande [ " + commande + " ]. Retour = [ " + retour + " ]"); // Remise à la valeur par défaaut si on vient de supprimer le fichier sélectionné : modele_fichiers_locaux.get(i).actif = false; // Permet que la 'selectionner_image()' qui suit fonctionne alors que la synchro du modèle n'est pas encore faite... } } // NB : la mise à jour du modèle local se fait automatiquement par FolderListModel } else if (sens === "cle_vers_shipheart") { for (i = 0; i < modele_fichiers_cle.count; i ++) { if (modele_fichiers_cle.get(i).actif) { commande = "rm " + shipheart_repertoire_cle_usb + ((sous_repertoire_cle === "") ? "" : "/" + sous_repertoire_cle) + "/" + modele_fichiers_cle.get(i).nom; retour = systeme.commande_shell(commande, ""); //console.log("Excution de la commande [ " + commande + " ]. Retour = [ " + retour + " ]"); } } ls(shipheart_repertoire_cle_usb + ((sous_repertoire_cle === "") ? "" : "/" + sous_repertoire_cle)); } } //============================================================================================================= // Lance le process de restauration du fichier sélectionnés (le fichier est forcément sur ShipBase !) //============================================================================================================= function restauration() { var commande, retour; var i; var flag_reboot = false; if (sens === "shipheart_vers_cle") { for (i = 0; i < modele_fichiers_locaux.count; i ++) { if (modele_fichiers_locaux.get(i).actif) { commande = "sudo cp " + nom_repertoire_local + "/" + modele_fichiers_locaux.get(i).nom + " " + shipheart_repertoire_versions_a_charger + "/" + modele_fichiers_locaux.get(i).nom; retour = systeme.commande_shell(commande, ""); //console.log("Excution de la commande [ " + commande + " ]. Retour = [ " + retour + " ]"); flag_reboot = true; break; } } if (flag_reboot) rebooter(); } } //============================================================================================================= // Synchroniser répertoire docs ShipRS //============================================================================================================= function synchro_repertoires_shiprs() { var commande; commande = "rsync -aPs --delete -e \"ssh -p 2022 -o StrictHostKeyChecking=no \" koriolan@" + AppInfo.adresse_shipbase + ":" + shipheart_repertoire_config + "/ " + shipheart_repertoire_config + "/"; systeme.commande_shell(commande, ""); } //============================================================================================================= // Sortie // Cette fonction remet dans l'état initial les alimentations de ports USB avant de sortir (SDIR #303) //============================================================================================================= function sortie() { // Remise à l'état initial de l'alim des ports USB : if (etat_initial_port_usb_avant === 0) { bdd.requete_unique('UPDATE TB_Circuits SET New_consigne=0 WHERE Adresse_module=0 AND No_circuit=1 '); } if (etat_initial_port_usb_arrière === 0) { bdd.requete_unique('UPDATE TB_Circuits SET New_consigne=0 WHERE Adresse_module=0 AND No_circuit=2 '); } // Demande de prise en compte des nouvelles consignes : synchro_bdd(shipheart_type_synchro_data); // Sortie effective de la page : stackView.pop(); } }