Files

687 lines
29 KiB
QML

//========================================================================================================================================================================
// CONFIG_PAGE.QML
// Ce fichier traite la configuration d'une page. La page permet notamment de :
// - Modifier la config de la page (ou de le créer la première fois),
// - Supprimer la page
// La page est appelée depuis la page config_pages.qml, en cliquant sur la page à modifier (ou sur le '+' en vue d'une création)
//========================================================================================================================================================================
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQml.Models
import qt.koriolan.shipheart 1.0
Shipheart_page {
id: page_config_page
// Mis en forme :
readonly property double pourcentage_largeur_colonne_gauche: 0.75
readonly property int espace_colonnes_principales: 20
readonly property double pourcentage_largeur_labels_formulaire: 0.5
readonly property double pourcentage_largeur_unites_formulaire: 0.1
readonly property double pourcentage_hauteur_ligne_haut: 1
readonly property int affichage_hauteur_utile: shipheart_hauteur_page - shipheart_hauteur_bandeau_haut - shipheart_hauteur_bandeau_bas
readonly property int espace_lignes_principales: 20
readonly property int hauteur_ligne_formulaire: 60
readonly property int hauteur_bouton_droit: 80
readonly property double pourcentage_bandeau_bas_largeur_zone_retour: 1.0
// Timings :
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
// Affichage :
property bool flag_init: true // Permet de bloquer certains affichage tant que l'init n'est pas terminée
// Données :
property int valeur_timer_appui_long: 0
property int id_page: 0
property string fichier: ""
property int opacite: 0
// Modèles :
// Note : les modèles chargés dans 'main.qml' n'ont pas à être rechargés dans les pages suivantes
//-------------------------------------------------
// Signaux :
//-------------------------------------------------
signal enregistrer_config_page(int new_id_page) // Valeurs à lire lorsque le "OnEnregistrer' est activé
//===========================================================
// 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;
}
else {
}
}
}
//===========================================================
// 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;
// Suppression de la page :
if (mousearea_bouton_supprimer.pressed)
{
if (check_avant_suppression() !== -1)
{
shipheart_clic();
suppression_page(); // Mise à jour des données saisies dans la BDD et reconfiguration par l'application pour prise en compte.
timer_tempo_reconfiguration.restart(); // Lancement du timer pour attendre la fin de la reconfiguration
}
}
}
}
}
//===========================================================
// Lorsque la page est sur le point d'être affichée dans la pile :
//===========================================================
StackView.onActivating: {
init_page();
}
// Titre de la page :
Shipheart_titre_1 {titre: (id_page === 0) ? qsTr("Création d'une page") : qsTr("Configuration de la page"); hauteur: shipheart_hauteur_bandeau_haut}
//-------------------------------------------------------
// Ecran Haut - Gauche :
//-------------------------------------------------------
Rectangle {
id: zone_affichage_haut_gauche
x: 0
y: shipheart_hauteur_bandeau_haut;
width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2)
height: (affichage_hauteur_utile * pourcentage_hauteur_ligne_haut) - (espace_lignes_principales / 2);
color: "transparent"
//=========================
// Liste des champs :
//=========================
ListView {
id: grille_principale
width: parent.width
height: parent.height
snapMode: GridView.SnapToRow // L'arret de l'affichage se fera sur une rangée entière
clip: true // Nécessaire pour que les Delegates s'arretent à l'intérieur de la GridView
model: modele_grille_principale
footer: Rectangle { // Permet de dégager la place suffisante en fin de GridView pour accéder même au dernier élément lorsque que clavier est déplié
height: shipheart_hauteur_clavier
color: "transparent"
}
ObjectModel {
id: modele_grille_principale
//-------------------------------------------------------------------------------
// Ligne de formulaire : Nom
Rectangle {
id: ligne_nom
width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2)
height: visible ? hauteur_ligne_formulaire : 0
color: "transparent"
Shipheart_formulaire_label {
text: qsTr("Nom de la page")
width: parent.width * pourcentage_largeur_labels_formulaire
couleur: (champ_formulaire_Nom.text !== "")
? shipheart_formulaire_couleur_texte_par_defaut
: shipheart_formulaire_couleur_texte_en_erreur
}
Shipheart_formulaire_textfield {
id: champ_formulaire_Nom
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
x: parent.width * pourcentage_largeur_labels_formulaire
}
Shipheart_formulaire_ligne_separation {
haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse
}
}
//-------------------------------------------------------------------------------
// Ligne de formulaire : Opacité
Rectangle {
id: ligne_opacite
width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2)
height: visible ? hauteur_ligne_formulaire : 0
color: "transparent"
visible: (!flag_init)
// && (champ_formulaire_Nom.text !== "")
Shipheart_formulaire_label {
text: qsTr("Opacité de la silhouette")
width: parent.width * pourcentage_largeur_labels_formulaire
couleur: ((opacite > 0) && (opacite <= 100))
? shipheart_formulaire_couleur_texte_par_defaut
: shipheart_formulaire_couleur_texte_en_erreur
}
Shipheart_formulaire_combobox {
id: champ_formulaire_Opacite
model: ListModel { }
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
onActivated: {
shipheart_clic();
opacite = champ_formulaire_Opacite.model.get(champ_formulaire_Opacite.currentIndex).valeur;
}
}
Shipheart_formulaire_ligne_separation {
haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse
}
}
//-------------------------------------------------------------------------------
// Ligne de formulaire : Fichier
Rectangle {
id: ligne_fichier
width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2)
height: visible ? hauteur_ligne_formulaire : 0
color: "transparent"
visible: ligne_opacite.visible
Shipheart_formulaire_label { // Label :
text: qsTr("Fichier de silhouette")
width: parent.width * pourcentage_largeur_labels_formulaire
couleur: shipheart_formulaire_couleur_texte_par_defaut
}
Shipheart_formulaire_valeur_fixe {
id: champ_formulaire_Fichier
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
x: parent.width * pourcentage_largeur_labels_formulaire
}
Shipheart_formulaire_ligne_separation {
haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse
}
}
//---------------------------------------
// Miniature :
Rectangle {
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
height: (6 * hauteur_ligne_formulaire)
x: parent.width * pourcentage_largeur_labels_formulaire
color: "transparent"
visible: !flag_init
Image {
source: (fichier !== "")
? "file://" + shipheart_repertoire_config + shipheart_sous_repertoire_images_silhouette + "/" + fichier
: ""
anchors.fill: parent
fillMode: Image.PreserveAspectFit
anchors {
verticalCenter: parent.verticalCenter
horizontalCenter: parent.horizontalCenter
}
opacity: (opacite / 100)
}
}
}
}
}
//-------------------------------------------------------
// Ecran Droite :
//-------------------------------------------------------
Rectangle {
id: zone_affichage_droite
x: zone_affichage_haut_gauche.width + espace_colonnes_principales
y: shipheart_hauteur_bandeau_haut;
width: (shipheart_largeur_page * (1 - pourcentage_largeur_colonne_gauche)) - (espace_colonnes_principales / 2)
height: (affichage_hauteur_utile * pourcentage_hauteur_ligne_haut) - (espace_lignes_principales / 2);
color: "transparent"
Column {
anchors.fill: parent
spacing: 10
//-------------------------------------------------------
// Bouton Enregistrer/créer :
//-------------------------------------------------------
Rectangle {
id: bouton_enregistrer_creer
width: parent.width
height: hauteur_bouton_droit
color: shipheart_couleur_fond_bouton
radius: shipheart_rayon_bouton
visible:
// !clavier.active && // Si le clavier est déplié, // SDIR #255
(champ_formulaire_Nom.text !== "") // ... ou si le nom n'est pas vide,
&& (opacite > 0) // ... ou si l'opacité est > 0%,
&& (opacite <= 100) // ... ou si l'opacité est <= 100%,
Text {
anchors {
verticalCenter: parent.verticalCenter
horizontalCenter: parent.horizontalCenter
}
font.pixelSize: 20
text: (id_page === 0) ? qsTr("Créer la page") : qsTr("Enregistrer")
color: couleur_blanc_casse
}
MouseArea {
anchors.fill: parent
onClicked: {
shipheart_clic();
if (id_page !== 0) mise_a_jour_page(); // Mise à jour des données saisies dans la BDD et reconfiguration par l'application pour prise en compte.
else creation_page();
timer_tempo_reconfiguration.restart();
}
}
}
//-------------------------------------------------------
// Bouton d'accès à l'éditeur
// NB : On donne l'accès à l'édition même si la page n'est pas encore créé MAIS que toutes les conditions de création sont réunies.
// Dans ce cas, on effectue la création automatiquement avant de donner l'accès à l'édition.
//-------------------------------------------------------
Rectangle {
width: parent.width
height: hauteur_bouton_droit
color: shipheart_couleur_fond_bouton
radius: shipheart_rayon_bouton
visible: bouton_enregistrer_creer.visible
Text {
anchors {
verticalCenter: parent.verticalCenter
horizontalCenter: parent.horizontalCenter
}
font.pixelSize: 20
text: qsTr("Silhouette")
color: couleur_blanc_casse
}
MouseArea {
anchors.fill: parent
onClicked: {
shipheart_clic();
if (id_page === 0) creation_page(); // Si la page n'a pas encore été créé et qu'on demande l'accès à la silhouette, on commence par créer la page
stackView.push("config_fichiers.qml", {"mode_config_fichiers": shipheart_mode_config_fichiers_silhouette,"id_page": id_page})
}
}
}
//-------------------------------------------------------
// Bouton de suppression
//-------------------------------------------------------
Rectangle {
width: parent.width
height: hauteur_bouton_droit
color: shipheart_couleur_fond_bouton
radius: shipheart_rayon_bouton
visible: bouton_enregistrer_creer.visible && (id_page !== 0)
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;
}
}
}
//-------------------------------------------------------
// Timer de reconfiguration :
//-------------------------------------------------------
Timer {
id: timer_tempo_reconfiguration
interval: 250 // Cette tempo n'est utilisée que pour le premier cycle
triggeredOnStart: false
running: false
repeat: true
onTriggered: {
if (bdd.check_fin_configuration())
{
timer_tempo_reconfiguration.stop();
if (id_page !== 0) {
page_config_page.enregistrer_config_page(id_page); // Renvoi la nouvelle valeur de 'id_page' si elle a été modifiée (création ou modification)
stackView.pop(); // Remonte d'une vue, classique.
}
else stackView.pop(stackView.get(stackView.depth - 3)); // Remonte de 2 vues, jusqu'à la 'config_pages' car la création a été annulée ou la page supprimée
}
else timer_tempo_reconfiguration.interval = 100 // Tempo plus courte pour les lectures suivantes
}
}
}
}
//-------------------------------------------------------
// Bandeau bas :
//-------------------------------------------------------
Row {
x: 0
y: shipheart_hauteur_page - shipheart_hauteur_bandeau_bas;
width: shipheart_largeur_page;
height: shipheart_hauteur_bandeau_bas;
spacing: 5
padding: 5
//.................................................
// Bouton retour
//.................................................
Rectangle {
id: bandeau_bas_zone_retour
width: (parent.width * pourcentage_bandeau_bas_largeur_zone_retour) - parent.leftPadding - (parent.spacing / 2)
height: shipheart_hauteur_bandeau_bas - parent.topPadding - parent.bottomPadding;
radius: shipheart_rayon_bouton
color: shipheart_couleur_fond_bouton
Image {
source: "/images/icone_retour.png"
sourceSize.height: 30
anchors {
verticalCenter: parent.verticalCenter
horizontalCenter: parent.horizontalCenter
}
}
MouseArea { // Zone d'interaction. On est obligé de la mettre dans la grille pour que Rectangle et MouseArea soient frères ou parent/enfant ET qu'on n'occupe qu'un espace dans la grille.
id: mouse_area_bandeau_bas_zone_retour
anchors.fill: parent
onClicked: {
shipheart_clic();
if (id_page !== 0) stackView.pop(); // Remonte d'une vue, classique.
else stackView.pop(stackView.get(stackView.depth - 3)); // Remonte de 2 vues, jusqu'à la 'config_pages' car la création a été annulée
}
}
}
}
//-----------------------------------------------espace_lignes_principales--------
// Boite d'info :
//-------------------------------------------------------
Shipheart_boite_dialogue {
id: boite_information
}
//===========================================================
// Busy Indicator :
//===========================================================
Shipheart_busy_indicator {
id: busy_indicator
running: timer_tempo_reconfiguration.running
}
// 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 i;
var liste_valeurs_textes;
//console.log("Id de la page = " + id_page);
//---------------------------------------------------------------------------------------
// Valeurs par défaut :
champ_formulaire_Nom.text = "";
fichier = "";
champ_formulaire_Fichier.text = qsTr("Aucun");
opacite = 50;
//---------------------------------------------------------------------------------------
// Caractéristiques de la page en cours :
if (id_page > 0)
{
req = 'SELECT Nom, ';
// req += ' Type, ';
req += ' Fichier, ';
req += ' Opacite, ';
req += ' Taille, ';
req += ' Offset_x, ';
req += ' Offset_y ';
req += ' FROM TB_Pages ';
req += ' WHERE Cle_primaire=' + id_page + ' ';
//console.log("Requête = [" + req + "]")
res = bdd.requete_unique(req);
// Récupération des données :
i = 0;
champ_formulaire_Nom.text = res[i ++];
// i ++; // Type
fichier = res[i ++];
opacite = Number(res[i ++]);
}
//---------------------------------------------------------------------------------------
// Fichier :
if (fichier === "") champ_formulaire_Fichier.text = qsTr("Aucun");
else champ_formulaire_Fichier.text = fichier;
//---------------------------------------------------------------------------------------
// Opacité :
champ_formulaire_Opacite.model.clear();
for (i = 1; i <= 20; i ++)
{
champ_formulaire_Opacite.model.append({"valeur": (5*i), "texte": ((5*i) + " %") });
}
// Positionnement de l'index sur la valeur en cours :
i = recherche_index_valeur_modele(opacite, champ_formulaire_Opacite.model, "Opacité");
if (i === -1) champ_formulaire_Opacite.currentIndex = 10; // Soit la valeur 50%
else champ_formulaire_Opacite.currentIndex = i;
//---------------------------------------------------------------------------------------
// Fin d'init :
flag_init = false; // Indique que l'init est terminée
}
//=============================================================================================================
// Mise à jour des valeurs saisies de la page
//=============================================================================================================
function mise_a_jour_page()
{
var req, res;
var nom;
nom = champ_formulaire_Nom.text;
// Requete de mise à jour :
req = 'UPDATE TB_Pages SET Nom="' + nom + '" ';
req += ', Opacite=' + opacite + ' ';
req += ' WHERE Cle_primaire=' + id_page + ' '
//console.log("Requête = [" + req + "]")
bdd.requete_unique(req);
}
//=============================================================================================================
// Création de la page
//=============================================================================================================
function creation_page()
{
var req, res;
var nom;
nom = champ_formulaire_Nom.text;
// Requete de création :
req = 'INSERT INTO TB_Pages (Nom';
req += ', Type';
req += ', Opacite';
req += ') ';
req += ' VALUES ("' + nom + '"';
req += ', ' + shipheart_type_page_personnalisee_masquable;
req += ', ' + opacite;
req += ') ';
//console.log("Requête = [" + req + "]")
bdd.requete_unique(req);
// Recherche de l'ID_Page correspondant à la page créée :
req = ' SELECT Cle_primaire FROM TB_Pages ORDER BY Cle_primaire DESC LIMIT 1 ';
//console.log("Requête = [" + req + "]")
res = bdd.requete_unique(req);
id_page = Number(res[0]);
}
//=============================================================================================================
// Check suppression du capteur
//=============================================================================================================
function check_avant_suppression()
{
var message = "";
//=========================================================================
// Recherche de l'impact de cette suppression sur les spécifiques clients :
switch(Number(shipheart_specifique_client[0]))
{
//------------------------------------------------------
default:
case shipheart_specifique_client_tous:
//console.log("Tous les clients")
break;
//------------------------------------------------------
case shipheart_specifique_client_suncy:
//console.log("Client Suncy")
break;
}
//=========================================================================
// Recherche de l'impact de cette suppression en général :
//=========================================================================
// Conclusion :
if (message === "") return(0); // Aucune réserve à supprimer le message....
else // Affichage de la boite de dialogue. La suppression n'est pas autorisée...
{
boite_information.niveau = 2;
boite_information.imageTitreSource = "/images/attention.png"
boite_information.message = message;
boite_information.alignementMessage = Text.AlignLeft
boite_information.open();
return(-1);
}
}
//=============================================================================================================
// Suppression de la page
//=============================================================================================================
function suppression_page()
{
var req;
// Suppression de la page :
req = 'DELETE FROM TB_Pages WHERE Cle_primaire=' + id_page + ' ';
bdd.requete_unique(req);
id_page = 0;
}
//=============================================================================================================
// Recherche de l'index d'une certaine valeur dans un modele
//=============================================================================================================
function recherche_index_valeur_modele(cible, modele, nom_modele)
{
var i;
for (i=0; i<modele.count; i ++)
{
if (modele.get(i).valeur === cible) break; // Cas où la valeur cible a été trouvée parmi les valeurs du modèle
}
if (i === modele.count)
{
console.log("Aucune valeur trouvée pour cible = [" + cible + "] du modèle = " + nom_modele);
i = -1; // Cas où la valeur n'a pas été trouvée parmi les valeurs du modèle
}
//else console.log("Valeur trouvée : [" + i + "] pour cible = [" + cible + "] soit texte = [" + modele.get(i).texte + "]");
return(i);
}
}