import QtQuick 2.12 import QtQuick.Controls 2.12 import"fonctions_date_heure.js" as Fonctions_date_heure Popup { id: boite_dialogue_reveils // Propriétés fixes : readonly property double pourcentage_largeur_page_popup: 0.7 readonly property double pourcentage_hauteur_page_popup: 0.8 readonly property int padding_popup: 20 readonly property double pourcentage_zone_titre: 0.20 readonly property double pourcentage_zone_principale: 1 - pourcentage_zone_titre - pourcentage_zone_boutons readonly property double pourcentage_zone_boutons: 0.15 readonly property int bouton_hauteur: 60 readonly property int hauteur_ligne_formulaire: 60 readonly property double pourcentage_zone_validite: 0.15 readonly property int bouton_largeur: 200 // Propriétés : property bool flag_init: true property int index_condition_horaire_en_cours: -1 // Propriétés alias : //------------------------------------------------- // Signaux : //------------------------------------------------- signal clicked(int bouton) // Valeurs à lire lorsque le "OnClicked' est activé //------------------------------------------------- // Ouverture : //------------------------------------------------- onAboutToShow: { // Activé une fois quand le popup va être affiché init(); // L'init n'a d'utilité que lorsqu'on va l'afficher... } onOpened: { // Quand la page est affichée } //------------------------------------------------- // Fermeture : //------------------------------------------------- onAboutToHide: { } x: (shipheart_largeur_page * (1 - pourcentage_largeur_page_popup)) / 2; y: (shipheart_hauteur_page * (1 - pourcentage_hauteur_page_popup)) / 2; width: shipheart_largeur_page * pourcentage_largeur_page_popup; height: shipheart_hauteur_page * pourcentage_hauteur_page_popup; padding: padding_popup modal: true // focus: true // SDIR # 224 : Il ne faut PAS activer le focus. Sinon, à la fermeture, le focus précédent est réactivé (comme le dernier TextField par exemple) closePolicy: Popup.NoAutoClose //Popup.CloseOnPressOutside background: Rectangle { color: shipheart_couleur_fond_boite_dialogue_niveau_0 radius: 20 } Column { id: affichage_boite_dialogue spacing: 20 //========================================================================= // Titre : //========================================================================= Rectangle { id: titre_boite_dialogue width: boite_dialogue_reveils.width - (2 * padding_popup) height: (boite_dialogue_reveils.height - (2 * padding_popup) - (2 * affichage_boite_dialogue.spacing)) * pourcentage_zone_titre color: "transparent" Image { id: image_titre source: "/images/reveil.png" sourceSize.height: 100 anchors { verticalCenter: parent.verticalCenter horizontalCenter: parent.horizontalCenter } visible: true } } //========================================================================= // Zone principale : //========================================================================= Rectangle { id: zone_principale width: boite_dialogue_reveils.width - (2 * padding_popup) height: (boite_dialogue_reveils.height - (2 * padding_popup) - (2 * affichage_boite_dialogue.spacing)) * pourcentage_zone_principale color: "transparent" GridView { id: grille_conditions_horaires 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: ListModel { } delegate: Rectangle { width: grille_conditions_horaires.cellWidth height: grille_conditions_horaires.cellHeight color: "transparent" //....................................................... // Bouton principal : //....................................................... Rectangle { height: parent.height - 10 width: (!model.bouton) ? ((parent.width * (1 - pourcentage_zone_validite)) - 10) : (parent.width) // visible: (!model.bouton) color: shipheart_couleur_fond_bouton radius: shipheart_rayon_bouton anchors { left: parent.left verticalCenter: parent.verticalCenter } Text { anchors.fill: parent verticalAlignment: Qt.AlignVCenter horizontalAlignment: (!model.bouton) ? Qt.AlignLeft : Qt.AlignHCenter leftPadding: (!model.bouton) ? 20 : 0 text: model.libelle color: couleur_blanc_casse font.pixelSize: (!model.bouton) ? 18 : (hauteur_ligne_formulaire * 0.8) } MouseArea{ anchors.fill : parent onClicked: { shipheart_clic(); if (model.bouton) // Cas du bouton '+' { index_condition_horaire_en_cours = -1; // Marqueur pour indiquer l'ajout d'un élément boite_selection_condition_horaire.valeur_tumbler_jour = 8; // Tous les jours par défaut boite_selection_condition_horaire.valeur_tumbler_heure = 0; boite_selection_condition_horaire.valeur_tumbler_minute = 0; boite_selection_condition_horaire.boutonSupprimer = false; } else // Cas d'une modification de condition existante : { index_condition_horaire_en_cours = index; boite_selection_condition_horaire.valeur_tumbler_jour = model.jour; boite_selection_condition_horaire.valeur_tumbler_heure = model.heure; boite_selection_condition_horaire.valeur_tumbler_minute = model.minute; boite_selection_condition_horaire.boutonSupprimer = true; } boite_selection_condition_horaire.x = 0; // Bloque le déplacement latéral classique de la boite de dialogue puisqu'on l'appelle d'une boite déjà ouverte... boite_selection_condition_horaire.y = titre_boite_dialogue.height; // Idem en Y mais avec un décalage permettant de toujours voir le titre de la boite appelante.... boite_selection_condition_horaire.open(); } } } //....................................................... // Bouton de validite : //....................................................... Rectangle { height: parent.height - 10 width: (parent.width * pourcentage_zone_validite) visible: (!model.bouton) color: shipheart_couleur_fond_bouton radius: shipheart_rayon_bouton anchors { right: parent.right verticalCenter: parent.verticalCenter } Image { id: image_info_paramètres source: (model.validite === 0) ? "/images/cloche_barree.png" : "/images/cloche_verte.png" sourceSize.height: parent.height * 0.5 anchors { verticalCenter: parent.verticalCenter horizontalCenter: parent.horizontalCenter } } MouseArea{ anchors.fill : parent onClicked: { shipheart_clic(); if (grille_conditions_horaires.model.get(index).validite === 0) { grille_conditions_horaires.model.set(index, {"validite": 1} ); } else grille_conditions_horaires.model.set(index, {"validite": 0} ); } } } } } // Fin de Gridview } //========================================================================= // Boutons de bas de fenêtre : //========================================================================= Row { height: (boite_dialogue_reveils.height - (2 * padding_popup) - (2 * affichage_boite_dialogue.spacing)) * pourcentage_zone_boutons anchors.horizontalCenter: parent.horizontalCenter spacing: 20 //....................................................... // Bouton Annuler : //....................................................... Rectangle { id: bouton_annuler width: bouton_largeur height: bouton_hauteur anchors.verticalCenter: parent.verticalCenter radius: shipheart_rayon_bouton color: couleur_gris_tres_fonce Label { id: bouton_annuler_label anchors.centerIn: parent text: qsTr("Annuler") color: couleur_blanc_casse font.pixelSize:20 } MouseArea { anchors.fill: parent onClicked: { shipheart_clic(); boite_dialogue_reveils.clicked(shipheart_boite_dialogue_bouton_2); } } } //....................................................... // Bouton Ok / Enregistrer : //....................................................... Rectangle { id: bouton_ok width: bouton_largeur height: bouton_hauteur anchors.verticalCenter: parent.verticalCenter radius: shipheart_rayon_bouton color: couleur_gris_tres_fonce Label { anchors.centerIn: parent text: qsTr("Enregistrer") color: couleur_blanc_casse font.pixelSize:20 } MouseArea { anchors.fill: parent onClicked: { shipheart_clic(); mise_a_jour(); } } } } } //------------------------------------------------------- // Boite de sélection d'une condition horaire : //------------------------------------------------------- Shipheart_boite_dialogue_condition_horaire { id: boite_selection_condition_horaire boutonOk: true boutonAnnuler: true onClicked: { //console.log("Le Bouton [" + bouton + "] est appuyé"); //------------------- // Bouton Ok : //------------------- if (bouton === shipheart_boite_dialogue_bouton_1) { //console.log("Jour = " + jour + ", Heure="+heure+" et Minute="+minute); //---------------------------------------- // Cas d'une mise à jour : if (index_condition_horaire_en_cours !== -1) { // Mise à jour de l'entrée du modèle avec les données saisies : grille_conditions_horaires.model.set(index_condition_horaire_en_cours, { "libelle": Fonctions_date_heure.nom_jour_semaine(jour) + " @ " + Fonctions_date_heure.nom_heure(heure, minute), "jour": jour, "heure": heure, "minute": minute} ); } //---------------------------------------- // Cas de l'ajout d'une condition : else { grille_conditions_horaires.model.insert( (grille_conditions_horaires.model.count - 1), { // Insertion juste avant le '+' "libelle": Fonctions_date_heure.nom_jour_semaine(jour) + " @ " + Fonctions_date_heure.nom_heure(heure, minute), "jour": jour, "heure": heure, "minute": minute, "validite": 1, "bouton": false }); } } //------------------- // Bouton Annuler : //------------------- if (bouton === shipheart_boite_dialogue_bouton_2) ; // Aucune action... //------------------- // Bouton Supprimer : //------------------- if (bouton === shipheart_boite_dialogue_bouton_3) { grille_conditions_horaires.model.remove(index_condition_horaire_en_cours, 1); } boite_selection_condition_horaire.close(); // Dans tous les cas... (notamment si ANNULER) } } //============================================================================================================= // Transitions d'ouverture et de fermeture de la boite de dialogue //============================================================================================================= enter: Transition { ParallelAnimation { NumberAnimation { property: "opacity" from: 0.0 to: 1.0 //easing.type: Easing.InElastic duration: 200 } NumberAnimation { property: "scale" from: 0.0 to: 1.0 // easing.type: Easing.OutBack duration: 200 } } } exit: Transition { ParallelAnimation { NumberAnimation { property: "opacity" from: 1.0 to: 0.0 duration: 200 } NumberAnimation { property: "scale" from: 1.0 to: 0.0 duration: 200 } } } //============================================================================================================= // Init des données de la boite de dialogue //============================================================================================================= function init() { var req, res; var i; var conditions; var condition var jour; var heure; var minute; var validite; flag_init = true; // On est obligé de le renseigne manuellement car la fonction 'init()' est appelée à chaque ouverture (et la valeur par défaut, qu'à l'ouverture initiale...) grille_conditions_horaires.model.clear(); req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Reveils" '; //console.log("Requête = [ " + req + '; ]') res = bdd.requete_unique(req); var conditions_horaires = res[0]; if (conditions_horaires !== "") { conditions = conditions_horaires.split(';'); for (i = 0; i < conditions.length; i ++) { condition = conditions[i].split('/'); if (condition.length === 4) { jour = Number(condition[0]); heure = Number(condition[1]); minute = Number(condition[2]); validite = Number(condition[3]); //console.log("Condition #"+(i+1)+" : jour="+Fonctions_date_heure.nom_jour_semaine(jour)+" à "+ Fonctions_date_heure.nom_heure(heure, minute) ); grille_conditions_horaires.model.append( { "libelle": Fonctions_date_heure.nom_jour_semaine(jour) + " @ " + Fonctions_date_heure.nom_heure(heure, minute), "jour": jour, "heure": heure, "minute": minute, "validite": validite, "bouton": false }); } } } // Ajout du bouton "+" : grille_conditions_horaires.model.append( { "libelle": "+", "jour": 0, "heure": 0, "minute": 0, "validite": 0, "bouton": true }); flag_init = false; } //============================================================================================================= // Mise à jour des données de la boite de dialogue //============================================================================================================= function mise_a_jour() { var req; var conditions_horaires; var flag_first; var i; conditions_horaires = ""; if ((grille_conditions_horaires.model.count - 1) > 0) // Le '-1' permet de neutraliser le bouton '+' qui est toujours présents { flag_first = true; for (i = 0; i < grille_conditions_horaires.model.count; i ++) // Parcours du modèle existant { if (!grille_conditions_horaires.model.get(i).bouton) // Ne prend pas en compte le bouton '+' { if (flag_first) flag_first = false; else conditions_horaires += ";" conditions_horaires += grille_conditions_horaires.model.get(i).jour; conditions_horaires += "/"; conditions_horaires += grille_conditions_horaires.model.get(i).heure; conditions_horaires += "/"; conditions_horaires += grille_conditions_horaires.model.get(i).minute; conditions_horaires += "/"; conditions_horaires += grille_conditions_horaires.model.get(i).validite; } } } else console.log("Aucune condition horaire n'a été configurée. La chaine 'Reveils' est laissée vide.") //console.log("Conditions horaires = [ " + conditions_horaires + " ]") req = 'UPDATE TB_Configuration SET Valeur="' + conditions_horaires + '" WHERE Nom="Reveils" '; console.log("Requête = [ " + req + '; ]') bdd.requete_unique(req); boite_dialogue_reveils.clicked(shipheart_boite_dialogue_bouton_1); } }