Files
shipheart-qt/Shipheart_boite_dialogue_condition_horaire.qml

578 lines
24 KiB
QML
Executable File

import QtQuick 2.12
import QtQuick.Controls 2.12
import"fonctions_date_heure.js" as Fonctions_date_heure
Popup {
id: boite_dialogue_condition_horaire
// Propriétés fixes :
readonly property double pourcentage_largeur_page_popup: 0.7
readonly property double pourcentage_hauteur_page_popup: 0.7
readonly property int padding_popup: 20
readonly property double pourcentage_boite_dialogue_titre: 0.20
readonly property double pourcentage_boite_dialogue_message: 1 - pourcentage_boite_dialogue_titre - pourcentage_boite_dialogue_ligne_boutons
readonly property double pourcentage_boite_dialogue_ligne_boutons: 0.2
readonly property int hauteur_icones_tumblers: 35
readonly property int bouton_largeur: 200
readonly property int espace_tumblers: 20
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
// Propriétés :
property int valeur_timer_appui_long: 0
property int jour_en_cours: 0
property int valeur_tumbler_jour: 0
property int valeur_tumbler_heure: 0
property int valeur_tumbler_minute: 0
// Propriétés alias :
property alias boutonOk: bouton_ok.visible
property alias boutonAnnuler: bouton_annuler.visible
property alias boutonSupprimer: bouton_supprimer.visible
//-------------------------------------------------
// Signaux :
//-------------------------------------------------
signal clicked(int bouton, int jour, int heure, int minute) // Valeurs à lire lorsque le "OnClicked' est activé
//-------------------------------------------------
// Init :
//-------------------------------------------------
onOpened: { // Activé une fois que le popup est complètement affiché
mise_a_jour(); // Met à jour les valeurs courantes des 3 tumbler en fonction des paramètres passés
}
//===========================================================
// 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(); // Charge le modèle des 3 tumblers (dès l'ouverture de "config_event.qml" !)
}
}
}
//===========================================================
// 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)
{
boite_dialogue_condition_horaire.clicked(shipheart_boite_dialogue_bouton_3, 0, 0, 0);
}
}
}
}
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_condition_horaire.width - (2 * padding_popup)
height: (boite_dialogue_condition_horaire.height - (2 * padding_popup) - (2 * affichage_boite_dialogue.spacing)) * pourcentage_boite_dialogue_titre
color: "transparent"
Image {
id: image_titre
source: "/images/condition_horaire.png"
sourceSize.height: 80
anchors {
verticalCenter: parent.verticalCenter
horizontalCenter: parent.horizontalCenter
}
}
}
//=========================================================================
// Choix :
//=========================================================================
Rectangle {
id: zone_choix
width: boite_dialogue_condition_horaire.width - (2 * padding_popup)
height: (boite_dialogue_condition_horaire.height - (2 * padding_popup) - (2 * affichage_boite_dialogue.spacing)) * pourcentage_boite_dialogue_message
color: "transparent"
Row {
anchors.horizontalCenter: parent.horizontalCenter
spacing: espace_tumblers
//-----------------------------------
// Jour de la semaine :
//-----------------------------------
Rectangle {
width: zone_choix.width * 0.3
height: zone_choix.height
color: "transparent"
Image {
source: "/images/calendrier.png"
sourceSize.height: hauteur_icones_tumblers
anchors {
top: parent.top
horizontalCenter: parent.horizontalCenter
}
}
Tumbler {
id: tumbler_jour
width: parent.width
height: parent.height * 0.85
anchors {
bottom: parent.bottom
}
visibleItemCount: 5
model: ListModel { }
delegate: bouton_jour
Component {
id: bouton_jour
Rectangle {
color: couleur_gris_fonce
opacity: 1.0 - Math.abs(Tumbler.displacement) / (Tumbler.tumbler.visibleItemCount / 2)
Text {
anchors.fill: parent
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
opacity: 1.0 - Math.abs(Tumbler.displacement) / (Tumbler.tumbler.visibleItemCount / 2)
text: model.libelle
color: (index === tumbler_jour.currentIndex) ? couleur_blanc_casse : couleur_gris_pale
font.pixelSize: 18
font.bold: (index === tumbler_jour.currentIndex)
}
}
}
background: Rectangle {
color: couleur_gris_tres_fonce
radius: shipheart_grand_rayon_bouton
}
}
}
//-----------------------------------
// Heure :
//-----------------------------------
Rectangle {
width: zone_choix.width * 0.3
height: zone_choix.height
color: "transparent"
Image {
source: "/images/heure.png"
sourceSize.height: hauteur_icones_tumblers
anchors {
top: parent.top
horizontalCenter: parent.horizontalCenter
}
}
Tumbler {
id: tumbler_heure
width: parent.width
height: parent.height * 0.85
anchors {
bottom: parent.bottom
}
visibleItemCount: 5
model: ListModel { }
delegate: bouton_heure
Component {
id: bouton_heure
Rectangle {
color: couleur_gris_fonce
opacity: 1.0 - Math.abs(Tumbler.displacement) / (Tumbler.tumbler.visibleItemCount / 2)
Text {
anchors.fill: parent
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
opacity: 1.0 - Math.abs(Tumbler.displacement) / (Tumbler.tumbler.visibleItemCount / 2)
text: model.libelle
color: (index === tumbler_heure.currentIndex) ? couleur_blanc_casse : couleur_gris_pale
font.pixelSize: 18
font.bold: (index === tumbler_heure.currentIndex)
}
}
}
background: Rectangle {
color: couleur_gris_tres_fonce
radius: shipheart_grand_rayon_bouton
}
}
}
//-----------------------------------
// Minute :
//-----------------------------------
Rectangle {
width: zone_choix.width * 0.3
height: zone_choix.height
color: "transparent"
Image {
source: "/images/minute.png"
sourceSize.height: hauteur_icones_tumblers
anchors {
top: parent.top
horizontalCenter: parent.horizontalCenter
}
visible: (tumbler_minute.opacity > 0)
}
Tumbler {
id: tumbler_minute
width: parent.width
height: parent.height * 0.85
anchors {
bottom: parent.bottom
}
visibleItemCount: 5
model: ListModel { }
delegate: bouton_minute
opacity : (tumbler_heure.model.get(tumbler_heure.currentIndex) !== undefined) ? // Sinon, génère un warning au démarrage...
((tumbler_heure.model.get(tumbler_heure.currentIndex).valeur <= 23) ? 1.0 : 0) :
1.0
Behavior on opacity {
NumberAnimation { duration: 300 }
}
Component {
id: bouton_minute
Rectangle {
color: couleur_gris_fonce
opacity: 1.0 - Math.abs(Tumbler.displacement) / (Tumbler.tumbler.visibleItemCount / 2)
Text {
anchors.fill: parent
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
opacity: 1.0 - Math.abs(Tumbler.displacement) / (Tumbler.tumbler.visibleItemCount / 2)
text: model.libelle
color: (index === tumbler_minute.currentIndex) ? couleur_blanc_casse : couleur_gris_pale
font.pixelSize: 18
font.bold: (index === tumbler_minute.currentIndex)
}
}
}
background: Rectangle {
color: couleur_gris_tres_fonce
radius: shipheart_grand_rayon_bouton
}
}
}
}
}
//=========================================================================
// Boutons :
//=========================================================================
Row {
height: (boite_dialogue_condition_horaire.height - (2 * padding_popup) - (2 * affichage_boite_dialogue.spacing)) * pourcentage_boite_dialogue_ligne_boutons
anchors.horizontalCenter: parent.horizontalCenter
spacing: 20
//.......................................................
// Bouton Ok :
//.......................................................
Rectangle {
id: bouton_ok
width: bouton_largeur
height: parent.height * 0.75
anchors.verticalCenter: parent.verticalCenter
radius: shipheart_rayon_bouton
color: couleur_gris_tres_fonce
Label {
id: bouton_ok_label
anchors.centerIn: parent
text: qsTr("OK")
color: couleur_blanc_casse
font.pixelSize:20
}
MouseArea {
anchors.fill: parent
onClicked: {
shipheart_clic();
boite_dialogue_condition_horaire.clicked(shipheart_boite_dialogue_bouton_1,
tumbler_jour.model.get(tumbler_jour.currentIndex).valeur,
tumbler_heure.model.get(tumbler_heure.currentIndex).valeur,
tumbler_minute.model.get(tumbler_minute.currentIndex).valeur);
}
}
}
//.......................................................
// Bouton Annuler :
//.......................................................
Rectangle {
id: bouton_annuler
width: bouton_largeur
height: parent.height * 0.75
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_condition_horaire.clicked(shipheart_boite_dialogue_bouton_2, 0, 0, 0);
}
}
}
//.......................................................
// Bouton de suppression
//.......................................................
Rectangle {
id: bouton_supprimer
width: bouton_largeur
height: parent.height * 0.75
anchors.verticalCenter: parent.verticalCenter
radius: shipheart_rayon_bouton
color: couleur_gris_tres_fonce
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 {
verticalCenter: parent.verticalCenter
horizontalCenter: parent.horizontalCenter
}
font.pixelSize: 20
text: qsTr("Supprimer")
color: couleur_blanc_casse
}
MouseArea {
id: mousearea_bouton_supprimer
anchors.fill: parent
onPressed: { // Déclenché lors de l'appui inital
timer_appui_long.running = true;
valeur_timer_appui_long = 0;
shipheart_clic();
}
onClicked: { // Déclenché si l'appui n'a pas été suffisement long pour avoir un Press&Hold :
timer_appui_long.running = false;
valeur_timer_appui_long = 0;
}
onExited: { // Déclenché si le doigt sort de la zone du bouton (sinon, on continue à compter alors qu'on est sorti de la zone et même relaché le doigt !!)
timer_appui_long.running = false;
valeur_timer_appui_long = 0;
}
}
}
}
}
//=============================================================================================================
// 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 i;
//-------------------------------------
// Jours de la semaine :
//-------------------------------------
tumbler_jour.model.clear();
// "Tous les jours" en premier :
tumbler_jour.model.append( { "valeur": 8, "libelle": Fonctions_date_heure.nom_jour_semaine(8) } );
// Ajout de lundi à dimanche :
for (i = 0; i < 7; i ++)
{
tumbler_jour.model.append( { "valeur": (i+1), "libelle": Fonctions_date_heure.nom_jour_semaine(i+1) } );
}
//-------------------------------------
// Heures :
//-------------------------------------
tumbler_heure.model.clear();
// Heures normales :
for (i = 0; i < 24; i ++)
{
tumbler_heure.model.append( { "valeur": i, "libelle": ((i < 10) ? "0"+i : ""+i)} );
}
// Heures spéciales
// tumbler_heure.model.append( { "valeur": shipheart_heure_speciale_fin_nuit, "libelle": qsTr("Fin de nuit") } );
tumbler_heure.model.append( { "valeur": shipheart_heure_speciale_aube_nautique, "libelle": qsTr("Aube nautique") } );
// tumbler_heure.model.append( { "valeur": shipheart_heure_speciale_aube, "libelle": qsTr("Aube") } );
tumbler_heure.model.append( { "valeur": shipheart_heure_speciale_lever_soleil, "libelle": qsTr("Lever du soleil") } );
tumbler_heure.model.append( { "valeur": shipheart_heure_speciale_zenith, "libelle": qsTr("Zénith") } );
tumbler_heure.model.append( { "valeur": shipheart_heure_speciale_coucher_soleil, "libelle": qsTr("Coucher du soleil") } );
// tumbler_heure.model.append( { "valeur": shipheart_heure_speciale_crepuscule, "libelle": qsTr("Crépuscule") } );
tumbler_heure.model.append( { "valeur": shipheart_heure_speciale_crepuscule_nautique, "libelle": qsTr("Crépuscule nautique") } );
// tumbler_heure.model.append( { "valeur": shipheart_heure_speciale_debut_nuit, "libelle": qsTr("Début de nuit") } );
//-------------------------------------
// Minutes :
//-------------------------------------
tumbler_minute.model.clear();
// Heures normales :
for (i = 0; i < 60; i ++)
{
tumbler_minute.model.append( { "valeur": i, "libelle": ((i < 10) ? "0"+i : ""+i) } );
}
}
//=============================================================================================================
// Mise à jour des données de la boite de dialogue
//=============================================================================================================
function mise_a_jour()
{
var i;
//-------------------------------------
// Jours de la semaine :
//-------------------------------------
// Rercherche de la valeur courante :
for (i = 0; i < tumbler_jour.model.count; i ++)
{
if (tumbler_jour.model.get(i).valeur === valeur_tumbler_jour)
{
tumbler_jour.currentIndex = i;
break;
}
}
//-------------------------------------
// Heures :
//-------------------------------------
// Rercherche de la valeur courante :
for (i = 0; i < tumbler_heure.model.count; i ++)
{
if (tumbler_heure.model.get(i).valeur === valeur_tumbler_heure)
{
tumbler_heure.currentIndex = i;
break;
}
}
//-------------------------------------
// Minutes :
//-------------------------------------
// Rercherche de la valeur courante :
for (i = 0; i < tumbler_minute.model.count; i ++)
{
if (tumbler_minute.model.get(i).valeur === valeur_tumbler_minute)
{
tumbler_minute.currentIndex = i;
break;
}
}
}
}