Import initial du projet shipheart_cm5
This commit is contained in:
+21
@@ -0,0 +1,21 @@
|
||||
# Dossiers de build CMake/Qt Creator
|
||||
build/
|
||||
CMakeFiles/
|
||||
CMakeCache.txt
|
||||
cmake_install.cmake
|
||||
Makefile
|
||||
Testing/
|
||||
.qt/
|
||||
.qtc_clangd/
|
||||
.qtcreator/
|
||||
|
||||
# Fichier de version régénéré à chaque build (cf generate_version.cmake)
|
||||
_version.h
|
||||
|
||||
# Objets compilés
|
||||
*.o
|
||||
*.obj
|
||||
|
||||
# Fichiers de session/éditeur
|
||||
*.autosave
|
||||
*~
|
||||
+130
@@ -0,0 +1,130 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(shipheart_cm5 LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
|
||||
find_package(Qt6 REQUIRED COMPONENTS
|
||||
Quick
|
||||
VirtualKeyboard
|
||||
Qml
|
||||
Sql
|
||||
QuickControls2
|
||||
Charts
|
||||
LinguistTools
|
||||
)
|
||||
set_target_properties(Qt6::lrelease PROPERTIES
|
||||
IMPORTED_LOCATION /usr/local/bin/lrelease-host
|
||||
IMPORTED_LOCATION_RELEASE /usr/local/bin/lrelease-host
|
||||
IMPORTED_LOCATION_NONE /usr/local/bin/lrelease-host
|
||||
)
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Version dynamique, injectée dans _version.h à CHAQUE build (pas seulement
|
||||
# à chaque reconfiguration CMake), au même format que le .pro d'origine
|
||||
# (yymmdd_HHMMSS, ex: 260807_133409) et avec la même garantie : deux
|
||||
# exécutables différents obtiennent toujours un horodatage différent.
|
||||
#
|
||||
# Mécanisme : une cible personnalisée sans suivi de fichier (add_custom_target
|
||||
# ... ALL, sans dépendance de fichier source) est donc TOUJOURS considérée
|
||||
# périmée par Ninja/Make et se ré-exécute avant chaque build, contrairement à
|
||||
# string(TIMESTAMP ...) seul qui ne s'évalue qu'à la configuration du projet.
|
||||
#
|
||||
# NB IMPORTANT - modification de main.cpp nécessaire : ce mécanisme régénère
|
||||
# le fichier source _version.h - il faut donc que main.cpp fasse
|
||||
# #include "_version.h"
|
||||
# (actuellement absent : VERSION n'y est utilisé que comme macro fournie par
|
||||
# le compilateur). Cet ajout est neutre pour la compilation CM4/qmake (qui
|
||||
# continue de fournir VERSION via DEFINES +=, sans jamais regénérer ni lire
|
||||
# le contenu de _version.h).
|
||||
# ---------------------------------------------------------------------------
|
||||
add_custom_target(generate_version ALL
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-DOUTPUT_FILE=${CMAKE_CURRENT_SOURCE_DIR}/_version.h
|
||||
-P ${CMAKE_CURRENT_SOURCE_DIR}/generate_version.cmake
|
||||
COMMENT "Régénération de _version.h (horodatage)"
|
||||
BYPRODUCTS ${CMAKE_CURRENT_SOURCE_DIR}/_version.h
|
||||
)
|
||||
|
||||
add_executable(shipheart_qt
|
||||
backend.cpp
|
||||
bdd.cpp
|
||||
main.cpp
|
||||
systeme.cpp
|
||||
tb_mesures.cpp
|
||||
# Headers listés pour visibilité dans l'IDE (non obligatoire pour la compilation) :
|
||||
_version.h
|
||||
backend.h
|
||||
bdd.h
|
||||
shipheart.h
|
||||
systeme.h
|
||||
tb_mesures.h
|
||||
# Ressources :
|
||||
qml.qrc
|
||||
traductions.qrc
|
||||
)
|
||||
|
||||
add_dependencies(shipheart_qt generate_version)
|
||||
|
||||
target_link_libraries(shipheart_qt PRIVATE
|
||||
Qt6::Quick
|
||||
Qt6::VirtualKeyboard
|
||||
Qt6::Qml
|
||||
Qt6::Sql
|
||||
Qt6::QuickControls2
|
||||
Qt6::Charts
|
||||
)
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Traductions (équivalent de TRANSLATIONS + lupdate/lrelease du .pro)
|
||||
# ---------------------------------------------------------------------------
|
||||
set(QT_LRELEASE_EXECUTABLE /usr/local/bin/lrelease-host)
|
||||
set(TS_FILES
|
||||
shipheart_fr_FR.ts
|
||||
shipheart_en_EN.ts
|
||||
shipheart_de_DE.ts
|
||||
shipheart_es_ES.ts
|
||||
shipheart_pt_PT.ts
|
||||
shipheart_nl_NL.ts
|
||||
shipheart_it_IT.ts
|
||||
shipheart_lv_LV.ts
|
||||
shipheart_ca_ES.ts
|
||||
)
|
||||
qt_add_translations(shipheart_qt TS_FILES ${TS_FILES})
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Dispositions de clavier virtuel personnalisées (virtualkeyboard_layouts_koriolan)
|
||||
#
|
||||
# RÉSOLU : ces fichiers sont déjà intégralement référencés dans qml.qrc
|
||||
# (confirmé), et chargés au runtime via une ressource Qt embarquée
|
||||
# (qputenv("QT_VIRTUALKEYBOARD_LAYOUT_PATH", ":/virtualkeyboard_layouts_koriolan/layouts")
|
||||
# dans main.cpp). Rien à ajouter ici : qml.qrc est déjà dans la liste des
|
||||
# sources de add_executable() ci-dessus, donc ces fichiers sont embarqués
|
||||
# dans le binaire comme sur CM4.
|
||||
#
|
||||
# Dette technique notée pour plus tard (hors scope de ce portage) : la
|
||||
# duplication complète de tous les layouts Qt (toutes langues, tous modes)
|
||||
# pour la seule modification d'une touche (Espace -> Moins) dans
|
||||
# fallback/digits.qml est disproportionnée. Une solution plus ciblée
|
||||
# existe probablement (héritage partiel des layouts standards), à explorer
|
||||
# séparément - à tester sur CM4 ET CM5 si entreprise, code source commun.
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Installation (équivalent target.path du .pro)
|
||||
# ---------------------------------------------------------------------------
|
||||
install(TARGETS shipheart_qt
|
||||
DESTINATION /home/koriolan/shipheart/versions/current
|
||||
)
|
||||
|
||||
# NB : le mécanisme QMAKE_POST_LINK du .pro d'origine copiait l'exécutable
|
||||
# vers un chemin LOCAL à l'ancien poste de développement Ubuntu
|
||||
# (/home/koriolan/SharePoint_Koriolan_Documents/...) - obsolète dans le
|
||||
# nouveau contexte (compilation croisée WSL2 + déploiement SSH piloté par
|
||||
# Qt Creator). Non repris ici ; à remplacer, si un historique des versions
|
||||
# compilées est toujours souhaité, par un mécanisme côté CM5 ou côté WSL2,
|
||||
# à définir séparément.
|
||||
Executable
+325
@@ -0,0 +1,325 @@
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
|
||||
|
||||
Popup {
|
||||
id: boite_dialogue
|
||||
|
||||
// Propriétés fixes :
|
||||
readonly property double pourcentage_largeur_page_popup: 0.6
|
||||
readonly property double pourcentage_hauteur_page_popup: 0.7
|
||||
readonly property int padding_popup: 50
|
||||
readonly property double pourcentage_boite_dialogue_titre: 0.25
|
||||
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.15
|
||||
readonly property int hauteur_progress_bar: 30
|
||||
|
||||
|
||||
|
||||
readonly property int bouton_largeur: 200
|
||||
|
||||
// Propriétés :
|
||||
property int niveau: 0
|
||||
property string message: "--"
|
||||
property int type: 0 // Utilisé uniquement par la page appelante pour distinguer les différents appels dans la même page
|
||||
|
||||
// Propriétés alias :
|
||||
property alias boutonOk: bouton_ok.visible
|
||||
property alias boutonAnnuler: bouton_annuler.visible
|
||||
property alias boutonPlusTard: bouton_plus_tard.visible
|
||||
property alias boutonOkTexte: bouton_ok_label.text
|
||||
property alias boutonAnnulerTexte: bouton_annuler_label.text
|
||||
property alias boutonPlusTardTexte: bouton_plus_tard_label.text
|
||||
property alias alignementMessage: texte_message.horizontalAlignment
|
||||
property alias progressBarValid: progress_bar.visible
|
||||
property alias progressBarValue: progress_bar.value
|
||||
property alias imageTitreSource: image_titre.source
|
||||
property alias affichageAscenseur: ascenseur.visible
|
||||
|
||||
|
||||
// Signaux :
|
||||
signal clicked(int bouton) // Valeur à lire lorsque le "OnClicked' est activé
|
||||
|
||||
|
||||
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 {
|
||||
radius: 20
|
||||
color: {
|
||||
switch(boite_dialogue.niveau)
|
||||
{
|
||||
default:
|
||||
case 0: color: shipheart_couleur_fond_boite_dialogue_niveau_0; break;
|
||||
case 1: color: shipheart_couleur_fond_boite_dialogue_niveau_1; break;
|
||||
case 2: color: shipheart_couleur_fond_boite_dialogue_niveau_2; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
id: affichage_boite_dialogue
|
||||
|
||||
spacing: 20
|
||||
|
||||
//=========================================================================
|
||||
// Titre :
|
||||
//=========================================================================
|
||||
Rectangle {
|
||||
id: titre_boite_dialogue
|
||||
|
||||
width: boite_dialogue.width - (2 * padding_popup)
|
||||
height: (boite_dialogue.height - (2 * padding_popup) - (2 * affichage_boite_dialogue.spacing)) * pourcentage_boite_dialogue_titre
|
||||
color: "transparent"
|
||||
|
||||
Image {
|
||||
id: image_titre
|
||||
source: ""
|
||||
sourceSize.height: parent.height
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
visible: true
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// Message :
|
||||
//=========================================================================
|
||||
Rectangle {
|
||||
id: message_boite_dialogue
|
||||
|
||||
width: boite_dialogue.width - (2 * padding_popup)
|
||||
height: (boite_dialogue.height - (2 * padding_popup) - (2 * affichage_boite_dialogue.spacing)) * pourcentage_boite_dialogue_message
|
||||
color: "transparent"
|
||||
|
||||
Flickable {
|
||||
anchors.fill: parent
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
contentWidth: texte_message.width
|
||||
contentHeight: texte_message.height
|
||||
flickableDirection: Flickable.VerticalFlick
|
||||
clip: true
|
||||
|
||||
ScrollBar.vertical: ScrollBar { // Important car permet de voir que la partie affichée n'est pas complète dans le message...
|
||||
id: ascenseur
|
||||
policy: ScrollBar.AlwaysOn
|
||||
width: 10
|
||||
visible: false
|
||||
}
|
||||
|
||||
TextEdit {
|
||||
id: texte_message
|
||||
width: message_boite_dialogue.width - ascenseur.width - 5 // Le '-5' permet de détacher le texte de l'ascenseur
|
||||
height: Math.max(message_boite_dialogue.height, implicitHeight) // Permet d'avoir la hauteur de la zone si le texte est "court" (et donc de centrer verticalement) puis la hauteur totale si le texte est "long" (et pouvoir se déplacer vers la fin et pas centré sur le milieu !)
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
readOnly:true
|
||||
wrapMode: Text.Wrap
|
||||
textFormat: Text.RichText
|
||||
text: boite_dialogue.message
|
||||
color: {
|
||||
switch(boite_dialogue.niveau)
|
||||
{
|
||||
default:
|
||||
case 0: shipheart_couleur_texte_boite_dialogue_niveau_0; break;
|
||||
case 1: shipheart_couleur_texte_boite_dialogue_niveau_1; break;
|
||||
case 2: shipheart_couleur_texte_boite_dialogue_niveau_2; break;
|
||||
}
|
||||
}
|
||||
font.pixelSize:18
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// Barre d'avancement :
|
||||
//=========================================================================
|
||||
ProgressBar {
|
||||
id: progress_bar
|
||||
width: parent.width
|
||||
visible: false // Par défaut
|
||||
|
||||
background: Rectangle {
|
||||
implicitWidth: parent.width
|
||||
implicitHeight: hauteur_progress_bar
|
||||
color: "transparent"
|
||||
border.color: couleur_gris_moyen
|
||||
border.width: 2
|
||||
radius: shipheart_rayon_bouton
|
||||
|
||||
Text {
|
||||
text: (progress_bar.value * 100).toFixed(0) + "%"
|
||||
anchors.fill: parent
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
color: {
|
||||
switch(boite_dialogue.niveau)
|
||||
{
|
||||
default:
|
||||
case 0: couleur_blanc_casse; break;
|
||||
case 1: couleur_blanc_casse; break;
|
||||
case 2: couleur_blanc_casse; break;
|
||||
}
|
||||
}
|
||||
font.pixelSize:18
|
||||
font.weight: Font.Bold
|
||||
}
|
||||
}
|
||||
|
||||
contentItem: Item {
|
||||
implicitWidth: parent.width
|
||||
implicitHeight: hauteur_progress_bar
|
||||
|
||||
Rectangle {
|
||||
width: progress_bar.value * parent.width
|
||||
height: parent.height
|
||||
radius: shipheart_rayon_bouton
|
||||
color: shipheart_couleur_fond_bouton_actif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// Boutons :
|
||||
//=========================================================================
|
||||
Row {
|
||||
height: (boite_dialogue.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
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
radius: shipheart_rayon_bouton
|
||||
color: couleur_gris_tres_fonce
|
||||
visible: true
|
||||
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.clicked(shipheart_boite_dialogue_bouton_1);
|
||||
boite_dialogue.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Bouton Annuler :
|
||||
Rectangle {
|
||||
id: bouton_annuler
|
||||
|
||||
width: bouton_largeur
|
||||
height: parent.height
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
radius: shipheart_rayon_bouton
|
||||
color: couleur_gris_tres_fonce
|
||||
visible: false
|
||||
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.clicked(shipheart_boite_dialogue_bouton_2);
|
||||
boite_dialogue.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Bouton Plus Tard :
|
||||
Rectangle {
|
||||
id: bouton_plus_tard
|
||||
|
||||
width: bouton_largeur
|
||||
height: parent.height
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
radius: shipheart_rayon_bouton
|
||||
color: couleur_gris_tres_fonce
|
||||
visible: false
|
||||
Label {
|
||||
id: bouton_plus_tard_label
|
||||
anchors.centerIn: parent
|
||||
text: qsTr("Plus tard")
|
||||
color: couleur_blanc_casse
|
||||
font.pixelSize:20
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
boite_dialogue.clicked(shipheart_boite_dialogue_bouton_3);
|
||||
boite_dialogue.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Executable
+411
@@ -0,0 +1,411 @@
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
|
||||
Popup {
|
||||
id: boite_dialogue_action_circuit
|
||||
|
||||
// Propriétés fixes :
|
||||
readonly property double pourcentage_largeur_page_popup: 0.8
|
||||
readonly property double pourcentage_hauteur_page_popup: 0.7
|
||||
readonly property int padding_popup: 20
|
||||
readonly property double pourcentage_boite_dialogue_titre: 0.3
|
||||
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.3
|
||||
|
||||
readonly property int bouton_largeur: 200
|
||||
readonly property int largeur_grand_bouton_action: (largeur_petit_bouton_action * 2) + espace_boutons
|
||||
readonly property int largeur_petit_bouton_action: 140
|
||||
readonly property int espace_boutons: 5
|
||||
|
||||
// Propriétés :
|
||||
property string nom_circuit: ""
|
||||
property int action_en_cours: -2
|
||||
property int mode_cde: 0
|
||||
|
||||
// Propriétés alias :
|
||||
property alias boutonAnnuler: bouton_annuler.visible
|
||||
property alias boutonAnnulerTexte: bouton_annuler_label.text
|
||||
|
||||
// Signaux :
|
||||
signal clicked(int bouton, int action) // Valeur à lire lorsque le "OnClicked' est activé
|
||||
|
||||
|
||||
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_action_circuit.width - (2 * padding_popup)
|
||||
height: (boite_dialogue_action_circuit.height - (2 * padding_popup) - (2 * affichage_boite_dialogue.spacing)) * pourcentage_boite_dialogue_titre
|
||||
color: "transparent"
|
||||
|
||||
Label {
|
||||
text: nom_circuit
|
||||
anchors.fill: parent
|
||||
verticalAlignment: Text.AlignTop
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
topPadding: 20
|
||||
wrapMode: Text.Wrap
|
||||
color: couleur_blanc_casse
|
||||
font.pixelSize:40
|
||||
font.weight: Font.Bold
|
||||
}
|
||||
Label {
|
||||
text: qsTr("Action à appliquer au circuit lorsque l'évènement se déclenche :")
|
||||
anchors.fill: parent
|
||||
verticalAlignment: Text.AlignBottom
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
bottomPadding: 20
|
||||
wrapMode: Text.Wrap
|
||||
color: couleur_blanc_casse
|
||||
font.pixelSize:18
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// Choix de l'action :
|
||||
//=========================================================================
|
||||
Rectangle {
|
||||
width: boite_dialogue_action_circuit.width - (2 * padding_popup)
|
||||
height: (boite_dialogue_action_circuit.height - (2 * padding_popup) - (2 * affichage_boite_dialogue.spacing)) * pourcentage_boite_dialogue_message
|
||||
color: "transparent"
|
||||
|
||||
//------------------------------------
|
||||
// Ligne des actions générales :
|
||||
Row {
|
||||
anchors {
|
||||
top: parent.top
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
height: (parent.height / 2) - (spacing / 2)
|
||||
spacing: espace_boutons
|
||||
|
||||
// Bouton Aucune action :
|
||||
Rectangle {
|
||||
property int val: -2
|
||||
width: largeur_grand_bouton_action
|
||||
height: parent.height
|
||||
radius: shipheart_rayon_bouton
|
||||
color: (action_en_cours === val) ? couleur_gris_fonce : couleur_gris_tres_fonce
|
||||
Label {
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Qt.AlignHCenter
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
text: qsTr("Aucune")
|
||||
font.pixelSize: 18
|
||||
color: (action_en_cours === parent.val) ? couleur_green_yellow : couleur_blanc_casse
|
||||
font.weight: (action_en_cours === parent.val) ? Font.Bold : Font.Normal
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
boite_dialogue_action_circuit.clicked(shipheart_boite_dialogue_bouton_1, parent.val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Bouton Bascule :
|
||||
Rectangle {
|
||||
property int val: -1
|
||||
width: largeur_grand_bouton_action
|
||||
height: parent.height
|
||||
radius: shipheart_rayon_bouton
|
||||
color: (action_en_cours === val) ? couleur_gris_fonce : couleur_gris_tres_fonce
|
||||
Label {
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Qt.AlignHCenter
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
topPadding: -(parent.height * 0.3)
|
||||
text: qsTr("Le circuit <b>bascule</b>")
|
||||
font.pixelSize: 18
|
||||
color: (action_en_cours === parent.val) ? couleur_green_yellow : couleur_blanc_casse
|
||||
font.weight: (action_en_cours === parent.val) ? Font.Bold : Font.Normal
|
||||
}
|
||||
Label { // Complment de texte en dessous du titre de bouton proprement-dit.
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Qt.AlignHCenter
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
topPadding: (parent.height * 0.3)
|
||||
text: qsTr("[passe à <b>ON</b> s'il est <b>OFF</b><br /> ou à <b>OFF</b> s'il est <b>ON</b>]")
|
||||
font.pixelSize: 15
|
||||
// color: (action_en_cours === parent.val) ? couleur_green_yellow : couleur_gris_pale
|
||||
color: couleur_gris_pale
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
boite_dialogue_action_circuit.clicked(shipheart_boite_dialogue_bouton_1, parent.val);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------
|
||||
// Ligne des consignes spécifiques :
|
||||
Row {
|
||||
anchors {
|
||||
bottom: parent.bottom
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
|
||||
height: (parent.height / 2) - (spacing / 2)
|
||||
spacing: espace_boutons
|
||||
|
||||
// Bouton OFF :
|
||||
Rectangle {
|
||||
property int val: 0
|
||||
width: (mode_cde === shipheart_mode_commande_circuit_soft_variable) ? largeur_petit_bouton_action : largeur_grand_bouton_action
|
||||
height: parent.height
|
||||
radius: shipheart_rayon_bouton
|
||||
color: (action_en_cours === 0) ? couleur_gris_fonce : couleur_gris_tres_fonce
|
||||
Label {
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Qt.AlignHCenter
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
text: qsTr("OFF")
|
||||
font.pixelSize: 18
|
||||
color: (action_en_cours === parent.val) ? couleur_green_yellow : couleur_blanc_casse
|
||||
font.weight: (action_en_cours === parent.val) ? Font.Bold : Font.Normal
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
boite_dialogue_action_circuit.clicked(shipheart_boite_dialogue_bouton_1, parent.val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Bouton 10% :
|
||||
Rectangle {
|
||||
property int val: 10
|
||||
width: largeur_petit_bouton_action
|
||||
height: parent.height
|
||||
radius: shipheart_rayon_bouton
|
||||
color: (action_en_cours === val) ? couleur_gris_fonce : couleur_gris_tres_fonce
|
||||
visible: (mode_cde === shipheart_mode_commande_circuit_soft_variable)
|
||||
Label {
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Qt.AlignHCenter
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
text: parent.val + "%"
|
||||
font.pixelSize: 18
|
||||
color: (action_en_cours === parent.val) ? couleur_green_yellow : couleur_blanc_casse
|
||||
font.weight: (action_en_cours === parent.val) ? Font.Bold : Font.Normal
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
boite_dialogue_action_circuit.clicked(shipheart_boite_dialogue_bouton_1, parent.val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Bouton 25% :
|
||||
Rectangle {
|
||||
property int val: 25
|
||||
width: largeur_petit_bouton_action
|
||||
height: parent.height
|
||||
radius: shipheart_rayon_bouton
|
||||
color: (action_en_cours === val) ? couleur_gris_fonce : couleur_gris_tres_fonce
|
||||
visible: (mode_cde === shipheart_mode_commande_circuit_soft_variable)
|
||||
Label {
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Qt.AlignHCenter
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
text: parent.val + "%"
|
||||
font.pixelSize: 18
|
||||
color: (action_en_cours === parent.val) ? couleur_green_yellow : couleur_blanc_casse
|
||||
font.weight: (action_en_cours === parent.val) ? Font.Bold : Font.Normal
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
boite_dialogue_action_circuit.clicked(shipheart_boite_dialogue_bouton_1, parent.val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Bouton 50% :
|
||||
Rectangle {
|
||||
property int val: 50
|
||||
width: largeur_petit_bouton_action
|
||||
height: parent.height
|
||||
radius: shipheart_rayon_bouton
|
||||
color: (action_en_cours === val) ? couleur_gris_fonce : couleur_gris_tres_fonce
|
||||
visible: (mode_cde === shipheart_mode_commande_circuit_soft_variable)
|
||||
Label {
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Qt.AlignHCenter
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
text: parent.val + "%"
|
||||
font.pixelSize: 18
|
||||
color: (action_en_cours === parent.val) ? couleur_green_yellow : couleur_blanc_casse
|
||||
font.weight: (action_en_cours === parent.val) ? Font.Bold : Font.Normal
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
boite_dialogue_action_circuit.clicked(shipheart_boite_dialogue_bouton_1, parent.val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Bouton 75% :
|
||||
Rectangle {
|
||||
property int val: 75
|
||||
width: largeur_petit_bouton_action
|
||||
height: parent.height
|
||||
radius: shipheart_rayon_bouton
|
||||
color: (action_en_cours === val) ? couleur_gris_fonce : couleur_gris_tres_fonce
|
||||
visible: (mode_cde === shipheart_mode_commande_circuit_soft_variable)
|
||||
Label {
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Qt.AlignHCenter
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
text: parent.val + "%"
|
||||
font.pixelSize: 18
|
||||
color: (action_en_cours === parent.val) ? couleur_green_yellow : couleur_blanc_casse
|
||||
font.weight: (action_en_cours === parent.val) ? Font.Bold : Font.Normal
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
boite_dialogue_action_circuit.clicked(shipheart_boite_dialogue_bouton_1, parent.val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Bouton ON :
|
||||
Rectangle {
|
||||
property int val: 100
|
||||
width: (mode_cde === shipheart_mode_commande_circuit_soft_variable) ? largeur_petit_bouton_action : largeur_grand_bouton_action
|
||||
height: parent.height
|
||||
radius: shipheart_rayon_bouton
|
||||
color: (action_en_cours === 100) ? couleur_gris_fonce : couleur_gris_tres_fonce
|
||||
Label {
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Qt.AlignHCenter
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
// text: qsTr("ON") + ((mode_cde === shipheart_mode_commande_circuit_soft_variable) ? "<br />100%" : "")
|
||||
text: qsTr("ON")
|
||||
font.pixelSize: 18
|
||||
color: (action_en_cours === parent.val) ? couleur_green_yellow : couleur_blanc_casse
|
||||
font.weight: (action_en_cours === parent.val) ? Font.Bold : Font.Normal
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
boite_dialogue_action_circuit.clicked(shipheart_boite_dialogue_bouton_1, parent.val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// Boutons :
|
||||
//=========================================================================
|
||||
Row {
|
||||
height: (boite_dialogue_action_circuit.height - (2 * padding_popup) - (2 * affichage_boite_dialogue.spacing)) * pourcentage_boite_dialogue_ligne_boutons
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
spacing: 20
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Bouton Annuler :
|
||||
Rectangle {
|
||||
id: bouton_annuler
|
||||
|
||||
width: bouton_largeur
|
||||
height: parent.height * 0.5
|
||||
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_action_circuit.clicked(shipheart_boite_dialogue_bouton_2, 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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,292 @@
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
|
||||
Popup {
|
||||
id: boite_dialogue_affichage_duree
|
||||
|
||||
// Propriétés fixes :
|
||||
readonly property double pourcentage_hauteur_page_popup: 0.7
|
||||
readonly property double pourcentage_hauteur_titre: 0.3
|
||||
readonly property double pourcentage_hauteur_compteur: 1 - pourcentage_hauteur_titre - pourcentage_hauteur_bargraph - pourcentage_hauteur_ligne_boutons
|
||||
readonly property double pourcentage_hauteur_bargraph: 0.07
|
||||
readonly property double pourcentage_hauteur_ligne_boutons: 0.25
|
||||
readonly property int bouton_hauteur: 60
|
||||
readonly property int hauteur_progress_bar: 30
|
||||
|
||||
readonly property double pourcentage_largeur_page_popup: 0.8
|
||||
readonly property int bouton_largeur: 200
|
||||
|
||||
readonly property int padding_popup: 20
|
||||
|
||||
readonly property int periode_raffraichissement_parametres: 100 // En ms
|
||||
readonly property int step_timer_appui_long: 30 // en ms
|
||||
|
||||
// Propriétés :
|
||||
property int compteur: 0
|
||||
property int diviseur: 1
|
||||
property string libelle_compteur_initial: ""
|
||||
|
||||
property string type: "minuteur" // Soit "chrono", soit "minuteur"
|
||||
|
||||
|
||||
// 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...
|
||||
timer_raffraichissement_parametres.start();
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// Fermeture :
|
||||
//-------------------------------------------------
|
||||
onAboutToHide: {
|
||||
timer_raffraichissement_parametres.stop();
|
||||
}
|
||||
|
||||
//===========================================================
|
||||
// Timer periode raffraichissement parametres :
|
||||
//===========================================================
|
||||
Timer {
|
||||
id: timer_raffraichissement_parametres
|
||||
interval: periode_raffraichissement_parametres
|
||||
triggeredOnStart: false
|
||||
running: false
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
mise_a_jour()
|
||||
}
|
||||
}
|
||||
|
||||
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_affichage_duree.width - (2 * padding_popup)
|
||||
height: (boite_dialogue_affichage_duree.height - (2 * padding_popup) - (2 * affichage_boite_dialogue.spacing)) * pourcentage_hauteur_titre
|
||||
color: "transparent"
|
||||
|
||||
Image {
|
||||
id: image_titre
|
||||
source: ""
|
||||
sourceSize.height: 120
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
visible: true
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// Zone principale :
|
||||
//=========================================================================
|
||||
Rectangle {
|
||||
id: zone_principale
|
||||
width: boite_dialogue_affichage_duree.width - (2 * padding_popup)
|
||||
height: (boite_dialogue_affichage_duree.height - (2 * padding_popup) - (3 * affichage_boite_dialogue.spacing)) * pourcentage_hauteur_compteur
|
||||
color: "transparent"
|
||||
|
||||
Label {
|
||||
text: Math.trunc(compteur / (60 * 60 * diviseur)).toString().padStart(2, '0') + ":" + Math.trunc((compteur / (60 * diviseur)) % 60).toString().padStart(2, '0') + ":" + Math.trunc((compteur / diviseur) % 60).toString().padStart(2, '0') + ((diviseur > 1) ? ("," + (compteur % diviseur)) : "")
|
||||
anchors.fill: parent
|
||||
verticalAlignment: Text.AlignBottom
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
wrapMode: Text.Wrap
|
||||
color: couleur_blanc_casse
|
||||
font.pixelSize:150
|
||||
font.weight: Font.Bold
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// Barre d'avancement :
|
||||
//=========================================================================
|
||||
ProgressBar {
|
||||
id: progress_bar
|
||||
width: parent.width
|
||||
height: (boite_dialogue_affichage_duree.height - (2 * padding_popup) - (3 * affichage_boite_dialogue.spacing)) * pourcentage_hauteur_bargraph
|
||||
value: (page_accueil.compteur_initial_minuteur !== 0) ? (compteur_minuteur / page_accueil.compteur_initial_minuteur) : 0
|
||||
visible: type === "minuteur"
|
||||
|
||||
background: Rectangle {
|
||||
implicitWidth: parent.width
|
||||
implicitHeight: hauteur_progress_bar
|
||||
color: shipheart_couleur_fond_bouton //"transparent"
|
||||
radius: shipheart_rayon_bouton
|
||||
|
||||
Text {
|
||||
// text: (progress_bar.value * 100).toFixed(0) + "%"
|
||||
text: "[ " + libelle_compteur_initial + " ]"
|
||||
anchors.fill: parent
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
color: shipheart_couleur_texte_slider
|
||||
font.pixelSize:18
|
||||
font.weight: Font.Bold
|
||||
}
|
||||
}
|
||||
|
||||
contentItem: Item {
|
||||
implicitWidth: parent.width
|
||||
implicitHeight: hauteur_progress_bar
|
||||
|
||||
Rectangle {
|
||||
width: progress_bar.value * parent.width
|
||||
height: parent.height
|
||||
radius: shipheart_rayon_bouton
|
||||
color: shipheart_couleur_fond_bouton_actif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//=========================================================================
|
||||
// Boutons de bas de fenêtre :
|
||||
//=========================================================================
|
||||
Row {
|
||||
height: (boite_dialogue_affichage_duree.height - (2 * padding_popup) - (3 * affichage_boite_dialogue.spacing)) * pourcentage_hauteur_ligne_boutons
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
spacing: 20
|
||||
|
||||
//.......................................................
|
||||
// Bouton Ok :
|
||||
//.......................................................
|
||||
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("Ok")
|
||||
color: couleur_blanc_casse
|
||||
font.pixelSize:20
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
boite_dialogue_affichage_duree.clicked(shipheart_boite_dialogue_bouton_1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================================================
|
||||
// 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()
|
||||
{
|
||||
|
||||
if (type === "chrono")
|
||||
{
|
||||
image_titre.source = "/images/chronometre.png"
|
||||
diviseur = 10;
|
||||
}
|
||||
else if (type === "minuteur")
|
||||
{
|
||||
image_titre.source = "/images/sablier.png"
|
||||
diviseur = 1;
|
||||
libelle_compteur_initial = Math.trunc(page_accueil.compteur_initial_minuteur / (60 * 60 * diviseur)).toString().padStart(2, '0') + ":" + Math.trunc((page_accueil.compteur_initial_minuteur / (60 * diviseur)) % 60).toString().padStart(2, '0') + ":" + Math.trunc((page_accueil.compteur_initial_minuteur / diviseur) % 60).toString().padStart(2, '0')
|
||||
}
|
||||
|
||||
mise_a_jour();
|
||||
|
||||
}
|
||||
|
||||
//=============================================================================================================
|
||||
// Mise à jour des données de la boite de dialogue
|
||||
//=============================================================================================================
|
||||
function mise_a_jour()
|
||||
{
|
||||
|
||||
if (type === "chrono")
|
||||
{
|
||||
compteur = page_accueil.compteur_chrono;
|
||||
}
|
||||
else if (type === "minuteur")
|
||||
{
|
||||
compteur = page_accueil.compteur_minuteur;
|
||||
}
|
||||
if (compteur <= 0) boite_dialogue_affichage_duree.close(); // A l'expiration du compteur, on ferme la boite dans tous les cas.
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
+577
@@ -0,0 +1,577 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
Executable
+234
@@ -0,0 +1,234 @@
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
|
||||
Popup {
|
||||
id: boite_dialogue_entrees_aux
|
||||
|
||||
// Propriétés fixes :
|
||||
readonly property double pourcentage_largeur_page_popup: 0.95
|
||||
readonly property double pourcentage_hauteur_page_popup: 0.7
|
||||
readonly property int padding_popup: 20
|
||||
readonly property double pourcentage_boite_dialogue_titre: 0.3
|
||||
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.3
|
||||
|
||||
|
||||
readonly property int bouton_largeur: 200
|
||||
|
||||
// Propriétés :
|
||||
|
||||
// Propriétés alias :
|
||||
property alias boutonAnnuler: bouton_annuler.visible
|
||||
property alias boutonAnnulerTexte: bouton_annuler_label.text
|
||||
|
||||
property string nom_equipement: ""
|
||||
|
||||
// Signaux :
|
||||
signal clicked(int bouton, int no_entree) // Valeur à lire lorsque le "OnClicked' est activé
|
||||
|
||||
|
||||
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_entrees_aux.width - (2 * padding_popup)
|
||||
height: (boite_dialogue_entrees_aux.height - (2 * padding_popup) - (2 * affichage_boite_dialogue.spacing)) * pourcentage_boite_dialogue_titre
|
||||
color: "transparent"
|
||||
|
||||
Label {
|
||||
text: qsTr("Entrées Auxiliaires")
|
||||
anchors.fill: parent
|
||||
verticalAlignment: Text.AlignTop
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
topPadding: 20
|
||||
wrapMode: Text.Wrap
|
||||
color: couleur_blanc_casse
|
||||
font.pixelSize:40
|
||||
font.weight: Font.Bold
|
||||
}
|
||||
Label {
|
||||
text: qsTr("Affectation de l'entrée n° %1 du %2").arg(entree_en_cours).arg(nom_equipement)
|
||||
anchors.fill: parent
|
||||
verticalAlignment: Text.AlignBottom
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
bottomPadding: 20
|
||||
wrapMode: Text.Wrap
|
||||
color: couleur_blanc_casse
|
||||
font.pixelSize:18
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// Choix de l'entrée :
|
||||
//=========================================================================
|
||||
Rectangle {
|
||||
width: boite_dialogue_entrees_aux.width - (2 * padding_popup)
|
||||
height: (boite_dialogue_entrees_aux.height - (2 * padding_popup) - (2 * affichage_boite_dialogue.spacing)) * pourcentage_boite_dialogue_message
|
||||
color: "transparent"
|
||||
|
||||
Grid {
|
||||
id: grille_entrees_aux
|
||||
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
columns: 4
|
||||
spacing: 20
|
||||
Repeater { // Constitue les blocs d'entrées, telq qu'ils sont physiquement (4 entrées + espace)
|
||||
model: modele_entrees_aux
|
||||
delegate: Row {
|
||||
width: (parent.width - (3 * grille_entrees_aux.spacing)) / 4
|
||||
height: (parent.height - grille_entrees_aux.spacing) / 2
|
||||
|
||||
Repeater { // Constitue les 4 entrées par bloc
|
||||
model: valeurs
|
||||
delegate: Rectangle { // Ce rectangle réserve la place pour chaque bouton mais n'est pas visible
|
||||
width: parent.width / 4
|
||||
height: parent.height
|
||||
color: "transparent"
|
||||
|
||||
Rectangle { // Ce rectangle est le bouton visible, légèrement plus petit que son père pour réserver un espace entre chaque entrée au sein du même bloc
|
||||
width: parent.width * 0.98
|
||||
height: parent.height
|
||||
|
||||
radius: shipheart_rayon_bouton
|
||||
color: ((model.used === 1) && (model.no_entree !== entree_en_cours)) ? couleur_gris_fonce : couleur_gris_tres_fonce
|
||||
Label {
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Qt.AlignHCenter
|
||||
verticalAlignment: Qt.AlignTop
|
||||
topPadding: 20
|
||||
text: no
|
||||
color: (model.used === 0) ? couleur_blanc_casse : couleur_gris_moyen
|
||||
font.pixelSize: 18
|
||||
font.bold: true
|
||||
}
|
||||
Label {
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Qt.AlignHCenter
|
||||
verticalAlignment: Qt.AlignBottom
|
||||
bottomPadding: 20
|
||||
visible: model.no_entree !== 0
|
||||
text: model.no_entree
|
||||
color: couleur_green_yellow
|
||||
font.pixelSize: 18
|
||||
font.bold: true
|
||||
}
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
enabled: (model.used === 0) || (model.no_entree === entree_en_cours)
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
boite_dialogue_entrees_aux.clicked(shipheart_boite_dialogue_bouton_1, no);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// Boutons :
|
||||
//=========================================================================
|
||||
Row {
|
||||
height: (boite_dialogue_entrees_aux.height - (2 * padding_popup) - (2 * affichage_boite_dialogue.spacing)) * pourcentage_boite_dialogue_ligne_boutons
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
spacing: 20
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Bouton Annuler :
|
||||
Rectangle {
|
||||
id: bouton_annuler
|
||||
|
||||
width: bouton_largeur
|
||||
height: parent.height * 0.5
|
||||
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_entrees_aux.clicked(shipheart_boite_dialogue_bouton_2, 0);
|
||||
boite_dialogue_entrees_aux.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//=============================================================================================================
|
||||
// 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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+229
@@ -0,0 +1,229 @@
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
|
||||
Popup {
|
||||
id: boite_dialogue_entrees_level_sensor
|
||||
|
||||
// Propriétés fixes :
|
||||
readonly property double pourcentage_largeur_page_popup: 0.8
|
||||
readonly property double pourcentage_hauteur_page_popup: 0.7
|
||||
readonly property int padding_popup: 20
|
||||
readonly property double pourcentage_boite_dialogue_titre: 0.3
|
||||
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.3
|
||||
|
||||
|
||||
readonly property int bouton_largeur: 200
|
||||
|
||||
// Propriétés :
|
||||
|
||||
// Propriétés alias :
|
||||
property alias boutonAnnuler: bouton_annuler.visible
|
||||
property alias boutonAnnulerTexte: bouton_annuler_label.text
|
||||
|
||||
// Signaux :
|
||||
signal clicked(int bouton, int no_entree) // Valeur à lire lorsque le "OnClicked' est activé
|
||||
|
||||
|
||||
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_entrees_level_sensor.width - (2 * padding_popup)
|
||||
height: (boite_dialogue_entrees_level_sensor.height - (2 * padding_popup) - (2 * affichage_boite_dialogue.spacing)) * pourcentage_boite_dialogue_titre
|
||||
color: "transparent"
|
||||
|
||||
Label {
|
||||
text: qsTr("Entrées Level Sensor")
|
||||
anchors.fill: parent
|
||||
verticalAlignment: Text.AlignTop
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
topPadding: 20
|
||||
wrapMode: Text.Wrap
|
||||
color: couleur_blanc_casse
|
||||
font.pixelSize:40
|
||||
font.weight: Font.Bold
|
||||
}
|
||||
Label {
|
||||
text: qsTr("Affectation de l'entrée du réservoir")
|
||||
anchors.fill: parent
|
||||
verticalAlignment: Text.AlignBottom
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
bottomPadding: 20
|
||||
wrapMode: Text.Wrap
|
||||
color: couleur_blanc_casse
|
||||
font.pixelSize:18
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// Choix de l'entrée :
|
||||
//=========================================================================
|
||||
Rectangle {
|
||||
width: boite_dialogue_entrees_level_sensor.width - (2 * padding_popup)
|
||||
height: (boite_dialogue_entrees_level_sensor.height - (2 * padding_popup) - (2 * affichage_boite_dialogue.spacing)) * pourcentage_boite_dialogue_message
|
||||
color: "transparent"
|
||||
|
||||
Grid {
|
||||
id: grille_entrees_level_sensor
|
||||
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
columns: 1
|
||||
spacing: 20
|
||||
Repeater { // Constitue les blocs d'entrées, telq qu'ils sont physiquement (4 entrées + espace)
|
||||
model: modele_entrees_level_sensor
|
||||
delegate: Row {
|
||||
width: (parent.width - ((grille_entrees_level_sensor.columns - 1) * grille_entrees_level_sensor.spacing)) / grille_entrees_level_sensor.columns
|
||||
height: (parent.height - grille_entrees_level_sensor.spacing) / 2
|
||||
|
||||
Repeater { // Constitue les 4 entrées par bloc
|
||||
model: valeurs
|
||||
delegate: Rectangle { // Ce rectangle réserve la place pour chaque bouton mais n'est pas visible
|
||||
width: parent.width / 4
|
||||
height: parent.height
|
||||
color: "transparent"
|
||||
|
||||
Rectangle { // Ce rectangle est le bouton visible, légèrement plus petit que son père pour réserver un espace entre chaque entrée au sein du même bloc
|
||||
width: parent.width * 0.98
|
||||
height: parent.height
|
||||
|
||||
radius: shipheart_rayon_bouton
|
||||
color: ((model.used === 1) && (model.no_entree !== entree_en_cours)) ? couleur_gris_fonce : couleur_gris_tres_fonce
|
||||
Label {
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Qt.AlignHCenter
|
||||
verticalAlignment: Qt.AlignTop
|
||||
topPadding: 20
|
||||
text: no
|
||||
color: (model.used === 0) ? couleur_blanc_casse : couleur_gris_moyen
|
||||
font.pixelSize: 18
|
||||
font.bold: true
|
||||
}
|
||||
Label {
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Qt.AlignHCenter
|
||||
verticalAlignment: Qt.AlignBottom
|
||||
bottomPadding: 20
|
||||
visible: model.no_entree !== 0
|
||||
text: "X"
|
||||
color: couleur_green_yellow
|
||||
font.pixelSize: 18
|
||||
font.bold: true
|
||||
}
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
enabled: (model.used === 0) || (model.no_entree === entree_en_cours)
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
boite_dialogue_entrees_level_sensor.clicked(shipheart_boite_dialogue_bouton_1, no);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// Boutons :
|
||||
//=========================================================================
|
||||
Row {
|
||||
height: (boite_dialogue_entrees_level_sensor.height - (2 * padding_popup) - (2 * affichage_boite_dialogue.spacing)) * pourcentage_boite_dialogue_ligne_boutons
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
spacing: 20
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Bouton Annuler :
|
||||
Rectangle {
|
||||
id: bouton_annuler
|
||||
|
||||
width: bouton_largeur
|
||||
height: parent.height * 0.5
|
||||
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_entrees_level_sensor.clicked(shipheart_boite_dialogue_bouton_2, 0);
|
||||
boite_dialogue_entrees_level_sensor.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================================================
|
||||
// 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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,380 @@
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
|
||||
Popup {
|
||||
id: boite_dialogue_liste_alarmes
|
||||
|
||||
// Propriétés fixes :
|
||||
readonly property double pourcentage_largeur_page_popup: 0.8
|
||||
readonly property double pourcentage_hauteur_page_popup: 0.7
|
||||
readonly property int padding_popup: 20
|
||||
readonly property double pourcentage_zone_titre: 0.3
|
||||
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 type_source: 0
|
||||
property int id_source: 0
|
||||
property int id_variable: 0
|
||||
property string titre: ""
|
||||
property string titre_widget: ""
|
||||
property string unite: ""
|
||||
|
||||
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: {
|
||||
timer_raffraichissement_parametres.stop();
|
||||
}
|
||||
|
||||
//===========================================================
|
||||
// Timer periode raffraichissement parametres :
|
||||
//===========================================================
|
||||
Timer {
|
||||
id: timer_raffraichissement_parametres
|
||||
interval: periode_raffraichissement_parametres
|
||||
triggeredOnStart: false
|
||||
running: false
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
mise_a_jour()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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_liste_alarmes.width - (2 * padding_popup)
|
||||
height: (boite_dialogue_liste_alarmes.height - (2 * padding_popup) - (2 * affichage_boite_dialogue.spacing)) * pourcentage_zone_titre
|
||||
color: "transparent"
|
||||
Image {
|
||||
id: image_titre
|
||||
source: "/images/cloche.png"
|
||||
sourceSize.height: parent.height * 0.4
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
verticalCenterOffset: -parent.height / 4
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
visible: true
|
||||
}
|
||||
Label {
|
||||
text: titre
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
verticalCenterOffset: parent.height / 4
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
wrapMode: Text.Wrap
|
||||
color: couleur_blanc_casse
|
||||
font.pixelSize:32
|
||||
font.weight: Font.Bold
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// Zone principale :
|
||||
//=========================================================================
|
||||
Rectangle {
|
||||
id: zone_principale
|
||||
width: boite_dialogue_liste_alarmes.width - (2 * padding_popup)
|
||||
height: (boite_dialogue_liste_alarmes.height - (2 * padding_popup) - (2 * affichage_boite_dialogue.spacing)) * pourcentage_zone_principale
|
||||
color: "transparent"
|
||||
|
||||
GridView {
|
||||
id: grille_alarmes
|
||||
|
||||
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_alarmes.cellWidth
|
||||
height: grille_alarmes.cellHeight
|
||||
color: "transparent"
|
||||
|
||||
//.......................................................
|
||||
// Bouton principal :
|
||||
//.......................................................
|
||||
Rectangle {
|
||||
height: parent.height - 10
|
||||
width: parent.width
|
||||
color: (model.etat_test === 0) ? shipheart_couleur_fond_bouton : couleur_rouge
|
||||
radius: shipheart_rayon_bouton
|
||||
anchors {
|
||||
left: parent.left
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
Text {
|
||||
anchors.fill: parent
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
horizontalAlignment: Qt.AlignLeft
|
||||
leftPadding: 20
|
||||
text: "<b>" + model.nom_event + "</b> [" + model.libelle_test + "]"
|
||||
wrapMode: Text.Wrap
|
||||
textFormat: Text.RichText
|
||||
color: couleur_blanc_casse
|
||||
font.pixelSize: 18
|
||||
}
|
||||
/* MouseArea{
|
||||
anchors.fill : parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
} // Fin de Gridview
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// Boutons de bas de fenêtre :
|
||||
//=========================================================================
|
||||
Row {
|
||||
height: (boite_dialogue_liste_alarmes.height - (2 * padding_popup) - (2 * affichage_boite_dialogue.spacing)) * pourcentage_zone_boutons
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
spacing: 20
|
||||
|
||||
//.......................................................
|
||||
// Bouton Ok :
|
||||
//.......................................................
|
||||
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("Ok")
|
||||
color: couleur_blanc_casse
|
||||
font.pixelSize:20
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
boite_dialogue_liste_alarmes.clicked(shipheart_boite_dialogue_bouton_1);
|
||||
boite_dialogue_liste_alarmes.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================================================
|
||||
// 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 nb;
|
||||
var i;
|
||||
var libelle_test;
|
||||
|
||||
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...)
|
||||
|
||||
console.log("id_variable="+id_variable)
|
||||
|
||||
grille_alarmes.model.clear();
|
||||
|
||||
req = 'SELECT Cle_primaire, '
|
||||
req += ' Nom, ';
|
||||
req += ' Test, ';
|
||||
req += ' Seuil, ';
|
||||
req += ' Etat_test ';
|
||||
req += ' FROM TB_Events ';
|
||||
req += ' WHERE Validite=1 ';
|
||||
req += ' AND Alarme_source>0 ';
|
||||
req += ' AND Type_source=' + type_source + ' ';
|
||||
req += ' AND ID_Source=' + id_source + ' ';
|
||||
req += ' AND ID_Variable=' + id_variable + ' ';
|
||||
req += ' ORDER BY Cle_primaire ';
|
||||
//console.log("Requête = [ " + req + "; ]");
|
||||
nb = bdd.requete(req);
|
||||
for (i = 0; i < nb; i ++)
|
||||
{
|
||||
res = bdd.lecture_ligne();
|
||||
if (!res.isEmpty)
|
||||
{
|
||||
libelle_test = titre_widget;
|
||||
switch(Number(res[2]))
|
||||
{
|
||||
case shipheart_test_non_defini:
|
||||
default:
|
||||
libelle_test += " ? "
|
||||
break;
|
||||
case shipheart_test_strictement_inferieur:
|
||||
libelle_test += " < "
|
||||
break;
|
||||
case shipheart_test_inferieur_ou_egal:
|
||||
libelle_test += " ≤ "
|
||||
break;
|
||||
case shipheart_test_egal:
|
||||
libelle_test += " = "
|
||||
break;
|
||||
case shipheart_test_superieur_ou_egal:
|
||||
libelle_test += " ≥ "
|
||||
break;
|
||||
case shipheart_test_strictement_superieur:
|
||||
libelle_test += " > "
|
||||
break;
|
||||
}
|
||||
libelle_test += Number(res[3]) + " " + unite;
|
||||
|
||||
grille_alarmes.model.append({
|
||||
"cle_primaire": Number(res[0]),
|
||||
"nom_event": res[1],
|
||||
"libelle_test": libelle_test,
|
||||
"etat_test": Number(res[4])
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
timer_raffraichissement_parametres.start();
|
||||
|
||||
flag_init = false;
|
||||
}
|
||||
|
||||
//=============================================================================================================
|
||||
// Mise à jour des données de la boite de dialogue
|
||||
//=============================================================================================================
|
||||
function mise_a_jour()
|
||||
{
|
||||
var req, res;
|
||||
var nb;
|
||||
var i, j;
|
||||
|
||||
|
||||
req = 'SELECT Cle_primaire, '
|
||||
req += ' Etat_test ';
|
||||
req += ' FROM TB_Events ';
|
||||
req += ' WHERE Validite=1 ';
|
||||
req += ' AND Alarme_source>0 ';
|
||||
req += ' AND Type_source=' + type_source + ' ';
|
||||
req += ' AND ID_Source=' + id_source + ' ';
|
||||
req += ' AND ID_Variable=' + id_variable + ' ';
|
||||
req += ' ORDER BY Cle_primaire ';
|
||||
//console.log("Requête = [ " + req + "; ]");
|
||||
nb = bdd.requete(req);
|
||||
for (i = 0; i < nb; i ++)
|
||||
{
|
||||
res = bdd.lecture_ligne();
|
||||
if (!res.isEmpty)
|
||||
{
|
||||
// Recherche dans le modèle la clé primaire de la ligne lue :
|
||||
for (j = 0; j < grille_alarmes.model.count; j ++)
|
||||
{
|
||||
if (grille_alarmes.model.get(i).cle_primaire === Number(res[0]))
|
||||
{
|
||||
grille_alarmes.model.set(i, {"etat_test": Number(res[1]) }); // Mise à jour de l'état du test
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,551 @@
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
|
||||
Popup {
|
||||
id: boite_dialogue_minuteur
|
||||
|
||||
// Propriétés fixes :
|
||||
readonly property double pourcentage_largeur_page_popup: 0.8
|
||||
readonly property double pourcentage_hauteur_page_popup: 0.8
|
||||
readonly property int padding_popup: 20
|
||||
readonly property double pourcentage_boite_dialogue_titre: 0.2
|
||||
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.15
|
||||
readonly property int bouton_hauteur: 60
|
||||
|
||||
readonly property double pourcentage_zone_tumblers: 0.75
|
||||
readonly property int bouton_largeur: 200
|
||||
readonly property int espace_tumblers: 20
|
||||
|
||||
|
||||
// Propriétés :
|
||||
property bool flag_init: true
|
||||
property int valeur_tumbler_heure: 0
|
||||
property int valeur_tumbler_minute: 0
|
||||
property int valeur_tumbler_seconde: 0
|
||||
|
||||
// Propriétés alias :
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// Signaux :
|
||||
//-------------------------------------------------
|
||||
signal clicked(int bouton, int heure, int minute, int seconde) // 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
|
||||
mise_a_jour(); // Nb : si on le fait à la suite de l'init, la première maj ne se fait pas car la page n'est pas encore ouverte...
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// 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_minuteur.width - (2 * padding_popup)
|
||||
height: (boite_dialogue_minuteur.height - (2 * padding_popup) - (2 * affichage_boite_dialogue.spacing)) * pourcentage_boite_dialogue_titre
|
||||
color: "transparent"
|
||||
|
||||
Image {
|
||||
id: image_titre
|
||||
source: "/images/sablier.png"
|
||||
sourceSize.height: 100
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// Zone principale :
|
||||
//=========================================================================
|
||||
Rectangle {
|
||||
id: zone_principale
|
||||
width: boite_dialogue_minuteur.width - (2 * padding_popup)
|
||||
height: (boite_dialogue_minuteur.height - (2 * padding_popup) - (2 * affichage_boite_dialogue.spacing)) * pourcentage_boite_dialogue_message
|
||||
color: "transparent"
|
||||
|
||||
//------------------------------------------
|
||||
// Tumblers de sélection manuelle :
|
||||
//------------------------------------------
|
||||
Row {
|
||||
id: zone_tumblers
|
||||
width: parent.width * pourcentage_zone_tumblers
|
||||
height: parent.height
|
||||
spacing: espace_tumblers
|
||||
|
||||
//-----------------------------------
|
||||
// Heure :
|
||||
//-----------------------------------
|
||||
Rectangle {
|
||||
width: zone_tumblers.width * 0.3
|
||||
height: zone_tumblers.height
|
||||
color: "transparent"
|
||||
|
||||
Text {
|
||||
anchors.top: parent.top
|
||||
width: parent.width
|
||||
height: parent.height - tumbler_heure.height
|
||||
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
text: qsTr("Heures")
|
||||
color: couleur_blanc_casse
|
||||
font.pixelSize: 18
|
||||
}
|
||||
|
||||
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.family: "Montserrat"
|
||||
font.pixelSize: 26
|
||||
font.bold: (index === tumbler_heure.currentIndex)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
color: couleur_gris_tres_fonce
|
||||
radius: shipheart_grand_rayon_bouton
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------
|
||||
// Minute :
|
||||
//-----------------------------------
|
||||
Rectangle {
|
||||
width: zone_tumblers.width * 0.3
|
||||
height: zone_tumblers.height
|
||||
color: "transparent"
|
||||
|
||||
Text {
|
||||
anchors.top: parent.top
|
||||
width: parent.width
|
||||
height: parent.height - tumbler_minute.height
|
||||
visible: (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) :
|
||||
true
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
text: qsTr("Minutes")
|
||||
color: couleur_blanc_casse
|
||||
font.pixelSize: 18
|
||||
}
|
||||
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
|
||||
|
||||
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.family: "Montserrat"
|
||||
font.pixelSize: 26
|
||||
font.bold: (index === tumbler_minute.currentIndex)
|
||||
}
|
||||
}
|
||||
}
|
||||
background: Rectangle {
|
||||
color: couleur_gris_tres_fonce
|
||||
radius: shipheart_grand_rayon_bouton
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------
|
||||
// Secondes :
|
||||
//-----------------------------------
|
||||
Rectangle {
|
||||
width: zone_tumblers.width * 0.3
|
||||
height: zone_tumblers.height
|
||||
color: "transparent"
|
||||
|
||||
Text {
|
||||
anchors.top: parent.top
|
||||
width: parent.width
|
||||
height: parent.height - tumbler_minute.height
|
||||
visible: (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) :
|
||||
true
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
text: qsTr("Secondes")
|
||||
color: couleur_blanc_casse
|
||||
font.pixelSize: 18
|
||||
}
|
||||
Tumbler {
|
||||
id: tumbler_seconde
|
||||
width: parent.width
|
||||
height: parent.height * 0.85
|
||||
anchors {
|
||||
bottom: parent.bottom
|
||||
}
|
||||
visibleItemCount: 5
|
||||
model: ListModel { }
|
||||
delegate: bouton_seconde
|
||||
|
||||
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
|
||||
|
||||
Component {
|
||||
id: bouton_seconde
|
||||
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_seconde.currentIndex) ? couleur_blanc_casse : couleur_gris_pale
|
||||
font.family: "Montserrat"
|
||||
font.pixelSize: 26
|
||||
font.bold: (index === tumbler_seconde.currentIndex)
|
||||
}
|
||||
}
|
||||
}
|
||||
background: Rectangle {
|
||||
color: couleur_gris_tres_fonce
|
||||
radius: shipheart_grand_rayon_bouton
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------
|
||||
// Boutons de droite :
|
||||
//------------------------------------------
|
||||
Column {
|
||||
id: colonne_boutons
|
||||
height: parent.height
|
||||
width: parent.width * (1 - pourcentage_zone_tumblers)
|
||||
anchors.right: parent.right
|
||||
spacing: 5
|
||||
|
||||
Repeater {
|
||||
model: ListModel { id: modele_boutons_preprogrammes }
|
||||
|
||||
// Bouton proprement dit :
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: (colonne_boutons.height - ((modele_boutons_preprogrammes.count - 1) * colonne_boutons.spacing)) / modele_boutons_preprogrammes.count
|
||||
radius: shipheart_rayon_bouton
|
||||
color: couleur_gris_tres_fonce
|
||||
Label {
|
||||
anchors.centerIn: parent
|
||||
text: model.libelle
|
||||
color: couleur_blanc_casse
|
||||
font.pixelSize:18
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
valeur_tumbler_heure = model.heure;
|
||||
valeur_tumbler_minute = model.minute;
|
||||
valeur_tumbler_seconde = model.seconde;
|
||||
mise_a_jour();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//=========================================================================
|
||||
// Boutons de bas de fenêtre :
|
||||
//=========================================================================
|
||||
Row {
|
||||
height: (boite_dialogue_minuteur.height - (2 * padding_popup) - (2 * affichage_boite_dialogue.spacing)) * pourcentage_boite_dialogue_ligne_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_minuteur.clicked(shipheart_boite_dialogue_bouton_2, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//.......................................................
|
||||
// Bouton Ok / Démarrer :
|
||||
//.......................................................
|
||||
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("Démarrer")
|
||||
color: mousearea_demarrer.enabled ? couleur_blanc_casse : couleur_gris_moyen
|
||||
font.pixelSize:20
|
||||
}
|
||||
MouseArea {
|
||||
id: mousearea_demarrer
|
||||
anchors.fill: parent
|
||||
enabled: (!flag_init) &&
|
||||
( (tumbler_heure.model.get(tumbler_heure.currentIndex).valeur !== 0)
|
||||
|| (tumbler_minute.model.get(tumbler_minute.currentIndex).valeur !== 0)
|
||||
|| (tumbler_seconde.model.get(tumbler_seconde.currentIndex).valeur !== 0) )
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
boite_dialogue_minuteur.clicked(shipheart_boite_dialogue_bouton_1,
|
||||
tumbler_heure.model.get(tumbler_heure.currentIndex).valeur,
|
||||
tumbler_minute.model.get(tumbler_minute.currentIndex).valeur,
|
||||
tumbler_seconde.model.get(tumbler_seconde.currentIndex).valeur);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================================================
|
||||
// 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;
|
||||
|
||||
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...)
|
||||
|
||||
//-------------------------------------
|
||||
// Heures :
|
||||
//-------------------------------------
|
||||
tumbler_heure.model.clear();
|
||||
|
||||
for (i = 0; i < 24; i ++)
|
||||
{
|
||||
tumbler_heure.model.append( { "valeur": i, "libelle": ((i < 10) ? "0"+i : ""+i)} );
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
// Minutes :
|
||||
//-------------------------------------
|
||||
tumbler_minute.model.clear();
|
||||
|
||||
for (i = 0; i < 60; i ++)
|
||||
{
|
||||
tumbler_minute.model.append( { "valeur": i, "libelle": ((i < 10) ? "0"+i : ""+i) } );
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
// secondes :
|
||||
//-------------------------------------
|
||||
tumbler_seconde.model.clear();
|
||||
|
||||
for (i = 0; i < 60; i ++)
|
||||
{
|
||||
tumbler_seconde.model.append( { "valeur": i, "libelle": ((i < 10) ? "0"+i : ""+i) } );
|
||||
}
|
||||
|
||||
modele_boutons_preprogrammes.clear();
|
||||
modele_boutons_preprogrammes.append( {"libelle": "00:01:00", "heure": 0, "minute": 1, "seconde": 0 } );
|
||||
modele_boutons_preprogrammes.append( {"libelle": "00:03:00", "heure": 0, "minute": 3, "seconde": 0 } );
|
||||
modele_boutons_preprogrammes.append( {"libelle": "00:05:00", "heure": 0, "minute": 5, "seconde": 0 } );
|
||||
modele_boutons_preprogrammes.append( {"libelle": "00:15:00", "heure": 0, "minute": 15, "seconde": 0 } );
|
||||
modele_boutons_preprogrammes.append( {"libelle": "00:30:00", "heure": 0, "minute": 30, "seconde": 0 } );
|
||||
modele_boutons_preprogrammes.append( {"libelle": "01:00:00", "heure": 1, "minute": 0, "seconde": 0 } );
|
||||
|
||||
flag_init = false;
|
||||
}
|
||||
|
||||
//=============================================================================================================
|
||||
// Mise à jour des données de la boite de dialogue
|
||||
//=============================================================================================================
|
||||
function mise_a_jour()
|
||||
{
|
||||
var i;
|
||||
|
||||
|
||||
//-------------------------------------
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
// Secondes :
|
||||
//-------------------------------------
|
||||
// Rercherche de la valeur courante :
|
||||
for (i = 0; i < tumbler_seconde.model.count; i ++)
|
||||
{
|
||||
if (tumbler_seconde.model.get(i).valeur === valeur_tumbler_seconde)
|
||||
{
|
||||
tumbler_seconde.currentIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
Executable
+202
@@ -0,0 +1,202 @@
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
|
||||
Popup {
|
||||
id: boite_dialogue_nettoyage_ecran
|
||||
|
||||
// Propriétés fixes :
|
||||
readonly property double pourcentage_largeur_page_popup: 0.8
|
||||
readonly property double pourcentage_hauteur_page_popup: 0.7
|
||||
readonly property int padding_popup: 50
|
||||
readonly property double pourcentage_boite_dialogue_titre: 0.2
|
||||
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.30
|
||||
readonly property int bouton_largeur: 500
|
||||
|
||||
readonly property int step_timer_sortie: 10 // en ms
|
||||
|
||||
// Propriétés :
|
||||
property int valeur_timer_sortie: 0
|
||||
|
||||
// Propriétés alias :
|
||||
|
||||
|
||||
// Signaux :
|
||||
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
Timer {
|
||||
id: timer_sortie
|
||||
interval: step_timer_sortie
|
||||
triggeredOnStart: false
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
if (valeur_timer_sortie < shipheart_mouse_press_and_hold_interval_tres_long) valeur_timer_sortie+= step_timer_sortie;
|
||||
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_sortie.running = false;
|
||||
valeur_timer_sortie = 0;
|
||||
shipheart_clic();
|
||||
boite_dialogue_nettoyage_ecran.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
id: affichage_boite_dialogue_nettoyage_ecran
|
||||
|
||||
spacing: 20
|
||||
|
||||
//=========================================================================
|
||||
// Titre :
|
||||
//=========================================================================
|
||||
Rectangle {
|
||||
id: titre_boite_dialogue_nettoyage_ecran
|
||||
|
||||
width: boite_dialogue_nettoyage_ecran.width - (2 * padding_popup)
|
||||
height: (boite_dialogue_nettoyage_ecran.height - (2 * padding_popup) - (2 * affichage_boite_dialogue_nettoyage_ecran.spacing)) * pourcentage_boite_dialogue_titre
|
||||
color: "transparent"
|
||||
|
||||
Text {
|
||||
text: qsTr("Nettoyage de l'écran")
|
||||
anchors.fill: parent
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
wrapMode: Text.Wrap
|
||||
color: couleur_blanc_casse
|
||||
font.pixelSize:40
|
||||
font.weight: Font.Bold
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// Message :
|
||||
//=========================================================================
|
||||
Rectangle {
|
||||
id: message_boite_dialogue_nettoyage_ecran
|
||||
|
||||
width: boite_dialogue_nettoyage_ecran.width - (2 * padding_popup)
|
||||
height: (boite_dialogue_nettoyage_ecran.height - (2 * padding_popup) - (2 * affichage_boite_dialogue_nettoyage_ecran.spacing)) * pourcentage_boite_dialogue_message
|
||||
color: "transparent"
|
||||
|
||||
Text {
|
||||
anchors.fill: parent
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
wrapMode: Text.Wrap
|
||||
text: qsTr("L'écran est actuellement figé afin de vous permettre de le nettoyer sans risque de déclencher des actions non désirées.<br /><br />Maintenez le bouton ci-dessous pendant plus de %1 secondes pour sortir de ce mode.").arg(shipheart_mouse_press_and_hold_interval_tres_long / 1000)
|
||||
color: couleur_blanc_casse
|
||||
font.pixelSize:18
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// Boutons :
|
||||
//=========================================================================
|
||||
Row {
|
||||
height: (boite_dialogue_nettoyage_ecran.height - (2 * padding_popup) - (2 * affichage_boite_dialogue_nettoyage_ecran.spacing)) * pourcentage_boite_dialogue_ligne_boutons
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
spacing: 20
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Bouton Sortie :
|
||||
Rectangle {
|
||||
id: bouton_sortie
|
||||
|
||||
width: bouton_largeur
|
||||
height: parent.height * 0.5
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
radius: shipheart_rayon_bouton
|
||||
color: couleur_gris_tres_fonce
|
||||
Label {
|
||||
id: bouton_sortie_label
|
||||
anchors.centerIn: parent
|
||||
text: qsTr("Sortie")
|
||||
color: couleur_blanc_casse
|
||||
font.pixelSize:20
|
||||
}
|
||||
|
||||
// Barre grandissante pour montrer durée d'appui vs tempo nécessaire :
|
||||
Rectangle {
|
||||
width: (valeur_timer_sortie / shipheart_mouse_press_and_hold_interval_tres_long) * parent.width
|
||||
height: parent.height
|
||||
color: couleur_gris_tres_pale_transparent
|
||||
radius: shipheart_rayon_bouton
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onPressed: { // Déclenché lors de l'appui inital
|
||||
valeur_timer_sortie = 0;
|
||||
timer_sortie.running = true;
|
||||
}
|
||||
onClicked: { // Déclenché si l'appui n'a pas été suffisement long pour avoir un Press&Hold :
|
||||
timer_sortie.running = false;
|
||||
valeur_timer_sortie = 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_sortie.running = false;
|
||||
valeur_timer_sortie = 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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Executable
+470
@@ -0,0 +1,470 @@
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
+316
@@ -0,0 +1,316 @@
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
|
||||
|
||||
Popup {
|
||||
id: boite_dialogue_validation_securisee
|
||||
|
||||
// Propriétés fixes :
|
||||
readonly property double pourcentage_largeur_page_popup: 0.6
|
||||
readonly property double pourcentage_hauteur_page_popup: 0.7
|
||||
readonly property int padding_popup: 50
|
||||
readonly property double pourcentage_boite_dialogue_titre: 0.25
|
||||
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.15
|
||||
|
||||
readonly property int bouton_largeur: 200
|
||||
|
||||
readonly property int step_timer_appui_long: 30 // en ms
|
||||
|
||||
|
||||
// Propriétés :
|
||||
property int valeur_timer_appui_long: 0
|
||||
|
||||
property int niveau: 0
|
||||
property string message: "--"
|
||||
property int type: 0 // Utilisé uniquement par la page appelante pour distinguer les différents appels dans la même page
|
||||
|
||||
// Propriétés alias :
|
||||
property alias boutonOk: bouton_ok.visible
|
||||
property alias boutonAnnuler: bouton_annuler.visible
|
||||
property alias boutonSecurise: bouton_securise.visible
|
||||
property alias boutonOkTexte: bouton_ok_label.text
|
||||
property alias boutonAnnulerTexte: bouton_annuler_label.text
|
||||
property alias boutonSecuriseTexte: bouton_securise_label.text
|
||||
property alias alignementMessage: texte_message.horizontalAlignment
|
||||
property alias imageTitreSource: image_titre.source
|
||||
property alias affichageAscenseur: ascenseur.visible
|
||||
|
||||
|
||||
// Signaux :
|
||||
signal clicked(int bouton) // Valeur à lire lorsque le "OnClicked' est activé
|
||||
|
||||
|
||||
//===========================================================
|
||||
// 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_securise.pressed)
|
||||
{
|
||||
boite_dialogue_validation_securisee.clicked(shipheart_boite_dialogue_bouton_4);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
radius: 20
|
||||
color: {
|
||||
switch(boite_dialogue_validation_securisee.niveau)
|
||||
{
|
||||
default:
|
||||
case 0: color: shipheart_couleur_fond_boite_dialogue_niveau_0; break;
|
||||
case 1: color: shipheart_couleur_fond_boite_dialogue_niveau_1; break;
|
||||
case 2: color: shipheart_couleur_fond_boite_dialogue_niveau_2; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
id: affichage_boite_dialogue
|
||||
|
||||
spacing: 20
|
||||
|
||||
//=========================================================================
|
||||
// Titre :
|
||||
//=========================================================================
|
||||
Rectangle {
|
||||
id: titre_boite_dialogue
|
||||
|
||||
width: boite_dialogue_validation_securisee.width - (2 * padding_popup)
|
||||
height: (boite_dialogue_validation_securisee.height - (2 * padding_popup) - (2 * affichage_boite_dialogue.spacing)) * pourcentage_boite_dialogue_titre
|
||||
color: "transparent"
|
||||
|
||||
Image {
|
||||
id: image_titre
|
||||
source: ""
|
||||
sourceSize.height: parent.height
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
visible: true
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// Message :
|
||||
//=========================================================================
|
||||
Rectangle {
|
||||
id: message_boite_dialogue
|
||||
|
||||
width: boite_dialogue_validation_securisee.width - (2 * padding_popup)
|
||||
height: (boite_dialogue_validation_securisee.height - (2 * padding_popup) - (2 * affichage_boite_dialogue.spacing)) * pourcentage_boite_dialogue_message
|
||||
color: "transparent"
|
||||
|
||||
Flickable {
|
||||
anchors.fill: parent
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
contentWidth: texte_message.width
|
||||
contentHeight: texte_message.height
|
||||
flickableDirection: Flickable.VerticalFlick
|
||||
clip: true
|
||||
|
||||
ScrollBar.vertical: ScrollBar { // Important car permet de voir que la partie affichée n'est pas complète dans le message...
|
||||
id: ascenseur
|
||||
policy: ScrollBar.AlwaysOn
|
||||
width: 10
|
||||
visible: false
|
||||
}
|
||||
|
||||
TextEdit {
|
||||
id: texte_message
|
||||
width: message_boite_dialogue.width - ascenseur.width - 5 // Le '-5' permet de détacher le texte de l'ascenseur
|
||||
height: Math.max(message_boite_dialogue.height, implicitHeight) // Permet d'avoir la hauteur de la zone si le texte est "court" (et donc de centrer verticalement) puis la hauteur totale si le texte est "long" (et pouvoir se déplacer vers la fin et pas centré sur le milieu !)
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
readOnly:true
|
||||
wrapMode: Text.Wrap
|
||||
textFormat: Text.RichText
|
||||
text: boite_dialogue_validation_securisee.message
|
||||
color: {
|
||||
switch(boite_dialogue_validation_securisee.niveau)
|
||||
{
|
||||
default:
|
||||
case 0: shipheart_couleur_texte_boite_dialogue_niveau_0; break;
|
||||
case 1: shipheart_couleur_texte_boite_dialogue_niveau_1; break;
|
||||
case 2: shipheart_couleur_texte_boite_dialogue_niveau_2; break;
|
||||
}
|
||||
}
|
||||
font.pixelSize:18
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=========================================================================
|
||||
// Boutons :
|
||||
//=========================================================================
|
||||
Row {
|
||||
height: (boite_dialogue_validation_securisee.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
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
radius: shipheart_rayon_bouton
|
||||
color: couleur_gris_tres_fonce
|
||||
visible: true
|
||||
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_validation_securisee.clicked(shipheart_boite_dialogue_bouton_1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Bouton Annuler :
|
||||
Rectangle {
|
||||
id: bouton_annuler
|
||||
|
||||
width: bouton_largeur
|
||||
height: parent.height
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
radius: shipheart_rayon_bouton
|
||||
color: couleur_gris_tres_fonce
|
||||
visible: false
|
||||
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_validation_securisee.clicked(shipheart_boite_dialogue_bouton_2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Bouton Sécurisé :
|
||||
Rectangle {
|
||||
id: bouton_securise
|
||||
|
||||
width: bouton_largeur
|
||||
height: parent.height
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
radius: shipheart_rayon_bouton
|
||||
color: couleur_gris_tres_fonce
|
||||
visible: false
|
||||
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_securise.pressed
|
||||
}
|
||||
Label {
|
||||
id: bouton_securise_label
|
||||
anchors.centerIn: parent
|
||||
text: qsTr("---")
|
||||
color: couleur_blanc_casse
|
||||
font.pixelSize:20
|
||||
}
|
||||
MouseArea {
|
||||
id: mousearea_bouton_securise
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
//-----------------------------------------------------------------------------------------------------
|
||||
// Fichier définissant un bouton de type Batterie sur la page d'accueil
|
||||
// A priori, appelé depuis "home.qml"
|
||||
//-----------------------------------------------------------------------------------------------------
|
||||
import QtQuick 2.12
|
||||
|
||||
|
||||
//=======================================================
|
||||
// Ensemble du bouton
|
||||
//=======================================================
|
||||
Rectangle {
|
||||
id: bouton_batterie
|
||||
|
||||
readonly property int largeur_bouton: batteries_grid.cellWidth - espace_colonnes_secondaires;
|
||||
readonly property int hauteur_bouton: batteries_grid.cellHeight - espace_lignes_secondaires;
|
||||
readonly property int rayon_bouton: 5
|
||||
readonly property double pourcentage_largeur_zone_affichage_nom: 0.85
|
||||
readonly property int seuil_haut: 75 // utilisé pour changer de couleur orange/vert
|
||||
readonly property int seuil_bas: 25 // utilisé pour changer de couleur rouge/orange
|
||||
|
||||
width: largeur_bouton
|
||||
height: hauteur_bouton
|
||||
color: "transparent" // On ne peut pas mettre l'opacité sur celui-ci, sinon tous ses enfants sont aussi semi-transparents...
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
// Bandeau latéral avec tension nominale :
|
||||
//---------------------------------------------------------------------------------------
|
||||
Image {
|
||||
id: bandeau_tension_batterie
|
||||
source: (model.Tension_nominale === 12) ? "/images/batterie_12v.png" : "/images/batterie_24v.png"
|
||||
sourceSize.height: parent.height
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
// Bouton dans son ensemble :
|
||||
//---------------------------------------------------------------------------------------
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
radius: rayon_bouton
|
||||
border.color: couleur_rouge
|
||||
border.width: (model.Etat_systeme === 0) ? 0 : 3
|
||||
color: shipheart_couleur_fond_bouton
|
||||
|
||||
MouseArea {
|
||||
id: mouse_area_zone_parametres
|
||||
anchors.fill: parent
|
||||
width: largeur_bouton
|
||||
height: hauteur_bouton
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
stackView.push("batterie.qml",
|
||||
{
|
||||
"id_batterie": model.Cle_primaire,
|
||||
"flag_detail_batterie": true,
|
||||
"nom":model.Nom
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Zone du nom (en haut à gauche) :
|
||||
//-------------------------------------------------------
|
||||
Rectangle {
|
||||
id: zone_nom
|
||||
x: bandeau_tension_batterie.width
|
||||
width: (largeur_bouton * pourcentage_largeur_zone_affichage_nom) - bandeau_tension_batterie.width;
|
||||
height: hauteur_bouton / 2;
|
||||
color: "transparent"
|
||||
|
||||
Text {
|
||||
text: model.Nom
|
||||
anchors.fill: parent // Permet que le texte occupe tout l'espace du parent (et que le centrage vertical qui suit fonctionne...)
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
leftPadding: 10
|
||||
font.pixelSize: 15
|
||||
elide: Text.ElideRight
|
||||
font.weight: Font.Bold
|
||||
color: couleur_blanc_casse
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Zone de valeur absolue :
|
||||
//-------------------------------------------------------
|
||||
Rectangle {
|
||||
id: zone_valeur
|
||||
x: bandeau_tension_batterie.width
|
||||
y: hauteur_bouton / 2;
|
||||
width: (largeur_bouton * pourcentage_largeur_zone_affichage_nom) - bandeau_tension_batterie.width;
|
||||
height: hauteur_bouton / 2;
|
||||
color: "transparent"
|
||||
visible: (model.Etat_systeme === 0)
|
||||
|
||||
Image {
|
||||
source: "/images/coin_bas_droite_rouge.png"
|
||||
sourceSize.height: 20
|
||||
anchors {
|
||||
bottom: parent.bottom
|
||||
right: parent.right
|
||||
}
|
||||
visible: (model.Etat_systeme === 0) // SDIR #285
|
||||
&& (model.Etat !== 0) // SDIR #285
|
||||
}
|
||||
|
||||
Text {
|
||||
text: (model.Tension).toFixed(2) + " V";
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
font.pixelSize: 18
|
||||
font.bold: true
|
||||
color: couleur_blanc_casse
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Zone niveau relatif :
|
||||
//-------------------------------------------------------
|
||||
Rectangle {
|
||||
id: zone_niveau_relatif
|
||||
color: "transparent" // Sinon, le fond du rectangle est blanc...
|
||||
x: largeur_bouton * pourcentage_largeur_zone_affichage_nom
|
||||
width: largeur_bouton * (1 - pourcentage_largeur_zone_affichage_nom);
|
||||
height: hauteur_bouton;
|
||||
radius: shipheart_rayon_bouton
|
||||
border.color: couleur_fond_bargraph_niveau_relatif()
|
||||
border.width: 1
|
||||
visible: (model.Etat_systeme === 0)
|
||||
|
||||
Text {
|
||||
id:zone_texte_niveau_relatif
|
||||
text: (model.Niveau).toFixed(0) + " %";
|
||||
anchors.fill: parent // Permet que le texte occupe tout l'espace du parent (et que le centrage vertical qui suit fonctionne...)
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
font.pixelSize: 12
|
||||
font.bold: (model.Niveau < 10) // soit < 10%
|
||||
color: couleur_texte_niveau_relatif()
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id:zone_bargraph_niveau_relatif
|
||||
color: couleur_fond_bargraph_niveau_relatif()
|
||||
y: parent.height * (100 - model.Niveau) / 100
|
||||
width: parent.width;
|
||||
height: parent.height * model.Niveau / 100;
|
||||
radius: shipheart_rayon_bouton
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
function couleur_texte_niveau_relatif()
|
||||
{
|
||||
switch(model.Logique)
|
||||
{
|
||||
case 1: return((model.Niveau >= seuil_haut) ? couleur_rouge : ((model.Niveau >= seuil_bas) ? couleur_orange : couleur_green_yellow))
|
||||
case 0: return((model.Niveau >= seuil_haut) ? couleur_rouge : ((model.Niveau >= seuil_bas) ? couleur_green_yellow : couleur_rouge))
|
||||
default: return((model.Niveau >= seuil_haut) ? couleur_green_yellow : ((model.Niveau >= seuil_bas) ? couleur_orange : couleur_rouge))
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
function couleur_fond_bargraph_niveau_relatif()
|
||||
{
|
||||
switch(model.Logique)
|
||||
{
|
||||
case 1: return((model.Niveau >= seuil_haut) ? couleur_rouge_transparent : ((model.Niveau >= seuil_bas) ? couleur_orange_transparent : couleur_vert_transparent))
|
||||
case 0: return((model.Niveau >= seuil_haut) ? couleur_rouge_transparent : ((model.Niveau >= seuil_bas) ? couleur_vert_transparent : couleur_rouge_transparent))
|
||||
default: return((model.Niveau >= seuil_haut) ? couleur_vert_transparent : ((model.Niveau >= seuil_bas) ? couleur_orange_transparent : couleur_rouge_transparent))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
//-----------------------------------------------------------------------------------------------------
|
||||
// Fichier définissant un bouton de type Capteur sur la page d'accueil
|
||||
// A priori, appelé depuis "home.qml"
|
||||
//-----------------------------------------------------------------------------------------------------
|
||||
import QtQuick 2.12
|
||||
|
||||
|
||||
//=======================================================
|
||||
// Ensemble du bouton
|
||||
//=======================================================
|
||||
Rectangle {
|
||||
id: bouton_capteur
|
||||
|
||||
readonly property int largeur_bouton: capteurs_grid.cellWidth - espace_colonnes_secondaires;
|
||||
readonly property int hauteur_bouton: capteurs_grid.cellHeight - espace_lignes_secondaires;
|
||||
readonly property int rayon_bouton: 5
|
||||
|
||||
width: largeur_bouton
|
||||
height: hauteur_bouton
|
||||
radius: rayon_bouton
|
||||
color: "transparent" // On ne peut pas mettre l'opacité sur celui-ci, sinon tous ses enfants sont aussi semi-transparents...
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Fond de bouton :
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: shipheart_couleur_fond_bouton
|
||||
radius: rayon_bouton
|
||||
border.color: couleur_rouge
|
||||
border.width: (model.Etat_systeme === 0) ? 0 : 3
|
||||
|
||||
//-------------------------
|
||||
// Triangle orange d'alerte :
|
||||
Image {
|
||||
source: "/images/coin_bas_droite_orange.png"
|
||||
sourceSize.height: 20
|
||||
anchors {
|
||||
bottom: parent.bottom
|
||||
right: parent.right
|
||||
}
|
||||
visible: (model.Etat_systeme === 0) && // SDIR #285
|
||||
((model.Etat_capteur === shipheart_capteur_etat_alerte) ||
|
||||
(model.Etat > 0) || // Nb alertes d'Events > 0
|
||||
(model.Obsolete) )
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
// Triangle rouge d'alarme :
|
||||
Image {
|
||||
source: "/images/coin_bas_droite_rouge.png"
|
||||
sourceSize.height: 20
|
||||
anchors {
|
||||
bottom: parent.bottom
|
||||
right: parent.right
|
||||
}
|
||||
visible: (model.Etat_systeme === 0) && // SDIR #285
|
||||
(model.Etat_capteur === shipheart_capteur_etat_alarme)
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Nom du capteur :
|
||||
Rectangle {
|
||||
id: nom_capteur
|
||||
width: parent.width
|
||||
height: parent.height * 0.25;
|
||||
color: "transparent"
|
||||
|
||||
Text {
|
||||
|
||||
text: model.Nom
|
||||
anchors.fill: parent
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
leftPadding: 10
|
||||
font.pixelSize: 15
|
||||
font.weight: Font.Bold
|
||||
color: couleur_blanc_casse
|
||||
elide: Text.ElideRight // Pas de wrap car on ne peut afficher qu'une seule ligne quoi qu'il arrive...
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Valeur si aucune unité :
|
||||
Rectangle {
|
||||
id: valeur_capteur_sans_unite
|
||||
anchors.top: nom_capteur.bottom
|
||||
width: parent.width
|
||||
height: parent.height - nom_capteur.height
|
||||
color: "transparent"
|
||||
visible: (model.Etat_systeme === 0) && (model.Unite === "")
|
||||
|
||||
Text {
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
padding: 10
|
||||
text: model.Valeur
|
||||
font.family: "Montserrat"
|
||||
fontSizeMode: Text.HorizontalFit;
|
||||
minimumPixelSize: 20;
|
||||
font.pixelSize: 50
|
||||
elide: Text.ElideRight
|
||||
wrapMode: Text.Wrap
|
||||
font.weight: Font.Bold
|
||||
// color: (model.Etat === 0) ? couleur_blanc_casse : couleur_rouge
|
||||
color: couleur_blanc_casse
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Valeur si unité :
|
||||
Rectangle {
|
||||
id: valeur_capteur_avec_unite
|
||||
anchors.top: nom_capteur.bottom
|
||||
width: parent.width
|
||||
height: parent.height - nom_capteur.height
|
||||
color: "transparent"
|
||||
visible: (model.Etat_systeme === 0) && (model.Unite !== "")
|
||||
|
||||
Text {
|
||||
id: valeur_actuelle
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
horizontalCenterOffset: -20
|
||||
}
|
||||
text: model.Valeur
|
||||
font.family: "Montserrat"
|
||||
font.pixelSize: 50
|
||||
font.weight: Font.Bold
|
||||
// color: (model.Etat === 0) ? couleur_blanc_casse : couleur_rouge
|
||||
color: couleur_blanc_casse
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Unite :
|
||||
Text {
|
||||
anchors {
|
||||
baseline: valeur_actuelle.baseline
|
||||
left: valeur_actuelle.right
|
||||
leftMargin: 10
|
||||
}
|
||||
text: model.Unite
|
||||
font.pixelSize: 15
|
||||
color: couleur_gris_pale
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Zone de clic :
|
||||
MouseArea { // Zone d'interaction Paramètres du reservoir
|
||||
id: mouse_area_zone_parametres
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
stackView.push("capteur.qml", {"id_capteur": model.Cle_primaire})
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,339 @@
|
||||
//-----------------------------------------------------------------------------------------------------
|
||||
// Fichier définissant un bouton de type Circuit sur la page d'accueil
|
||||
// A priori, appelé depuis "home.qml"
|
||||
//-----------------------------------------------------------------------------------------------------
|
||||
import QtQuick 2.12
|
||||
|
||||
|
||||
//=======================================================
|
||||
// Ensemble du bouton
|
||||
//=======================================================
|
||||
Item {
|
||||
id: bouton_circuit
|
||||
|
||||
// Paramètres d'affichage :
|
||||
readonly property int largeur_bouton: circuits_grid.cellWidth - espace_colonnes_secondaires;
|
||||
readonly property int hauteur_bouton: circuits_grid.cellHeight - espace_lignes_secondaires;
|
||||
readonly property double pourcentage_largeur_zone_affichage_nom: 0.60
|
||||
readonly property double pourcentage_largeur_zone_affichage_consigne: 0.25
|
||||
readonly property int espace_interne: 5
|
||||
// | zone affichage nom | cdes auto | consigne |
|
||||
// | zone affichage intensité | | |
|
||||
|
||||
|
||||
width: largeur_bouton
|
||||
height: hauteur_bouton
|
||||
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
color: (model.Etat_systeme === 0) ? "transparent" : shipheart_couleur_fond_bouton // On ne peut pas mettre l'opacité sur celui-ci, sinon tous ses enfants sont aussi semi-transparents...
|
||||
radius: shipheart_rayon_bouton
|
||||
border.color: couleur_rouge
|
||||
border.width: (model.Etat_systeme === 0) ? 0 : 3
|
||||
|
||||
//------------------------------------------------------------------------------------------
|
||||
// Zone de parametres (toute la partie gauche, hors consigne et hors cde AUTO s'il y en a :
|
||||
//------------------------------------------------------------------------------------------
|
||||
Rectangle {
|
||||
id: zone_parametres
|
||||
x: 0
|
||||
y: 0
|
||||
width: ((model.Type_circuit === shipheart_type_module_shipbase) && (model.No_circuit === 0)) ?
|
||||
parent.width : // Cas du circuit #0 de ShipBase
|
||||
(model.Validation_cdes_events >= 0) ? // Cas général :
|
||||
(parent.width * pourcentage_largeur_zone_affichage_nom) - espace_interne : // Avec commandes AUTO
|
||||
parent.width * (1 - pourcentage_largeur_zone_affichage_consigne) // Sans commandes AUTO
|
||||
height: parent.height;
|
||||
color: (model.Etat_systeme === 0) ? shipheart_couleur_fond_bouton : "transparent"
|
||||
radius: shipheart_rayon_bouton
|
||||
|
||||
Image { // Affichage du coin inférieur-droit en rouge ou orange si alarme ou alerte
|
||||
source: ( (Etat_circuit === shipheart_etat_circuit_limitation) ||
|
||||
(Etat_circuit === shipheart_etat_circuit_protection) ||
|
||||
(Etat_circuit === shipheart_etat_circuit_disjonte) ||
|
||||
(Etat_circuit === shipheart_etat_circuit_absence_terre) ||
|
||||
(Etat_circuit === shipheart_etat_circuit_absence_masse) )
|
||||
? "/images/coin_bas_droite_rouge.png"
|
||||
: "/images/coin_bas_droite_orange.png"
|
||||
|
||||
// (Etat_commande_carte === shipheart_etat_commande_module_test) ||
|
||||
// (Etat_commande_carte === shipheart_etat_commande_module_undervoltage) ||
|
||||
// (Etat_circuit === shipheart_etat_circuit_cc_batterie) ||
|
||||
// (Etat_circuit === shipheart_etat_circuit_deleste) ||
|
||||
// (Etat_circuit === shipheart_etat_circuit_inversion_phase_neutre) ||
|
||||
// (Etat_circuit === shipheart_etat_circuit_undervoltage) ||
|
||||
// (Etat_events > 0)
|
||||
sourceSize.height: 20
|
||||
anchors {
|
||||
bottom: parent.bottom
|
||||
right: parent.right
|
||||
}
|
||||
visible: ( (Etat_commande_carte !== shipheart_etat_commande_module_ok)
|
||||
|| (Etat_circuit !== shipheart_etat_circuit_ok)
|
||||
|| (Etat_events > 0) )
|
||||
&& (model.Etat_systeme === 0) // SDIR #285
|
||||
}
|
||||
|
||||
MouseArea { // Zone d'interaction Paramètres du circuit
|
||||
id: mouse_area_zone_parametres
|
||||
x: 0
|
||||
y: 0
|
||||
anchors.fill: parent
|
||||
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
stackView.push("circuit.qml", {"id_circuit": model.Cle_primaire, "consigne": model.Consigne })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Zone du nom (en haut à gauche et au milieu) :
|
||||
//-------------------------------------------------------
|
||||
Rectangle {
|
||||
id: nom
|
||||
color: "transparent"
|
||||
x: 0
|
||||
y: 0
|
||||
width: (parent.width * pourcentage_largeur_zone_affichage_nom) - espace_interne
|
||||
height: parent.height / 2;
|
||||
|
||||
Text {
|
||||
text: model.Nom
|
||||
anchors.fill: parent // Permet que le texte occupe tout l'espace du parent (et que le centrage vertical qui suit fonctionne...)
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
leftPadding: 10
|
||||
font.pixelSize: 15
|
||||
font.weight: Font.Bold
|
||||
color: couleur_blanc_casse
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Zone de cdes auto (en haut au centre) :
|
||||
//-------------------------------------------------------
|
||||
Rectangle {
|
||||
id: cdes_auto
|
||||
x: parent.width * pourcentage_largeur_zone_affichage_nom
|
||||
y: 0;
|
||||
width: (parent.width * (1 - pourcentage_largeur_zone_affichage_nom - pourcentage_largeur_zone_affichage_consigne));
|
||||
height: parent.height;
|
||||
radius: shipheart_rayon_bouton
|
||||
color: shipheart_couleur_fond_bouton
|
||||
visible: (model.Etat_systeme === 0) && (model.Validation_cdes_events >= 0)
|
||||
|
||||
Text {
|
||||
text: "Auto" // Attention : Non traduit...
|
||||
anchors.fill: parent // Permet que le texte occupe tout l'espace du parent (et que le centrage vertical qui suit fonctionne...)
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
font.pixelSize: 15
|
||||
font.weight: Font.Bold
|
||||
color : (model.Validation_cdes_events === 0) ? couleur_gris_moyen : couleur_green_yellow
|
||||
}
|
||||
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_cdes_auto
|
||||
x: 0
|
||||
y: 0
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
pressAndHoldInterval: shipheart_mouse_press_and_hold_interval_long
|
||||
onPressAndHold: {
|
||||
shipheart_clic();
|
||||
toggle_cdes_auto();
|
||||
timer_home.restart(); // Permet de réarmer le timer (qui ne doit PAS être 'triggeredOnStart' !) afin de reporter la prochaine mise à jour à une période entière de timer. Cela évite qu'un raffraichissement arrive trop tôt, avant que la nouvelle consigne ne soit prise en compte => On>Off>On ou Off>On>Off...
|
||||
}
|
||||
}
|
||||
// Halo autour du bouton pendant l'appui :
|
||||
Rectangle {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
width: Math.max(parent.width, parent.height) + 100
|
||||
height: width
|
||||
radius: width / 2
|
||||
color : (model.Validation_cdes_events === 0) ? couleur_gris_moyen : couleur_green_yellow
|
||||
opacity: 0.2
|
||||
visible: mouse_area_cdes_auto.pressed
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Zone du courant instantané (en bas à gauche) :
|
||||
//-------------------------------------------------------
|
||||
Rectangle {
|
||||
id: courant_instantane
|
||||
color: "transparent" // Sinon, le fond du rectangle est blanc...
|
||||
x: 0
|
||||
y: hauteur_bouton / 2;
|
||||
width: parent.width * pourcentage_largeur_zone_affichage_nom;
|
||||
height: parent.height / 2;
|
||||
visible: (model.Etat_systeme === 0) ? (consigne_principale.text !== qsTr("Off")) : 0
|
||||
|
||||
Image {
|
||||
source: "/images/icone_consommation_electrique.png"
|
||||
sourceSize.height: 20
|
||||
anchors.left: courant_instantane.left
|
||||
anchors.leftMargin: 5
|
||||
anchors.verticalCenter: courant_instantane.verticalCenter
|
||||
}
|
||||
|
||||
Text {
|
||||
text: (model.Type_circuit !== shipheart_type_module_shippower4AC ?
|
||||
"DC " + model.Tension.toFixed(2) + " V " + (model.Intensite > shipheart_plancher_intensite_circuit_sp8xx ? " | " + model.Intensite.toFixed(2) + " A | " + (model.Tension * model.Intensite).toFixed(0) + " W" : "") :
|
||||
"AC " + model.Tension.toFixed(0) + " V | " + model.Frequence.toFixed(1) + " Hz " + (model.Intensite > shipheart_plancher_intensite_circuit_sp4ac ? " | " + model.Intensite.toFixed(1) + " A | " + (model.Tension * model.Intensite).toFixed(0) + " VA" : ""))
|
||||
|
||||
anchors.fill: parent // Permet que le texte occupe tout l'espace du parent (et que le centrage vertical qui suit fonctionne...)
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
leftPadding: 20
|
||||
font.pixelSize: 12
|
||||
color: couleur_gris_tres_tres_pale
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Zone de consigne (au milieu, à droite) :
|
||||
//-------------------------------------------------------
|
||||
Rectangle {
|
||||
id: consigne
|
||||
x: (parent.width * (1 - pourcentage_largeur_zone_affichage_consigne)) + espace_interne
|
||||
width: (parent.width * pourcentage_largeur_zone_affichage_consigne) - espace_interne
|
||||
height: parent.height;
|
||||
//color: (model.Etat_commande_carte === shipheart_etat_commande_module_ok) ? ((model.Consigne === 0) ? couleur_rouge_transparent : couleur_vert_transparent) : "transparent"
|
||||
color: (model.Etat_commande_carte === shipheart_etat_commande_module_ok) ? ((model.Consigne === 0) ? shipheart_couleur_fond_bouton : couleur_vert_transparent) : "transparent" // SDIR #207
|
||||
radius: shipheart_rayon_bouton
|
||||
border.width: (model.Etat_commande_carte === shipheart_etat_commande_module_ok) ? 0 : 3
|
||||
border.color: (model.Etat_commande_carte === shipheart_etat_commande_module_ok) ? // SDIR #182
|
||||
((model.Consigne === 0) ? couleur_rouge : couleur_green_yellow) : // SDIR #159. En pratique, inutile car dans ce cas, border.width=0
|
||||
// ((model.Mode_test === 0) ? couleur_rouge : couleur_green_yellow) // SDIR #182
|
||||
((model.Mode_test === 0) ? shipheart_couleur_fond_bouton : couleur_green_yellow) // SDIR #182 & SDIR #207
|
||||
visible: (model.Etat_systeme === 0) && ((model.Type_circuit !== shipheart_type_module_shipbase) || (model.No_circuit !== 0))
|
||||
|
||||
Text {
|
||||
id: consigne_principale
|
||||
text: (model.Etat_commande_carte === shipheart_etat_commande_module_undervoltage) ?
|
||||
"Off" :
|
||||
((model.Etat_commande_carte === shipheart_etat_commande_module_ok) ?
|
||||
((model.Consigne === 0) ? qsTr("Off") : qsTr("On")) :
|
||||
((model.Mode_test === 0) ? qsTr("Off") : qsTr("On")))
|
||||
anchors.verticalCenter: consigne.verticalCenter
|
||||
anchors.verticalCenterOffset: ((model.Etat_commande_carte === shipheart_etat_commande_module_ok) && (model.Consigne > 0) && (model.Consigne < 100)) ? -10 : 0
|
||||
anchors.horizontalCenter: consigne.horizontalCenter
|
||||
font.pixelSize: 20
|
||||
font.weight: Font.Bold
|
||||
color: (model.Etat_commande_carte === shipheart_etat_commande_module_ok) ? // SDIR #182
|
||||
((model.Consigne === 0) ? couleur_gris_pale : couleur_green_yellow) : // SDIR #159 & SDIR #207
|
||||
((model.Mode_test === 0) ? couleur_gris_pale : couleur_green_yellow) // SDIR #182 & SDIR #207
|
||||
}
|
||||
|
||||
Text {
|
||||
id: consigne_secondaire
|
||||
text: (model.Etat_commande_carte === shipheart_etat_commande_module_undervoltage) ?
|
||||
"" :
|
||||
((model.Etat_commande_carte === shipheart_etat_commande_module_ok) ?
|
||||
((model.Consigne === 0) ? "" : ((model.Consigne === 100) ? "" : (model.Consigne + "%"))) :
|
||||
"" )
|
||||
anchors.top: consigne_principale.bottom
|
||||
anchors.horizontalCenter: consigne.horizontalCenter
|
||||
font.pixelSize: 16
|
||||
color: (model.Consigne === 0) ? couleur_gris_pale : couleur_green_yellow // SDIR #159 & SDIR #207
|
||||
}
|
||||
|
||||
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_consigne
|
||||
anchors.fill: parent
|
||||
enabled: (model.Etat_commande_carte === shipheart_etat_commande_module_ok) // Si on est en Undelvoltage ou en Test, on rend le bouton inoppérant...
|
||||
pressAndHoldInterval: shipheart_mouse_press_and_hold_interval_long
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
|
||||
var new_consigne;
|
||||
if (model.Consigne === 0)
|
||||
{
|
||||
if (model.Old_consigne === 0) new_consigne = 100; // Si OLD = 0, on passe la consigne à 100%
|
||||
else new_consigne = model.Old_consigne; // Sinon, on applique OLD à NEW
|
||||
}
|
||||
else new_consigne = 0;
|
||||
|
||||
// Mise à jour de la nouvelle consigne :
|
||||
changement_consigne(new_consigne, -1);
|
||||
timer_home.restart(); // Permet de réarmer le timer (qui ne doit PAS être 'triggeredOnStart' !) afin de reporter la prochaine mise à jour à une période entière de timer. Cela évite qu'un raffraichissement arrive trop tôt, avant que la nouvelle consigne ne soit prise en compte => On>Off>On ou Off>On>Off...
|
||||
}
|
||||
onPressAndHold: {
|
||||
shipheart_clic();
|
||||
if ((model.Consigne > 0) && (model.Consigne <100)) // On ne traite l'appui long que si on est ON [ET] en gradateur
|
||||
{
|
||||
// Mise à jour des nouvelles Consigne et Old_consigne :
|
||||
changement_consigne(100, 100);
|
||||
timer_home.restart(); // Permet de réarmer le timer (qui ne doit PAS être 'triggeredOnStart' !) afin de reporter la prochaine mise à jour à une période entière de timer. Cela évite qu'un raffraichissement arrive trop tôt, avant que la nouvelle consigne ne soit prise en compte => On>Off>On ou Off>On>Off...
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Fin de 'Zone de consigne'
|
||||
//-------------------------------------------------------
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Zone d'interaction du circuit lorsque le circuit est ABSENT :
|
||||
//-------------------------------------------------------
|
||||
MouseArea {
|
||||
id: mouse_area_absence
|
||||
anchors.fill: parent
|
||||
width: largeur_bouton * pourcentage_largeur_zone_affichage_nom;
|
||||
height: hauteur_bouton;
|
||||
enabled: (model.Etat_systeme !== 0)
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
stackView.push("circuit.qml", {"id_circuit": model.Cle_primaire })
|
||||
}
|
||||
}
|
||||
// Fin de 'mouse_area_absence'
|
||||
//-------------------------------------------------------
|
||||
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================================================
|
||||
// Mise à jour de la valeuer de consigne
|
||||
//=============================================================================================================
|
||||
function changement_consigne(new_consigne, old_consigne)
|
||||
{
|
||||
var req;
|
||||
|
||||
// Mise à jour immédiate du modèle pour que l'affichage réagisse immédiatement :
|
||||
modele_circuits.setProperty(index , "Consigne", new_consigne);
|
||||
|
||||
// Mise à jour dans la BDD :
|
||||
req = "UPDATE TB_Circuits SET New_consigne=" + new_consigne + " ";
|
||||
if (old_consigne !== -1) req += ", Old_consigne=" + old_consigne + " ";
|
||||
req += " WHERE Cle_primaire='" + model.Cle_primaire + "'";
|
||||
//console.log("Requête = [" + req + "]");
|
||||
bdd.requete_unique(req);
|
||||
|
||||
synchro_bdd(shipheart_type_synchro_data);
|
||||
}
|
||||
|
||||
//=============================================================================================================
|
||||
// Mise à jour de Cdes Auto
|
||||
//=============================================================================================================
|
||||
function toggle_cdes_auto()
|
||||
{
|
||||
var req;
|
||||
var mode;
|
||||
|
||||
if (model.Validation_cdes_events === 0) mode = 1;
|
||||
else mode = 0;
|
||||
|
||||
// Mise à jour immédiate du modèle pour que l'affichage réagisse immédiatement :
|
||||
modele_circuits.setProperty(index , "Validation_cdes_events", mode);
|
||||
|
||||
// Mise à jour dans la BDD :
|
||||
bdd.requete_unique("UPDATE TB_Circuits SET Validation_cdes_events=" + mode + " WHERE Cle_primaire='" + model.Cle_primaire + "'")
|
||||
|
||||
// Note : le modèle sera ensuite remis à jour par la routine périodique dans HOME. en l'occurence, le modèle sera déjà à jour sur ce champ...
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,200 @@
|
||||
//-----------------------------------------------------------------------------------------------------
|
||||
// Fichier définissant un bouton de type Réservoir sur la page d'accueil
|
||||
// A priori, appelé depuis "home.qml"
|
||||
//-----------------------------------------------------------------------------------------------------
|
||||
import QtQuick 2.12
|
||||
|
||||
import"fonctions.js" as Fonctions
|
||||
|
||||
//=======================================================
|
||||
// Ensemble du bouton
|
||||
//=======================================================
|
||||
Rectangle {
|
||||
id: bouton_reservoir
|
||||
|
||||
readonly property int largeur_bouton: reservoirs_grid.cellWidth - espace_colonnes_secondaires;
|
||||
readonly property int hauteur_bouton: reservoirs_grid.cellHeight - espace_lignes_secondaires;
|
||||
readonly property double pourcentage_largeur_zone_affichage_nom: 0.85
|
||||
readonly property int seuil_haut: 75 // utilisé pour changer de couleur orange/vert
|
||||
readonly property int seuil_bas: 25 // utilisé pour changer de couleur rouge/orange
|
||||
|
||||
width: largeur_bouton
|
||||
height: hauteur_bouton
|
||||
radius: shipheart_rayon_bouton
|
||||
color: "transparent" // On ne peut pas mettre l'opacité sur celui-ci, sinon tous ses enfants sont aussi semi-transparents...
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Bouton dans son ensemble :
|
||||
//-------------------------------------------------------
|
||||
Rectangle {
|
||||
width: largeur_bouton;
|
||||
height: hauteur_bouton;
|
||||
color: shipheart_couleur_fond_bouton
|
||||
radius: shipheart_rayon_bouton
|
||||
border.color: couleur_rouge
|
||||
border.width: (model.Etat_systeme === 0) ? 0 : 3
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
width: largeur_bouton;
|
||||
height: hauteur_bouton;
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
stackView.push("reservoir.qml",
|
||||
{
|
||||
"id_reservoir": model.Cle_primaire,
|
||||
"nom_reservoir": model.Nom,
|
||||
"niveau": model.Niveau,
|
||||
"capacite": model.Capacite,
|
||||
"id_famille": model.ID_Famille
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Zone du nom (en haut à gauche) :
|
||||
//-------------------------------------------------------
|
||||
Rectangle {
|
||||
id: zone_nom
|
||||
width: largeur_bouton * pourcentage_largeur_zone_affichage_nom;
|
||||
height: hauteur_bouton / 2;
|
||||
color: "transparent"
|
||||
|
||||
Text {
|
||||
text: model.Nom
|
||||
anchors.fill: parent // Permet que le texte occupe tout l'espace du parent (et que le centrage vertical qui suit fonctionne...)
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
leftPadding: 10
|
||||
font.pixelSize: 15
|
||||
elide: Text.ElideRight
|
||||
font.weight: Font.Bold
|
||||
color: couleur_blanc_casse
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Zone niveau absolu :
|
||||
//-------------------------------------------------------
|
||||
Rectangle {
|
||||
id: zone_niveau_absolu
|
||||
y: hauteur_bouton / 2;
|
||||
width: largeur_bouton * pourcentage_largeur_zone_affichage_nom;
|
||||
height: hauteur_bouton / 2;
|
||||
color: "transparent"
|
||||
visible: (model.Etat_systeme === 0)
|
||||
|
||||
//-------------------------
|
||||
// Triangle orange d'alerte :
|
||||
Image {
|
||||
source: "/images/coin_bas_droite_orange.png"
|
||||
sourceSize.height: 20
|
||||
anchors {
|
||||
bottom: parent.bottom
|
||||
right: parent.right
|
||||
}
|
||||
visible: (model.Etat_systeme === 0) // SDIR #285
|
||||
&& (model.Etat === 1) // SDIR #285
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
// Triangle rouge d'alarme :
|
||||
Image {
|
||||
source: "/images/coin_bas_droite_rouge.png"
|
||||
sourceSize.height: 20
|
||||
anchors {
|
||||
bottom: parent.bottom
|
||||
right: parent.right
|
||||
}
|
||||
visible: (model.Etat_systeme === 0) // SDIR #285
|
||||
&& (model.Etat === 2) // SDIR #285
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
// Contenance actuelle :
|
||||
Text {
|
||||
id: niveau_absolu
|
||||
text: Fonctions.conversion_volume(((model.Niveau / 100) * model.Capacite), shipheart_unite_volume, shipheart_unite_volume_symbole, 0);
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
font.pixelSize: 18
|
||||
font.bold: true
|
||||
color: couleur_blanc_casse
|
||||
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
// Capacité :
|
||||
Text {
|
||||
id: capacite
|
||||
text: "/ " + Fonctions.conversion_volume(model.Capacite, shipheart_unite_volume, shipheart_unite_volume_symbole, 0);
|
||||
anchors {
|
||||
left: niveau_absolu.right
|
||||
leftMargin: 20
|
||||
bottom: niveau_absolu.bottom
|
||||
}
|
||||
font.pixelSize: 15
|
||||
color: couleur_gris_moyen
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Zone niveau relatif :
|
||||
//-------------------------------------------------------
|
||||
Rectangle {
|
||||
id: zone_niveau_relatif
|
||||
color: "transparent" // Sinon, le fond du rectangle est blanc...
|
||||
x: largeur_bouton * pourcentage_largeur_zone_affichage_nom
|
||||
width: largeur_bouton * (1 - pourcentage_largeur_zone_affichage_nom);
|
||||
height: hauteur_bouton;
|
||||
radius: shipheart_rayon_bouton
|
||||
border.color: couleur_fond_bargraph_niveau_relatif()
|
||||
border.width: 1
|
||||
visible: (model.Etat_systeme === 0)
|
||||
|
||||
Text {
|
||||
id:zone_texte_niveau_relatif
|
||||
text: (model.Niveau).toFixed(0) + " %";
|
||||
anchors.fill: parent // Permet que le texte occupe tout l'espace du parent (et que le centrage vertical qui suit fonctionne...)
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
font.pixelSize: 12
|
||||
font.bold: (model.Niveau < 10) // soit < 10%
|
||||
color: couleur_texte_niveau_relatif()
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id:zone_bargraph_niveau_relatif
|
||||
color: couleur_fond_bargraph_niveau_relatif()
|
||||
y: parent.height * (100 - model.Niveau) / 100
|
||||
width: parent.width;
|
||||
height: parent.height * model.Niveau / 100;
|
||||
radius: shipheart_rayon_bouton
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
function couleur_texte_niveau_relatif()
|
||||
{
|
||||
switch(model.Logique)
|
||||
{
|
||||
case 1: return((model.Niveau >= seuil_haut) ? couleur_rouge : ((model.Niveau >= seuil_bas) ? couleur_orange : couleur_green_yellow))
|
||||
case 0: return((model.Niveau >= seuil_haut) ? couleur_rouge : ((model.Niveau >= seuil_bas) ? couleur_green_yellow : couleur_rouge))
|
||||
default: return((model.Niveau >= seuil_haut) ? couleur_green_yellow : ((model.Niveau >= seuil_bas) ? couleur_orange : couleur_rouge))
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------
|
||||
function couleur_fond_bargraph_niveau_relatif()
|
||||
{
|
||||
switch(model.Logique)
|
||||
{
|
||||
case 1: return((model.Niveau >= seuil_haut) ? couleur_rouge_transparent : ((model.Niveau >= seuil_bas) ? couleur_orange_transparent : couleur_vert_transparent))
|
||||
case 0: return((model.Niveau >= seuil_haut) ? couleur_rouge_transparent : ((model.Niveau >= seuil_bas) ? couleur_vert_transparent : couleur_rouge_transparent))
|
||||
default: return((model.Niveau >= seuil_haut) ? couleur_vert_transparent : ((model.Niveau >= seuil_bas) ? couleur_orange_transparent : couleur_rouge_transparent))
|
||||
}
|
||||
}
|
||||
}
|
||||
Executable
+68
@@ -0,0 +1,68 @@
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
|
||||
BusyIndicator {
|
||||
id: busy_indicator
|
||||
|
||||
running: false
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
width: 120
|
||||
height: width // Par principe, la forme est carrée...
|
||||
contentItem: Item {
|
||||
x: parent.width / 2
|
||||
y: parent.height / 2
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
|
||||
Item {
|
||||
id: item
|
||||
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
opacity: busy_indicator.running ? 1 : 0
|
||||
|
||||
Behavior on opacity { // Permet l'apparition et la disparition progressive du BI
|
||||
OpacityAnimator {
|
||||
duration: 250
|
||||
}
|
||||
}
|
||||
|
||||
RotationAnimator { // Donne le mouvement de rotation de l'ensemble des points
|
||||
target: item
|
||||
running: true
|
||||
from: 0
|
||||
to: 360
|
||||
loops: Animation.Infinite
|
||||
duration: 1000 // Durée d'un tour complet
|
||||
}
|
||||
|
||||
Repeater {
|
||||
id: repeater
|
||||
model: 7 // Nombre de points formant le BI
|
||||
|
||||
Rectangle {
|
||||
x: (item.width / 2) - (width / 2)
|
||||
y: (item.height / 2) - (height / 2)
|
||||
implicitWidth: item.width / 5 // Largeur du point
|
||||
implicitHeight: item.height / 5 // Hauteur du point
|
||||
radius: implicitWidth / 2 // Donne la forme circulaire du point
|
||||
color: shipheart_couleur_fond_boite_dialogue_niveau_0 // Couleur du point
|
||||
opacity: (index + 1) / (repeater.count + 1) // Donne l'opacité variable des points
|
||||
transform: [
|
||||
Translate {
|
||||
y: -(Math.min(item.width, item.height) / 2) + (width / 2) // Permet de positionner le premier point en haut et au centre de la zone
|
||||
},
|
||||
Rotation {
|
||||
angle: (index / repeater.count) * 360 // Tourne de x° en fonction de l'index
|
||||
origin.x: width / 2 // Le centre de rotation est le centre de la zone
|
||||
origin.y: height / 2
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
import QtQuick 2.12
|
||||
|
||||
|
||||
Rectangle {
|
||||
id: formulaire_bouton
|
||||
|
||||
property bool actif: false
|
||||
property bool affichage_fleche: false // Indique si l'on affiche les flèches haut/bas, ou pas.
|
||||
property bool fleche_haut: false // Utilisé uniquement si 'affichage_fleche' est TRUE, indique si la flèche à utiliser est vers le haut (true) ou vers le bas (false)
|
||||
property string titre: ""
|
||||
property color couleur_titre: couleur_blanc_casse
|
||||
property bool gras_titre: false
|
||||
|
||||
color: actif ? shipheart_couleur_fond_bouton_actif : shipheart_couleur_fond_bouton
|
||||
radius: shipheart_rayon_bouton
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
height: parent.height - 10 // Nb : la Width est donnée au moment de l'appel de Combobox
|
||||
|
||||
|
||||
Image {
|
||||
source: "/images/up.png"
|
||||
sourceSize.height: 15
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
right: parent.right
|
||||
rightMargin: 20
|
||||
}
|
||||
visible: affichage_fleche && fleche_haut
|
||||
}
|
||||
|
||||
Image {
|
||||
source: "/images/down.png"
|
||||
sourceSize.height: 15
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
right: parent.right
|
||||
rightMargin: 20
|
||||
}
|
||||
visible: affichage_fleche && !fleche_haut
|
||||
}
|
||||
|
||||
Text {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
text: titre
|
||||
font.pixelSize: 18
|
||||
font.bold: gras_titre
|
||||
color: couleur_titre
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
CheckBox {
|
||||
id: formulaire_checkbox
|
||||
|
||||
property bool flag_num_only: false
|
||||
property bool password_type: false
|
||||
|
||||
anchors {
|
||||
right: parent.right
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
width: parent.width - 50
|
||||
height: parent.height - 10
|
||||
|
||||
tristate: false
|
||||
checked: false
|
||||
text: ""
|
||||
font.pixelSize: 18
|
||||
indicator: Rectangle {
|
||||
anchors {
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
implicitWidth: 40
|
||||
implicitHeight: 40
|
||||
radius: 5
|
||||
color: "transparent"
|
||||
border.color: couleur_gris_tres_fonce //couleur_bleu_koriolan_clair
|
||||
border.width: formulaire_checkbox.checked ? 0 : 1
|
||||
Rectangle {
|
||||
visible: formulaire_checkbox.checked
|
||||
color: couleur_gris_tres_tres_pale //couleur_bleu_koriolan_clair
|
||||
radius: 5
|
||||
anchors.fill: parent
|
||||
}
|
||||
Text {
|
||||
visible: formulaire_checkbox.checked
|
||||
text: "\u2713" // U+2714 est la coche épaisse, U+2713 est la coche normale
|
||||
color: couleur_bleu_koriolan
|
||||
font.pixelSize: parent.height
|
||||
anchors {
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Executable
+121
@@ -0,0 +1,121 @@
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
|
||||
ComboBox {
|
||||
id: formulaire_combobox
|
||||
|
||||
property bool groupe: false
|
||||
property bool actif: true
|
||||
property string prefixe_repos: ""
|
||||
property string suffixe_repos: ""
|
||||
|
||||
//=============================================================================================
|
||||
// Partie au repos :
|
||||
//=============================================================================================
|
||||
|
||||
anchors {
|
||||
right: parent.right
|
||||
leftMargin: 20
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
// height: parent.height - 10 // Nb : la Width est donnée au moment de l'appel de Combobox
|
||||
height: Math.max( (combobox_text.contentHeight + 10), (hauteur_ligne_formulaire - 10) )
|
||||
textRole: "texte"
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
// Petite image dans la version repos :
|
||||
indicator: Image {
|
||||
id: icone_combo_box
|
||||
source: "/images/down.png"
|
||||
sourceSize.height: 15
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
right: parent.right
|
||||
rightMargin: 20
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
// Texte au repos :
|
||||
contentItem: Text {
|
||||
id: combobox_text
|
||||
leftPadding: 10
|
||||
rightPadding: formulaire_combobox.indicator.width + formulaire_combobox.spacing
|
||||
text: prefixe_repos + formulaire_combobox.currentText + suffixe_repos
|
||||
font.pixelSize: 18
|
||||
color: couleur_blanc_casse
|
||||
wrapMode: Text.Wrap
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
textFormat: Text.RichText
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
// Fond au repos
|
||||
background: Rectangle {
|
||||
radius: shipheart_rayon_bouton
|
||||
color: shipheart_couleur_fond_bouton
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================================
|
||||
// Partie dépliée :
|
||||
//=============================================================================================
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
// Fond :
|
||||
popup: Popup {
|
||||
y: formulaire_combobox.height - 1
|
||||
width: formulaire_combobox.width
|
||||
implicitHeight: contentItem.implicitHeight
|
||||
padding: 0
|
||||
|
||||
// Note : si une un warning gest émis sur cette ligne, du genre 'ListView: Binding loop detected for property "implicitHeight"', c'est que la hauteur des lignes
|
||||
// de la comboxbox (lorsqu'elle est ouverte) est trop importante. Une solution est de fixer la hauteur des lignes (cf la ligne commentée (92 environ) ci-dessous)
|
||||
// L'inconvénient est que toutes les lignes ont alors la même hauteur... Il semble que ce warning ne soit pas grave donc laissé en l'état pour le moment... (02/2023)
|
||||
|
||||
contentItem: ListView { // Listview listant les éléments dépliés
|
||||
clip: true
|
||||
implicitHeight: contentHeight
|
||||
model: formulaire_combobox.popup.visible ? formulaire_combobox.delegateModel : null
|
||||
currentIndex: formulaire_combobox.highlightedIndex
|
||||
|
||||
ScrollIndicator.vertical: ScrollIndicator { } // Scrollbar quand il y a beaucoup d'éléments dépliés
|
||||
}
|
||||
|
||||
background: Rectangle { // Fond de la partie dépliée
|
||||
color: "transparent"
|
||||
radius: shipheart_rayon_bouton
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
// Eléments dépliés :
|
||||
delegate: ItemDelegate {
|
||||
|
||||
width: formulaire_combobox.width
|
||||
//height: 100
|
||||
enabled: groupe ? false : (actif ? true : false)
|
||||
contentItem: Text { // Texte des éléments dépliés
|
||||
text: model.texte
|
||||
color: groupe ? couleur_bleu_koriolan : (actif ? couleur_blanc_casse : couleur_gris_tres_pale_transparent)
|
||||
font.pixelSize: 18
|
||||
font.weight: groupe ? Font.Bold : Font.Normal
|
||||
topPadding: 5
|
||||
bottomPadding: 5
|
||||
leftPadding: groupe ? 0 : 30
|
||||
rightPadding: formulaire_combobox.indicator.width + formulaire_combobox.spacing
|
||||
wrapMode: Text.Wrap
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
textFormat: Text.RichText
|
||||
}
|
||||
background: Rectangle { // Fond de chaque entrée dépliée
|
||||
border.width: model.erreur ? 2 : 1
|
||||
border.color: model.erreur ? couleur_rouge : couleur_gris_fonce
|
||||
radius: shipheart_rayon_bouton
|
||||
color: (highlightedIndex === index) ? couleur_bleu_koriolan : couleur_gris_tres_fonce
|
||||
|
||||
}
|
||||
highlighted: highlightedIndex === index
|
||||
}
|
||||
}
|
||||
Executable
+168
@@ -0,0 +1,168 @@
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
|
||||
ComboBox {
|
||||
id: formulaire_combobox
|
||||
|
||||
property bool groupe: false
|
||||
property bool actif: true
|
||||
property string prefixe_repos: ""
|
||||
property string suffixe_repos: ""
|
||||
|
||||
//=============================================================================================
|
||||
// Partie au repos :
|
||||
//=============================================================================================
|
||||
|
||||
anchors {
|
||||
right: parent.right
|
||||
leftMargin: 20
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
height: parent.height - 10 // Nb : la Width est donnée au moment de l'appel de Combobox
|
||||
textRole: "texte"
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
// Petite image dans la version repos :
|
||||
indicator: Image {
|
||||
id: icone_combo_box
|
||||
source: "/images/down.png"
|
||||
sourceSize.height: 15
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
right: parent.right
|
||||
rightMargin: 20
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
// Texte au repos :
|
||||
contentItem: Rectangle {
|
||||
color: "transparent"
|
||||
anchors.fill: parent
|
||||
|
||||
//-------------------------------------
|
||||
// Icone :
|
||||
Image {
|
||||
source: (formulaire_combobox.currentIndex >= 0) && (formulaire_combobox.model.get(formulaire_combobox.currentIndex).icone !== "")
|
||||
? "/images/" + formulaire_combobox.model.get(formulaire_combobox.currentIndex).icone
|
||||
: ""
|
||||
fillMode: Image.PreserveAspectFit
|
||||
height: parent.height * 0.6
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
left: parent.left
|
||||
leftMargin: 10
|
||||
}
|
||||
visible: (formulaire_combobox.currentIndex >= 0)
|
||||
&& (formulaire_combobox.model.get(formulaire_combobox.currentIndex).icone !== "")
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
// Texte :
|
||||
Text {
|
||||
leftPadding: 10
|
||||
rightPadding: formulaire_combobox.indicator.width + formulaire_combobox.spacing
|
||||
text: prefixe_repos + formulaire_combobox.currentText + suffixe_repos
|
||||
font.pixelSize: 18
|
||||
color: couleur_blanc_casse
|
||||
wrapMode: Text.Wrap
|
||||
anchors.fill: parent
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
textFormat: Text.RichText
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
// Fond au repos
|
||||
background: Rectangle {
|
||||
radius: shipheart_rayon_bouton
|
||||
color: shipheart_couleur_fond_bouton
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================================
|
||||
// Partie dépliée :
|
||||
//=============================================================================================
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
// Fond :
|
||||
popup: Popup {
|
||||
y: formulaire_combobox.height - 1
|
||||
width: formulaire_combobox.width
|
||||
implicitHeight: contentItem.implicitHeight
|
||||
padding: 0
|
||||
|
||||
// Note : si une un warning gest émis sur cette ligne, du genre 'ListView: Binding loop detected for property "implicitHeight"', c'est que la hauteur des lignes
|
||||
// de la comboxbox (lorsqu'elle est ouverte) est trop importante. Une solution est de fixer la hauteur des lignes (cf la ligne commentée (95 environ) ci-dessous)
|
||||
// L'inconvénient est que toutes les lignes ont alors la même hauteur... Il semble que ce warning ne soit pas grave donc laissé en l'état pour le moment... (02/2023)
|
||||
|
||||
contentItem: ListView { // Listview listant les éléments dépliés
|
||||
clip: true
|
||||
implicitHeight: contentHeight
|
||||
model: formulaire_combobox.popup.visible ? formulaire_combobox.delegateModel : null
|
||||
currentIndex: formulaire_combobox.highlightedIndex
|
||||
|
||||
ScrollIndicator.vertical: ScrollIndicator { } // Scrollbar quand il y a beaucoup d'éléments dépliés
|
||||
}
|
||||
|
||||
background: Rectangle { // Fond de la partie dépliée
|
||||
color: "transparent"
|
||||
radius: shipheart_rayon_bouton
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
// Eléments dépliés :
|
||||
delegate: ItemDelegate {
|
||||
|
||||
width: formulaire_combobox.width
|
||||
height: 50
|
||||
enabled: groupe ? false : (actif ? true : false)
|
||||
contentItem: Rectangle {
|
||||
color: "transparent"
|
||||
anchors.fill: parent
|
||||
|
||||
//-------------------------------------
|
||||
// Icone :
|
||||
Image {
|
||||
source: (model.icone !== "")
|
||||
? "/images/" + model.icone
|
||||
: ""
|
||||
fillMode: Image.PreserveAspectFit
|
||||
height: parent.height * 0.6
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
left: parent.left
|
||||
leftMargin: 10
|
||||
}
|
||||
visible: (model.icone !== "")
|
||||
}
|
||||
|
||||
//-------------------------------------
|
||||
// Texte :
|
||||
Text { // Texte des éléments dépliés
|
||||
text: model.texte
|
||||
color: groupe ? couleur_bleu_koriolan : (actif ? couleur_blanc_casse : couleur_gris_tres_pale_transparent)
|
||||
font.pixelSize: 18
|
||||
font.weight: groupe ? Font.Bold : Font.Normal
|
||||
topPadding: 5
|
||||
bottomPadding: 5
|
||||
leftPadding: groupe ? 5 : 35
|
||||
rightPadding: formulaire_combobox.indicator.width + formulaire_combobox.spacing
|
||||
wrapMode: Text.Wrap
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
textFormat: Text.RichText
|
||||
anchors.fill: parent
|
||||
}
|
||||
}
|
||||
background: Rectangle { // Fond de chaque entrée dépliée
|
||||
border.width: model.erreur ? 2 : 1
|
||||
border.color: model.erreur ? couleur_rouge : couleur_gris_fonce
|
||||
radius: shipheart_rayon_bouton
|
||||
color: (highlightedIndex === index) ? couleur_bleu_koriolan : couleur_gris_tres_fonce
|
||||
|
||||
}
|
||||
highlighted: highlightedIndex === index
|
||||
}
|
||||
}
|
||||
Executable
+17
@@ -0,0 +1,17 @@
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
|
||||
|
||||
Label {
|
||||
|
||||
property color couleur: shipheart_formulaire_couleur_texte_par_defaut
|
||||
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
// horizontalAlignment: Text.AlignHCenter
|
||||
leftPadding: 20
|
||||
width: parent.width
|
||||
font.pixelSize: 18
|
||||
color: couleur
|
||||
text: "--"
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import QtQuick 2.12
|
||||
|
||||
|
||||
Item {
|
||||
id: ligne_separation
|
||||
|
||||
property int haut_bas_hautbas: shipheart_formulaire_ligne_separation_haute_basse // 1= haut, 2= bas, 3= haut et bas
|
||||
property int force: shipheart_formulaire_ligne_separation_force_faible // 1=très clair, 2=moyen, 3=très vif
|
||||
property double largeur_parent: parent.width
|
||||
property double hauteur_parent: parent.height
|
||||
property int epaisseur_ligne: 1
|
||||
|
||||
Rectangle { // Trait du haut :
|
||||
width: largeur_parent
|
||||
height: epaisseur_ligne
|
||||
color: force === shipheart_formulaire_ligne_separation_force_faible ? couleur_gris_tres_fonce_transparent : (force === shipheart_formulaire_ligne_separation_force_moyenne ? couleur_gris_fonce : couleur_gris_pale)
|
||||
visible: ((haut_bas_hautbas & 1) === 1) ? true : false
|
||||
}
|
||||
|
||||
Rectangle { // Trait du bas :
|
||||
y: hauteur_parent - epaisseur_ligne
|
||||
width: largeur_parent
|
||||
height: epaisseur_ligne
|
||||
color: force === shipheart_formulaire_ligne_separation_force_faible ? couleur_gris_tres_fonce_transparent : (force === shipheart_formulaire_ligne_separation_force_moyenne ? couleur_gris_fonce : couleur_gris_pale)
|
||||
visible: ((haut_bas_hautbas & 2) === 2) ? true : false
|
||||
}
|
||||
}
|
||||
Executable
+41
@@ -0,0 +1,41 @@
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
|
||||
// Toutes les valeurs ci-dessous sont des valeurs par défaut qui passent à peu près partout.
|
||||
// Mais elles peuvent toutes êtes overridées lors de l'appel de la forme :
|
||||
//
|
||||
// Shipheart_formulaire_textfield {
|
||||
// text: libelle
|
||||
// placeholderText: qsTr("truc bidule")
|
||||
// anchors.left: label.right
|
||||
// width: parent.width - label.width - anchors.leftMargin
|
||||
// ... etc...
|
||||
// }
|
||||
|
||||
|
||||
|
||||
TextArea {
|
||||
id: formulaire_textarea
|
||||
|
||||
anchors {
|
||||
right: parent.right
|
||||
top: parent.top
|
||||
}
|
||||
padding: 10
|
||||
|
||||
placeholderText: ""
|
||||
placeholderTextColor: couleur_gris_tres_pale_transparent
|
||||
|
||||
font.pixelSize: 18
|
||||
color: couleur_blanc_casse
|
||||
font.family: shipheart_font_saisie_textarea
|
||||
|
||||
|
||||
text: ""
|
||||
background: Rectangle {
|
||||
color: shipheart_couleur_fond_bouton
|
||||
radius: shipheart_rayon_bouton
|
||||
}
|
||||
|
||||
}
|
||||
Executable
+53
@@ -0,0 +1,53 @@
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
// Toutes les valeurs ci-dessous sont des valeurs par défaut qui passent à peu près partout.
|
||||
// Mais elles peuvent toutes êtes overridées lors de l'appel de la forme :
|
||||
//
|
||||
// Shipheart_formulaire_textfield {
|
||||
// text: libelle
|
||||
// placeholderText: qsTr("truc bidule")
|
||||
// anchors.left: label.right
|
||||
// width: parent.width - label.width - anchors.leftMargin
|
||||
// ... etc...
|
||||
// }
|
||||
|
||||
|
||||
|
||||
TextField {
|
||||
id: formulaire_textfield
|
||||
|
||||
property bool flag_num_only: false
|
||||
property bool password_type: false
|
||||
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
leftPadding: 10
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
|
||||
width: parent.width
|
||||
height: parent.height - 10
|
||||
placeholderText: ""
|
||||
inputMethodHints: flag_num_only ? Qt.ImhDigitsOnly : Qt.ImhNone // Affiche les chiffres et le '.' mais pas les signes (notamment, impossible d'entrer '-')
|
||||
// inputMethodHints: flag_num_only ? Qt.ImhFormattedNumbersOnly : Qt.ImhNone
|
||||
// inputMethodHints: flag_num_only ? Qt.ImhPreferNumbers : Qt.ImhNone // Affiche les chiffres et les signes, y compris '-'
|
||||
|
||||
font.pixelSize: 18
|
||||
color: couleur_blanc_casse
|
||||
font.family: shipheart_font_saisie_textfield
|
||||
font.letterSpacing: password_type ? 5.0 : 1.0 // Evite que les points (en mode pwd) soient collés les uns aux autres
|
||||
|
||||
echoMode: password_type ? TextInput.Password : TextInput.Normal
|
||||
passwordMaskDelay: 1000
|
||||
// passwordCharacter: "="
|
||||
text: ""
|
||||
background: Rectangle {
|
||||
color: shipheart_couleur_fond_bouton
|
||||
radius: shipheart_rayon_bouton
|
||||
}
|
||||
onAccepted: {
|
||||
// console.log("Saisie du Textfield avec valeur = [" + text + "]");
|
||||
}
|
||||
|
||||
}
|
||||
Executable
+15
@@ -0,0 +1,15 @@
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
|
||||
|
||||
Label {
|
||||
|
||||
x: parent.width - width
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
width: parent.width
|
||||
font.pixelSize: 18
|
||||
color: couleur_blanc_casse
|
||||
text: "--"
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import QtQuick.Controls
|
||||
|
||||
Label {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
leftPadding: 10
|
||||
width: parent.width
|
||||
font.pixelSize: 18
|
||||
color: couleur_blanc_casse
|
||||
text: "--"
|
||||
}
|
||||
Executable
+171
@@ -0,0 +1,171 @@
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
// Shipheart_page est un composant au sens QML. Il commence donc par une majuscule.
|
||||
// Il peut être utilisé partout dans le projet.
|
||||
|
||||
Page {
|
||||
|
||||
id: page
|
||||
|
||||
background: Rectangle { // Attention : Background ne peut avoir qu'un seul élément [a priori, pas complètement sûr...] => on créé un Rectangle de plus haut niveau et on met ensuite dedans ce qu'on veut...
|
||||
anchors.fill: parent
|
||||
color: shipheart_theme_couleur_fond_ecran
|
||||
|
||||
Image {
|
||||
anchors.fill: parent
|
||||
fillMode: Image.Tile
|
||||
// fillMode: Image.PreserveAspectCrop
|
||||
source: shipheart_theme_fichier_fond_ecran
|
||||
visible: (shipheart_theme_fichier_fond_ecran !== "")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//=================================================================================================
|
||||
// Fonction : Shipheart_clic
|
||||
// Cette fonction est normalement appelé à chaque appel d'un 'MouseArea.OnClick'
|
||||
//=================================================================================================
|
||||
function shipheart_clic()
|
||||
{
|
||||
emission_bip();
|
||||
reload_economiseur();
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
// Fonction : Vérifie si la configuration en cours nécessite l'émission d'un bip.
|
||||
// Si oui, met à jour le champ correspondant dans la BDD et fait une demande
|
||||
// de synchro pour que celle-ci soit prise en compte rapidmeent.
|
||||
// Reçoit : Rien
|
||||
// Retour : Rien
|
||||
//=====================================================================================
|
||||
function emission_bip()
|
||||
{
|
||||
|
||||
if ((shipheart_bips !== "") && // Si shipheart_bips = "", il n'y a aucun bip à émettre...
|
||||
(shipheart_type_installation === shipheart_type_installation_shipbase)) // SDIR 317 : ... et si on est sur ShipRS, on n'émet pas de bips
|
||||
{
|
||||
bdd.requete_unique("UPDATE TB_Systeme SET Valeur='" + shipheart_bips + "/0/0/0' WHERE Nom='New_bip'");
|
||||
synchro_bdd(shipheart_type_synchro_data);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
// Fonction : Réarmement économiseur
|
||||
//=================================================================================================
|
||||
function reload_economiseur()
|
||||
{
|
||||
var req, res;
|
||||
|
||||
/* // La valeur est relue à chaque fois dans la BDD pour être certain d'avoir la dernière valeur :
|
||||
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom LIKE "%Time_out_economiseur%" ';
|
||||
res = bdd.requete_unique(req);
|
||||
shipheart_compteur_economiseur = Number(res[0]);
|
||||
*/
|
||||
shipheart_compteur_economiseur = shipheart_time_out_economiseur;
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
// Fonction : Demande de mise en veille (on ou off)
|
||||
//=================================================================================================
|
||||
function mise_en_veille(veille)
|
||||
{
|
||||
if (shipheart_type_installation !== shipheart_type_installation_shipbase) return; // SDIR #251
|
||||
|
||||
if (veille === 0) // On sort toujours du mode veille si c'est demandé
|
||||
{
|
||||
bdd.requete_unique('UPDATE TB_Systeme SET Valeur=' + veille + ' WHERE Nom="Veille"');
|
||||
synchro_bdd(shipheart_type_synchro_data);
|
||||
//console.log("Sortie de veille");
|
||||
|
||||
flag_economiseur_actif = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((veille === 1) && (get_validation_economiseur() === 1)) // On ne rentre en veille que si c'est demandé (le time-out a expiré ET l'économiseur est valide)
|
||||
{
|
||||
bdd.requete_unique('UPDATE TB_Systeme SET Valeur=' + veille + ' WHERE Nom="Veille"');
|
||||
synchro_bdd(shipheart_type_synchro_data);
|
||||
|
||||
flag_economiseur_actif = true;
|
||||
}
|
||||
//else console.log("Demande d'activation de l'économiseur alors qu'il est dévalidé")
|
||||
}
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
// Fonction : Change l'état de la validation économiseur
|
||||
//=================================================================================================
|
||||
function changer_validation_economiseur()
|
||||
{
|
||||
var req, res;
|
||||
var new_val;
|
||||
|
||||
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom LIKE "%Validation_economiseur%" ';
|
||||
res = bdd.requete_unique(req);
|
||||
|
||||
if (Number(res[0]) === 0) new_val = '1';
|
||||
else new_val = '0';
|
||||
|
||||
bdd.requete_unique('UPDATE TB_Configuration SET Valeur=' + new_val + ' WHERE Nom LIKE "%Validation_economiseur%" ');
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
// Fonction : Retourne l'état actuel de la validation de l'économiseur
|
||||
//=================================================================================================
|
||||
function get_validation_economiseur()
|
||||
{
|
||||
var req, res;
|
||||
|
||||
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom LIKE "%Validation_economiseur%" ';
|
||||
res = bdd.requete_unique(req);
|
||||
|
||||
return(Number(res[0]));
|
||||
}
|
||||
|
||||
//=================================================================================================
|
||||
// Fonction : Charge les paramètres du thème en cours
|
||||
//=================================================================================================
|
||||
function chargement_theme()
|
||||
{
|
||||
var req, res;
|
||||
|
||||
// Récupération du paramètre 'TB_Configuration.Theme'
|
||||
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Theme" ';
|
||||
res = bdd.requete_unique(req);
|
||||
|
||||
// Vérifie que la n° de thème sélectionné est bien compatible avec les thèmes présents sur cette version (on peut imaginer qu'on en ait supprimé...) :
|
||||
if (Number(res[0]) >= shipheart_config_themes.length)
|
||||
{
|
||||
shipheart_theme = 0; // Valeur par défaut
|
||||
req = 'UPDATE TB_Configuration '; // Mise à jour dans la BDD pour les prochains démarrages
|
||||
req += ' SET Valeur="' + shipheart_theme + '" ';
|
||||
req += ' WHERE Nom="Theme" ';
|
||||
//console.log("Requête = " + req)
|
||||
bdd.requete_unique(req);
|
||||
}
|
||||
else shipheart_theme = Number(res[0]); // Cas normal
|
||||
|
||||
// Mise à jour des paramètres d'affcihage liés au thème choisit :
|
||||
shipheart_theme_fichier_fond_ecran = shipheart_config_themes[shipheart_theme][shipheart_index_theme_fichier_fond_ecran];
|
||||
shipheart_theme_couleur_fond_ecran = shipheart_config_themes[shipheart_theme][shipheart_index_theme_couleur_fond_ecran];
|
||||
shipheart_couleur_fond_bouton_actif = shipheart_config_themes[shipheart_theme][shipheart_index_theme_couleur_fond_bouton_actif];
|
||||
shipheart_couleur_texte_titre_1 = shipheart_config_themes[shipheart_theme][shipheart_index_theme_couleur_texte_titre_1];
|
||||
shipheart_couleur_texte_titre_2 = shipheart_config_themes[shipheart_theme][shipheart_index_theme_couleur_texte_titre_2];
|
||||
shipheart_couleur_texte_titre_3 = shipheart_config_themes[shipheart_theme][shipheart_index_theme_couleur_texte_titre_3];
|
||||
shipheart_couleur_fond_boite_dialogue_niveau_0 = shipheart_config_themes[shipheart_theme][shipheart_index_theme_couleur_fond_boite_dialogue_niveau_0];
|
||||
shipheart_couleur_fond_boite_dialogue_niveau_1 = shipheart_config_themes[shipheart_theme][shipheart_index_theme_couleur_fond_boite_dialogue_niveau_1];
|
||||
shipheart_couleur_fond_boite_dialogue_niveau_2 = shipheart_config_themes[shipheart_theme][shipheart_index_theme_couleur_fond_boite_dialogue_niveau_2];
|
||||
shipheart_couleur_texte_boite_dialogue_niveau_0 = shipheart_config_themes[shipheart_theme][shipheart_index_theme_couleur_texte_boite_dialogue_niveau_0];
|
||||
shipheart_couleur_texte_boite_dialogue_niveau_1 = shipheart_config_themes[shipheart_theme][shipheart_index_theme_couleur_texte_boite_dialogue_niveau_1];
|
||||
shipheart_couleur_texte_boite_dialogue_niveau_2 = shipheart_config_themes[shipheart_theme][shipheart_index_theme_couleur_texte_boite_dialogue_niveau_2];
|
||||
shipheart_couleur_texte_slider = shipheart_config_themes[shipheart_theme][shipheart_index_theme_couleur_texte_slider];
|
||||
shipheart_couleur_bordure_courbes = shipheart_config_themes[shipheart_theme][shipheart_index_theme_couleur_bordure_courbes];
|
||||
|
||||
//console.log("Thème d'affichage à utiliser = " + shipheart_theme + " [fichier = '" + shipheart_theme_fichier_fond_ecran + "' et couleur = '" + shipheart_theme_couleur_fond_ecran + "']");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import QtQuick 2.12
|
||||
|
||||
Rectangle {
|
||||
|
||||
property string titre
|
||||
property int hauteur
|
||||
|
||||
id: titre_1
|
||||
width: parent.width
|
||||
height: hauteur
|
||||
radius: 5
|
||||
color: "transparent"
|
||||
// color: couleur_green_yellow_transparent
|
||||
|
||||
Text {
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
text: titre
|
||||
color: shipheart_couleur_texte_titre_1
|
||||
font.pixelSize : 30
|
||||
font.weight: Font.Black
|
||||
font.capitalization: Font.SmallCaps
|
||||
anchors.verticalCenter: parent.verticalCenter // Centrage vertical sur la hauteur du titre reçu en paramètre
|
||||
anchors.left: parent.left // Nécessaire pour que le leftMargin suivant fonctionne
|
||||
anchors.leftMargin: 10
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
import QtQuick 2.12
|
||||
|
||||
Rectangle {
|
||||
|
||||
property string titre: ""
|
||||
property string icone: ""
|
||||
property int hauteur: visible ? shipheart_hauteur_titre_2 : 0
|
||||
|
||||
width: parent.width
|
||||
height: hauteur
|
||||
radius: 5
|
||||
color: "transparent"
|
||||
// color: couleur_gris_tres_fonce_transparent
|
||||
|
||||
Image {
|
||||
id: icone_titre_2
|
||||
source: (icone !== "") ? "/images/" + icone : "" // Si on laisse '/images/' seule, cela génère une erreur si le nom du fichier est vide...
|
||||
sourceSize.height: parent.height * 0.8
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
left: parent.left
|
||||
}
|
||||
visible: icone !== ""
|
||||
}
|
||||
|
||||
Text {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter // Centrage vertical sur la hauteur du titre reçu en paramètre
|
||||
left: (icone !== "") ? icone_titre_2.right : parent.left
|
||||
leftMargin: 10
|
||||
}
|
||||
|
||||
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
text: titre
|
||||
color: shipheart_couleur_texte_titre_2
|
||||
font.pixelSize : 24
|
||||
// font.weight: Font.Black
|
||||
|
||||
visible: titre !== ""
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
import QtQuick 2.12
|
||||
|
||||
Rectangle {
|
||||
|
||||
property string titre: ""
|
||||
property string icone: ""
|
||||
property int hauteur: visible ? shipheart_hauteur_titre_2 : 0
|
||||
|
||||
width: parent.width
|
||||
height: hauteur
|
||||
radius: 5
|
||||
color: "transparent"
|
||||
// color: couleur_gris_tres_fonce_transparent
|
||||
|
||||
Image {
|
||||
id: icone_titre_3
|
||||
source: (icone !== "") ? "/images/" + icone : "" // Si on laisse '/images/' seule, cela génère une erreur si le nom du fichier est vide...
|
||||
sourceSize.height: parent.height * 0.8
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
left: parent.left
|
||||
}
|
||||
visible: icone !== ""
|
||||
}
|
||||
|
||||
Text {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter // Centrage vertical sur la hauteur du titre reçu en paramètre
|
||||
left: (icone !== "") ? icone_titre_3.right : parent.left
|
||||
leftMargin: 50
|
||||
}
|
||||
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
text: titre
|
||||
color: shipheart_couleur_texte_titre_3
|
||||
font.pixelSize : 21
|
||||
font.weight: Font.Bold
|
||||
|
||||
visible: titre !== ""
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
#include "backend.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QApplication>
|
||||
#include <QQmlApplicationEngine>
|
||||
#include <QTranslator>
|
||||
|
||||
extern QTranslator translator;
|
||||
|
||||
Backend::Backend() : QObject()
|
||||
{
|
||||
}
|
||||
|
||||
//===================================================================================================
|
||||
// Fonction : Reçoit le code de la langue (par exemple 'en_EN') sélectionnée par l'utilisateur,
|
||||
// supprime le fichier de langue en cours et charge le nouveau.
|
||||
//===================================================================================================
|
||||
void Backend::change_langue(QString lang)
|
||||
{
|
||||
if (!translator.isEmpty()) QApplication::instance()->removeTranslator(&translator);
|
||||
|
||||
if (translator.load(":/shipheart_"+ lang))
|
||||
{
|
||||
if (QApplication::instance()->installTranslator(&translator))
|
||||
{
|
||||
QQmlApplicationEngine *engine = QApplication::instance()->findChild<QQmlApplicationEngine *>("currentEngine");
|
||||
engine->retranslate();
|
||||
}
|
||||
else qDebug() << "\tL'installation de " << lang << " a rencontré une erreur. Aucune langue n'est désormais installée (retour au FR)";
|
||||
}
|
||||
else qDebug() << "\tLe chargement de " << lang << " a rencontré une erreur. Aucune langue n'est désormais chargée (retour au FR)";
|
||||
|
||||
QQmlApplicationEngine *engine = QApplication::instance()->findChild<QQmlApplicationEngine *>("currentEngine");
|
||||
engine->retranslate();
|
||||
|
||||
qDebug() << "L'activation de la langue [" << lang << "] a été effectuée avec succès.";
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
#ifndef BACKEND_H
|
||||
#define BACKEND_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QProcess>
|
||||
|
||||
class Backend : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
Backend();
|
||||
// explicit Backend(QObject *parent = 0);
|
||||
|
||||
|
||||
|
||||
public slots:
|
||||
void change_langue(QString lang);
|
||||
};
|
||||
|
||||
#endif // BACKEND_H
|
||||
+2000
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,179 @@
|
||||
#include "bdd.h"
|
||||
|
||||
|
||||
#include <QDebug>
|
||||
#include <QSqlRecord>
|
||||
#include <QSqlQuery>
|
||||
//#include <QDateTime>
|
||||
#include <QCryptographicHash>
|
||||
|
||||
|
||||
//============================================================================
|
||||
// Création du modèle
|
||||
//============================================================================
|
||||
Bdd::Bdd() :
|
||||
QObject() {
|
||||
|
||||
m_lignes.clear();
|
||||
m_ptr_ligne = 0;
|
||||
}
|
||||
|
||||
//================================================================================================================================
|
||||
// Fonction : Lit dans TB_Systeme l'état de 'Etat_cm3p' et le retourne.
|
||||
// Reçoit : Rien
|
||||
// Retour : 0=En cours d'initialisation, 1=Démarré Ok ou -1=Démarrage impossible
|
||||
//================================================================================================================================
|
||||
qint16 Bdd::check_fin_configuration()
|
||||
{
|
||||
QSqlQuery query;
|
||||
bool retour;
|
||||
|
||||
retour = false;
|
||||
|
||||
if (query.exec("SELECT Valeur FROM TB_Systeme WHERE Nom='Etat_cm3p' ")) // Exécution de la requête (sans erreur)
|
||||
{
|
||||
if (query.next()) // Cas normal où on a trouvé une valeur :
|
||||
{
|
||||
retour = query.record().value(0).toInt();
|
||||
}
|
||||
else qDebug() << "La requête n'a renvoyé aucune valeur...";
|
||||
}
|
||||
else qDebug() << "/!\\ Erreur d'exécution de la requête !";
|
||||
|
||||
return(retour);
|
||||
}
|
||||
|
||||
|
||||
//================================================================================================================================
|
||||
// Fonction : Exécute la requête SQL reçue en paramètre puis va récupérer les résultats. Seule le premier enregistrement est
|
||||
// retourné car je ne sais pas renvoyer un vecteur de StringList (seul les vecteurs de String fonctionnent côté QML).
|
||||
// Juste avant le retour, on appelle la fonction de mise à jour du modèle. Cela permet de s'assurer que toutes les
|
||||
// valeurs utilisées dans QML sont à jour immédiatement (utile notamment après un UPDATE).
|
||||
// Reçoit : la requête à exécuter
|
||||
// Retour : un tableau de String avec autant d'entrées que de colonnes renvoyées par MariaDB. (Important : si elle renvoit
|
||||
// plus d'une ligne, seule la première est retournée)
|
||||
//================================================================================================================================
|
||||
QStringList Bdd::requete_unique(QString requete)
|
||||
{
|
||||
int i;
|
||||
|
||||
QStringList resultats;
|
||||
QSqlQuery query(requete);
|
||||
while (query.next())
|
||||
{
|
||||
QSqlRecord resultat = query.record();
|
||||
|
||||
for(i = 0; i < resultat.count(); i++)
|
||||
{
|
||||
resultats << resultat.value(i).toString();
|
||||
}
|
||||
|
||||
break; // On ne renvoie que le premier enregistrement quoi qu'il arrive
|
||||
}
|
||||
|
||||
return(resultats);
|
||||
}
|
||||
|
||||
|
||||
//================================================================================================================================
|
||||
// Fonction : Exécute la requête SQL reçue en paramètre puis va récupérer les résultats. Les résultats sont stockés dans la
|
||||
// variable 'm_lignes' et la fonction renvoit soit -1 si erreur, soit le nombre d'enregistrements récupérés dans la BDD.
|
||||
// Reçoit : la requête à exécuter
|
||||
// Retour : -1 si erreur, n>=0 sinon (n = nombre de lignes récupérés dans la BDD par la requête)
|
||||
//================================================================================================================================
|
||||
qint64 Bdd::requete(QString requete)
|
||||
{
|
||||
QSqlQuery query;
|
||||
QStringList ligne; // Ligne temporaire
|
||||
qint64 nb_lignes = 0; // Nombre de lignes en retour de requête
|
||||
qint16 nb_champs; // Nombre de champs de la ligne
|
||||
qint16 i;
|
||||
|
||||
//QTime myTimer;
|
||||
//myTimer.start();
|
||||
|
||||
m_lignes.clear(); // RAZ de la liste
|
||||
m_ptr_ligne = 0; // RAZ du pointeur sur la liste
|
||||
|
||||
//qDebug() << "REQUETE : Temps écoulé avant exec : " << myTimer.elapsed() << "ms";
|
||||
|
||||
query.setForwardOnly(true); // Permet d'améliorer l'efficacité (mais oblige ensuite à accéder dans l'ordre aux enregistrements)
|
||||
if (!query.exec(requete)) return(-1); // Exécution de la requête
|
||||
|
||||
//qDebug() << "REQUETE : Temps écoulé après exec : " << myTimer.elapsed() << "ms";
|
||||
|
||||
while (query.next()) // Boucle sur tous les enregistrements
|
||||
{
|
||||
QSqlRecord resultat = query.record(); // Récupération de enregistrement
|
||||
nb_champs = resultat.count(); // Récupération du nombre de champs
|
||||
//ligne = QStringList(); // Ligne vide
|
||||
ligne.clear();
|
||||
|
||||
for(i = 0; i < nb_champs; i++) // Boucle sur tous les champs
|
||||
{
|
||||
ligne << query.value(i).toString(); // Chargement du champs dans la ligne temporaire ('query.value' est réputé plus rapide que 'record.value'
|
||||
}
|
||||
|
||||
m_lignes << ligne; // Stockage de la ligne temporaire dans la liste de lignes
|
||||
nb_lignes ++; // Maj du nombre de lignes
|
||||
}
|
||||
|
||||
//qDebug() << "REQUETE : Temps écoulé après chargement lignes : " << myTimer.elapsed() << "ms";
|
||||
//qDebug() << "Taille de 'm_lignes' = " hash.toHex()<< m_lignes.count();
|
||||
|
||||
return(nb_lignes);
|
||||
}
|
||||
|
||||
//================================================================================================================================
|
||||
// Fonction : Lit la ligne suivante dans la liste 'm_lignes'
|
||||
// Reçoit : Rien
|
||||
// Retour : un tableau de String avec autant d'entrées que de colonnes renvoyées par MariaDB.
|
||||
//================================================================================================================================
|
||||
QStringList Bdd::lecture_ligne()
|
||||
{
|
||||
QStringList ligne = QStringList(); // Ligne temporaire
|
||||
|
||||
|
||||
ligne = m_lignes.at(m_ptr_ligne);
|
||||
m_ptr_ligne ++; // Maj du pointeur sur la liste
|
||||
|
||||
|
||||
return(ligne);
|
||||
}
|
||||
|
||||
|
||||
//================================================================================================================================
|
||||
// Fonction : Calcule le hash de la chaine reçue en entrée et le retourne
|
||||
// Reçoit : La chaine à hacher
|
||||
// Retour : La chaine hachée
|
||||
//================================================================================================================================
|
||||
QString Bdd::sha256(QString entree)
|
||||
{
|
||||
QByteArray hash = QCryptographicHash::hash(entree.toUtf8(), QCryptographicHash::Sha256);
|
||||
return(hash.toHex());
|
||||
}
|
||||
|
||||
|
||||
//================================================================================================================================
|
||||
// Fonction : Convertit un entier signé sur 16 bits en une chaine de 4 caractères hexa
|
||||
// Reçoit : La valeur à convertir
|
||||
// Retour : La chaine en hexa
|
||||
//================================================================================================================================
|
||||
QString Bdd::int16_to_chaine_hexa(qint16 entree)
|
||||
{
|
||||
char chaine[20] = "";
|
||||
char retour[5] = "";
|
||||
uint16_t lg;
|
||||
|
||||
sprintf(chaine, "%04X", (int16_t) entree);
|
||||
|
||||
lg = strlen(chaine);
|
||||
if (lg > 4) sprintf(retour, "%s", (chaine + lg - 4)); // Nécessaire pour les valeurs négatives qui renvoient FFFF avant. Par exemple : 'FFFFFEC8' au lieu de 'FEC8'
|
||||
else sprintf(retour, "%s", chaine); // Cas normal de chaines déjà sur 4 octets
|
||||
|
||||
//qDebug() << "Chaine = " << chaine << " et Retour = [" << retour << "] et longueur = " << strlen(retour) ;
|
||||
return(retour);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
#ifndef BDD_H
|
||||
#define BDD_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
|
||||
|
||||
|
||||
//==============================================================
|
||||
class Bdd : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
||||
QList<QStringList> m_lignes;
|
||||
qint64 m_ptr_ligne;
|
||||
|
||||
|
||||
public:
|
||||
Bdd();
|
||||
|
||||
Q_INVOKABLE qint16 check_fin_configuration();
|
||||
Q_INVOKABLE QStringList requete_unique(QString requete);
|
||||
Q_INVOKABLE qint64 requete(QString requete);
|
||||
Q_INVOKABLE QStringList lecture_ligne();
|
||||
|
||||
Q_INVOKABLE QString sha256(QString entree);
|
||||
Q_INVOKABLE QString int16_to_chaine_hexa(qint16 entree);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // BDD_H
|
||||
+1168
File diff suppressed because it is too large
Load Diff
+2156
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,454 @@
|
||||
//========================================================================================================================================================================
|
||||
// CONFIG_ACCES_PARAMETRES.QML
|
||||
// Ce fichier traite la configuration des accès aux pages de paramètres.
|
||||
// La page est appelée depuis la page parametres_avances.qml, en cliquant sur "Sécurité" > "Accès aux paramètres"
|
||||
//========================================================================================================================================================================
|
||||
import QtQuick 2.12
|
||||
import QtQml.Models
|
||||
|
||||
import qt.koriolan.shipheart 1.0
|
||||
|
||||
|
||||
|
||||
Shipheart_page {
|
||||
id: page_config_acces_parametres
|
||||
|
||||
|
||||
// Mis en forme :
|
||||
readonly property double pourcentage_largeur_colonne_gauche: 0.75
|
||||
readonly property double espace_colonnes_principales: 20
|
||||
readonly property double pourcentage_hauteur_ligne_haut: 1
|
||||
readonly property double espace_lignes_principales: 20
|
||||
readonly property double affichage_hauteur_utile: shipheart_hauteur_page - shipheart_hauteur_bandeau_haut - shipheart_hauteur_bandeau_bas
|
||||
|
||||
readonly property int hauteur_ligne_formulaire: 60
|
||||
readonly property double pourcentage_largeur_labels_formulaire: 0.4
|
||||
|
||||
readonly property int hauteur_bouton_droit: 80
|
||||
|
||||
readonly property double pourcentage_bandeau_bas_largeur_zone_retour: 1
|
||||
|
||||
|
||||
readonly property int periode_init_raffraichissement_parametres: 1 // En ms
|
||||
readonly property int periode_raffraichissement_parametres: 1000 // En ms
|
||||
|
||||
// Affichage :
|
||||
property bool bouton_bandeau_bas_zone_retour_actif: false
|
||||
property int protection_mode: 0
|
||||
|
||||
|
||||
// Données :
|
||||
property int min_taille_code: 6
|
||||
property int max_taille_code: 8
|
||||
|
||||
|
||||
// Modèles :
|
||||
// Note : les modèles chargés dans 'main.qml' n'ont pas à être rechargés dans les pages suivantes
|
||||
|
||||
|
||||
|
||||
//===========================================================
|
||||
// Timer periode raffraichissement parametres :
|
||||
//===========================================================
|
||||
Timer {
|
||||
id: timer_raffraichissement_parametres
|
||||
interval: periode_init_raffraichissement_parametres
|
||||
triggeredOnStart: false
|
||||
running: true
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
if (interval == periode_init_raffraichissement_parametres) { // Premier passage, 1ms après le premier chargement
|
||||
interval = periode_raffraichissement_parametres;
|
||||
|
||||
init_page();
|
||||
}
|
||||
else if (!bouton_bandeau_bas_zone_retour_actif) {
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Titre de la page :
|
||||
Shipheart_titre_1 {titre:qsTr("Configuration de l'accès aux paramètres avancés"); 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"
|
||||
|
||||
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 : Time-out accès
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: visible ? hauteur_ligne_formulaire : 0
|
||||
color: "transparent"
|
||||
|
||||
Shipheart_formulaire_label {
|
||||
text: qsTr("Durée de maintien de l'accès")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
}
|
||||
|
||||
Shipheart_formulaire_combobox {
|
||||
id: champ_formulaire_Time_out_niveau_acces
|
||||
model: ListModel { }
|
||||
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
|
||||
onActivated: {
|
||||
shipheart_clic();
|
||||
}
|
||||
}
|
||||
|
||||
// Shipheart_formulaire_ligne_separation {
|
||||
// haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
// Espace :
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: 50
|
||||
color: "transparent"
|
||||
}
|
||||
// Sous-titre :
|
||||
Shipheart_titre_2 {titre:qsTr("Nouveau code"); hauteur: shipheart_hauteur_bandeau_haut}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Ligne de formulaire : Code
|
||||
Rectangle {
|
||||
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("Code d'accès")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
}
|
||||
|
||||
Shipheart_formulaire_textfield {
|
||||
id: champ_formulaire_Code
|
||||
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
|
||||
x: parent.width * pourcentage_largeur_labels_formulaire
|
||||
flag_num_only: true
|
||||
password_type: true
|
||||
maximumLength: max_taille_code_pattern
|
||||
}
|
||||
}
|
||||
//-------------------------------------------------------------------------------
|
||||
// Ligne de formulaire : Répéter Code
|
||||
Rectangle {
|
||||
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("Répéter le code d'accès")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
}
|
||||
|
||||
Shipheart_formulaire_textfield {
|
||||
id: champ_formulaire_Code_repetition
|
||||
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
|
||||
x: parent.width * pourcentage_largeur_labels_formulaire
|
||||
flag_num_only: true
|
||||
password_type: true
|
||||
maximumLength: max_taille_code_pattern
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// 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 :
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: hauteur_bouton_droit
|
||||
color: shipheart_couleur_fond_bouton
|
||||
radius: shipheart_rayon_bouton
|
||||
// visible: !clavier.active // SDIR #255
|
||||
Text {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
font.pixelSize: 20
|
||||
text: qsTr("Enregistrer")
|
||||
color: couleur_blanc_casse
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
if (mise_a_jour() !== -1) stackView.pop(); // On ne revient à la page précédente que si la saisie est valide...
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Bandeau bas :
|
||||
//-------------------------------------------------------
|
||||
Row {
|
||||
x: 0
|
||||
y: shipheart_hauteur_page - shipheart_hauteur_bandeau_bas;
|
||||
width: shipheart_largeur_page;
|
||||
height: shipheart_hauteur_bandeau_bas;
|
||||
spacing: 5
|
||||
padding: 5
|
||||
|
||||
//.................................................
|
||||
// Bouton retour
|
||||
//.................................................
|
||||
Rectangle {
|
||||
id: bandeau_bas_zone_retour
|
||||
width: (parent.width * pourcentage_bandeau_bas_largeur_zone_retour) - (2 * parent.padding)
|
||||
height: shipheart_hauteur_bandeau_bas - parent.topPadding - parent.bottomPadding;
|
||||
radius: shipheart_rayon_bouton
|
||||
color: shipheart_couleur_fond_bouton
|
||||
|
||||
Image {
|
||||
source: "/images/icone_retour.png"
|
||||
sourceSize.height: 30
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea { // Zone d'interaction. On est obligé de la mettre dans la grille pour que Rectangle et MouseArea soient frères ou parent/enfant ET qu'on n'occupe qu'un espace dans la grille.
|
||||
id: mouse_area_bandeau_bas_zone_retour
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
stackView.pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Boite d'information :
|
||||
//-------------------------------------------------------
|
||||
Shipheart_boite_dialogue {
|
||||
id: boite_information
|
||||
}
|
||||
|
||||
|
||||
//===========================================================
|
||||
// Economiseur : Doit être placé en fin de page pour fonctionner
|
||||
//===========================================================
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
preventStealing: true // Permet que cela fonctionne même si un élément flickable (notamment) soit derrière et "vole" le click
|
||||
enabled: flag_economiseur_actif
|
||||
onClicked: {
|
||||
mise_en_veille(0);
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================================================
|
||||
// Init de la page
|
||||
//=============================================================================================================
|
||||
function init_page()
|
||||
{
|
||||
var req, res;
|
||||
var nb;
|
||||
var i;
|
||||
var time_out_niveau_acces, defaut_time_out_niveau_acces = (5 * 60);
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
// Taille du code :
|
||||
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Min_taille_code" ';
|
||||
res = bdd.requete_unique(req);
|
||||
min_taille_code = Number(res[0]);
|
||||
|
||||
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Max_taille_code" ';
|
||||
res = bdd.requete_unique(req);
|
||||
max_taille_code = Number(res[0]);
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
// Time-out (en x 1s) :
|
||||
|
||||
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Time_out_acces" ';
|
||||
res = bdd.requete_unique(req);
|
||||
time_out_niveau_acces = Number(res[0]);
|
||||
|
||||
champ_formulaire_Time_out_niveau_acces.model.clear();
|
||||
champ_formulaire_Time_out_niveau_acces.model.append({"valeur": (0), "texte": qsTr("Aucune (saisie du code à chaque accès)") });
|
||||
champ_formulaire_Time_out_niveau_acces.model.append({"valeur": (1*60), "texte": qsTr("1 minute") });
|
||||
champ_formulaire_Time_out_niveau_acces.model.append({"valeur": defaut_time_out_niveau_acces, "texte": qsTr("5 minutes") });
|
||||
champ_formulaire_Time_out_niveau_acces.model.append({"valeur": (15*60), "texte": qsTr("15 minutes") });
|
||||
champ_formulaire_Time_out_niveau_acces.model.append({"valeur": (60*60), "texte": qsTr("1 heure") });
|
||||
champ_formulaire_Time_out_niveau_acces.model.append({"valeur": -1, "texte": qsTr("Infinie (aucune protection des paramètres avancés)") });
|
||||
|
||||
// Positionnement de l'index sur la valeur en cours :
|
||||
i = recherche_index_valeur_modele(time_out_niveau_acces, champ_formulaire_Time_out_niveau_acces.model, "Time_out_economiseur");
|
||||
if (i === -1) champ_formulaire_Time_out_niveau_acces.currentIndex = recherche_index_valeur_modele(defaut_time_out_niveau_acces, champ_formulaire_Time_out_niveau_acces.model, "Time_out_economiseur");
|
||||
else champ_formulaire_Time_out_niveau_acces.currentIndex = i;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================================================
|
||||
// Mise à jour des valeurs saisies
|
||||
//=============================================================================================================
|
||||
function mise_a_jour()
|
||||
{
|
||||
var req;
|
||||
var val;
|
||||
|
||||
//-------------------------------------------
|
||||
// Configuration du time-out :
|
||||
val = champ_formulaire_Time_out_niveau_acces.model.get(champ_formulaire_Time_out_niveau_acces.currentIndex).valeur;
|
||||
//console.log("Valeur = " + val)
|
||||
switch(val)
|
||||
{
|
||||
case 0 :
|
||||
shipheart_niveau_acces_en_cours = shipheart_niveau_acces_aucun;
|
||||
break;
|
||||
|
||||
case -1 :
|
||||
if (shipheart_niveau_acces_en_cours === shipheart_niveau_acces_aucun) shipheart_niveau_acces_en_cours = shipheart_niveau_acces_user;
|
||||
break;
|
||||
|
||||
default :
|
||||
if (shipheart_niveau_acces_en_cours === shipheart_niveau_acces_aucun) shipheart_niveau_acces_en_cours = shipheart_niveau_acces_user;
|
||||
break;
|
||||
}
|
||||
|
||||
req = 'UPDATE TB_Configuration ';
|
||||
req += ' SET Valeur="' + val + '" ';
|
||||
req += ' WHERE Nom ="Time_out_acces" ';
|
||||
//console.log("Requête = " + req)
|
||||
bdd.requete_unique(req);
|
||||
|
||||
shipheart_time_out_niveau_acces = val;
|
||||
shipheart_compteur_time_out_niveau_acces = shipheart_time_out_niveau_acces;
|
||||
|
||||
|
||||
//-------------------------------------------
|
||||
// Configuration du code d'accès :
|
||||
var nouveau_code_saisi, nouveau_code_repetition_saisi;
|
||||
var nouveau_code_saisi_encrypte;
|
||||
var erreur = false;
|
||||
|
||||
nouveau_code_saisi = champ_formulaire_Code.text
|
||||
nouveau_code_repetition_saisi = champ_formulaire_Code_repetition.text
|
||||
do { // Fake loop
|
||||
|
||||
//.........................................
|
||||
// Si aucune valeur de code n'est saisie :
|
||||
if ((nouveau_code_saisi === "") && (nouveau_code_repetition_saisi === "")) break;
|
||||
|
||||
//.................................................
|
||||
// Si la répétition n'est pas égale à l'original :
|
||||
if (nouveau_code_repetition_saisi !== nouveau_code_saisi)
|
||||
{
|
||||
boite_information.niveau = 1
|
||||
boite_information.imageTitreSource = "/images/attention.png"
|
||||
boite_information.message = qsTr("Les deux valeurs saisies doivent être identiques !\n\nDe plus, le code doit contenir :\n- %1 chiffres au minimum\n- %2 chiffres au maximum.").arg(min_taille_code).arg(max_taille_code);
|
||||
boite_information.open();
|
||||
|
||||
erreur = true;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
//.................................................
|
||||
// Si le format du nouveau code n'est pas correct :
|
||||
if ((nouveau_code_saisi.length < min_taille_code) || (nouveau_code_saisi.length > max_taille_code))
|
||||
{
|
||||
//console.log("Le code saisie a une longueur anormale [" + nouveau_code_saisi.length + "]")
|
||||
boite_information.niveau = 1
|
||||
boite_information.imageTitreSource = "/images/attention.png"
|
||||
boite_information.message = qsTr("Le nouveau code doit contenir :\n- %1 chiffres au minimum\n- %2 chiffres au maximum.\n\nLe code saisi ne répond pas à ces critères et sa mise à jour n'est donc pas effectuée.\n\nMerci de saisir un code au format valide si vous souhaitez le modifier.").arg(min_taille_code).arg(max_taille_code);
|
||||
boite_information.open();
|
||||
|
||||
erreur = true;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
//.................................................
|
||||
// Si tout est Ok :
|
||||
nouveau_code_saisi_encrypte = bdd.sha256(nouveau_code_saisi);
|
||||
req = 'UPDATE TB_Configuration ';
|
||||
req += ' SET Valeur="' + nouveau_code_saisi_encrypte + '" ';
|
||||
req += ' WHERE Nom="Code" ';
|
||||
//console.log("Requête = " + req)
|
||||
bdd.requete_unique(req);
|
||||
|
||||
} while (0);
|
||||
|
||||
if (erreur === false) return(0);
|
||||
else return(-1);
|
||||
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================================================
|
||||
// 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,484 @@
|
||||
//========================================================================================================================================================================
|
||||
// CONFIG_AFFICHAGE.QML
|
||||
// Ce fichier traite la configuration des paramètres d'affichage.
|
||||
// La page est appelée depuis la page parametres_avances.qml, en cliquant sur "Vos paramètres" > "Affichage"
|
||||
//========================================================================================================================================================================
|
||||
import QtQuick 2.12
|
||||
|
||||
import qt.koriolan.shipheart 1.0
|
||||
|
||||
|
||||
Shipheart_page {
|
||||
id: page_config_affichage
|
||||
|
||||
|
||||
// Mis en forme :
|
||||
readonly property double pourcentage_largeur_colonne_gauche: 0.75
|
||||
readonly property double espace_colonnes_principales: 20
|
||||
readonly property double pourcentage_hauteur_ligne_haut: 1
|
||||
readonly property double espace_lignes_principales: 20
|
||||
readonly property double affichage_hauteur_utile: shipheart_hauteur_page - shipheart_hauteur_bandeau_haut - shipheart_hauteur_bandeau_bas
|
||||
|
||||
readonly property int hauteur_ligne_formulaire: 60
|
||||
readonly property double pourcentage_largeur_labels_formulaire: 0.4
|
||||
|
||||
readonly property int hauteur_bouton_droit: 80
|
||||
|
||||
readonly property double pourcentage_bandeau_bas_largeur_zone_retour: 1
|
||||
|
||||
|
||||
readonly property int periode_init_raffraichissement_parametres: 1 // En ms
|
||||
readonly property int periode_raffraichissement_parametres: 1000 // En ms
|
||||
|
||||
|
||||
|
||||
// Affichage :
|
||||
property bool bouton_bandeau_bas_zone_retour_actif: false
|
||||
property int protection_mode: 0
|
||||
|
||||
|
||||
// Données :
|
||||
|
||||
|
||||
// Modèles :
|
||||
// Note : les modèles chargés dans 'main.qml' n'ont pas à être rechargés dans les pages suivantes
|
||||
|
||||
|
||||
//===========================================================
|
||||
// Timer periode raffraichissement parametres :
|
||||
//===========================================================
|
||||
Timer {
|
||||
id: timer_raffraichissement_parametres
|
||||
interval: periode_init_raffraichissement_parametres
|
||||
triggeredOnStart: false
|
||||
running: true
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
if (interval == periode_init_raffraichissement_parametres) { // Premier passage, 1ms après le premier chargement
|
||||
interval = periode_raffraichissement_parametres;
|
||||
|
||||
init_page();
|
||||
}
|
||||
else if (!bouton_bandeau_bas_zone_retour_actif) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Titre de la page :
|
||||
Shipheart_titre_1 {titre:qsTr("Configuration de l'affichage"); 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"
|
||||
|
||||
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 du bateau
|
||||
Rectangle {
|
||||
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 du bateau")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
}
|
||||
|
||||
Shipheart_formulaire_textfield {
|
||||
id: champ_formulaire_Nom_bateau
|
||||
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 : Fuseau horaire
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: visible ? hauteur_ligne_formulaire : 0
|
||||
color: "transparent"
|
||||
|
||||
Shipheart_formulaire_label {
|
||||
text: qsTr("Fuseau horaire")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
}
|
||||
|
||||
Shipheart_formulaire_combobox {
|
||||
id: champ_formulaire_Fuseau_horaire
|
||||
model: ListModel { }
|
||||
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
|
||||
onActivated: {
|
||||
shipheart_clic();
|
||||
}
|
||||
}
|
||||
|
||||
Shipheart_formulaire_ligne_separation {
|
||||
haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Ligne de formulaire : Time-out économiseur d'écran
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: visible ? hauteur_ligne_formulaire : 0
|
||||
color: "transparent"
|
||||
|
||||
Shipheart_formulaire_label {
|
||||
text: qsTr("Temporisaton économiseur d'écran")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
}
|
||||
|
||||
Shipheart_formulaire_combobox {
|
||||
id: champ_formulaire_Time_out_economiseur
|
||||
model: ListModel { }
|
||||
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
|
||||
onActivated: {
|
||||
shipheart_clic();
|
||||
}
|
||||
}
|
||||
|
||||
Shipheart_formulaire_ligne_separation {
|
||||
haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Ligne de formulaire : Thème d'affichage
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: visible ? hauteur_ligne_formulaire : 0
|
||||
color: "transparent"
|
||||
|
||||
Shipheart_formulaire_label {
|
||||
text: qsTr("Thème d'affichage")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
}
|
||||
|
||||
Shipheart_formulaire_combobox {
|
||||
id: champ_formulaire_Theme
|
||||
model: ListModel { }
|
||||
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
|
||||
onActivated: {
|
||||
shipheart_clic();
|
||||
}
|
||||
}
|
||||
|
||||
Shipheart_formulaire_ligne_separation {
|
||||
haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// 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 :
|
||||
//---------------------------
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: hauteur_bouton_droit
|
||||
color: shipheart_couleur_fond_bouton
|
||||
radius: shipheart_rayon_bouton
|
||||
// visible: !clavier.active // SDIR #255
|
||||
Text {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
font.pixelSize: 20
|
||||
text: qsTr("Enregistrer")
|
||||
color: couleur_blanc_casse
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
mise_a_jour(); // Mise à jour des données saisies dans la BDD et reconfiguration par l'application pour prise en compte.
|
||||
stackView.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Bandeau bas :
|
||||
//-------------------------------------------------------
|
||||
Row {
|
||||
x: 0
|
||||
y: shipheart_hauteur_page - shipheart_hauteur_bandeau_bas;
|
||||
width: shipheart_largeur_page;
|
||||
height: shipheart_hauteur_bandeau_bas;
|
||||
spacing: 5
|
||||
padding: 5
|
||||
|
||||
//.................................................
|
||||
// Bouton retour
|
||||
//.................................................
|
||||
Rectangle {
|
||||
id: bandeau_bas_zone_retour
|
||||
width: (parent.width * pourcentage_bandeau_bas_largeur_zone_retour) - (2 * parent.padding)
|
||||
height: shipheart_hauteur_bandeau_bas - parent.topPadding - parent.bottomPadding;
|
||||
radius: shipheart_rayon_bouton
|
||||
color: shipheart_couleur_fond_bouton
|
||||
|
||||
Image {
|
||||
source: "/images/icone_retour.png"
|
||||
sourceSize.height: 30
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea { // Zone d'interaction. On est obligé de la mettre dans la grille pour que Rectangle et MouseArea soient frères ou parent/enfant ET qu'on n'occupe qu'un espace dans la grille.
|
||||
id: mouse_area_bandeau_bas_zone_retour
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
stackView.pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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 defaut_time_out_economiseur = 0;
|
||||
var capteur_temperature_accueil, defaut_capteur_temperature_accueil = 0;
|
||||
var theme, defaut_theme = 0;
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
// Nom du bateau :
|
||||
//---------------------------------------------------------------------------------------
|
||||
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Nom_du_bateau" ';
|
||||
res = bdd.requete_unique(req);
|
||||
champ_formulaire_Nom_bateau.text = res[0];
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
// Fuseau horaire :
|
||||
//---------------------------------------------------------------------------------------
|
||||
|
||||
// Config actuelle :
|
||||
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Fuseau_horaire" ';
|
||||
res = bdd.requete_unique(req);
|
||||
shipheart_fuseau_horaire = Number(res[0]);
|
||||
|
||||
// Liste des fuseaux possibles :
|
||||
champ_formulaire_Fuseau_horaire.model.clear();
|
||||
champ_formulaire_Fuseau_horaire.model.append({"valeur": (-12), "texte": qsTr("UTC-12 (Yankee)") });
|
||||
champ_formulaire_Fuseau_horaire.model.append({"valeur": (-11), "texte": qsTr("UTC-11 (X-Ray)") });
|
||||
champ_formulaire_Fuseau_horaire.model.append({"valeur": (-10), "texte": qsTr("UTC-10 (Whisky)") });
|
||||
champ_formulaire_Fuseau_horaire.model.append({"valeur": (-9), "texte": qsTr("UTC-9 (Victor)") });
|
||||
champ_formulaire_Fuseau_horaire.model.append({"valeur": (-8), "texte": qsTr("UTC-8 (Uniform)") });
|
||||
champ_formulaire_Fuseau_horaire.model.append({"valeur": (-7), "texte": qsTr("UTC-7 (Tango)") });
|
||||
champ_formulaire_Fuseau_horaire.model.append({"valeur": (-6), "texte": qsTr("UTC-6 (Sierra)") });
|
||||
champ_formulaire_Fuseau_horaire.model.append({"valeur": (-5), "texte": qsTr("UTC-5 (Romeo)") });
|
||||
champ_formulaire_Fuseau_horaire.model.append({"valeur": (-4), "texte": qsTr("UTC-4 (Quebec)") });
|
||||
champ_formulaire_Fuseau_horaire.model.append({"valeur": (-3), "texte": qsTr("UTC-3 (Papa)") });
|
||||
champ_formulaire_Fuseau_horaire.model.append({"valeur": (-2), "texte": qsTr("UTC-2 (Oscar)") });
|
||||
champ_formulaire_Fuseau_horaire.model.append({"valeur": (-1), "texte": qsTr("UTC-1 (November)") });
|
||||
champ_formulaire_Fuseau_horaire.model.append({"valeur": (0), "texte": qsTr("UTC (Zoulou)") });
|
||||
champ_formulaire_Fuseau_horaire.model.append({"valeur": (1), "texte": qsTr("UTC+1 (Alpha)") });
|
||||
champ_formulaire_Fuseau_horaire.model.append({"valeur": (2), "texte": qsTr("UTC+2 (Bravo)") });
|
||||
champ_formulaire_Fuseau_horaire.model.append({"valeur": (3), "texte": qsTr("UTC+3 (Charlie)") });
|
||||
champ_formulaire_Fuseau_horaire.model.append({"valeur": (4), "texte": qsTr("UTC+4 (Delta)") });
|
||||
champ_formulaire_Fuseau_horaire.model.append({"valeur": (5), "texte": qsTr("UTC+5 (Echo)") });
|
||||
champ_formulaire_Fuseau_horaire.model.append({"valeur": (6), "texte": qsTr("UTC+6 (Foxtrot)") });
|
||||
champ_formulaire_Fuseau_horaire.model.append({"valeur": (7), "texte": qsTr("UTC+7 (Golf)") });
|
||||
champ_formulaire_Fuseau_horaire.model.append({"valeur": (8), "texte": qsTr("UTC+8 (Hotel)") });
|
||||
champ_formulaire_Fuseau_horaire.model.append({"valeur": (9), "texte": qsTr("UTC+9 (India)") });
|
||||
champ_formulaire_Fuseau_horaire.model.append({"valeur": (10), "texte": qsTr("UTC+10 (Kilo)") });
|
||||
champ_formulaire_Fuseau_horaire.model.append({"valeur": (11), "texte": qsTr("UTC+11 (Lima)") });
|
||||
champ_formulaire_Fuseau_horaire.model.append({"valeur": (12), "texte": qsTr("UTC+12 (Mike)") });
|
||||
|
||||
// Positionnement de l'index sur la valeur en cours :
|
||||
i = recherche_index_valeur_modele(shipheart_fuseau_horaire, champ_formulaire_Fuseau_horaire.model, "Fuseau_horaire");
|
||||
if (i === -1) champ_formulaire_Fuseau_horaire.currentIndex = recherche_index_valeur_modele(defaut_fuseau_horaire, champ_formulaire_Fuseau_horaire.model, "Fuseau_horaire");
|
||||
else champ_formulaire_Fuseau_horaire.currentIndex = i;
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
// Time-out économiseur :
|
||||
//---------------------------------------------------------------------------------------
|
||||
|
||||
// Liste des time-outs possibles (en x 1s) :
|
||||
champ_formulaire_Time_out_economiseur.model.clear();
|
||||
champ_formulaire_Time_out_economiseur.model.append({"valeur": (15), "texte": qsTr("15 secondes") });
|
||||
champ_formulaire_Time_out_economiseur.model.append({"valeur": (30), "texte": qsTr("30 secondes") });
|
||||
champ_formulaire_Time_out_economiseur.model.append({"valeur": (1*60), "texte": qsTr("1 minute") });
|
||||
champ_formulaire_Time_out_economiseur.model.append({"valeur": (3*60), "texte": qsTr("3 minutes") });
|
||||
champ_formulaire_Time_out_economiseur.model.append({"valeur": (10*60), "texte": qsTr("10 minutes") });
|
||||
champ_formulaire_Time_out_economiseur.model.append({"valeur": defaut_time_out_economiseur, "texte": qsTr("Aucune limite") });
|
||||
|
||||
// Positionnement de l'index sur la valeur en cours :
|
||||
console.log("shipheart_time_out_economiseur AVANT recherche = " + shipheart_time_out_economiseur);
|
||||
|
||||
i = recherche_index_valeur_modele(shipheart_time_out_economiseur, champ_formulaire_Time_out_economiseur.model, "Time_out_economiseur");
|
||||
if (i === -1) champ_formulaire_Time_out_economiseur.currentIndex = recherche_index_valeur_modele(defaut_time_out_economiseur, champ_formulaire_Time_out_economiseur.model, "Time_out_economiseur");
|
||||
else champ_formulaire_Time_out_economiseur.currentIndex = i;
|
||||
console.log("shipheart_time_out_economiseur : valeur de i après recherche = " + i);
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
// Theme d'affichage :
|
||||
//---------------------------------------------------------------------------------------
|
||||
|
||||
// Récupération de la valeur actuelle :
|
||||
theme = shipheart_theme;
|
||||
|
||||
// Liste des time-outs possibles (en x 1s) :
|
||||
champ_formulaire_Theme.model.clear();
|
||||
for (i = 0; i < shipheart_config_themes.length; i++)
|
||||
{
|
||||
champ_formulaire_Theme.model.append({"valeur": i, "texte": shipheart_config_themes[i][shipheart_index_theme_nom] });
|
||||
}
|
||||
|
||||
// Positionnement de l'index sur la valeur en cours :
|
||||
i = recherche_index_valeur_modele(theme, champ_formulaire_Theme.model, "Theme");
|
||||
if (i === -1) champ_formulaire_Theme.currentIndex = recherche_index_valeur_modele(defaut_theme, champ_formulaire_Theme.model, "Theme");
|
||||
else champ_formulaire_Theme.currentIndex = i;
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================================================
|
||||
// Mise à jour des valeurs saisies
|
||||
//=============================================================================================================
|
||||
function mise_a_jour()
|
||||
{
|
||||
var req;
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
// Nom du bateau :
|
||||
//---------------------------------------------------------------------------------------
|
||||
req = 'UPDATE TB_Configuration ';
|
||||
req += ' SET Valeur="' + champ_formulaire_Nom_bateau.text + '" ';
|
||||
req += ' WHERE Nom="Nom_du_bateau" ';
|
||||
//console.log("Requête = " + req)
|
||||
bdd.requete_unique(req);
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
// Fuseau horaire :
|
||||
//---------------------------------------------------------------------------------------
|
||||
|
||||
shipheart_fuseau_horaire = champ_formulaire_Fuseau_horaire.model.get(champ_formulaire_Fuseau_horaire.currentIndex).valeur;
|
||||
|
||||
req = 'UPDATE TB_Configuration ';
|
||||
req += ' SET Valeur="' + shipheart_fuseau_horaire + '" ';
|
||||
req += ' WHERE Nom="Fuseau_horaire" ';
|
||||
//console.log("Requête = " + req)
|
||||
bdd.requete_unique(req);
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
// Time-out économiseur :
|
||||
//---------------------------------------------------------------------------------------
|
||||
|
||||
shipheart_time_out_economiseur = champ_formulaire_Time_out_economiseur.model.get(champ_formulaire_Time_out_economiseur.currentIndex).valeur;
|
||||
|
||||
req = 'UPDATE TB_Configuration ';
|
||||
req += ' SET Valeur="' + shipheart_time_out_economiseur + '" ';
|
||||
req += ' WHERE Nom="Time_out_economiseur" ';
|
||||
//console.log("Requête = " + req)
|
||||
bdd.requete_unique(req);
|
||||
|
||||
// Mise à jour de la nouvelle valeur de time-out dans le compteur en cours :
|
||||
shipheart_compteur_economiseur = shipheart_time_out_economiseur;
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
// Thème :
|
||||
//---------------------------------------------------------------------------------------
|
||||
|
||||
// Mise à jour dans la BDD :
|
||||
req = 'UPDATE TB_Configuration ';
|
||||
req += ' SET Valeur="' + champ_formulaire_Theme.model.get(champ_formulaire_Theme.currentIndex).valeur + '" ';
|
||||
req += ' WHERE Nom="Theme" ';
|
||||
//console.log("Requête = " + req)
|
||||
bdd.requete_unique(req);
|
||||
|
||||
chargement_theme(); // Permet de faire les vérifications de cohérence (a priori, peu utile ici) et, surtout, de charger toutes les variables liées au thème
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================================================
|
||||
// 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,481 @@
|
||||
//========================================================================================================================================================================
|
||||
// CONFIG_AUDIO.QML
|
||||
// Ce fichier traite les paramètres de configuration liés à l'audio
|
||||
// La page est appelée depuis la page parametres_avances.qml, en cliquant sur "Audio" depuis la colonne "Vos paramètres"
|
||||
//========================================================================================================================================================================
|
||||
import QtQuick 2.12
|
||||
import QtQml.Models
|
||||
|
||||
import qt.koriolan.shipheart 1.0
|
||||
|
||||
|
||||
|
||||
Shipheart_page {
|
||||
id: page_config_versions
|
||||
|
||||
|
||||
// Mis en forme :
|
||||
readonly property double pourcentage_largeur_colonne_gauche: 0.75
|
||||
readonly property double espace_colonnes_principales: 20
|
||||
readonly property double pourcentage_hauteur_ligne_haut: 0.3
|
||||
readonly property double espace_lignes_principales: 20
|
||||
readonly property double affichage_hauteur_utile: shipheart_hauteur_page - shipheart_hauteur_bandeau_haut - shipheart_hauteur_bandeau_bas
|
||||
|
||||
readonly property int hauteur_ligne_formulaire: 60
|
||||
readonly property double pourcentage_largeur_labels_formulaire: 0.4
|
||||
|
||||
readonly property int hauteur_bouton_droit: 80
|
||||
|
||||
readonly property double pourcentage_bandeau_bas_largeur_zone_retour: 1
|
||||
|
||||
|
||||
readonly property int periode_init_raffraichissement_parametres: 1 // En ms
|
||||
readonly property int periode_raffraichissement_parametres: 1000 // En ms
|
||||
|
||||
|
||||
|
||||
// Affichage :
|
||||
property bool bouton_bandeau_bas_zone_retour_actif: false
|
||||
property int protection_mode: 0
|
||||
|
||||
|
||||
// Données :
|
||||
|
||||
|
||||
// Modèles :
|
||||
// Note : les modèles chargés dans 'main.qml' n'ont pas à être rechargés dans les pages suivantes
|
||||
|
||||
|
||||
//===========================================================
|
||||
// Timer periode raffraichissement parametres :
|
||||
//===========================================================
|
||||
Timer {
|
||||
id: timer_raffraichissement_parametres
|
||||
interval: periode_init_raffraichissement_parametres
|
||||
triggeredOnStart: false
|
||||
running: true
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
if (interval == periode_init_raffraichissement_parametres) { // Premier passage, 1ms après le premier chargement
|
||||
interval = periode_raffraichissement_parametres;
|
||||
|
||||
init_page();
|
||||
}
|
||||
else if (!bouton_bandeau_bas_zone_retour_actif) {
|
||||
mise_a_jour_periodique();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Titre de la page :
|
||||
Shipheart_titre_1 {titre:qsTr("Configuration audio"); 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;
|
||||
color: "transparent"
|
||||
|
||||
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 : Bips
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: visible ? hauteur_ligne_formulaire : 0
|
||||
color: "transparent"
|
||||
|
||||
Shipheart_formulaire_label {
|
||||
text: qsTr("Bips de clic")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
}
|
||||
|
||||
Shipheart_formulaire_combobox {
|
||||
id: champ_formulaire_Bips
|
||||
model: ListModel { }
|
||||
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
|
||||
onActivated: {
|
||||
shipheart_clic();
|
||||
test_bip(champ_formulaire_Bips.model.get(champ_formulaire_Bips.currentIndex).valeur);
|
||||
}
|
||||
}
|
||||
|
||||
Shipheart_formulaire_ligne_separation {
|
||||
haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Ligne de formulaire : Fonction_jack
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: visible ? (1.6 * hauteur_ligne_formulaire) : 0
|
||||
color: "transparent"
|
||||
|
||||
Shipheart_formulaire_label {
|
||||
text: qsTr("Fonctionnement de la sortie Audio")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
}
|
||||
|
||||
Shipheart_formulaire_combobox {
|
||||
id: champ_formulaire_Fonction_jack
|
||||
model: ListModel { }
|
||||
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
|
||||
onActivated: {
|
||||
shipheart_clic();
|
||||
}
|
||||
}
|
||||
|
||||
Shipheart_formulaire_ligne_separation {
|
||||
haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Ecran Milieu - Gauche :
|
||||
//-------------------------------------------------------
|
||||
Rectangle {
|
||||
id: zone_affichage_milieu_gauche
|
||||
x: 0
|
||||
y: shipheart_hauteur_bandeau_haut + zone_affichage_haut_gauche.height + espace_lignes_principales;
|
||||
width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2)
|
||||
height: (affichage_hauteur_utile * (1 - pourcentage_hauteur_ligne_haut)) - espace_lignes_principales;
|
||||
color: "transparent"
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Grille pour afficher les valeurs des paramètres non configurables :
|
||||
GridView {
|
||||
id: grille_informations
|
||||
|
||||
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_grille_informations
|
||||
delegate: Rectangle {
|
||||
width: zone_affichage_milieu_gauche.width // L'utilisation de 'parent' génère un warning au moment de la MAJ périodique (clear du modèle)
|
||||
height: visible ? hauteur_ligne_formulaire : 0
|
||||
color: "transparent"
|
||||
|
||||
Shipheart_formulaire_label {
|
||||
text: model.nom_champ
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
}
|
||||
Shipheart_formulaire_valeur_fixe {
|
||||
text: model.valeur_champ
|
||||
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
|
||||
}
|
||||
}
|
||||
ListModel {
|
||||
id: modele_grille_informations
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// 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 :
|
||||
//.......................................................
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: hauteur_bouton_droit
|
||||
color: shipheart_couleur_fond_bouton
|
||||
radius: shipheart_rayon_bouton
|
||||
// visible: !clavier.active // SDIR #255
|
||||
Text {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
font.pixelSize: 20
|
||||
text: qsTr("Enregistrer")
|
||||
color: couleur_blanc_casse
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
mise_a_jour(); // Mise à jour des données saisies dans la BDD et reconfiguration par l'application pour prise en compte.
|
||||
timer_tempo_reconfiguration.restart();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//.......................................................
|
||||
// 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();
|
||||
stackView.pop(); // Retour à la page de config des capteurs
|
||||
}
|
||||
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) - (2 * parent.padding)
|
||||
height: shipheart_hauteur_bandeau_bas - parent.topPadding - parent.bottomPadding;
|
||||
radius: shipheart_rayon_bouton
|
||||
color: shipheart_couleur_fond_bouton
|
||||
|
||||
Image {
|
||||
source: "/images/icone_retour.png"
|
||||
sourceSize.height: 30
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea { // Zone d'interaction. On est obligé de la mettre dans la grille pour que Rectangle et MouseArea soient frères ou parent/enfant ET qu'on n'occupe qu'un espace dans la grille.
|
||||
id: mouse_area_bandeau_bas_zone_retour
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
stackView.pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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 bips;
|
||||
var fonction_jack;
|
||||
|
||||
|
||||
mise_a_jour_periodique();
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
// Bips :
|
||||
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Bips" ';
|
||||
res = bdd.requete_unique(req);
|
||||
bips = res[0];
|
||||
|
||||
champ_formulaire_Bips.model.clear();
|
||||
champ_formulaire_Bips.model.append({"valeur": "", "texte": qsTr("Aucun bip") });
|
||||
champ_formulaire_Bips.model.append({"valeur": "beep-28.mp3", "texte": qsTr("Bip par défaut") });
|
||||
champ_formulaire_Bips.model.append({"valeur": "beep-027.mp3", "texte": qsTr("Bip 2") });
|
||||
champ_formulaire_Bips.model.append({"valeur": "beep-07.mp3", "texte": qsTr("Bip 3") });
|
||||
champ_formulaire_Bips.model.append({"valeur": "beep-25.mp3", "texte": qsTr("Bip 4") });
|
||||
champ_formulaire_Bips.model.append({"valeur": "beep-28.mp3", "texte": qsTr("Bip 5") });
|
||||
champ_formulaire_Bips.model.append({"valeur": "beep-30b.mp3", "texte": qsTr("Bip 6") });
|
||||
champ_formulaire_Bips.model.append({"valeur": "button-17.mp3", "texte": qsTr("Bip 7") });
|
||||
champ_formulaire_Bips.model.append({"valeur": "button-21.mp3", "texte": qsTr("Bip 8") });
|
||||
champ_formulaire_Bips.model.append({"valeur": "button-27.mp3", "texte": qsTr("Bip 9") });
|
||||
champ_formulaire_Bips.model.append({"valeur": "button-28.mp3", "texte": qsTr("Bip 10") });
|
||||
champ_formulaire_Bips.model.append({"valeur": "button-32.mp3", "texte": qsTr("Bip 11") });
|
||||
champ_formulaire_Bips.model.append({"valeur": "button-33a.mp3", "texte": qsTr("Bip 12") });
|
||||
champ_formulaire_Bips.model.append({"valeur": "button-35.mp3", "texte": qsTr("Bip 13") });
|
||||
champ_formulaire_Bips.model.append({"valeur": "button-42.mp3", "texte": qsTr("Bip 14") });
|
||||
|
||||
// Positionnement de l'index sur la valeur en cours :
|
||||
i = recherche_index_valeur_modele(bips, champ_formulaire_Bips.model, "bips");
|
||||
if (i === -1) champ_formulaire_Bips.currentIndex = recherche_index_valeur_modele("beep-28.mp3", champ_formulaire_Bips.model, "bips");
|
||||
else champ_formulaire_Bips.currentIndex = i;
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
// Fonction Jack :
|
||||
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Fonction_jack" ';
|
||||
res = bdd.requete_unique(req);
|
||||
fonction_jack = Number(res[0]);
|
||||
|
||||
champ_formulaire_Fonction_jack.model.clear();
|
||||
// Mise à jour des textes pour tenir compte du fait que l'état de la prise jack ne peut pas être remonté correctement (cf SDIR #232).
|
||||
// champ_formulaire_Fonction_jack.model.append({"valeur": 0, "texte": qsTr("Le son de ShipBase est coupé lorsqu'une prise jack est présente sur la sortie AUDIO") });
|
||||
// champ_formulaire_Fonction_jack.model.append({"valeur": 1, "texte": qsTr("Le son de ShipBase est toujours diffusé, même lorsqu'une prise jack est présente sur la sortie AUDIO") });
|
||||
champ_formulaire_Fonction_jack.model.append({"valeur": 0, "texte": qsTr("Le son de ShipBase est coupé. Le son est uniquement diffusé sur la sortie AUDIO") });
|
||||
champ_formulaire_Fonction_jack.model.append({"valeur": 1, "texte": qsTr("Le son est diffusé sur ShipBase et sur la sortie AUDIO") });
|
||||
|
||||
// Positionnement de l'index sur la valeur en cours :
|
||||
i = recherche_index_valeur_modele(fonction_jack, champ_formulaire_Fonction_jack.model, "fonction_jack");
|
||||
if (i === -1) champ_formulaire_Fonction_jack.currentIndex = recherche_index_valeur_modele(2, champ_formulaire_Fonction_jack.model, "fonction_jack");
|
||||
else champ_formulaire_Fonction_jack.currentIndex = i;
|
||||
}
|
||||
|
||||
//=============================================================================================================
|
||||
// Mise à jour périodique
|
||||
//=============================================================================================================
|
||||
function mise_a_jour_periodique()
|
||||
{
|
||||
var req, res;
|
||||
var nb;
|
||||
var i;
|
||||
var nom_champ, valeur_champ;
|
||||
|
||||
modele_grille_informations.clear();
|
||||
|
||||
req = 'SELECT Nom, Valeur FROM TB_Systeme ORDER BY Cle_primaire';
|
||||
//console.log("req =" + req);
|
||||
nb = bdd.requete(req);
|
||||
|
||||
for (i = 0; i < nb; i ++)
|
||||
{
|
||||
res = bdd.lecture_ligne();
|
||||
if (!res.isEmpty)
|
||||
{
|
||||
switch(res[0])
|
||||
{
|
||||
// L'affichage de l'état de la prise Jack a été supprimé car sa détection ne fonctionne pas, malgré le traitement du SDIR #232.
|
||||
// case "Presence_jack":
|
||||
// nom_champ = qsTr("Prise jack sur la sortie AUDIO");
|
||||
// valeur_champ = (Number(res[1]) ? qsTr("Présente") : qsTr("Absente"));
|
||||
// break;
|
||||
|
||||
default: continue;
|
||||
}
|
||||
modele_grille_informations.append({"commande": false, "nom_champ": nom_champ, "valeur_champ": valeur_champ});
|
||||
}
|
||||
else break; // Ne devrait pas arriver....
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================================================
|
||||
// Mise à jour des valeurs saisies
|
||||
//=============================================================================================================
|
||||
function mise_a_jour()
|
||||
{
|
||||
var req;
|
||||
|
||||
// Maj de la variable globale pour prise en compte immédiate :
|
||||
shipheart_bips = champ_formulaire_Bips.model.get(champ_formulaire_Bips.currentIndex).valeur;
|
||||
|
||||
// Mise à jour de la nouvelle valeur Bips dans la BDD :
|
||||
req = 'UPDATE TB_Configuration SET Valeur="' + shipheart_bips + '" WHERE Nom="Bips" '
|
||||
//console.log("Requête = " + req)
|
||||
bdd.requete_unique(req);
|
||||
|
||||
// Mise à jour dans la BDD de la valeur du bip déjà positionnée par 'shipheart_clic() > emission_bip()' (mais pas encore traitée) :
|
||||
req = "UPDATE TB_Systeme SET Valeur='" + shipheart_bips + "/0/0/0' WHERE Nom='New_bip' ";
|
||||
//console.log("Requête = " + req)
|
||||
bdd.requete_unique(req);
|
||||
|
||||
// Mise à jour de la nouvelle valeur Fonction_jack dans la BDD :
|
||||
req = 'UPDATE TB_Configuration SET Valeur="' + champ_formulaire_Fonction_jack.model.get(champ_formulaire_Fonction_jack.currentIndex).valeur + '" WHERE Nom="Fonction_jack" '
|
||||
//console.log("Requête = " + req)
|
||||
bdd.requete_unique(req);
|
||||
|
||||
// Demande de reconfiguration système via la BDD car on a modifié des valeurs de configuration :
|
||||
synchro_bdd(shipheart_type_synchro_config);
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================================================
|
||||
// Test de bip
|
||||
//=============================================================================================================
|
||||
function test_bip(type_bip)
|
||||
{
|
||||
var req;
|
||||
|
||||
req = "UPDATE TB_Systeme SET Valeur='" + type_bip + "/0/0/0' WHERE Nom='New_bip'";
|
||||
bdd.requete_unique(req);
|
||||
//console.log("Requête = " + req)
|
||||
synchro_bdd(shipheart_type_synchro_data);
|
||||
}
|
||||
|
||||
//=============================================================================================================
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
+1998
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,309 @@
|
||||
//========================================================================================================================================================================
|
||||
// CONFIG_BATTERIES.QML
|
||||
// Ce fichier traite la configuration des batteries. La page permet notamment de :
|
||||
// - Afficher, pour toutes les batteries déjà configurées (et donc d'accéder à la configuration détaillée de l'une d'elle ; ou sa création)
|
||||
// - Accéder au menu de changement de l'ordre d'affichage sur la page d'accueil
|
||||
// La page est appelée depuis la page PARAMETRES_AVANCES, en cliquant sur "Batteries"
|
||||
//========================================================================================================================================================================
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
import qt.koriolan.shipheart 1.0
|
||||
|
||||
|
||||
|
||||
Shipheart_page {
|
||||
id: page_config_batteries
|
||||
|
||||
|
||||
// Mis en forme :
|
||||
readonly property double affichage_hauteur_utile: shipheart_hauteur_page - shipheart_hauteur_bandeau_haut - shipheart_hauteur_bandeau_bas
|
||||
readonly property int hauteur_bouton_droit: 80
|
||||
|
||||
readonly property double pourcentage_largeur_colonne_gauche: 0.75
|
||||
readonly property double pourcentage_bandeau_bas_largeur_zone_retour: 1.0
|
||||
readonly property int espace_colonnes_principales: 20
|
||||
|
||||
readonly property int nombre_batteries_affiches_sur_une_colonne: 8
|
||||
|
||||
readonly property int periode_init_raffraichissement_parametres: 1 // En ms
|
||||
readonly property int periode_raffraichissement_parametres: 100 // En ms
|
||||
|
||||
|
||||
// Affichage :
|
||||
property int niveau_page: 0
|
||||
property bool bouton_bandeau_bas_zone_retour_actif: false
|
||||
|
||||
|
||||
|
||||
// Modèles :
|
||||
// Note : les modèles chargés dans 'main.qml' n'ont pas à être rechargés dans les pages suivantes
|
||||
|
||||
|
||||
//===========================================================
|
||||
// Timer periode raffraichissement parametres :
|
||||
//===========================================================
|
||||
Timer {
|
||||
id: timer_raffraichissement_parametres
|
||||
interval: periode_init_raffraichissement_parametres
|
||||
triggeredOnStart: false
|
||||
running: true
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
if (interval == periode_init_raffraichissement_parametres) // Premier passage, 1ms après le premier chargement
|
||||
{
|
||||
interval = periode_raffraichissement_parametres;
|
||||
init_page();
|
||||
}
|
||||
|
||||
if (stackView.depth === (niveau_page + 1)) // Désactive le raffraichissement quand la page n'est pas activée dans la pile
|
||||
{
|
||||
if (!bouton_bandeau_bas_zone_retour_actif)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================
|
||||
// Lorsque la page est sur le point d'être affichée dans la pile :
|
||||
//===========================================================
|
||||
StackView.onActivating: {
|
||||
mise_a_jour_donnees(); // Permet que lors du retour sur la page, l'état des différentes variables soit mise à jour avant l'affichage proprement dit.
|
||||
}
|
||||
|
||||
// Titre de la page :
|
||||
Shipheart_titre_1 {titre:qsTr("Configuration des batteries"); hauteur: shipheart_hauteur_bandeau_haut}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Ecran de gauche (liste des batteries) :
|
||||
//-------------------------------------------------------
|
||||
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 batteries :
|
||||
GridView {
|
||||
id: grille_principale
|
||||
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
cellWidth: parent.width;
|
||||
cellHeight: height / nombre_batteries_affiches_sur_une_colonne
|
||||
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
|
||||
delegate: Rectangle {
|
||||
width: grille_principale.cellWidth
|
||||
height: grille_principale.cellHeight
|
||||
color: "transparent"
|
||||
Rectangle { // c'est le bouton proprement dit...
|
||||
height: parent.height - 10
|
||||
width:parent.width - 10
|
||||
color: shipheart_couleur_fond_bouton
|
||||
border.color: couleur_rouge
|
||||
border.width: (model.etat_systeme === 0) ? 0 : 3
|
||||
radius: shipheart_rayon_bouton
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
Text {
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Qt.AlignLeft
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
leftPadding: 20
|
||||
text: model.nom
|
||||
color: couleur_blanc_casse
|
||||
font.pixelSize: 18
|
||||
wrapMode: Label.Wrap
|
||||
}
|
||||
MouseArea{
|
||||
anchors.fill : parent
|
||||
enabled : !grille_principale.moving // Permet de bloquer le Mousearea pendant le déplacement de la grille
|
||||
onReleased: { // Permet déclencher à la fin d'un clic (court) sans mouvement
|
||||
shipheart_clic();
|
||||
stackView.push("config_batterie.qml", {"id_batterie": model.id})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ListModel {
|
||||
id: modele_grille_principale
|
||||
}
|
||||
Label {
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Qt.AlignHCenter
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
visible: parent.count === 0
|
||||
text: qsTr("Aucune batterie n'est encore configurée...")
|
||||
color: couleur_rouge_transparent
|
||||
font.pixelSize: 15
|
||||
font.bold: true
|
||||
wrapMode: Label.Wrap
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Ecran Droite :
|
||||
//-------------------------------------------------------
|
||||
Rectangle {
|
||||
id: zone_affichage_droite
|
||||
x: zone_affichage_gauche.width + espace_colonnes_principales
|
||||
y: shipheart_hauteur_bandeau_haut + 5; // Le +5 permet d'aligner le haut du premier bouton de droite avec le haut du premier bouton de la liste de gauche (
|
||||
width: (shipheart_largeur_page * (1 - pourcentage_largeur_colonne_gauche)) - (espace_colonnes_principales / 2)
|
||||
height: affichage_hauteur_utile
|
||||
color: "transparent"
|
||||
|
||||
|
||||
Column {
|
||||
anchors.fill: parent
|
||||
spacing: 10
|
||||
|
||||
//----------------------
|
||||
// Bouton + :
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: hauteur_bouton_droit
|
||||
color: shipheart_couleur_fond_bouton
|
||||
radius: shipheart_rayon_bouton
|
||||
visible: !clavier.active
|
||||
Text {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
font.pixelSize: 40
|
||||
text: qsTr("+")
|
||||
color: couleur_blanc_casse
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
stackView.push("config_batterie.qml");
|
||||
}
|
||||
}
|
||||
}
|
||||
//----------------------
|
||||
// Bouton tri :
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: hauteur_bouton_droit
|
||||
color: shipheart_couleur_fond_bouton
|
||||
radius: shipheart_rayon_bouton
|
||||
visible: !clavier.active // && (modele_grille_principale.count > 1) // SDIR #258
|
||||
Image {
|
||||
id: image_parametres
|
||||
source: "/images/tri.png"
|
||||
sourceSize.height: 25
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
stackView.push("config_ordre_elements.qml", {"table": "TB_Batteries"})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Bandeau bas :
|
||||
//-------------------------------------------------------
|
||||
Row {
|
||||
x: 0
|
||||
y: shipheart_hauteur_page - shipheart_hauteur_bandeau_bas;
|
||||
width: shipheart_largeur_page;
|
||||
height: shipheart_hauteur_bandeau_bas;
|
||||
padding: 5
|
||||
spacing: 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();
|
||||
stackView.pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 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()
|
||||
{
|
||||
niveau_page = stackView.depth - 1; // Permet de stocker le niveau de la page dans la Stackview
|
||||
|
||||
mise_a_jour_donnees();
|
||||
}
|
||||
|
||||
//=============================================================================================================
|
||||
// Mise à jour des données
|
||||
//=============================================================================================================
|
||||
function mise_a_jour_donnees()
|
||||
{
|
||||
var req, res;
|
||||
var i;
|
||||
var nb_batteries;
|
||||
|
||||
|
||||
modele_grille_principale.clear(); // RAZ des valeurs existantes
|
||||
|
||||
req = 'SELECT Cle_primaire, ';
|
||||
req += ' Etat_systeme, ';
|
||||
req += ' Nom ';
|
||||
req += ' FROM TB_Batteries ORDER BY Priorite_affichage_accueil';
|
||||
//console.log("req = [ " + req + '; ]');
|
||||
nb_batteries = bdd.requete(req);
|
||||
|
||||
for (i = 0; i < nb_batteries; i ++)
|
||||
{
|
||||
res = bdd.lecture_ligne();
|
||||
if (!res.isEmpty)
|
||||
{
|
||||
|
||||
modele_grille_principale.append({"id": Number(res[0]), "etat_systeme": Number(res[1]), "nom": res[2] });
|
||||
|
||||
}
|
||||
else break; // Ne devrait pas arriver....
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2555
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,874 @@
|
||||
//========================================================================================================================================================================
|
||||
// CONFIG_CIRCUIT_CONDITION_COMMANDE_AUTO.QML
|
||||
// Ce fichier traite la configuration d'une condition d'une commande Auto d'un circuit. La page permet notamment de :
|
||||
// - Modifier la config de cette condition (ou de la créer la première fois),
|
||||
// La page est appelée depuis la page config_circuit_commande_auto
|
||||
//========================================================================================================================================================================
|
||||
import QtQuick 2.12
|
||||
import QtQml.Models
|
||||
|
||||
import qt.koriolan.shipheart 1.0
|
||||
import"fonctions.js" as Fonctions
|
||||
|
||||
|
||||
|
||||
Shipheart_page {
|
||||
id: page_config_capteur_calcule_booleen_condition
|
||||
|
||||
|
||||
// Mis en forme :
|
||||
readonly property double pourcentage_largeur_colonne_gauche: 0.75
|
||||
readonly property double espace_colonnes_principales: 20
|
||||
readonly property double pourcentage_hauteur_ligne_haut: 1
|
||||
readonly property double espace_lignes_principales: 20
|
||||
readonly property double affichage_hauteur_utile: shipheart_hauteur_page - shipheart_hauteur_bandeau_haut - shipheart_hauteur_bandeau_bas
|
||||
|
||||
readonly property int hauteur_ligne_formulaire: 60
|
||||
readonly property double pourcentage_largeur_labels_formulaire: 0.4
|
||||
readonly property double pourcentage_largeur_unites_formulaire: 0.1
|
||||
|
||||
readonly property int hauteur_bouton_droit: 80
|
||||
|
||||
readonly property double pourcentage_bandeau_bas_largeur_zone_retour: 1
|
||||
|
||||
readonly property int periode_init_raffraichissement_parametres: 1 // En ms
|
||||
readonly property int periode_raffraichissement_parametres: 1000 // En ms
|
||||
|
||||
|
||||
// Données :
|
||||
property bool flag_init: true // Permet de bloquer certains affichage tant que l'init n'est pas terminée
|
||||
|
||||
property string nom_capteur: ""
|
||||
|
||||
property bool flag_new;
|
||||
property int type_source: 0
|
||||
property int id_source: 0
|
||||
property int id_variable: 0
|
||||
property int test: 0
|
||||
property double seuil: 0
|
||||
property string seuil_unite: ""
|
||||
|
||||
property bool flag_test_binaire: false // Indique si l'évènement porte sur une condition binaire ou non (exemple: Capteur>Entrée AUX)
|
||||
|
||||
|
||||
// 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_capteur_calcule_booleen_condition(bool flag_new, int type_source, int id_source, int id_variable, int test, double seuil) // 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;
|
||||
|
||||
init_page();
|
||||
}
|
||||
else {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Titre de la page :
|
||||
Shipheart_titre_1 {titre: qsTr("Création d'une condition du capteur [%1]").arg(nom_capteur); 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"
|
||||
|
||||
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 : Type_source
|
||||
Rectangle {
|
||||
width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2)
|
||||
height: visible ? hauteur_ligne_formulaire : 0 // Permet que la ligne n'occupe aucune place quand elle n'est pas visible
|
||||
color: "transparent"
|
||||
visible: (!flag_init)
|
||||
|
||||
Shipheart_formulaire_label {
|
||||
text: qsTr("Type")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
couleur: (champ_formulaire_Type_source.currentIndex !== 0)
|
||||
? shipheart_formulaire_couleur_texte_par_defaut
|
||||
: shipheart_formulaire_couleur_texte_en_erreur
|
||||
}
|
||||
|
||||
Shipheart_formulaire_combobox {
|
||||
id: champ_formulaire_Type_source
|
||||
model: ListModel { }
|
||||
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
|
||||
onActivated: {
|
||||
shipheart_clic();
|
||||
if (type_source !== champ_formulaire_Type_source.model.get(champ_formulaire_Type_source.currentIndex).valeur)
|
||||
{
|
||||
type_source = champ_formulaire_Type_source.model.get(champ_formulaire_Type_source.currentIndex).valeur;
|
||||
id_source = 0;
|
||||
id_variable = 0;
|
||||
test = 0;
|
||||
mise_a_jour_source();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Shipheart_formulaire_ligne_separation {
|
||||
haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Ligne de formulaire : Source
|
||||
Rectangle {
|
||||
width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2)
|
||||
height: visible ? hauteur_ligne_formulaire : 0 // Permet que la ligne n'occupe aucune place quand elle n'est pas visible
|
||||
color: "transparent"
|
||||
visible: (!flag_init)
|
||||
&& (type_source > 0)
|
||||
|
||||
Shipheart_formulaire_label {
|
||||
text: qsTr("Source")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
couleur: (champ_formulaire_Source.currentIndex !== 0)
|
||||
? shipheart_formulaire_couleur_texte_par_defaut
|
||||
: shipheart_formulaire_couleur_texte_en_erreur
|
||||
}
|
||||
|
||||
Shipheart_formulaire_combobox {
|
||||
id: champ_formulaire_Source
|
||||
model: ListModel { }
|
||||
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
|
||||
onActivated: {
|
||||
shipheart_clic();
|
||||
if (id_source !== champ_formulaire_Source.model.get(champ_formulaire_Source.currentIndex).valeur)
|
||||
{
|
||||
id_source = champ_formulaire_Source.model.get(champ_formulaire_Source.currentIndex).valeur;
|
||||
id_variable = 0;
|
||||
test = 0;
|
||||
mise_a_jour_variable();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Shipheart_formulaire_ligne_separation {
|
||||
haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Ligne de formulaire : Variable
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: visible ? hauteur_ligne_formulaire : 0 // Permet que la ligne n'occupe aucune place quand elle n'est pas visible
|
||||
color: "transparent"
|
||||
visible: (!flag_init)
|
||||
&& (type_source > 0)
|
||||
&& (id_source > 0)
|
||||
&& (champ_formulaire_Variable.model.count > 2) // Comme on a toujours "Non défini", si Count<=2, c'est qu'on n'a qu'un seul choix qu'il n'est pas nécessaire d'afficher...
|
||||
|
||||
Shipheart_formulaire_label {
|
||||
text: qsTr("Variable")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
couleur: (champ_formulaire_Variable.currentIndex !== 0)
|
||||
? shipheart_formulaire_couleur_texte_par_defaut
|
||||
: shipheart_formulaire_couleur_texte_en_erreur
|
||||
}
|
||||
|
||||
Shipheart_formulaire_combobox {
|
||||
id: champ_formulaire_Variable
|
||||
model: ListModel { }
|
||||
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
|
||||
onActivated: {
|
||||
shipheart_clic();
|
||||
if (id_variable !== champ_formulaire_Variable.model.get(champ_formulaire_Variable.currentIndex).valeur)
|
||||
{
|
||||
id_variable = champ_formulaire_Variable.model.get(champ_formulaire_Variable.currentIndex).valeur;
|
||||
seuil_unite = champ_formulaire_Variable.model.get(champ_formulaire_Variable.currentIndex).unite;
|
||||
mise_a_jour_test();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Shipheart_formulaire_ligne_separation {
|
||||
haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Ligne de formulaire : Test
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: visible ? hauteur_ligne_formulaire : 0 // Permet que la ligne n'occupe aucune place quand elle n'est pas visible
|
||||
color: "transparent"
|
||||
visible: (!flag_init)
|
||||
&& (type_source > 0)
|
||||
&& (id_source > 0)
|
||||
&& (id_variable > 0)
|
||||
|
||||
Shipheart_formulaire_label {
|
||||
text: qsTr("Test")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
couleur: (champ_formulaire_Test.currentIndex !== 0)
|
||||
? shipheart_formulaire_couleur_texte_par_defaut
|
||||
: shipheart_formulaire_couleur_texte_en_erreur
|
||||
}
|
||||
|
||||
Shipheart_formulaire_combobox {
|
||||
id: champ_formulaire_Test
|
||||
model: ListModel { }
|
||||
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
|
||||
onActivated: {
|
||||
shipheart_clic();
|
||||
test = champ_formulaire_Test.model.get(champ_formulaire_Test.currentIndex).valeur;
|
||||
}
|
||||
}
|
||||
|
||||
Shipheart_formulaire_ligne_separation {
|
||||
haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Ligne de formulaire : Seuil
|
||||
Rectangle {
|
||||
width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2)
|
||||
height: visible ? hauteur_ligne_formulaire : 0 // Permet que la ligne n'occupe aucune place quand elle n'est pas visible
|
||||
color: "transparent"
|
||||
visible: (!flag_init)
|
||||
&& (type_source > 0)
|
||||
&& (id_source > 0)
|
||||
&& (id_variable > 0)
|
||||
&& (!flag_test_binaire) // Si on est sur un test binaire, il est inutile d'afficher le seuil...
|
||||
|
||||
Shipheart_formulaire_label {
|
||||
text: qsTr("Seuil")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
}
|
||||
|
||||
Shipheart_formulaire_textfield {
|
||||
id: champ_formulaire_Seuil
|
||||
width: parent.width * (1 - pourcentage_largeur_labels_formulaire - pourcentage_largeur_unites_formulaire)
|
||||
x: parent.width * pourcentage_largeur_labels_formulaire
|
||||
flag_num_only: true
|
||||
}
|
||||
|
||||
Shipheart_formulaire_unite { // Unités :
|
||||
text: seuil_unite
|
||||
width: parent.width * pourcentage_largeur_unites_formulaire
|
||||
}
|
||||
|
||||
Shipheart_formulaire_ligne_separation {
|
||||
haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse
|
||||
}
|
||||
}
|
||||
|
||||
} // Fin de modele grille principale (ObjectModel )
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// 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 {
|
||||
width: parent.width
|
||||
height: hauteur_bouton_droit
|
||||
color: shipheart_couleur_fond_bouton
|
||||
radius: shipheart_rayon_bouton
|
||||
visible:
|
||||
// (!clavier.active) && // SDIR #255
|
||||
(type_source > 0) &&
|
||||
(id_source > 0) &&
|
||||
(id_variable > 0) &&
|
||||
(test > 0)
|
||||
Text {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
font.pixelSize: 20
|
||||
text: flag_new ? qsTr("Créer la condition") : qsTr("Enregistrer")
|
||||
color: couleur_blanc_casse
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
|
||||
seuil = champ_formulaire_Seuil.text;
|
||||
|
||||
// Renvoi des nouvelles valeurs vers la page d'appel (qu'on soit en Création ou Modification) :
|
||||
page_config_capteur_calcule_booleen_condition.enregistrer_config_capteur_calcule_booleen_condition(flag_new, type_source, id_source, id_variable, test, seuil);
|
||||
|
||||
// Fermeture de la page dès que les données ont été remontées :
|
||||
stackView.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// 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();
|
||||
stackView.pop();
|
||||
}
|
||||
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) - (2 * parent.padding)
|
||||
height: shipheart_hauteur_bandeau_bas - parent.topPadding - parent.bottomPadding;
|
||||
radius: shipheart_rayon_bouton
|
||||
color: shipheart_couleur_fond_bouton
|
||||
|
||||
Image {
|
||||
source: "/images/icone_retour.png"
|
||||
sourceSize.height: 30
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea { // Zone d'interaction. On est obligé de la mettre dans la grille pour que Rectangle et MouseArea soient frères ou parent/enfant ET qu'on n'occupe qu'un espace dans la grille.
|
||||
id: mouse_area_bandeau_bas_zone_retour
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
stackView.pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================
|
||||
// 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 i;
|
||||
|
||||
// Détection d'une création vs une modification :
|
||||
if ((type_source > 0) && (id_source> 0) && (id_variable> 0)) flag_new = false;
|
||||
else flag_new = true;
|
||||
|
||||
|
||||
// Mise à jour des champs texte :
|
||||
champ_formulaire_Seuil.text = seuil;
|
||||
|
||||
// Mise à jour du modèle de Type de source :
|
||||
champ_formulaire_Type_source.model.clear();
|
||||
champ_formulaire_Type_source.model.append( {
|
||||
"valeur": 0,
|
||||
"texte": qsTr("Non défini") });
|
||||
champ_formulaire_Type_source.model.append( {
|
||||
"valeur": shipheart_source_mesure_circuit,
|
||||
"texte": qsTr("Circuit") });
|
||||
champ_formulaire_Type_source.model.append( {
|
||||
"valeur": shipheart_source_mesure_capteur,
|
||||
"texte": qsTr("Capteur") });
|
||||
champ_formulaire_Type_source.model.append( {
|
||||
"valeur": shipheart_source_mesure_reservoir,
|
||||
"texte": qsTr("Réservoir") });
|
||||
champ_formulaire_Type_source.model.append( {
|
||||
"valeur": shipheart_source_mesure_batterie,
|
||||
"texte": qsTr("Batterie") });
|
||||
|
||||
// Type source : positionnement de l'index sur la valeur en cours :
|
||||
i = recherche_index_valeur_modele(type_source, champ_formulaire_Type_source.model, "Type_source");
|
||||
if (i === -1) champ_formulaire_Type_source.currentIndex = recherche_index_valeur_modele(-1, champ_formulaire_Type_source.model, "Type_source");
|
||||
else champ_formulaire_Type_source.currentIndex = i;
|
||||
|
||||
// Mise à jour en cascade :
|
||||
if (type_source > 0) mise_a_jour_source();
|
||||
|
||||
flag_init = false; // Indique que l'init est terminée
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================================================
|
||||
// Mise à jour du modèle de source
|
||||
//=============================================================================================================
|
||||
function mise_a_jour_source()
|
||||
{
|
||||
var req, res;
|
||||
var nb;
|
||||
var i;
|
||||
var flag_familles;
|
||||
|
||||
champ_formulaire_Source.model.clear();
|
||||
champ_formulaire_Source.model.append({"valeur": 0, "texte": qsTr("Non défini") , "groupe": false });
|
||||
|
||||
// Choix de le requete en fonction du type :
|
||||
switch(type_source)
|
||||
{
|
||||
case shipheart_source_mesure_circuit:
|
||||
req = 'SELECT Cle_primaire, Nom, Nom_famille, Priorite_affichage_accueil FROM TB_Circuits, '
|
||||
req += ' (SELECT Cle_primaire AS Cle_famille, Nom AS Nom_famille, Priorite_affichage AS Priorite_famille FROM TB_Familles WHERE Type_source=' + shipheart_type_source_circuits + ') AS TB_Familles '
|
||||
req += ' WHERE ID_Famille=Cle_famille '
|
||||
req += ' ORDER BY Priorite_famille, ABS(Priorite_affichage_accueil) ';
|
||||
flag_familles = true;
|
||||
break;
|
||||
case shipheart_source_mesure_capteur:
|
||||
req = 'SELECT Cle_primaire, Nom, Nom_famille, Priorite_affichage_accueil, Type_entrees FROM TB_Capteurs, '
|
||||
req += ' (SELECT Cle_primaire AS Cle_famille, Nom AS Nom_famille, Priorite_affichage AS Priorite_famille FROM TB_Familles WHERE Type_source=' + shipheart_type_source_capteurs + ') AS TB_Familles ';
|
||||
req += ' WHERE ID_Famille=Cle_famille ';
|
||||
req += ' ORDER BY Priorite_famille, ABS(Priorite_affichage_accueil) ';
|
||||
flag_familles = true;
|
||||
break;
|
||||
case shipheart_source_mesure_reservoir:
|
||||
req = 'SELECT Cle_primaire, Nom, Nom_famille, Priorite_affichage_accueil FROM TB_Reservoirs, '
|
||||
req += ' (SELECT Cle_primaire AS Cle_famille, Nom AS Nom_famille, Priorite_affichage AS Priorite_famille FROM TB_Familles WHERE Type_source=' + shipheart_type_source_reservoirs + ') AS TB_Familles '
|
||||
req += ' WHERE ID_Famille=Cle_famille '
|
||||
req += ' ORDER BY Priorite_famille, ABS(Priorite_affichage_accueil) ';
|
||||
flag_familles = true;
|
||||
break;
|
||||
case shipheart_source_mesure_batterie:
|
||||
req = 'SELECT Cle_primaire, Nom FROM TB_Batteries '
|
||||
req += 'WHERE 1 '
|
||||
req += 'ORDER BY Priorite_affichage_accueil, Nom';
|
||||
flag_familles = false;
|
||||
break;
|
||||
}
|
||||
//console.log("req = [ " + req + "; ]");
|
||||
nb = bdd.requete(req);
|
||||
var prec_famille = "";
|
||||
var flag_aine_famille;
|
||||
var flag_capteur_calcule;
|
||||
for (i = 0; i < nb; i ++)
|
||||
{
|
||||
res = bdd.lecture_ligne();
|
||||
if (!res.isEmpty)
|
||||
{
|
||||
// Ajout d'une ligne par famille (si le type l'autorise) :
|
||||
if (flag_familles)
|
||||
{
|
||||
if (prec_famille !== res[2])
|
||||
{
|
||||
champ_formulaire_Source.model.append({"valeur": Number(res[0]), "texte": res[2], "groupe": true, "actif": true, "capteur_calcule": false });
|
||||
prec_famille = res[2];
|
||||
}
|
||||
}
|
||||
|
||||
// Détection d'un capteur calculé :
|
||||
flag_capteur_calcule = false;
|
||||
if (type_source === shipheart_source_mesure_capteur)
|
||||
{
|
||||
if (Number(res[4]) >= shipheart_capteur_type_entrees_calculee_booleen) flag_capteur_calcule = true;
|
||||
}
|
||||
|
||||
// Ajout de la ligne "normale" dans le modèle :
|
||||
champ_formulaire_Source.model.append({"valeur": Number(res[0]), "texte": res[1], "groupe": false, "actif": true, "capteur_calcule": flag_capteur_calcule });
|
||||
}
|
||||
else break; // Ne devrait pas arriver....
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Dévalidation des entrées du modèle qui créeraient des références circulaires :
|
||||
if (type_source === shipheart_source_mesure_capteur) // Cas d'une condition sur capteur uniquement
|
||||
{
|
||||
// Parcours de tout le modèle :
|
||||
for (i = 0; i < champ_formulaire_Source.model.count; i ++)
|
||||
{
|
||||
if (champ_formulaire_Source.model.get(i).capteur_calcule) // On ne traite que les capteurs calculés (les autres ne présentent pas de risque de réf circulaires)
|
||||
{
|
||||
var cle_capteur = champ_formulaire_Source.model.get(i).valeur;
|
||||
|
||||
// Dévalidation de tous les capteurs calculés dans le doute :
|
||||
champ_formulaire_Source.model.set(i, {"actif": false });
|
||||
/*
|
||||
// Dévalidation du capteur auquel appartient la condition :
|
||||
if (cle_capteur === id_capteur) champ_formulaire_Source.model.set(i, {"actif": false });
|
||||
else
|
||||
{
|
||||
// A TRAITER !!!!!
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------------
|
||||
// Source : positionnement de l'index sur la valeur en cours :
|
||||
i = recherche_index_valeur_modele(id_source, champ_formulaire_Source.model, "Source");
|
||||
if (i === -1) champ_formulaire_Source.currentIndex = recherche_index_valeur_modele(0, champ_formulaire_Source.model, "Source");
|
||||
else champ_formulaire_Source.currentIndex = i;
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------------
|
||||
// Mise à jour en cascade :
|
||||
if (id_source > 0) mise_a_jour_variable();
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================================================
|
||||
// Mise à jour du modèle de variable
|
||||
//=============================================================================================================
|
||||
function mise_a_jour_variable()
|
||||
{
|
||||
var req, res;
|
||||
var nb;
|
||||
var i;
|
||||
var libelle;
|
||||
|
||||
// Effacement du modèle et premier enregistrement avec 'Non défini' ::
|
||||
champ_formulaire_Variable.model.clear();
|
||||
champ_formulaire_Variable.model.append( {
|
||||
"valeur": 0,
|
||||
"texte": qsTr("Non défini"),
|
||||
"unite": "",
|
||||
"actif": true });
|
||||
switch(type_source)
|
||||
{
|
||||
//----------------------------------------
|
||||
case shipheart_source_mesure_circuit:
|
||||
|
||||
// Recherche du type de circuit :
|
||||
req = 'SELECT Type FROM TB_Modules_config WHERE Adresse_k_bus IN (SELECT Adresse_module FROM TB_Circuits WHERE Cle_primaire=' + id_source + ')';
|
||||
//console.log("Requête = [ " + req + "; ]");
|
||||
res = bdd.requete_unique(req);
|
||||
var type_circuit = Number(res[0]);
|
||||
|
||||
// Recherche des entrées de TB_Variables applicables à la source sélectionnée :
|
||||
req = "SELECT Cle_primaire, Unite, Code FROM TB_Variables WHERE Type=" + type_source + "; ";
|
||||
//console.log("Requête = [ " + req + "; ]");
|
||||
nb = bdd.requete(req);
|
||||
|
||||
for (i = 0; i < nb; i ++)
|
||||
{
|
||||
res = bdd.lecture_ligne();
|
||||
if (!res.isEmpty)
|
||||
{
|
||||
switch(res[2])
|
||||
{
|
||||
//---------------------
|
||||
case "Circ_tension":
|
||||
if (type_circuit === shipheart_type_module_shippower4AC) continue;
|
||||
break;
|
||||
|
||||
//---------------------
|
||||
case "Circ_frequence":
|
||||
if (type_circuit !== shipheart_type_module_shippower4AC) continue;
|
||||
break;
|
||||
|
||||
//---------------------
|
||||
case "Circ_tension_secteur":
|
||||
if (type_circuit !== shipheart_type_module_shippower4AC) continue;
|
||||
break;
|
||||
}
|
||||
libelle = Fonctions.nom_variable(res[2]);
|
||||
|
||||
|
||||
champ_formulaire_Variable.model.append( {
|
||||
"valeur": Number(res[0]),
|
||||
"texte": libelle,
|
||||
"unite": res[1],
|
||||
"actif": true });
|
||||
}
|
||||
}
|
||||
|
||||
// Mise à jour du flag de test binaire :
|
||||
flag_test_binaire = false;
|
||||
|
||||
break;
|
||||
|
||||
//----------------------------------------
|
||||
case shipheart_source_mesure_capteur:
|
||||
|
||||
// Recherche de la variable du capteur :
|
||||
req = "SELECT ID_Variable, Type_entrees FROM TB_Capteurs WHERE Cle_primaire=" + id_source + "; ";
|
||||
//console.log("Requête = [ " + req + "; ]");
|
||||
res = bdd.requete_unique(req);
|
||||
var type = Number(res[1]);
|
||||
|
||||
if (type < shipheart_capteur_type_entrees_calculee_booleen) // Si le capteur est calculé, on ne peut pas chercher (et trouver d'ID_Variable)
|
||||
{
|
||||
// Recherche des informations de la variable du capteur dans TB_Variables :
|
||||
req = "SELECT Cle_primaire, Nom, Unite FROM TB_Variables WHERE Cle_primaire=" + Number(res[0]) + "; ";
|
||||
//console.log("Requête = [ " + req + "; ]");
|
||||
res = bdd.requete_unique(req);
|
||||
|
||||
champ_formulaire_Variable.model.append( {
|
||||
"valeur": Number(res[0]),
|
||||
"texte": res[1],
|
||||
"unite": res[2],
|
||||
"actif": true });
|
||||
|
||||
// Mise à jour de la variable car on n'a pas le choix :
|
||||
id_variable = Number(res[0]);
|
||||
}
|
||||
|
||||
// Mise à jour du flag de test binaire :
|
||||
if ((type == shipheart_capteur_type_entrees_aux) ||
|
||||
(type == shipheart_capteur_type_entrees_calculee_booleen) ) flag_test_binaire = true;
|
||||
else flag_test_binaire = false;
|
||||
|
||||
break;
|
||||
|
||||
//----------------------------------------
|
||||
case shipheart_source_mesure_reservoir:
|
||||
|
||||
// Recherche des entrées de TB_Variables applicables à la source sélectionnée :
|
||||
req = "SELECT Cle_primaire, Nom, Unite FROM TB_Variables WHERE Code='Res_niveau'; ";
|
||||
//console.log("Requête = [ " + req + "; ]");
|
||||
res = bdd.requete_unique(req);
|
||||
|
||||
champ_formulaire_Variable.model.append( {
|
||||
"valeur": Number(res[0]),
|
||||
"texte": res[1],
|
||||
"unite": res[2],
|
||||
"actif": true });
|
||||
|
||||
// Mise à jour de la variable car on n'a pas le choix :
|
||||
id_variable = Number(res[0]);
|
||||
|
||||
// Mise à jour du flag de test binaire :
|
||||
flag_test_binaire = false;
|
||||
|
||||
break;
|
||||
|
||||
//----------------------------------------
|
||||
case shipheart_source_mesure_batterie:
|
||||
|
||||
// Recherche du type de capteur de batterie :
|
||||
req = "SELECT Type_entrees FROM TB_Batteries WHERE Cle_primaire=" + id_source + "; ";
|
||||
//console.log("Requête = [ " + req + "; ]");
|
||||
res = bdd.requete_unique(req);
|
||||
var type_entrees = Number(res[0]);
|
||||
|
||||
// Recherche des entrées de TB_Variables applicables à la source sélectionnée :
|
||||
req = "SELECT Cle_primaire, Unite, Code FROM TB_Variables WHERE Type=" + type_source + "; ";
|
||||
//console.log("Requête = [ " + req + "; ]");
|
||||
nb = bdd.requete(req);
|
||||
|
||||
for (i = 0; i < nb; i ++)
|
||||
{
|
||||
res = bdd.lecture_ligne();
|
||||
if (!res.isEmpty)
|
||||
{
|
||||
switch(res[2])
|
||||
{
|
||||
//---------------------
|
||||
case "Batt_temperature":
|
||||
if (type_entrees !== shipheart_capteur_type_entrees_ibs) continue;
|
||||
break;
|
||||
|
||||
//---------------------
|
||||
case "Batt_courant_differentiel":
|
||||
if (type_entrees !== shipheart_capteur_type_entrees_ibs) continue;
|
||||
break;
|
||||
|
||||
//---------------------
|
||||
case "Batt_courant_charge":
|
||||
if (type_entrees !== shipheart_capteur_type_entrees_ibs) continue;
|
||||
break;
|
||||
|
||||
//---------------------
|
||||
case "Batt_soh":
|
||||
if (type_entrees !== shipheart_capteur_type_entrees_ibs) continue;
|
||||
break;
|
||||
|
||||
//---------------------
|
||||
/* case "Batt_autonomie":
|
||||
if (type_entrees !== shipheart_capteur_type_entrees_ibs) continue;
|
||||
break;
|
||||
*/
|
||||
}
|
||||
libelle = Fonctions.nom_variable(res[2]);
|
||||
|
||||
champ_formulaire_Variable.model.append( {
|
||||
"valeur": Number(res[0]),
|
||||
"texte": libelle,
|
||||
"unite": res[1],
|
||||
"actif": true });
|
||||
}
|
||||
}
|
||||
|
||||
// Mise à jour du flag de test binaire :
|
||||
flag_test_binaire = false;
|
||||
|
||||
break;
|
||||
|
||||
//----------------------------------------
|
||||
default:
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// Mise à jour de l'index courant du modèle :
|
||||
i = recherche_index_valeur_modele(id_variable, champ_formulaire_Variable.model, "id_variable");
|
||||
if (i === -1) champ_formulaire_Variable.currentIndex = recherche_index_valeur_modele(0, champ_formulaire_Variable.model, "id_variable");
|
||||
else champ_formulaire_Variable.currentIndex = i;
|
||||
|
||||
// Mise à jour de l'unité correspondant à la variable en cours :
|
||||
seuil_unite = champ_formulaire_Variable.model.get(champ_formulaire_Variable.currentIndex).unite;
|
||||
|
||||
// Mise à jour en cascade :
|
||||
if (id_variable > 0) mise_a_jour_test();
|
||||
}
|
||||
|
||||
//=============================================================================================================
|
||||
// Mise à jour du modèle
|
||||
//=============================================================================================================
|
||||
function mise_a_jour_test()
|
||||
{
|
||||
var i;
|
||||
|
||||
champ_formulaire_Test.model.clear();
|
||||
champ_formulaire_Test.model.append( {
|
||||
"valeur": shipheart_test_non_defini,
|
||||
"texte": qsTr("Non défini"),
|
||||
"actif": true });
|
||||
if (flag_test_binaire)
|
||||
{
|
||||
champ_formulaire_Test.model.append( {
|
||||
"valeur": shipheart_test_strictement_superieur,
|
||||
"texte": qsTr("Actif"),
|
||||
"actif": true });
|
||||
champ_formulaire_Test.model.append( {
|
||||
"valeur": shipheart_test_strictement_inferieur,
|
||||
"texte": qsTr("Inactif"),
|
||||
"actif": true });
|
||||
}
|
||||
else
|
||||
{
|
||||
champ_formulaire_Test.model.append( {
|
||||
"valeur": shipheart_test_strictement_inferieur,
|
||||
"texte": qsTr("< au seuil"),
|
||||
"actif": true });
|
||||
champ_formulaire_Test.model.append( {
|
||||
"valeur": shipheart_test_inferieur_ou_egal,
|
||||
"texte": qsTr("≤ au seuil"),
|
||||
"actif": true });
|
||||
champ_formulaire_Test.model.append( {
|
||||
"valeur": shipheart_test_egal,
|
||||
"texte": qsTr("= au seuil"),
|
||||
"actif": true });
|
||||
champ_formulaire_Test.model.append( {
|
||||
"valeur": shipheart_test_superieur_ou_egal,
|
||||
"texte": qsTr("≥ au seuil"),
|
||||
"actif": true });
|
||||
champ_formulaire_Test.model.append( {
|
||||
"valeur": shipheart_test_strictement_superieur,
|
||||
"texte": qsTr("> au seuil"),
|
||||
"actif": true });
|
||||
}
|
||||
// Mise à jour de l'index courant du modèle :
|
||||
i = recherche_index_valeur_modele(test, champ_formulaire_Test.model, "Test");
|
||||
if (i === -1) champ_formulaire_Test.currentIndex = recherche_index_valeur_modele(0, champ_formulaire_Test.model, "Test");
|
||||
else champ_formulaire_Test.currentIndex = i;
|
||||
}
|
||||
|
||||
//=============================================================================================================
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,478 @@
|
||||
//========================================================================================================================================================================
|
||||
// CONFIG_CAPTEURS.QML
|
||||
// Ce fichier traite la configuration des capteurs. La page permet notamment de :
|
||||
// - Afficher, pour tous les capteurs déjà configurés (et donc d'accéder à la configuration détaillée de l'un d'eux ; ou sa création)
|
||||
// - Déclencher la recherche de nouveaux capteurs OW
|
||||
// La page est appelée depuis la page PARAMETRES_AVANCES, en cliquant sur "Capteurs"
|
||||
//========================================================================================================================================================================
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
import qt.koriolan.shipheart 1.0
|
||||
import"fonctions.js" as Fonctions
|
||||
|
||||
|
||||
|
||||
Shipheart_page {
|
||||
id: page_config_capteurs
|
||||
|
||||
|
||||
// Mis en forme :
|
||||
readonly property double affichage_hauteur_utile: shipheart_hauteur_page - shipheart_hauteur_bandeau_haut - shipheart_hauteur_bandeau_bas
|
||||
readonly property int hauteur_bouton_droit: 80
|
||||
|
||||
readonly property double pourcentage_largeur_colonne_gauche: 0.75
|
||||
readonly property int espace_colonnes_principales: 20
|
||||
readonly property double pourcentage_bandeau_bas_largeur_zone_retour: 1.0
|
||||
|
||||
readonly property int nombre_capteurs_affiches_sur_une_colonne: 8
|
||||
|
||||
readonly property int periode_init_raffraichissement_parametres: 1 // En ms
|
||||
readonly property int periode_raffraichissement_parametres: 1000 // En ms /!\ Laisser à 1s afin que le compteur secondes fonctionne correctement...
|
||||
|
||||
// Affichage :
|
||||
|
||||
|
||||
|
||||
// Modèles :
|
||||
// Note : les modèles chargés dans 'main.qml' n'ont pas à être rechargés dans les pages suivantes
|
||||
|
||||
|
||||
//===========================================================
|
||||
// Timer periode raffraichissement parametres :
|
||||
//===========================================================
|
||||
Timer {
|
||||
id: timer_raffraichissement_parametres
|
||||
interval: periode_init_raffraichissement_parametres
|
||||
triggeredOnStart: false
|
||||
running: true
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
if (interval == periode_init_raffraichissement_parametres) // Premier passage, 1ms après le premier chargement
|
||||
{
|
||||
interval = periode_raffraichissement_parametres;
|
||||
// init_page(); // Fait via StackView.onActivating
|
||||
}
|
||||
else
|
||||
{
|
||||
mise_a_jour_donnees();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================
|
||||
// Lorsque la page est sur le point d'être affichée dans la pile :
|
||||
//===========================================================
|
||||
StackView.onActivating: {
|
||||
mise_a_jour_donnees(); // Permet que lors du retour sur la page, l'état des différentes variables soit mise à jour avant l'affichage proprement dit.
|
||||
}
|
||||
|
||||
// Titre de la page :
|
||||
Shipheart_titre_1 {titre:qsTr("Configuration des capteurs"); hauteur: shipheart_hauteur_bandeau_haut}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Ecran de gauche (liste des capteurs) :
|
||||
//-------------------------------------------------------
|
||||
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 capteurs :
|
||||
GridView {
|
||||
id: grille_principale
|
||||
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
cellWidth: parent.width;
|
||||
cellHeight: height / nombre_capteurs_affiches_sur_une_colonne
|
||||
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
|
||||
delegate: Rectangle {
|
||||
width: grille_principale.cellWidth
|
||||
height: grille_principale.cellHeight
|
||||
color: "transparent"
|
||||
|
||||
// Ajout d'une ligne de sous-titre avec le nom du famille de capteurs si c'est le premier capteur de la famille :
|
||||
Shipheart_titre_3 {titre:model.nom_famille; hauteur: (affichage_hauteur_utile / nombre_capteurs_affiches_sur_une_colonne); visible: (model.nom_famille !== "")}
|
||||
|
||||
Rectangle { // c'est le bouton proprement dit...
|
||||
height: parent.height - 10
|
||||
width:parent.width - 10
|
||||
color: shipheart_couleur_fond_bouton
|
||||
radius: shipheart_rayon_bouton
|
||||
border.color: couleur_rouge
|
||||
border.width: (model.etat_systeme === 0) ? 0 : 3
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
visible: (model.nom_famille === "")
|
||||
|
||||
// Nom du capteur :
|
||||
Text {
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Qt.AlignLeft
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
leftPadding: 20
|
||||
text: model.nom
|
||||
color: couleur_blanc_casse
|
||||
font.pixelSize: 18
|
||||
wrapMode: Label.Wrap
|
||||
}
|
||||
|
||||
// Valeur actuelle du capteur :
|
||||
Text {
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Qt.AlignRight
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
rightPadding: 20
|
||||
text: model.valeur
|
||||
color: couleur_gris_moyen
|
||||
font.pixelSize: 18
|
||||
}
|
||||
|
||||
// Triangle bleu indiquant un capteur masqué :
|
||||
Image {
|
||||
id: image_capteur_masque // Affichage du coin inférieur-droit en couleur si le capteur est masqué
|
||||
source: "/images/coin_bas_droite_bleu_koriolan.png"
|
||||
sourceSize.height: 20
|
||||
anchors {
|
||||
bottom: parent.bottom
|
||||
right: parent.right
|
||||
}
|
||||
visible: model.flag_masque ? true : false
|
||||
}
|
||||
MouseArea{
|
||||
anchors.fill : parent
|
||||
enabled : !grille_principale.moving // Permet de bloquer le Mousearea pendant le déplacement de la grille
|
||||
onReleased: { // Permet déclencher à la fin d'un clic (court) sans mouvement
|
||||
shipheart_clic();
|
||||
stackView.push("config_capteur.qml", {"id_capteur": model.id})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ListModel {
|
||||
id: modele_grille_principale
|
||||
}
|
||||
Label {
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Qt.AlignHCenter
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
visible: parent.count === 0
|
||||
text: qsTr("Aucun capteur n'est encore configuré...")
|
||||
color: couleur_rouge_transparent
|
||||
font.pixelSize: 15
|
||||
font.bold: true
|
||||
wrapMode: Label.Wrap
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Ecran Droite :
|
||||
//-------------------------------------------------------
|
||||
Rectangle {
|
||||
id: zone_affichage_droite
|
||||
x: zone_affichage_gauche.width + espace_colonnes_principales
|
||||
y: shipheart_hauteur_bandeau_haut + 5; // Le +5 permet d'aligner le haut du premier bouton de droite avec le haut du premier bouton de la liste de gauche (
|
||||
width: (shipheart_largeur_page * (1 - pourcentage_largeur_colonne_gauche)) - (espace_colonnes_principales / 2)
|
||||
height: affichage_hauteur_utile
|
||||
color: "transparent"
|
||||
|
||||
|
||||
Column {
|
||||
anchors.fill: parent
|
||||
spacing: 10
|
||||
|
||||
//----------------------
|
||||
// Bouton + :
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: hauteur_bouton_droit
|
||||
color: shipheart_couleur_fond_bouton
|
||||
radius: shipheart_rayon_bouton
|
||||
visible: !clavier.active
|
||||
Text {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
font.pixelSize: 40
|
||||
text: qsTr("+")
|
||||
color: couleur_blanc_casse
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
stackView.push("config_capteur.qml");
|
||||
}
|
||||
}
|
||||
}
|
||||
//----------------------
|
||||
// Bouton tri :
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: hauteur_bouton_droit
|
||||
color: shipheart_couleur_fond_bouton
|
||||
radius: shipheart_rayon_bouton
|
||||
visible: !clavier.active // && (modele_grille_principale.count > 1) // SDIR #258
|
||||
Image {
|
||||
id: image_parametres
|
||||
source: "/images/tri.png"
|
||||
sourceSize.height: 25
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
stackView.push("config_ordre_elements.qml", {"table": "TB_Capteurs"})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Bandeau bas :
|
||||
//-------------------------------------------------------
|
||||
Row {
|
||||
x: 0
|
||||
y: shipheart_hauteur_page - shipheart_hauteur_bandeau_bas;
|
||||
width: shipheart_largeur_page;
|
||||
height: shipheart_hauteur_bandeau_bas;
|
||||
padding: 5
|
||||
spacing: 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();
|
||||
stackView.pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 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()
|
||||
{
|
||||
|
||||
mise_a_jour_donnees();
|
||||
}
|
||||
|
||||
//=============================================================================================================
|
||||
// Mise à jour des données
|
||||
//=============================================================================================================
|
||||
function mise_a_jour_donnees()
|
||||
{
|
||||
var req, res;
|
||||
var sous_req, sous_res;
|
||||
var i, j;
|
||||
var nb_capteurs;
|
||||
var prec_famille;
|
||||
|
||||
|
||||
// Grille principale (liste des capteurs configurés) :
|
||||
modele_grille_principale.clear();
|
||||
|
||||
// Recherche des valeurs en BDD :
|
||||
req = ' SELECT Cle_primaire, ';
|
||||
req += ' Etat_systeme, '
|
||||
req += ' Nom, ';
|
||||
req += ' Type_entrees, ';
|
||||
req += ' Entrees, ';
|
||||
req += ' ID_Variable, ';
|
||||
req += ' Valeur, ';
|
||||
req += ' Precision_affichage_accueil, ';
|
||||
req += ' Liste_valeurs_textes, ';
|
||||
req += ' Nom_famille, ';
|
||||
req += ' Priorite_affichage_accueil ';
|
||||
req += ' FROM TB_Capteurs, ';
|
||||
req += ' (SELECT Cle_primaire AS Cle_famille, Nom AS Nom_famille, Priorite_affichage AS Priorite_famille ';
|
||||
req += ' FROM TB_Familles WHERE Type_source=' + shipheart_type_source_capteurs + ') AS TB_Familles ';
|
||||
req += ' WHERE ID_Famille=Cle_famille ';
|
||||
req += ' ORDER BY Priorite_famille, ABS(Priorite_affichage_accueil)';
|
||||
//console.log("Requête = [ " + req + "; ]");
|
||||
|
||||
nb_capteurs = bdd.requete(req);
|
||||
|
||||
prec_famille = "";
|
||||
|
||||
// Boucle sur tous les capteurs :
|
||||
for (i = 0; i < nb_capteurs; i ++)
|
||||
{
|
||||
res = bdd.lecture_ligne();
|
||||
if (!res.isEmpty)
|
||||
{
|
||||
// Récup de toutes les données du capteur (pas forcément super efficace mais BEAUCOUP plus simple à maintenir...) :
|
||||
j = 0;
|
||||
var cle_primaire = Number(res[j++]);
|
||||
var etat_systeme = Number(res[j++]);
|
||||
var nom = res[j++];
|
||||
var type_entrees = Number(res[j++]);
|
||||
var entrees = res[j++];
|
||||
var id_variable = Number(res[j++]);
|
||||
var valeur = Number(res[j++]);
|
||||
var precision_affichage = Number(res[j++]);
|
||||
var liste_valeurs_textes = res[j++];
|
||||
var nom_famille = res[j++];
|
||||
var priorite_affichage_accueil = Number(res[j++]);
|
||||
|
||||
// Recherche des infos stockées dans la Variable pointée par ID_Variable :
|
||||
sous_res = bdd.requete_unique('SELECT Unite, Conversion_unite FROM TB_Variables WHERE Cle_primaire="' + id_variable + '" ');
|
||||
j = 0;
|
||||
var symbole_unite = sous_res[j++];
|
||||
var conversion_unite = Number(sous_res[j++]);
|
||||
var nouvelle_unite;
|
||||
var type_unite;
|
||||
|
||||
// Traitement des conversions d'unités :
|
||||
switch(conversion_unite)
|
||||
{
|
||||
case shipheart_type_unite_volume:
|
||||
nouvelle_unite = shipheart_unite_volume;
|
||||
symbole_unite = shipheart_unite_volume_symbole;
|
||||
type_unite = shipheart_type_unite_volume;
|
||||
break;
|
||||
case shipheart_type_unite_temperature:
|
||||
nouvelle_unite = shipheart_unite_temperature;
|
||||
symbole_unite = shipheart_unite_temperature_symbole;
|
||||
type_unite = shipheart_type_unite_temperature;
|
||||
break;
|
||||
case shipheart_type_unite_latitude:
|
||||
nouvelle_unite = 0;
|
||||
symbole_unite = "";
|
||||
type_unite = shipheart_type_unite_latitude;
|
||||
break;
|
||||
case shipheart_type_unite_longitude:
|
||||
nouvelle_unite = 0;
|
||||
symbole_unite = "";
|
||||
type_unite = shipheart_type_unite_longitude;
|
||||
break;
|
||||
default:
|
||||
nouvelle_unite = 0;
|
||||
type_unite = 0;
|
||||
symbole_unite = sous_res[0];
|
||||
break;
|
||||
}
|
||||
|
||||
// Cas spécifiques en fonction du type de capteur :
|
||||
var chaine_valeur = Fonctions.conversion_unites( valeur, nouvelle_unite, "", precision_affichage, type_unite);
|
||||
switch(type_entrees)
|
||||
{
|
||||
//-----------------------------------------------------------------
|
||||
case shipheart_capteur_type_entrees_aux:
|
||||
case shipheart_capteur_type_entrees_calculee_booleen:
|
||||
|
||||
// Traitement des listes :
|
||||
var chaines_valeurs_textes = liste_valeurs_textes.split(';');
|
||||
for (let chaine_valeur_texte of chaines_valeurs_textes)
|
||||
{
|
||||
var chaine = chaine_valeur_texte.split('/');
|
||||
if (chaine.length === 2) // Evite de traiter les cas invalides (notamment, une chaine totalement vide qui arrive ici avec un length de 1...)
|
||||
{
|
||||
if (valeur === Number(chaine [0])) // Si l'une des valeurs de la liste correspond à la valeur actuelle :
|
||||
{
|
||||
chaine_valeur = chaine[1]; // La valeur affichée sera le texte correspondant.
|
||||
break; // Et il est inutile de chercher d'autres valeurs...
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
case shipheart_capteur_type_entrees_level_sensor:
|
||||
break;
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
case shipheart_capteur_type_entrees_ow:
|
||||
break;
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
case shipheart_capteur_type_entrees_predefinie:
|
||||
break;
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
default :
|
||||
break;
|
||||
}
|
||||
|
||||
// Cas particulier d'un capteur absent :
|
||||
if (etat_systeme !== 0) chaine_valeur = "---"
|
||||
|
||||
|
||||
// Ajout de le ligne de famille :
|
||||
if (prec_famille !== nom_famille)
|
||||
{
|
||||
modele_grille_principale.append({
|
||||
"nom_famille": nom_famille,
|
||||
"id": 0,
|
||||
"etat_systeme": 0,
|
||||
"nom": "",
|
||||
"flag_masque": false,
|
||||
"valeur": ""} );
|
||||
prec_famille = nom_famille;
|
||||
}
|
||||
|
||||
// Entrée normale :
|
||||
modele_grille_principale.append({
|
||||
"nom_famille": "",
|
||||
"id": cle_primaire,
|
||||
"etat_systeme": etat_systeme,
|
||||
"nom": nom,
|
||||
"flag_masque": (priorite_affichage_accueil < 1) ? true : false,
|
||||
"valeur": chaine_valeur + " " + symbole_unite } );
|
||||
}
|
||||
else break; // Ne devrait pas arriver....
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1714
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,376 @@
|
||||
//========================================================================================================================================================================
|
||||
// CONFIG_CIRCUITS.QML
|
||||
// Ce fichier traite la configuration des circuits. La page permet notamment de :
|
||||
// - Afficher, pour tous les circuits déjà configurés (et donc d'accéder à la configuration détaillée de l'un d'eux ; ou sa création)
|
||||
// - Accéder au menu de changement de l'ordre d'affichage sur la page d'accueil
|
||||
// La page est appelée depuis la page PARAMETRES_AVANCES, en cliquant sur "Circuits"
|
||||
//========================================================================================================================================================================
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
import qt.koriolan.shipheart 1.0
|
||||
|
||||
|
||||
|
||||
Shipheart_page {
|
||||
id: page_config_circuits
|
||||
|
||||
|
||||
// Mis en forme :
|
||||
readonly property double affichage_hauteur_utile: shipheart_hauteur_page - shipheart_hauteur_bandeau_haut - shipheart_hauteur_bandeau_bas
|
||||
readonly property int hauteur_bouton_droit: 80
|
||||
|
||||
readonly property double pourcentage_largeur_colonne_gauche: 0.75
|
||||
readonly property int espace_colonnes_principales: 20
|
||||
readonly property double pourcentage_bandeau_bas_largeur_zone_retour: 1.0
|
||||
|
||||
readonly property int nombre_circuits_affiches_sur_une_colonne: 8
|
||||
|
||||
readonly property int periode_init_raffraichissement_parametres: 1 // En ms
|
||||
readonly property int periode_raffraichissement_parametres: 100 // En ms
|
||||
|
||||
|
||||
// Affichage :
|
||||
property int niveau_page: 0
|
||||
property bool bouton_bandeau_bas_zone_retour_actif: false
|
||||
|
||||
|
||||
// Modèles :
|
||||
// Note : les modèles chargés dans 'main.qml' n'ont pas à être rechargés dans les pages suivantes
|
||||
|
||||
|
||||
//===========================================================
|
||||
// Timer periode raffraichissement parametres :
|
||||
//===========================================================
|
||||
Timer {
|
||||
id: timer_raffraichissement_parametres
|
||||
interval: periode_init_raffraichissement_parametres
|
||||
triggeredOnStart: false
|
||||
running: true
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
if (interval == periode_init_raffraichissement_parametres) // Premier passage, 1ms après le premier chargement
|
||||
{
|
||||
interval = periode_raffraichissement_parametres;
|
||||
init_page();
|
||||
}
|
||||
|
||||
if (stackView.depth === (niveau_page + 1)) // Désactive le raffraichissement quand la page n'est pas activée dans la pile
|
||||
{
|
||||
if (!bouton_bandeau_bas_zone_retour_actif)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================
|
||||
// Lorsque la page est sur le point d'être affichée dans la pile :
|
||||
//===========================================================
|
||||
StackView.onActivating: {
|
||||
mise_a_jour_donnees(); // Permet que lors du retour sur la page, l'état des différentes variables soit mise à jour avant l'affichage proprement dit.
|
||||
}
|
||||
|
||||
// Titre de la page :
|
||||
Shipheart_titre_1 {titre:qsTr("Configuration des circuits"); hauteur: shipheart_hauteur_bandeau_haut}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Ecran de gauche (liste des circuits) :
|
||||
//-------------------------------------------------------
|
||||
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 circuits :
|
||||
GridView {
|
||||
id: grille_principale
|
||||
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
cellWidth: parent.width;
|
||||
cellHeight: height / nombre_circuits_affiches_sur_une_colonne
|
||||
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
|
||||
delegate: Rectangle {
|
||||
width: grille_principale.cellWidth
|
||||
height: grille_principale.cellHeight
|
||||
color: "transparent"
|
||||
|
||||
// Ajout d'une ligne de sous-titre avec le nom du famille de capteurs si c'est le premier capteur de la famille :
|
||||
Shipheart_titre_3 {titre:model.nom_famille; hauteur: (affichage_hauteur_utile / nombre_circuits_affiches_sur_une_colonne); visible: (model.nom_famille !== "")}
|
||||
|
||||
Rectangle { // c'est le bouton proprement dit...
|
||||
height: parent.height - 10
|
||||
width:parent.width - 10
|
||||
color: (model.adresse_module >= 0) ? shipheart_couleur_fond_bouton : couleur_rouge_transparent
|
||||
radius: shipheart_rayon_bouton
|
||||
border.color: couleur_rouge
|
||||
border.width: ((model.etat_systeme === 0) && (model.adresse_module >= 0)) ? 0 : 3
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
visible: (model.nom_famille === "")
|
||||
|
||||
// Nom du circuit :
|
||||
Text {
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Qt.AlignLeft
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
leftPadding: 20
|
||||
text: model.nom
|
||||
color: couleur_blanc_casse
|
||||
font.pixelSize: 18
|
||||
wrapMode: Label.Wrap
|
||||
}
|
||||
|
||||
// Triangle bleu indiquant un circuit masqué :
|
||||
Image {
|
||||
id: image_circuit_masque // Affichage du coin inférieur-droit en couleur si le circuit est masqué
|
||||
source: "/images/coin_bas_droite_bleu_koriolan.png"
|
||||
sourceSize.height: 20
|
||||
anchors {
|
||||
bottom: parent.bottom
|
||||
right: parent.right
|
||||
}
|
||||
visible: model.flag_masque ? true : false
|
||||
}
|
||||
MouseArea{
|
||||
anchors.fill : parent
|
||||
enabled : !grille_principale.moving // Permet de bloquer le Mousearea pendant le déplacement de la grille
|
||||
onReleased: { // Permet déclencher à la fin d'un clic (court) sans mouvement
|
||||
shipheart_clic();
|
||||
stackView.push("config_circuit.qml", {"id_circuit": model.id})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ListModel {
|
||||
id: modele_grille_principale
|
||||
}
|
||||
|
||||
Label {
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Qt.AlignHCenter
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
visible: parent.count === 0
|
||||
text: qsTr("Aucun circuit n'est encore configuré...")
|
||||
color: couleur_rouge_transparent
|
||||
font.pixelSize: 15
|
||||
font.bold: true
|
||||
wrapMode: Label.Wrap
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Ecran Droite :
|
||||
//-------------------------------------------------------
|
||||
Rectangle {
|
||||
id: zone_affichage_droite
|
||||
x: zone_affichage_gauche.width + espace_colonnes_principales
|
||||
y: shipheart_hauteur_bandeau_haut + 5; // Le +5 permet d'aligner le haut du premier bouton de droite avec le haut du premier bouton de la liste de gauche (
|
||||
width: (shipheart_largeur_page * (1 - pourcentage_largeur_colonne_gauche)) - (espace_colonnes_principales / 2)
|
||||
height: affichage_hauteur_utile
|
||||
color: "transparent"
|
||||
|
||||
|
||||
Column {
|
||||
anchors.fill: parent
|
||||
spacing: 10
|
||||
|
||||
//----------------------
|
||||
// Bouton + :
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: hauteur_bouton_droit
|
||||
color: shipheart_couleur_fond_bouton
|
||||
radius: shipheart_rayon_bouton
|
||||
visible: !clavier.active
|
||||
Text {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
font.pixelSize: 40
|
||||
text: qsTr("+")
|
||||
color: couleur_blanc_casse
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
stackView.push("config_circuit.qml");
|
||||
}
|
||||
}
|
||||
}
|
||||
//----------------------
|
||||
// Bouton tri :
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: hauteur_bouton_droit
|
||||
color: shipheart_couleur_fond_bouton
|
||||
radius: shipheart_rayon_bouton
|
||||
visible: !clavier.active // && (modele_grille_principale.count > 1) // SDIR #258
|
||||
Image {
|
||||
id: image_parametres
|
||||
source: "/images/tri.png"
|
||||
sourceSize.height: 25
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
stackView.push("config_ordre_elements.qml", {"table": "TB_Circuits"})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Bandeau bas :
|
||||
//-------------------------------------------------------
|
||||
Row {
|
||||
x: 0
|
||||
y: shipheart_hauteur_page - shipheart_hauteur_bandeau_bas;
|
||||
width: shipheart_largeur_page;
|
||||
height: shipheart_hauteur_bandeau_bas;
|
||||
padding: 5
|
||||
spacing: 5
|
||||
|
||||
//.................................................
|
||||
// Bouton retour
|
||||
//.................................................
|
||||
Rectangle {
|
||||
id: bandeau_bas_zone_retour
|
||||
width: (parent.width * pourcentage_bandeau_bas_largeur_zone_retour) - (2 * parent.padding)
|
||||
height: shipheart_hauteur_bandeau_bas - parent.topPadding - parent.bottomPadding;
|
||||
radius: shipheart_rayon_bouton
|
||||
color: shipheart_couleur_fond_bouton
|
||||
Image {
|
||||
source: "/images/icone_retour.png"
|
||||
sourceSize.height: 30
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
}
|
||||
MouseArea { // Zone d'interaction. On est obligé de la mettre dans la grille pour que Rectangle et MouseArea soient frères ou parent/enfant ET qu'on n'occupe qu'un espace dans la grille.
|
||||
id: mouse_area_bandeau_bas_zone_retour
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
stackView.pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 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()
|
||||
{
|
||||
niveau_page = stackView.depth - 1; // Permet de stocker le niveau de la page dans la Stackview
|
||||
|
||||
mise_a_jour_donnees();
|
||||
}
|
||||
|
||||
//=============================================================================================================
|
||||
// Mise à jour des données
|
||||
//=============================================================================================================
|
||||
function mise_a_jour_donnees()
|
||||
{
|
||||
var req, res;
|
||||
var sous_req, sous_res;
|
||||
var i, j;
|
||||
var nb_circuits;
|
||||
var prec_famille;
|
||||
|
||||
|
||||
// Grille principale (liste des capteurs configurés) :
|
||||
modele_grille_principale.clear();
|
||||
|
||||
// Recherche des valeurs en BDD :
|
||||
req = ' SELECT Cle_primaire, ';
|
||||
req += ' Adresse_module, '
|
||||
req += ' Etat_systeme, '
|
||||
req += ' Nom, ';
|
||||
req += ' Nom_famille, ';
|
||||
req += ' Priorite_affichage_accueil ';
|
||||
req += ' FROM TB_Circuits, ';
|
||||
req += ' (SELECT Cle_primaire AS Cle_famille, Nom AS Nom_famille, Priorite_affichage AS Priorite_famille ';
|
||||
req += ' FROM TB_Familles WHERE Type_source=' + shipheart_type_source_circuits + ') AS TB_Familles ';
|
||||
req += ' WHERE ID_Famille=Cle_famille ';
|
||||
req += ' AND ID_Circuit_esclave>=0 '; // On n'affiche tout simplement pas les circuits esclaves...
|
||||
req += ' ORDER BY Priorite_famille, ABS(Priorite_affichage_accueil)';
|
||||
//console.log("Requête = [ " + req + "; ]");
|
||||
|
||||
nb_circuits = bdd.requete(req);
|
||||
|
||||
prec_famille = "";
|
||||
|
||||
// Boucle sur tous les capteurs :
|
||||
for (i = 0; i < nb_circuits; i ++)
|
||||
{
|
||||
res = bdd.lecture_ligne();
|
||||
if (!res.isEmpty)
|
||||
{
|
||||
// Récup de toutes les données du capteur (pas forcément super efficace mais BEAUCOUP plus simple à maintenir...) :
|
||||
j = 0;
|
||||
var cle_primaire = Number(res[j++]);
|
||||
var adresse_module = Number(res[j++]);
|
||||
var etat_systeme = Number(res[j++]);
|
||||
var nom = res[j++];
|
||||
var nom_famille = res[j++];
|
||||
var priorite_affichage_accueil = Number(res[j++]);
|
||||
|
||||
// Ajout de le ligne de famille :
|
||||
if (prec_famille !== nom_famille)
|
||||
{
|
||||
modele_grille_principale.append({
|
||||
"nom_famille": nom_famille,
|
||||
"id": 0,
|
||||
"adresse_module": 0,
|
||||
"etat_systeme": 0,
|
||||
"nom": "",
|
||||
"flag_masque": false} );
|
||||
prec_famille = nom_famille;
|
||||
}
|
||||
|
||||
// Entrée normale :
|
||||
modele_grille_principale.append({
|
||||
"nom_famille": "",
|
||||
"id": cle_primaire,
|
||||
"adresse_module": adresse_module,
|
||||
"etat_systeme": etat_systeme,
|
||||
"nom": nom,
|
||||
"flag_masque": (priorite_affichage_accueil < 1) ? true : false } );
|
||||
}
|
||||
else break; // Ne devrait pas arriver....
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
+2164
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,428 @@
|
||||
//========================================================================================================================================================================
|
||||
// CONFIG_EVENTS.QML
|
||||
// Ce fichier traite la configuration des évènements. La page permet notamment de :
|
||||
// - Afficher tous les évènements déjà configurés (et donc d'accéder à la configuration détaillée de l'un d'eux ; ou sa création)
|
||||
// La page est appelée depuis la page PARAMETRES_AVANCES, en cliquant sur "Evènements"
|
||||
//========================================================================================================================================================================
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
import qt.koriolan.shipheart 1.0
|
||||
|
||||
|
||||
|
||||
Shipheart_page {
|
||||
id: page_config_evenements
|
||||
|
||||
|
||||
// Mis en forme :
|
||||
readonly property double affichage_hauteur_utile: shipheart_hauteur_page - shipheart_hauteur_bandeau_haut - shipheart_hauteur_bandeau_bas
|
||||
readonly property int hauteur_bouton_droit: 80
|
||||
|
||||
readonly property double pourcentage_largeur_colonne_gauche: 0.75
|
||||
readonly property double pourcentage_largeur_bouton_auto_dans_colonne_gauche: 0.15
|
||||
|
||||
readonly property int espace_colonnes_principales: 20
|
||||
readonly property double pourcentage_bandeau_bas_largeur_zone_retour: 1.0
|
||||
|
||||
readonly property int nombre_capteurs_affiches_sur_une_colonne: 8
|
||||
|
||||
readonly property int periode_init_raffraichissement_parametres: 1 // En ms
|
||||
readonly property int periode_raffraichissement_parametres: 1000 // En ms /!\ Laisser à 1s afin que le compteur secondes fonctionne correctement...
|
||||
|
||||
// Données :
|
||||
|
||||
property int nombre_events: 0
|
||||
|
||||
|
||||
// Modèles :
|
||||
// Note : les modèles chargés dans 'main.qml' n'ont pas à être rechargés dans les pages suivantes
|
||||
|
||||
|
||||
//===========================================================
|
||||
// Timer periode raffraichissement parametres :
|
||||
//===========================================================
|
||||
Timer {
|
||||
id: timer_raffraichissement_parametres
|
||||
interval: periode_init_raffraichissement_parametres
|
||||
triggeredOnStart: false
|
||||
running: true
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
if (interval == periode_init_raffraichissement_parametres) // Premier passage, 1ms après le premier chargement
|
||||
{
|
||||
interval = periode_raffraichissement_parametres;
|
||||
init_page();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================
|
||||
// Lorsque la page est sur le point d'être affichée dans la pile :
|
||||
//===========================================================
|
||||
StackView.onActivating: {
|
||||
mise_a_jour_donnees(); // Permet que lors du retour sur la page, l'état des différentes variables soit mise à jour avant l'affichage proprement dit.
|
||||
}
|
||||
|
||||
// Titre de la page :
|
||||
Shipheart_titre_1 {titre:qsTr("Configuration des évènements"); hauteur: shipheart_hauteur_bandeau_haut}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Ecran de gauche (liste des capteurs) :
|
||||
//-------------------------------------------------------
|
||||
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 évènements :
|
||||
GridView {
|
||||
id: grille_principale
|
||||
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
cellWidth: parent.width;
|
||||
cellHeight: height / nombre_capteurs_affiches_sur_une_colonne
|
||||
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
|
||||
highlightRangeMode: ListView.StrictlyEnforceRange // Permet de faire défiler la liste jusqu'à ne garder que le dernier élément affiché (et comme la liste des modules physiques est obligée d'utiliser ce paramètre, on fait pareil sur cette liste pour que les deux soient synchro)
|
||||
|
||||
model: modele_grille_principale
|
||||
delegate: Rectangle {
|
||||
width: grille_principale.cellWidth
|
||||
height: grille_principale.cellHeight
|
||||
color: "transparent"
|
||||
|
||||
// Ajout d'une ligne de sous-titre avec le nom du type d'event si c'est le premier event du type :
|
||||
Shipheart_titre_3 {titre:model.nom_famille; hauteur: (affichage_hauteur_utile / nombre_capteurs_affiches_sur_une_colonne); visible: model.famille}
|
||||
|
||||
//------------------------------------
|
||||
// Bouton avec le nom de l'event :
|
||||
//------------------------------------
|
||||
Rectangle {
|
||||
height: parent.height - 10
|
||||
width: (parent.width * (1 - pourcentage_largeur_bouton_auto_dans_colonne_gauche)) - 10
|
||||
color: shipheart_couleur_fond_bouton
|
||||
radius: shipheart_rayon_bouton
|
||||
anchors {
|
||||
left: parent.left
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
visible: !model.famille
|
||||
Text {
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Qt.AlignLeft
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
leftPadding: 20
|
||||
text: model.nom
|
||||
color: couleur_blanc_casse
|
||||
font.pixelSize: 18
|
||||
wrapMode: Label.Wrap
|
||||
}
|
||||
MouseArea{
|
||||
anchors.fill : parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
stackView.push("config_event.qml", {"id_event": model.id})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------
|
||||
// Bouton AUTO :
|
||||
//------------------------------------
|
||||
Rectangle {
|
||||
x: (parent.width * (1 - pourcentage_largeur_bouton_auto_dans_colonne_gauche))
|
||||
height: parent.height - 10
|
||||
width:(parent.width * pourcentage_largeur_bouton_auto_dans_colonne_gauche)
|
||||
anchors {
|
||||
right: parent.right
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
radius: shipheart_rayon_bouton
|
||||
color: shipheart_couleur_fond_bouton
|
||||
visible: !model.famille
|
||||
|
||||
Image {
|
||||
source: (model.validite === 0) ? "/images/faux.png" : "/images/vrai.png"
|
||||
sourceSize.height: parent.height * 0.5
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: mouse_area_cdes_auto
|
||||
x: 0
|
||||
y: 0
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
pressAndHoldInterval: shipheart_mouse_press_and_hold_interval_long
|
||||
|
||||
onPressed: {
|
||||
}
|
||||
onReleased: {
|
||||
}
|
||||
onPressAndHold: {
|
||||
shipheart_clic();
|
||||
toggle_validite(model.index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
ListModel {
|
||||
id: modele_grille_principale
|
||||
}
|
||||
Label {
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Qt.AlignHCenter
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
visible: parent.count === 0
|
||||
text: qsTr("Aucun évènement n'est encore configuré...")
|
||||
color: couleur_rouge_transparent
|
||||
font.pixelSize: 15
|
||||
font.bold: true
|
||||
wrapMode: Label.Wrap
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Ecran Droite :
|
||||
//-------------------------------------------------------
|
||||
Rectangle {
|
||||
id: zone_affichage_droite
|
||||
x: zone_affichage_gauche.width + espace_colonnes_principales
|
||||
y: shipheart_hauteur_bandeau_haut + 5; // Le +5 permet d'aligner le haut du premier bouton de droite avec le haut du premier bouton de la liste de gauche (
|
||||
width: (shipheart_largeur_page * (1 - pourcentage_largeur_colonne_gauche)) - (espace_colonnes_principales / 2)
|
||||
height: affichage_hauteur_utile
|
||||
color: "transparent"
|
||||
|
||||
|
||||
Column {
|
||||
anchors.fill: parent
|
||||
spacing: 10
|
||||
|
||||
//----------------------
|
||||
// Bouton + :
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: hauteur_bouton_droit
|
||||
color: shipheart_couleur_fond_bouton
|
||||
radius: shipheart_rayon_bouton
|
||||
visible: !clavier.active
|
||||
Text {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
font.pixelSize: 40
|
||||
text: "+"
|
||||
color: couleur_blanc_casse
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
if (nombre_events < shipheart_max_nombre_events) stackView.push("config_event.qml");
|
||||
else
|
||||
{
|
||||
boite_information.niveau = 1;
|
||||
boite_information.imageTitreSource = "/images/ampoule.png"
|
||||
boite_information.message = qsTr("Le nombre total d'évènements est limité à %1.<br /><br />Vous ne pouvez pas ajouter de nouvel évènement avant d'en avoir supprimé préalablement.").arg(shipheart_max_nombre_events);
|
||||
boite_information.open();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Bandeau bas :
|
||||
//-------------------------------------------------------
|
||||
Row {
|
||||
x: 0
|
||||
y: shipheart_hauteur_page - shipheart_hauteur_bandeau_bas;
|
||||
width: shipheart_largeur_page;
|
||||
height: shipheart_hauteur_bandeau_bas;
|
||||
padding: 5
|
||||
spacing: 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();
|
||||
stackView.pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Boite de validation :
|
||||
//-------------------------------------------------------
|
||||
Shipheart_boite_dialogue {
|
||||
id: boite_information
|
||||
}
|
||||
|
||||
// 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()
|
||||
{
|
||||
|
||||
mise_a_jour_donnees();
|
||||
}
|
||||
|
||||
//=============================================================================================================
|
||||
// Mise à jour des données
|
||||
//=============================================================================================================
|
||||
function mise_a_jour_donnees()
|
||||
{
|
||||
var req, res;
|
||||
var sous_req, sous_res;
|
||||
var i;
|
||||
var nb_events;
|
||||
|
||||
//=======================================================================
|
||||
// Grille principale (liste des évènements configurés) :
|
||||
modele_grille_principale.clear(); // RAZ des valeurs existantes
|
||||
nombre_events = 0;
|
||||
|
||||
req = "SELECT TB_Events.Cle_primaire AS cle_event, TB_Events.Nom AS nom_event, Type_source, TB_Events.Validite";
|
||||
req += " FROM TB_Events";
|
||||
req += " WHERE Type_source=0";
|
||||
req += " UNION";
|
||||
req += " SELECT TB_Events.Cle_primaire AS cle_event, CONCAT(tb_source.Nom, ' - ', TB_Events.Nom) AS nom_event, Type_source, TB_Events.Validite";
|
||||
req += " FROM TB_Events";
|
||||
req += " INNER JOIN TB_Circuits AS tb_source ON TB_Events.ID_Source=tb_source.Cle_primaire";
|
||||
req += " WHERE Type_source=1";
|
||||
req += " UNION";
|
||||
req += " SELECT TB_Events.Cle_primaire AS cle_event, CONCAT(tb_source.Nom, ' - ', TB_Events.Nom) AS nom_event, Type_source, TB_Events.Validite";
|
||||
req += " FROM TB_Events";
|
||||
req += " INNER JOIN TB_Capteurs AS tb_source ON TB_Events.ID_Source=tb_source.Cle_primaire";
|
||||
req += " WHERE Type_source=2";
|
||||
req += " UNION";
|
||||
req += " SELECT TB_Events.Cle_primaire AS cle_event, CONCAT(tb_source.Nom, ' - ', TB_Events.Nom) AS nom_event, Type_source, TB_Events.Validite";
|
||||
req += " FROM TB_Events";
|
||||
req += " INNER JOIN TB_Reservoirs AS tb_source ON TB_Events.ID_Source=tb_source.Cle_primaire";
|
||||
req += " WHERE Type_source=3";
|
||||
req += " UNION";
|
||||
req += " SELECT TB_Events.Cle_primaire AS cle_event, CONCAT(tb_source.Nom, ' - ', TB_Events.Nom) AS nom_event, Type_source, TB_Events.Validite";
|
||||
req += " FROM TB_Events";
|
||||
req += " INNER JOIN TB_Batteries AS tb_source ON TB_Events.ID_Source=tb_source.Cle_primaire";
|
||||
req += " WHERE Type_source=4 ORDER BY Type_source, nom_event ";
|
||||
//console.log("req = [ " + req + "; ]");
|
||||
nb_events = bdd.requete(req);
|
||||
|
||||
var prec_type = -1;
|
||||
for (i = 0; i < nb_events; i ++)
|
||||
{
|
||||
res = bdd.lecture_ligne();
|
||||
if (!res.isEmpty)
|
||||
{
|
||||
// Ajout de le ligne de Type :
|
||||
if (prec_type !== Number(res[2]))
|
||||
{
|
||||
modele_grille_principale.append({"famille":true, "nom": "", "id": 0, "nom_famille": nom_type_source(Number(res[2])), "validite": 0 });
|
||||
prec_type = Number(res[2]);
|
||||
}
|
||||
|
||||
// Entrée normale :
|
||||
modele_grille_principale.append({"famille":false, "nom": res[1], "id": Number(res[0]), "nom_famille": nom_type_source(Number(res[2])), "validite": Number(res[3]) });
|
||||
nombre_events ++;
|
||||
}
|
||||
else break; // Ne devrait pas arriver....
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================================================
|
||||
// Nom type de source
|
||||
//=============================================================================================================
|
||||
function nom_type_source(source)
|
||||
{
|
||||
|
||||
switch(source)
|
||||
{
|
||||
case shipheart_source_mesure_circuit:
|
||||
return(qsTr("Sur circuits"));
|
||||
|
||||
case shipheart_source_mesure_capteur:
|
||||
return(qsTr("Sur capteurs"));
|
||||
|
||||
case shipheart_source_mesure_reservoir:
|
||||
return(qsTr("Sur réservoirs"));
|
||||
|
||||
case shipheart_source_mesure_batterie:
|
||||
return(qsTr("Sur batteries"));
|
||||
|
||||
default:
|
||||
return(qsTr("Horaire seulement"));
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================================================
|
||||
// Bascule de la visibilité d'un évènement
|
||||
//=============================================================================================================
|
||||
function toggle_validite(index)
|
||||
{
|
||||
var req;
|
||||
var validite;
|
||||
|
||||
// Recherche de la valeur actuelle et calcul de la nouvelle :
|
||||
validite = modele_grille_principale.get(index).validite;
|
||||
if (validite === 0) validite = 1;
|
||||
else validite = 0;
|
||||
|
||||
// Mise à jour de la nouvelle valeur dans le modèle :
|
||||
modele_grille_principale.set(index, {"validite": validite});
|
||||
|
||||
// Mis eà jour de la nouvelle valeur dans la BDD :
|
||||
req = 'UPDATE TB_Events SET Validite=' + validite + ' WHERE Cle_primaire=' + modele_grille_principale.get(index).id + ' ';
|
||||
//console.log("Requête = [ " + req + "; ]");
|
||||
bdd.requete_unique(req);
|
||||
|
||||
// Demande de reconfiguration système via la BDD car on a modifié des valeurs de configuration :
|
||||
synchro_bdd(shipheart_type_synchro_config);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
+2148
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,406 @@
|
||||
//========================================================================================================================================================================
|
||||
// CONFIG_GROUPE_ELEMENTS.QML
|
||||
// Ce fichier traite la configuration des groupes d'éléments (circuits notamment)
|
||||
// La page est appelée depuis la page config_ordre_elements.qml, en cliquant sur "+" ou par pression longue sur un groupe existant
|
||||
//========================================================================================================================================================================
|
||||
import QtQuick 2.12
|
||||
import QtQml.Models
|
||||
|
||||
import qt.koriolan.shipheart 1.0
|
||||
|
||||
|
||||
|
||||
Shipheart_page {
|
||||
id: page_config_groupe_elements
|
||||
|
||||
|
||||
// Mis en forme :
|
||||
readonly property double pourcentage_largeur_colonne_gauche: 0.75
|
||||
readonly property double espace_colonnes_principales: 20
|
||||
readonly property double pourcentage_hauteur_ligne_haut: 1
|
||||
readonly property double espace_lignes_principales: 20
|
||||
readonly property double affichage_hauteur_utile: shipheart_hauteur_page - shipheart_hauteur_bandeau_haut - shipheart_hauteur_bandeau_bas
|
||||
|
||||
readonly property int hauteur_ligne_formulaire: 60
|
||||
readonly property double pourcentage_largeur_labels_formulaire: 0.4
|
||||
|
||||
readonly property int hauteur_bouton_droit: 80
|
||||
|
||||
readonly property double pourcentage_bandeau_bas_largeur_zone_retour: 1
|
||||
|
||||
|
||||
readonly property int periode_init_raffraichissement_parametres: 1 // En ms
|
||||
readonly property int periode_raffraichissement_parametres: 1000 // En ms
|
||||
|
||||
|
||||
|
||||
// Affichage :
|
||||
property bool bouton_bandeau_bas_zone_retour_actif: false
|
||||
property int protection_mode: 0
|
||||
|
||||
|
||||
// Données :
|
||||
property int type_source: shipheart_type_source_inconnu
|
||||
property int id_groupe: 0
|
||||
|
||||
|
||||
// Modèles :
|
||||
// Note : les modèles chargés dans 'main.qml' n'ont pas à être rechargés dans les pages suivantes
|
||||
|
||||
|
||||
//===========================================================
|
||||
// Timer periode raffraichissement parametres :
|
||||
//===========================================================
|
||||
Timer {
|
||||
id: timer_raffraichissement_parametres
|
||||
interval: periode_init_raffraichissement_parametres
|
||||
triggeredOnStart: false
|
||||
running: true
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
if (interval == periode_init_raffraichissement_parametres) { // Premier passage, 1ms après le premier chargement
|
||||
interval = periode_raffraichissement_parametres;
|
||||
|
||||
init_page();
|
||||
}
|
||||
else if (!bouton_bandeau_bas_zone_retour_actif) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Titre de la page :
|
||||
Shipheart_titre_1 {titre:(id_groupe === 0) ? qsTr("Création d'un groupe") : qsTr("Modification d'un groupe"); 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;
|
||||
color: "transparent"
|
||||
|
||||
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 du groupe
|
||||
Rectangle {
|
||||
width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2)
|
||||
height: visible ? hauteur_ligne_formulaire : 0
|
||||
color: "transparent"
|
||||
visible: true
|
||||
|
||||
Shipheart_formulaire_label {
|
||||
text: qsTr("Nom du groupe")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// 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 :
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: hauteur_bouton_droit
|
||||
color: shipheart_couleur_fond_bouton
|
||||
radius: shipheart_rayon_bouton
|
||||
visible:
|
||||
// (!clavier.active) && // Si le clavier est replié... // SDIR #255
|
||||
(champ_formulaire_Nom.text !== "") // Si le nom n'est pas vide...
|
||||
|
||||
Text {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
font.pixelSize: 20
|
||||
text: (id_groupe === 0) ? qsTr("Créer le groupe") : qsTr("Enregistrer")
|
||||
color: couleur_blanc_casse
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
mise_a_jour(); // Mise à jour des données saisies dans la BDD
|
||||
stackView.pop(); // Retour
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Bouton Supprimer :
|
||||
Rectangle {
|
||||
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é...
|
||||
(id_groupe === 0)) // Si le groupe n'existe pas encore...
|
||||
? false // ...on ne propose pas le bouton
|
||||
: true
|
||||
Text {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
font.pixelSize: 20
|
||||
text: qsTr("Supprimer")
|
||||
color: couleur_blanc_casse
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
if (suppression() === 0) stackView.pop(); // Retour
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Bandeau bas :
|
||||
//-------------------------------------------------------
|
||||
Row {
|
||||
x: 0
|
||||
y: shipheart_hauteur_page - shipheart_hauteur_bandeau_bas;
|
||||
width: shipheart_largeur_page;
|
||||
height: shipheart_hauteur_bandeau_bas;
|
||||
spacing: 5
|
||||
padding: 5
|
||||
|
||||
//.................................................
|
||||
// Bouton retour
|
||||
//.................................................
|
||||
Rectangle {
|
||||
id: bandeau_bas_zone_retour
|
||||
width: (parent.width * pourcentage_bandeau_bas_largeur_zone_retour) - (2 * parent.padding)
|
||||
height: shipheart_hauteur_bandeau_bas - parent.topPadding - parent.bottomPadding;
|
||||
radius: shipheart_rayon_bouton
|
||||
color: shipheart_couleur_fond_bouton
|
||||
|
||||
Image {
|
||||
source: "/images/icone_retour.png"
|
||||
sourceSize.height: 30
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea { // Zone d'interaction. On est obligé de la mettre dans la grille pour que Rectangle et MouseArea soient frères ou parent/enfant ET qu'on n'occupe qu'un espace dans la grille.
|
||||
id: mouse_area_bandeau_bas_zone_retour
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
stackView.pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Boite d'info :
|
||||
//-------------------------------------------------------
|
||||
Shipheart_boite_dialogue {
|
||||
id: boite_information
|
||||
}
|
||||
|
||||
|
||||
// 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;
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
// Nom du groupe :
|
||||
if (id_groupe > 0)
|
||||
{
|
||||
req = 'SELECT Nom FROM TB_Familles WHERE Cle_primaire=' + id_groupe + ' ';
|
||||
//console.log("Requête = " + req)
|
||||
res = bdd.requete_unique(req);
|
||||
champ_formulaire_Nom.text = res[0];
|
||||
}
|
||||
else champ_formulaire_Nom.text = "";
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================================================
|
||||
// Mise à jour des valeurs saisies
|
||||
//=============================================================================================================
|
||||
function mise_a_jour()
|
||||
{
|
||||
var req;
|
||||
|
||||
if (id_groupe === 0) // Création :
|
||||
{
|
||||
// Insertion d'une nouvelle entrée dans la BDD :
|
||||
req = 'INSERT INTO TB_Familles (Nom, Priorite_affichage, Type_source) VALUES ("' + champ_formulaire_Nom.text + '", 99, ' + type_source + ')';
|
||||
//console.log("Requête = " + req)
|
||||
bdd.requete_unique(req);
|
||||
}
|
||||
else // Modification
|
||||
{
|
||||
// Mise à jour des nouvelles valeurs dans la BDD :
|
||||
req = 'UPDATE TB_Familles SET Nom="' + champ_formulaire_Nom.text + '" WHERE Cle_primaire=' + id_groupe + ' ';
|
||||
//console.log("Requête = " + req)
|
||||
bdd.requete_unique(req);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//=============================================================================================================
|
||||
// Suppression d'un groupe
|
||||
//=============================================================================================================
|
||||
function suppression()
|
||||
{
|
||||
var req, res;
|
||||
var nb, nb_masques;
|
||||
var retour = 0;
|
||||
var table_elements;
|
||||
var nom_elements;
|
||||
|
||||
|
||||
// Vérification que le groupe est vide :
|
||||
switch(type_source)
|
||||
{
|
||||
//----------------------------------------------------
|
||||
case shipheart_type_source_batteries:
|
||||
table_elements = "TB_Batteries";
|
||||
nom_elements = qsTr("batteries");
|
||||
break;
|
||||
|
||||
//----------------------------------------------------
|
||||
case shipheart_type_source_capteurs:
|
||||
table_elements = "TB_Capteurs";
|
||||
nom_elements = qsTr("capteurs");
|
||||
break;
|
||||
|
||||
//----------------------------------------------------
|
||||
case shipheart_type_source_circuits:
|
||||
table_elements = "TB_Circuits";
|
||||
nom_elements = qsTr("circuits");
|
||||
break;
|
||||
|
||||
//----------------------------------------------------
|
||||
case shipheart_type_source_reservoirs:
|
||||
table_elements = "TB_Reservoirs";
|
||||
nom_elements = qsTr("réservoirs");
|
||||
break;
|
||||
|
||||
//----------------------------------------------------
|
||||
default:
|
||||
table_elements = "";
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (table_elements !== "")
|
||||
{
|
||||
nb = 0;
|
||||
req = 'SELECT COUNT(*) AS Nb FROM ' + table_elements + ' WHERE ID_Famille=' + id_groupe + ' ';
|
||||
//console.log("Requête = " + req)
|
||||
res = bdd.requete_unique(req);
|
||||
nb = Number(res[0]);
|
||||
|
||||
if (nb === 0) // La table ne contient aucun élément lié à cette famille.
|
||||
{
|
||||
// Vérification que ce groupe n'est pas le dernier (on n'accepte pas de n'avoir AUCUN groupe) :
|
||||
req = 'SELECT COUNT(*) AS Nb FROM TB_Familles WHERE Type_source=' + type_source + ' ';
|
||||
//console.log("Requête = " + req)
|
||||
res = bdd.requete_unique(req);
|
||||
if (Number(res[0]) > 1) // Il reste d'autres groupes valides. On peut donc supprimer celle-ci :
|
||||
{
|
||||
req = 'DELETE FROM TB_Familles WHERE Cle_primaire=' + id_groupe + ' ';
|
||||
//console.log("Requête = " + req)
|
||||
bdd.requete_unique(req);
|
||||
}
|
||||
else // C'est le dernier groupe valide, on interdit donc sa suppression.
|
||||
{
|
||||
// Définition des paramètres de la boite de dialogue :
|
||||
boite_information.niveau = 1;
|
||||
boite_information.imageTitreSource = "/images/attention.png"
|
||||
boite_information.message = qsTr("Ce groupe est le dernier encore valide.<br /><br />Vous ne pourrez le supprimer qu'après en avoir préalablement créé au moins un autre (il n'est pas possible de fonctionner sans aucun groupe de %1).").arg(nom_elements)
|
||||
boite_information.open();
|
||||
retour = -1;
|
||||
}
|
||||
}
|
||||
else // La table contient encore des éléments liés à cette famille
|
||||
{
|
||||
// Recherche des éléments masqués :
|
||||
req = 'SELECT COUNT(*) AS Nb FROM ' + table_elements + ' WHERE ID_Famille=' + id_groupe + ' AND Priorite_affichage_accueil<=0 ';
|
||||
//console.log("Requête = " + req)
|
||||
res = bdd.requete_unique(req);
|
||||
nb_masques = Number(res[0]);
|
||||
|
||||
// Définition des paramètres de la boite de dialogue :
|
||||
boite_information.niveau = 1;
|
||||
boite_information.imageTitreSource = "/images/attention.png"
|
||||
if (nb_masques === 0) boite_information.message = qsTr("Ce groupe comprend encore %1 %2.<br /><br />Il est nécessaire d'affecter ces %2 à un autre groupe avant de pouvoir le supprimer.").arg(nb).arg(nom_elements).arg(nb_masques);
|
||||
else boite_information.message = qsTr("Ce groupe comprend encore %1 %2,<br />dont %3 configuré(s) comme \"masqué(s)\".<br /><br />Il est nécessaire d'affecter ces %2 à un autre groupe avant de pouvoir le supprimer.").arg(nb).arg(nom_elements).arg(nb_masques);
|
||||
boite_information.open();
|
||||
retour = -1;
|
||||
}
|
||||
}
|
||||
|
||||
return (retour);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,520 @@
|
||||
//========================================================================================================================================================================
|
||||
// CONFIG_INSTALLATION.QML
|
||||
// Ce fichier traite la configuration des paramètres d'installation.
|
||||
// La page est appelée depuis la page parametres_avances.qml, en cliquant sur "Système" > "Installation"
|
||||
//========================================================================================================================================================================
|
||||
import QtQuick 2.12
|
||||
import QtQml.Models
|
||||
|
||||
import qt.koriolan.shipheart 1.0
|
||||
|
||||
|
||||
|
||||
|
||||
Shipheart_page {
|
||||
id: page_config_installation
|
||||
|
||||
|
||||
// Mis en forme :
|
||||
readonly property double pourcentage_largeur_colonne_gauche: 0.75
|
||||
readonly property double espace_colonnes_principales: 20
|
||||
readonly property double pourcentage_hauteur_ligne_haut: 1
|
||||
readonly property double espace_lignes_principales: 20
|
||||
readonly property double affichage_hauteur_utile: shipheart_hauteur_page - shipheart_hauteur_bandeau_haut - shipheart_hauteur_bandeau_bas
|
||||
|
||||
readonly property int hauteur_ligne_formulaire: 60
|
||||
readonly property double pourcentage_largeur_labels_formulaire: 0.4
|
||||
|
||||
readonly property int hauteur_bouton_droit: 80
|
||||
|
||||
readonly property double pourcentage_bandeau_bas_largeur_zone_retour: 1
|
||||
|
||||
|
||||
readonly property int periode_init_raffraichissement_parametres: 1 // En ms
|
||||
readonly property int periode_raffraichissement_parametres: 1000 // En ms
|
||||
|
||||
|
||||
|
||||
// Affichage :
|
||||
property bool bouton_bandeau_bas_zone_retour_actif: false
|
||||
property int protection_mode: 0
|
||||
|
||||
|
||||
// Données :
|
||||
|
||||
|
||||
// Modèles :
|
||||
// Note : les modèles chargés dans 'main.qml' n'ont pas à être rechargés dans les pages suivantes
|
||||
|
||||
|
||||
//===========================================================
|
||||
// Timer periode raffraichissement parametres :
|
||||
//===========================================================
|
||||
Timer {
|
||||
id: timer_raffraichissement_parametres
|
||||
interval: periode_init_raffraichissement_parametres
|
||||
triggeredOnStart: false
|
||||
running: true
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
if (interval == periode_init_raffraichissement_parametres) { // Premier passage, 1ms après le premier chargement
|
||||
interval = periode_raffraichissement_parametres;
|
||||
|
||||
init_page();
|
||||
}
|
||||
else if (!bouton_bandeau_bas_zone_retour_actif) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Titre de la page :
|
||||
Shipheart_titre_1 {titre:qsTr("Coordonnées de l'installateur"); 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"
|
||||
|
||||
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 : Raison sociale
|
||||
Rectangle {
|
||||
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("Raison sociale")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
}
|
||||
|
||||
Shipheart_formulaire_textfield {
|
||||
id: champ_formulaire_Raison_sociale
|
||||
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 : Rue_1
|
||||
Rectangle {
|
||||
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("N° & Rue")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
}
|
||||
|
||||
Shipheart_formulaire_textfield {
|
||||
id: champ_formulaire_Rue_1
|
||||
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 : Rue_2
|
||||
Rectangle {
|
||||
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("Complément d'adresse")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
}
|
||||
|
||||
Shipheart_formulaire_textfield {
|
||||
id: champ_formulaire_Rue_2
|
||||
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 : Code_postal
|
||||
Rectangle {
|
||||
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("Code postal")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
}
|
||||
|
||||
Shipheart_formulaire_textfield {
|
||||
id: champ_formulaire_Code_postal
|
||||
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 : Ville
|
||||
Rectangle {
|
||||
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("Ville")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
}
|
||||
|
||||
Shipheart_formulaire_textfield {
|
||||
id: champ_formulaire_Ville
|
||||
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 : Nom_contact
|
||||
Rectangle {
|
||||
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 du contact")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
}
|
||||
|
||||
Shipheart_formulaire_textfield {
|
||||
id: champ_formulaire_Nom_contact
|
||||
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 : Téléphone
|
||||
Rectangle {
|
||||
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("Téléphone")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
}
|
||||
|
||||
Shipheart_formulaire_textfield {
|
||||
id: champ_formulaire_Telephone
|
||||
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
|
||||
x: parent.width * pourcentage_largeur_labels_formulaire
|
||||
inputMethodHints: Qt.ImhDialableCharactersOnly // N'affiche que les caractères destinés à un n° de téléphone
|
||||
}
|
||||
|
||||
Shipheart_formulaire_ligne_separation {
|
||||
haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Ligne de formulaire : Email
|
||||
Rectangle {
|
||||
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("Email")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
}
|
||||
|
||||
Shipheart_formulaire_textfield {
|
||||
id: champ_formulaire_Email
|
||||
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
|
||||
x: parent.width * pourcentage_largeur_labels_formulaire
|
||||
inputMethodHints: Qt.ImhEmailCharactersOnly // N'affiche que les caractères destinés à un Email
|
||||
}
|
||||
|
||||
Shipheart_formulaire_ligne_separation {
|
||||
haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Ligne de formulaire : Site web
|
||||
Rectangle {
|
||||
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("Site web")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
}
|
||||
|
||||
Shipheart_formulaire_textfield {
|
||||
id: champ_formulaire_Site_web
|
||||
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
|
||||
x: parent.width * pourcentage_largeur_labels_formulaire
|
||||
inputMethodHints: Qt.ImhUrlCharactersOnly // N'affiche que les caractères destinés à une URL
|
||||
}
|
||||
|
||||
Shipheart_formulaire_ligne_separation {
|
||||
haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// 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 :
|
||||
//---------------------------
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: hauteur_bouton_droit
|
||||
color: shipheart_couleur_fond_bouton
|
||||
radius: shipheart_rayon_bouton
|
||||
// visible: !clavier.active // SDIR #255
|
||||
Text {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
font.pixelSize: 20
|
||||
text: qsTr("Enregistrer")
|
||||
color: couleur_blanc_casse
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
mise_a_jour(); // Mise à jour des données saisies dans la BDD et reconfiguration par l'application pour prise en compte.
|
||||
stackView.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Bandeau bas :
|
||||
//-------------------------------------------------------
|
||||
Row {
|
||||
x: 0
|
||||
y: shipheart_hauteur_page - shipheart_hauteur_bandeau_bas;
|
||||
width: shipheart_largeur_page;
|
||||
height: shipheart_hauteur_bandeau_bas;
|
||||
spacing: 5
|
||||
padding: 5
|
||||
|
||||
//.................................................
|
||||
// Bouton retour
|
||||
//.................................................
|
||||
Rectangle {
|
||||
id: bandeau_bas_zone_retour
|
||||
width: (parent.width * pourcentage_bandeau_bas_largeur_zone_retour) - (2 * parent.padding)
|
||||
height: shipheart_hauteur_bandeau_bas - parent.topPadding - parent.bottomPadding;
|
||||
radius: shipheart_rayon_bouton
|
||||
color: shipheart_couleur_fond_bouton
|
||||
|
||||
Image {
|
||||
source: "/images/icone_retour.png"
|
||||
sourceSize.height: 30
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea { // Zone d'interaction. On est obligé de la mettre dans la grille pour que Rectangle et MouseArea soient frères ou parent/enfant ET qu'on n'occupe qu'un espace dans la grille.
|
||||
id: mouse_area_bandeau_bas_zone_retour
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
stackView.pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Raison_sociale_installateur" ';
|
||||
res = bdd.requete_unique(req);
|
||||
champ_formulaire_Raison_sociale.text = res[0];
|
||||
|
||||
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Rue_1_installateur" ';
|
||||
res = bdd.requete_unique(req);
|
||||
champ_formulaire_Rue_1.text = res[0];
|
||||
|
||||
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Rue_2_installateur" ';
|
||||
res = bdd.requete_unique(req);
|
||||
champ_formulaire_Rue_2.text = res[0];
|
||||
|
||||
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Code_postal_installateur" ';
|
||||
res = bdd.requete_unique(req);
|
||||
champ_formulaire_Code_postal.text = res[0];
|
||||
|
||||
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Ville_installateur" ';
|
||||
res = bdd.requete_unique(req);
|
||||
champ_formulaire_Ville.text = res[0];
|
||||
|
||||
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Nom_contact_installateur" ';
|
||||
res = bdd.requete_unique(req);
|
||||
champ_formulaire_Nom_contact.text = res[0];
|
||||
|
||||
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Telephone_installateur" ';
|
||||
res = bdd.requete_unique(req);
|
||||
champ_formulaire_Telephone.text = res[0];
|
||||
|
||||
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Adresse_email_installateur" ';
|
||||
res = bdd.requete_unique(req);
|
||||
champ_formulaire_Email.text = res[0];
|
||||
|
||||
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Site_web_installateur" ';
|
||||
res = bdd.requete_unique(req);
|
||||
champ_formulaire_Site_web.text = res[0];
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================================================
|
||||
// Mise à jour des valeurs saisies
|
||||
//=============================================================================================================
|
||||
function mise_a_jour()
|
||||
{
|
||||
var req;
|
||||
|
||||
|
||||
req = 'UPDATE TB_Configuration ';
|
||||
req += ' SET Valeur="' + champ_formulaire_Raison_sociale.text + '" ';
|
||||
req += ' WHERE Nom="Raison_sociale_installateur" ';
|
||||
//console.log("Requête = [ " + req + "; ]")
|
||||
bdd.requete_unique(req);
|
||||
|
||||
req = 'UPDATE TB_Configuration ';
|
||||
req += ' SET Valeur="' + champ_formulaire_Rue_1.text + '" ';
|
||||
req += ' WHERE Nom="Rue_1_installateur" ';
|
||||
//console.log("Requête = [ " + req + "; ]")
|
||||
bdd.requete_unique(req);
|
||||
|
||||
req = 'UPDATE TB_Configuration ';
|
||||
req += ' SET Valeur="' + champ_formulaire_Rue_2.text + '" ';
|
||||
req += ' WHERE Nom="Rue_2_installateur" ';
|
||||
//console.log("Requête = [ " + req + "; ]")
|
||||
bdd.requete_unique(req);
|
||||
|
||||
req = 'UPDATE TB_Configuration ';
|
||||
req += ' SET Valeur="' + champ_formulaire_Code_postal.text + '" ';
|
||||
req += ' WHERE Nom="Code_postal_installateur" ';
|
||||
//console.log("Requête = [ " + req + "; ]")
|
||||
bdd.requete_unique(req);
|
||||
|
||||
req = 'UPDATE TB_Configuration ';
|
||||
req += ' SET Valeur="' + champ_formulaire_Ville.text + '" ';
|
||||
req += ' WHERE Nom="Ville_installateur" ';
|
||||
//console.log("Requête = [ " + req + "; ]")
|
||||
bdd.requete_unique(req);
|
||||
|
||||
req = 'UPDATE TB_Configuration ';
|
||||
req += ' SET Valeur="' + champ_formulaire_Nom_contact.text + '" ';
|
||||
req += ' WHERE Nom="Nom_contact_installateur" ';
|
||||
//console.log("Requête = [ " + req + "; ]")
|
||||
bdd.requete_unique(req);
|
||||
|
||||
req = 'UPDATE TB_Configuration ';
|
||||
req += ' SET Valeur="' + champ_formulaire_Telephone.text + '" ';
|
||||
req += ' WHERE Nom="Telephone_installateur" ';
|
||||
//console.log("Requête = [ " + req + "; ]")
|
||||
bdd.requete_unique(req);
|
||||
|
||||
req = 'UPDATE TB_Configuration ';
|
||||
req += ' SET Valeur="' + champ_formulaire_Email.text + '" ';
|
||||
req += ' WHERE Nom="Adresse_email_installateur" ';
|
||||
//console.log("Requête = [ " + req + "; ]")
|
||||
bdd.requete_unique(req);
|
||||
|
||||
req = 'UPDATE TB_Configuration ';
|
||||
req += ' SET Valeur="' + champ_formulaire_Site_web.text + '" ';
|
||||
req += ' WHERE Nom="Site_web_installateur" ';
|
||||
//console.log("Requête = [ " + req + "; ]")
|
||||
bdd.requete_unique(req);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,514 @@
|
||||
//========================================================================================================================================================================
|
||||
// CONFIG_KORIOLAN.QML
|
||||
// Ce fichier traite les paramètres de configuration qui sont réservés à Koriolan
|
||||
// La page est appelée depuis la page parametres_avances.qml, en cliquant sur "Accès réservé Koriolan" depuis la colonne "Sécurité"
|
||||
// Note importante : ce menu n'est accéssible que si l'accés à été fait avec un code au moins de niveau Administrateur.
|
||||
//========================================================================================================================================================================
|
||||
import QtQuick 2.12
|
||||
import QtQml.Models
|
||||
|
||||
import qt.koriolan.shipheart 1.0
|
||||
|
||||
|
||||
|
||||
Shipheart_page {
|
||||
id: page_config_koriolan
|
||||
|
||||
|
||||
// Mis en forme :
|
||||
readonly property double pourcentage_largeur_colonne_gauche: 0.75
|
||||
readonly property double espace_colonnes_principales: 20
|
||||
readonly property double pourcentage_hauteur_ligne_haut: 0.2
|
||||
readonly property double espace_lignes_principales: 20
|
||||
readonly property double affichage_hauteur_utile: shipheart_hauteur_page - shipheart_hauteur_bandeau_haut - shipheart_hauteur_bandeau_bas
|
||||
|
||||
readonly property int hauteur_ligne_formulaire: 60
|
||||
readonly property double pourcentage_largeur_labels_formulaire: 0.6
|
||||
|
||||
readonly property int hauteur_bouton_droit: 80
|
||||
|
||||
readonly property double pourcentage_bandeau_bas_largeur_zone_retour: 1
|
||||
|
||||
|
||||
readonly property int periode_init_raffraichissement_parametres: 1 // En ms
|
||||
readonly property int periode_raffraichissement_parametres: 1000 // En ms
|
||||
|
||||
|
||||
|
||||
// Affichage :
|
||||
property bool bouton_bandeau_bas_zone_retour_actif: false
|
||||
property int mode_maj_firmwares: 0
|
||||
|
||||
|
||||
// Données :
|
||||
|
||||
|
||||
// Modèles :
|
||||
// Note : les modèles chargés dans 'main.qml' n'ont pas à être rechargés dans les pages suivantes
|
||||
|
||||
|
||||
//===========================================================
|
||||
// Timer periode raffraichissement parametres :
|
||||
//===========================================================
|
||||
Timer {
|
||||
id: timer_raffraichissement_parametres
|
||||
interval: periode_init_raffraichissement_parametres
|
||||
triggeredOnStart: false
|
||||
running: true
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
if (interval == periode_init_raffraichissement_parametres) { // Premier passage, 1ms après le premier chargement
|
||||
interval = periode_raffraichissement_parametres;
|
||||
|
||||
init_page();
|
||||
}
|
||||
else if (!bouton_bandeau_bas_zone_retour_actif) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Titre de la page :
|
||||
Shipheart_titre_1 {titre:qsTr("Accès réservé Koriolan"); 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;
|
||||
color: "transparent"
|
||||
|
||||
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 : Client spécifique
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: visible ? hauteur_ligne_formulaire : 0
|
||||
color: "transparent"
|
||||
|
||||
Shipheart_formulaire_label {
|
||||
text: qsTr("Client spécifique")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
}
|
||||
|
||||
Shipheart_formulaire_combobox {
|
||||
id: champ_formulaire_Specifique_client
|
||||
model: ListModel { }
|
||||
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
|
||||
onActivated: {
|
||||
shipheart_clic();
|
||||
}
|
||||
}
|
||||
|
||||
Shipheart_formulaire_ligne_separation {
|
||||
haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Ligne de formulaire : Mode maj firmwares
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: visible ? hauteur_ligne_formulaire : 0
|
||||
color: "transparent"
|
||||
|
||||
Shipheart_formulaire_label {
|
||||
text: qsTr("Mode de mise à jour des firmwares")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
}
|
||||
|
||||
Shipheart_formulaire_combobox {
|
||||
id: champ_formulaire_Mode_maj_firmwares
|
||||
model: ListModel { }
|
||||
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
|
||||
onActivated: {
|
||||
shipheart_clic();
|
||||
}
|
||||
}
|
||||
|
||||
Shipheart_formulaire_ligne_separation {
|
||||
haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Ecran Milieu - Gauche :
|
||||
//-------------------------------------------------------
|
||||
Rectangle {
|
||||
id: zone_affichage_milieu_gauche
|
||||
x: 0
|
||||
y: shipheart_hauteur_bandeau_haut + zone_affichage_haut_gauche.height + espace_lignes_principales;
|
||||
width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2)
|
||||
height: (affichage_hauteur_utile * (1 - pourcentage_hauteur_ligne_haut)) - espace_lignes_principales;
|
||||
color: "transparent"
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Grille pour afficher les valeurs des paramètres non configurables :
|
||||
GridView {
|
||||
id: grille_informations
|
||||
|
||||
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_grille_informations
|
||||
delegate: Rectangle {
|
||||
width: parent.width
|
||||
height: visible ? hauteur_ligne_formulaire : 0
|
||||
color: "transparent"
|
||||
|
||||
Shipheart_formulaire_label {
|
||||
text: model.nom_champ
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
}
|
||||
Shipheart_formulaire_valeur_fixe {
|
||||
text: model.valeur_champ
|
||||
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
|
||||
}
|
||||
}
|
||||
ListModel {
|
||||
id: modele_grille_informations
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// 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 :
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: hauteur_bouton_droit
|
||||
color: shipheart_couleur_fond_bouton
|
||||
radius: shipheart_rayon_bouton
|
||||
// visible: !clavier.active // SDIR #255
|
||||
Text {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
font.pixelSize: 20
|
||||
text: qsTr("Enregistrer")
|
||||
color: couleur_blanc_casse
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
mise_a_jour(); // Mise à jour des données saisies dans la BDD et reconfiguration par l'application pour prise en compte.
|
||||
stackView.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Bouton Test matériel :
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: hauteur_bouton_droit
|
||||
color: shipheart_couleur_fond_bouton
|
||||
radius: shipheart_rayon_bouton
|
||||
visible: !clavier.active
|
||||
Text {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
font.pixelSize: 20
|
||||
text: qsTr("Tests matériel")
|
||||
color: couleur_blanc_casse
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
stackView.push("shipheart_test_home.qml")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Bandeau bas :
|
||||
//-------------------------------------------------------
|
||||
Row {
|
||||
x: 0
|
||||
y: shipheart_hauteur_page - shipheart_hauteur_bandeau_bas;
|
||||
width: shipheart_largeur_page;
|
||||
height: shipheart_hauteur_bandeau_bas;
|
||||
spacing: 5
|
||||
padding: 5
|
||||
|
||||
//.................................................
|
||||
// Bouton retour
|
||||
//.................................................
|
||||
Rectangle {
|
||||
id: bandeau_bas_zone_retour
|
||||
width: (parent.width * pourcentage_bandeau_bas_largeur_zone_retour) - (2 * parent.padding)
|
||||
height: shipheart_hauteur_bandeau_bas - parent.topPadding - parent.bottomPadding;
|
||||
radius: shipheart_rayon_bouton
|
||||
color: shipheart_couleur_fond_bouton
|
||||
|
||||
Image {
|
||||
source: "/images/icone_retour.png"
|
||||
sourceSize.height: 30
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea { // Zone d'interaction. On est obligé de la mettre dans la grille pour que Rectangle et MouseArea soient frères ou parent/enfant ET qu'on n'occupe qu'un espace dans la grille.
|
||||
id: mouse_area_bandeau_bas_zone_retour
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
stackView.pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 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;
|
||||
var specifique_client;
|
||||
|
||||
|
||||
modele_grille_informations.clear();
|
||||
|
||||
req = 'SELECT Nom, Valeur FROM TB_Configuration ORDER BY Cle_primaire';
|
||||
//console.log("req =" + req);
|
||||
nb = bdd.requete(req);
|
||||
|
||||
for (i = 0; i < nb; i ++)
|
||||
{
|
||||
res = bdd.lecture_ligne();
|
||||
if (!res.isEmpty)
|
||||
{
|
||||
switch(res[0])
|
||||
{
|
||||
case "Nb_jours_avant_suppression_historique": nom_champ = qsTr("Nombre jours avant suppression historique"); valeur_champ = res[1]; break;
|
||||
case "Nb_jours_avant_suppression_mesures": nom_champ = qsTr("Nombre jours avant suppression mesures"); valeur_champ = res[1]; break;
|
||||
case "Periode_sauvegarde_bdd": nom_champ = qsTr("Période de sauvegarde BDD"); valeur_champ = res[1]; break;
|
||||
case "Periode_check_download": nom_champ = qsTr("Période de vérification download"); valeur_champ = res[1]; break;
|
||||
|
||||
default: continue;
|
||||
}
|
||||
modele_grille_informations.append({"commande": false, "nom_champ": nom_champ, "valeur_champ": valeur_champ});
|
||||
}
|
||||
else break; // Ne devrait pas arriver....
|
||||
}
|
||||
|
||||
req = 'SELECT Nom, Valeur FROM TB_Systeme ORDER BY Cle_primaire';
|
||||
//console.log("req =" + req);
|
||||
nb = bdd.requete(req);
|
||||
|
||||
for (i = 0; i < nb; i ++)
|
||||
{
|
||||
res = bdd.lecture_ligne();
|
||||
if (!res.isEmpty)
|
||||
{
|
||||
switch(res[0])
|
||||
{
|
||||
case "Date_dernier_archivage_mesures": nom_champ = qsTr("Date de dernier archivage mesures"); valeur_champ = res[1]; break;
|
||||
|
||||
default: continue;
|
||||
}
|
||||
modele_grille_informations.append({"commande": false, "nom_champ": nom_champ, "valeur_champ": valeur_champ});
|
||||
}
|
||||
else break; // Ne devrait pas arriver....
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
// Specifique_client :
|
||||
|
||||
// Mise à jour depuis la BDD au cas où... :
|
||||
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Specifique_client" ';
|
||||
res = bdd.requete_unique(req);
|
||||
shipheart_specifique_client = res[0].split(';') // Mémorisation de l'ensemble du tableau
|
||||
specifique_client = Number(shipheart_specifique_client[0]);
|
||||
|
||||
champ_formulaire_Specifique_client.model.clear();
|
||||
champ_formulaire_Specifique_client.model.append({"valeur": shipheart_specifique_client_tous, "texte": qsTr("Aucune spécificité") });
|
||||
champ_formulaire_Specifique_client.model.append({"valeur": shipheart_specifique_client_suncy, "texte": qsTr("Client Suncy Concept") });
|
||||
|
||||
// Positionnement de l'index sur la valeur en cours :
|
||||
i = recherche_index_valeur_modele(specifique_client, champ_formulaire_Specifique_client.model, "specifique_client");
|
||||
if (i === -1) champ_formulaire_Specifique_client.currentIndex = recherche_index_valeur_modele(shipheart_specifique_client_tous, champ_formulaire_Specifique_client.model, "specifique_client");
|
||||
else champ_formulaire_Specifique_client.currentIndex = i;
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
// Mode de mise à jour des firmwares :
|
||||
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Mode_maj_firmwares" ';
|
||||
res = bdd.requete_unique(req);
|
||||
mode_maj_firmwares = Number(res[0]);
|
||||
|
||||
|
||||
champ_formulaire_Mode_maj_firmwares.model.clear();
|
||||
champ_formulaire_Mode_maj_firmwares.model.append({"valeur": 0, "texte": qsTr("Normal (si version installée est antérieure à la version en cours)") });
|
||||
champ_formulaire_Mode_maj_firmwares.model.append({"valeur": 1, "texte": qsTr("Différente (si version installée est différente de version en cours)") });
|
||||
champ_formulaire_Mode_maj_firmwares.model.append({"valeur": 2, "texte": qsTr("Toujours (à utiliser avec modération...)") });
|
||||
|
||||
// Positionnement de l'index sur la valeur en cours :
|
||||
i = recherche_index_valeur_modele(mode_maj_firmwares, champ_formulaire_Mode_maj_firmwares.model, "mode_maj_firmwares");
|
||||
if (i === -1) champ_formulaire_Mode_maj_firmwares.currentIndex = recherche_index_valeur_modele(0, champ_formulaire_Mode_maj_firmwares.model, "mode_maj_firmwares");
|
||||
else champ_formulaire_Mode_maj_firmwares.currentIndex = i;
|
||||
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================================================
|
||||
// Mise à jour des valeurs saisies
|
||||
//=============================================================================================================
|
||||
function mise_a_jour()
|
||||
{
|
||||
var req;
|
||||
var specifique_client;
|
||||
var chaine_specifique_client = "";
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------
|
||||
// Spécifique client :
|
||||
specifique_client = champ_formulaire_Specifique_client.model.get(champ_formulaire_Specifique_client.currentIndex).valeur;
|
||||
|
||||
if (Number(shipheart_specifique_client[0]) !== specifique_client) // Si le code client a changé :
|
||||
{
|
||||
switch(specifique_client)
|
||||
{
|
||||
default:
|
||||
case shipheart_specifique_client_tous:
|
||||
chaine_specifique_client = shipheart_specifique_client_tous;
|
||||
break;
|
||||
|
||||
case shipheart_specifique_client_suncy:
|
||||
chaine_specifique_client = shipheart_specifique_client_suncy;
|
||||
chaine_specifique_client += ";id_circuit_activation_moteur=0"
|
||||
break;
|
||||
}
|
||||
|
||||
// Mise à jour de la nouvelle valeur dans la BDD :
|
||||
req = 'UPDATE TB_Configuration SET Valeur="' + chaine_specifique_client + '" ';
|
||||
req += ' WHERE Nom="Specifique_client" '
|
||||
//console.log("Requête = [ " + req + "; ]");
|
||||
bdd.requete_unique(req);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------
|
||||
// Mode de mise à jour des firmwares :
|
||||
if (mode_maj_firmwares !== champ_formulaire_Mode_maj_firmwares.model.get(champ_formulaire_Mode_maj_firmwares.currentIndex).valeur)
|
||||
{
|
||||
mode_maj_firmwares = champ_formulaire_Mode_maj_firmwares.model.get(champ_formulaire_Mode_maj_firmwares.currentIndex).valeur;
|
||||
|
||||
switch(mode_maj_firmwares)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
// Mise à jour de la nouvelle valeur dans la BDD :
|
||||
req = 'UPDATE TB_Configuration SET Valeur="' + mode_maj_firmwares + '" ';
|
||||
req += ' WHERE Nom="Mode_maj_firmwares" '
|
||||
//console.log("Requête = [ " + req + "; ]");
|
||||
bdd.requete_unique(req);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
// ATTENTION : le rechargement de la config ne suffira pas la plupart du temps. Il faudra procéder à un reset de ShipHeart...
|
||||
|
||||
// Demande de reconfiguration système via la BDD car on a modifié des valeurs de configuration :
|
||||
synchro_bdd(shipheart_type_synchro_config);
|
||||
}
|
||||
|
||||
//=============================================================================================================
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
+1085
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,422 @@
|
||||
//========================================================================================================================================================================
|
||||
// CONFIG_MODULE_CREATION.QML
|
||||
// Ce fichier traite la création d'un module dans la table TB_Modules_config
|
||||
// La page est appelée depuis la page config_réseau_k_bus.qml, en cliquant sur "+"
|
||||
//========================================================================================================================================================================
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
import QtQml.Models
|
||||
|
||||
import qt.koriolan.shipheart 1.0
|
||||
import"fonctions.js" as Fonctions
|
||||
|
||||
|
||||
Shipheart_page {
|
||||
id: page_config_module_modification
|
||||
|
||||
|
||||
// Mis en forme :
|
||||
readonly property double pourcentage_largeur_colonne_gauche: 0.75
|
||||
readonly property double pourcentage_largeur_unites_formulaire: 0.1
|
||||
readonly property double espace_colonnes_principales: 20
|
||||
readonly property double pourcentage_hauteur_ligne_haut: 1
|
||||
readonly property double espace_lignes_principales: 20
|
||||
readonly property double affichage_hauteur_utile: shipheart_hauteur_page - shipheart_hauteur_bandeau_haut - shipheart_hauteur_bandeau_bas
|
||||
|
||||
readonly property int hauteur_ligne_formulaire: 60
|
||||
readonly property double pourcentage_largeur_labels_formulaire: 0.4
|
||||
|
||||
readonly property int hauteur_bouton_droit: 80
|
||||
|
||||
readonly property double pourcentage_bandeau_bas_largeur_zone_retour: 1
|
||||
|
||||
readonly property int periode_init_raffraichissement_parametres: 1 // En ms
|
||||
readonly property int periode_raffraichissement_parametres: 1000 // En ms
|
||||
|
||||
// Affichage :
|
||||
|
||||
|
||||
// Données :
|
||||
property int type_module: -1
|
||||
property string nom_module: ""
|
||||
property int adresse_module: 0
|
||||
|
||||
|
||||
// Modèles :
|
||||
// Note : les modèles chargés dans 'main.qml' n'ont pas à être rechargés dans les pages suivantes
|
||||
|
||||
|
||||
|
||||
//===========================================================
|
||||
// Timer periode raffraichissement parametres :
|
||||
//===========================================================
|
||||
Timer {
|
||||
id: timer_raffraichissement_parametres
|
||||
interval: periode_init_raffraichissement_parametres
|
||||
triggeredOnStart: false
|
||||
running: true
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
if (interval == periode_init_raffraichissement_parametres) { // Premier passage, 1ms après le premier chargement
|
||||
interval = periode_raffraichissement_parametres;
|
||||
|
||||
init_page();
|
||||
}
|
||||
else {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Titre de la page :
|
||||
Shipheart_titre_1 {titre:qsTr("Création d'un module à l'adresse [%1]").arg(adresse_module); 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"
|
||||
|
||||
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 : Type de module
|
||||
Rectangle {
|
||||
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("Type de module")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
couleur: (champ_formulaire_Type_module.currentIndex !== 0)
|
||||
? shipheart_formulaire_couleur_texte_par_defaut
|
||||
: shipheart_formulaire_couleur_texte_en_erreur
|
||||
}
|
||||
|
||||
Shipheart_formulaire_combobox {
|
||||
id: champ_formulaire_Type_module
|
||||
model: ListModel { }
|
||||
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
|
||||
onActivated: {
|
||||
shipheart_clic();
|
||||
type_module = champ_formulaire_Type_module.model.get(champ_formulaire_Type_module.currentIndex).valeur;
|
||||
// champ_formulaire_Nom.text = Fonctions.nom_type_module(champ_formulaire_Type_module.model.get(champ_formulaire_Type_module.currentIndex).valeur) + " @" + adresse_module;
|
||||
}
|
||||
}
|
||||
|
||||
Shipheart_formulaire_ligne_separation {
|
||||
haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Ligne de séparation :
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: 5
|
||||
color: "transparent"
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Ligne de formulaire : Nom
|
||||
Rectangle {
|
||||
width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2)
|
||||
implicitHeight: champ_formulaire_Nom.implicitHeight + 10
|
||||
color: "transparent"
|
||||
visible: (champ_formulaire_Type_module.currentIndex !== 0)
|
||||
|
||||
Shipheart_formulaire_label {
|
||||
text: qsTr("Nom du module")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
anchors.top: parent.top // Ces deux lignes permettent...
|
||||
verticalAlignment: Text.AlignTop // ... d'aligner le label avec le haut du Textarea qui suit (utile loesque le textarea est très long)
|
||||
}
|
||||
|
||||
Shipheart_formulaire_textarea {
|
||||
id: champ_formulaire_Nom
|
||||
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
|
||||
horizontalAlignment: Text.AlignJustify
|
||||
wrapMode: Label.Wrap
|
||||
}
|
||||
|
||||
Shipheart_formulaire_ligne_separation {
|
||||
haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Ligne de formulaire : Emplacement
|
||||
Rectangle {
|
||||
width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2)
|
||||
implicitHeight: champ_formulaire_Emplacement.implicitHeight + 10
|
||||
color: "transparent"
|
||||
visible: (champ_formulaire_Type_module.currentIndex !== 0) &&
|
||||
(champ_formulaire_Nom.text !== "")
|
||||
|
||||
Shipheart_formulaire_label {
|
||||
text: qsTr("Emplacement du module à bord")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
anchors.top: parent.top // Ces deux lignes permettent...
|
||||
verticalAlignment: Text.AlignTop // ... d'aligner le label avec le haut du Textarea qui suit (utile loesque le textarea est très long)
|
||||
}
|
||||
|
||||
Shipheart_formulaire_textarea {
|
||||
id: champ_formulaire_Emplacement
|
||||
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
|
||||
horizontalAlignment: Text.AlignJustify
|
||||
wrapMode: Label.Wrap
|
||||
}
|
||||
|
||||
Shipheart_formulaire_ligne_separation {
|
||||
haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Ligne de séparation :
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: 5
|
||||
color: "transparent"
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Ligne de formulaire : Commentaires
|
||||
Rectangle {
|
||||
width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2)
|
||||
implicitHeight: champ_formulaire_Commentaires.implicitHeight + 10
|
||||
color: "transparent"
|
||||
visible: (champ_formulaire_Type_module.currentIndex !== 0) &&
|
||||
(champ_formulaire_Nom.text !== "")
|
||||
|
||||
Shipheart_formulaire_label {
|
||||
text: qsTr("Commentaires")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
anchors.top: parent.top // Ces deux lignes permettent...
|
||||
verticalAlignment: Text.AlignTop // ... d'aligner le label avec le haut du Textarea qui suit (utile loesque le textarea est très long)
|
||||
}
|
||||
|
||||
Shipheart_formulaire_textarea {
|
||||
id: champ_formulaire_Commentaires
|
||||
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
|
||||
horizontalAlignment: Text.AlignJustify
|
||||
wrapMode: Label.Wrap
|
||||
}
|
||||
|
||||
Shipheart_formulaire_ligne_separation {
|
||||
haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Ligne d'extension pour laisser la liste remonter au-dessus de l'écran si besoin :
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: 100
|
||||
color: "transparent"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// 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 :
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: hauteur_bouton_droit
|
||||
color: shipheart_couleur_fond_bouton
|
||||
radius: shipheart_rayon_bouton
|
||||
// visible: !clavier.active // SDIR #255
|
||||
Text {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
font.pixelSize: 20
|
||||
text: qsTr("Enregistrer")
|
||||
color: couleur_blanc_casse
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
creation();
|
||||
stackView.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Bandeau bas :
|
||||
//-------------------------------------------------------
|
||||
Row {
|
||||
x: 0
|
||||
y: shipheart_hauteur_page - shipheart_hauteur_bandeau_bas;
|
||||
width: shipheart_largeur_page;
|
||||
height: shipheart_hauteur_bandeau_bas;
|
||||
spacing: 5
|
||||
padding: 5
|
||||
|
||||
//.................................................
|
||||
// Bouton retour
|
||||
//.................................................
|
||||
Rectangle {
|
||||
id: bandeau_bas_zone_retour
|
||||
width: (parent.width * pourcentage_bandeau_bas_largeur_zone_retour) - (2 * parent.padding)
|
||||
height: shipheart_hauteur_bandeau_bas - parent.topPadding - parent.bottomPadding;
|
||||
radius: shipheart_rayon_bouton
|
||||
color: shipheart_couleur_fond_bouton
|
||||
|
||||
Image {
|
||||
source: "/images/icone_retour.png"
|
||||
sourceSize.height: 30
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea { // Zone d'interaction. On est obligé de la mettre dans la grille pour que Rectangle et MouseArea soient frères ou parent/enfant ET qu'on n'occupe qu'un espace dans la grille.
|
||||
id: mouse_area_bandeau_bas_zone_retour
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
stackView.pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
// Type de module :
|
||||
champ_formulaire_Type_module.model.clear();
|
||||
champ_formulaire_Type_module.model.append({"valeur": shipheart_type_module_inconnu, "texte": Fonctions.nom_type_module(shipheart_type_module_inconnu) });
|
||||
// champ_formulaire_Type_module.model.append({"valeur": shipheart_type_module_shipbase, "texte": Fonctions.nom_type_module(shipheart_type_module_shipbase) });
|
||||
champ_formulaire_Type_module.model.append({"valeur": shipheart_type_module_shippower8DC, "texte": Fonctions.nom_type_module(shipheart_type_module_shippower8DC) });
|
||||
champ_formulaire_Type_module.model.append({"valeur": shipheart_type_module_shippower812, "texte": Fonctions.nom_type_module(shipheart_type_module_shippower812) });
|
||||
champ_formulaire_Type_module.model.append({"valeur": shipheart_type_module_shippower4AC, "texte": Fonctions.nom_type_module(shipheart_type_module_shippower4AC) });
|
||||
champ_formulaire_Type_module.model.append({"valeur": shipheart_type_module_shipBS, "texte": Fonctions.nom_type_module(shipheart_type_module_shipBS) });
|
||||
|
||||
|
||||
|
||||
|
||||
// Positionnement de l'index sur la valeur en cours :
|
||||
i = recherche_index_valeur_modele(type_module, champ_formulaire_Type_module.model, "Type_module");
|
||||
champ_formulaire_Type_module.currentIndex = i; // La valeur de retour d'erreur de la fonction étant '-1', comme la valeur 'Non-définie', on peut l'affecter directement, sans vérifier la valeir de retour. Dans ces 2 cas, on sera en NON DEFINI...
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================================================
|
||||
// Création du module
|
||||
//=============================================================================================================
|
||||
function creation()
|
||||
{
|
||||
var req;
|
||||
var val;
|
||||
var texte_nom;
|
||||
var texte_emplacement;
|
||||
var texte_commentaires;
|
||||
|
||||
// Mise à jour des textes :
|
||||
texte_nom = champ_formulaire_Nom.text.replace(/\"/g, "\\\"");
|
||||
//console.log("Nom = [" + champ_formulaire_Nom.text + "] et texte modifié = [" + texte_nom + "]")
|
||||
texte_emplacement = champ_formulaire_Emplacement.text.replace(/\"/g, "\\\"");
|
||||
//console.log("Emplacement = [" + champ_formulaire_Emplacement.text + "] et texte modifié = [" + texte_emplacement + "]")
|
||||
texte_commentaires = champ_formulaire_Commentaires.text.replace(/\"/g, "\\\"");
|
||||
//console.log("Commentaires = [" + champ_formulaire_Commentaires.text + "] et texte modifié = [" + texte_commentaires + "]")
|
||||
|
||||
req = 'INSERT INTO TB_Modules_config ';
|
||||
req += '(Adresse_k_bus, ';
|
||||
req += 'Nom, ';
|
||||
req += 'Type, ';
|
||||
req += 'Emplacement, ';
|
||||
req += 'Commentaires) ';
|
||||
req += ' VALUES (';
|
||||
req += adresse_module + ' ';
|
||||
req += ', "' + texte_nom + '" ';
|
||||
req += ', ' + type_module + ' ';
|
||||
req += ', "' + texte_emplacement + '" ';
|
||||
req += ', "' + texte_commentaires + '" ';
|
||||
req += ') ';
|
||||
console.log("Requête = [ " + req + "; ]")
|
||||
bdd.requete_unique(req);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================================================
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,398 @@
|
||||
//========================================================================================================================================================================
|
||||
// CONFIG_MODULE.QML
|
||||
// Ce fichier traite la configuration des paramètres d'un module en particulier
|
||||
// La page est appelée depuis la page config_modules.qml, en cliquant sur "Modifier les informations du module"
|
||||
//========================================================================================================================================================================
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
import QtQml.Models
|
||||
|
||||
import qt.koriolan.shipheart 1.0
|
||||
import"fonctions.js" as Fonctions
|
||||
|
||||
|
||||
Shipheart_page {
|
||||
id: page_config_module_modification
|
||||
|
||||
|
||||
// Mis en forme :
|
||||
readonly property double pourcentage_largeur_colonne_gauche: 0.75
|
||||
readonly property double pourcentage_largeur_unites_formulaire: 0.1
|
||||
readonly property double espace_colonnes_principales: 20
|
||||
readonly property double pourcentage_hauteur_ligne_haut: 1
|
||||
readonly property double espace_lignes_principales: 20
|
||||
readonly property double affichage_hauteur_utile: shipheart_hauteur_page - shipheart_hauteur_bandeau_haut - shipheart_hauteur_bandeau_bas
|
||||
|
||||
readonly property int hauteur_ligne_formulaire: 60
|
||||
readonly property double pourcentage_largeur_labels_formulaire: 0.4
|
||||
|
||||
readonly property int hauteur_bouton_droit: 80
|
||||
|
||||
readonly property double pourcentage_bandeau_bas_largeur_zone_retour: 1
|
||||
|
||||
readonly property int periode_init_raffraichissement_parametres: 1 // En ms
|
||||
readonly property int periode_raffraichissement_parametres: 1000 // En ms
|
||||
|
||||
// Affichage :
|
||||
|
||||
|
||||
// Données :
|
||||
// property int adresse: 0
|
||||
property int type_module: 0
|
||||
property string nom_module: ""
|
||||
property int adresse_module: 0
|
||||
|
||||
|
||||
// Modèles :
|
||||
// Note : les modèles chargés dans 'main.qml' n'ont pas à être rechargés dans les pages suivantes
|
||||
|
||||
|
||||
|
||||
//===========================================================
|
||||
// Timer periode raffraichissement parametres :
|
||||
//===========================================================
|
||||
Timer {
|
||||
id: timer_raffraichissement_parametres
|
||||
interval: periode_init_raffraichissement_parametres
|
||||
triggeredOnStart: false
|
||||
running: true
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
if (interval == periode_init_raffraichissement_parametres) { // Premier passage, 1ms après le premier chargement
|
||||
interval = periode_raffraichissement_parametres;
|
||||
|
||||
init_page();
|
||||
}
|
||||
else {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Titre de la page :
|
||||
Shipheart_titre_1 {titre:qsTr("Configuration du module [%1] à l'adresse [%2]").arg(nom_module).arg(adresse_module); 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"
|
||||
|
||||
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 {
|
||||
width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2)
|
||||
implicitHeight: champ_formulaire_Nom.implicitHeight + 10
|
||||
color: "transparent"
|
||||
|
||||
Shipheart_formulaire_label {
|
||||
text: qsTr("Nom du module")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
anchors.top: parent.top // Ces deux lignes permettent...
|
||||
verticalAlignment: Text.AlignTop // ... d'aligner le label avec le haut du Textarea qui suit (utile loesque le textarea est très long)
|
||||
}
|
||||
|
||||
Shipheart_formulaire_textarea {
|
||||
id: champ_formulaire_Nom
|
||||
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
|
||||
horizontalAlignment: Text.AlignJustify
|
||||
wrapMode: Label.Wrap
|
||||
}
|
||||
|
||||
Shipheart_formulaire_ligne_separation {
|
||||
haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Ligne de séparation :
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: 5
|
||||
color: "transparent"
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Ligne de formulaire : Emplacement
|
||||
Rectangle {
|
||||
width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2)
|
||||
implicitHeight: champ_formulaire_Emplacement.implicitHeight + 10
|
||||
color: "transparent"
|
||||
|
||||
Shipheart_formulaire_label {
|
||||
text: qsTr("Emplacement du module à bord")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
anchors.top: parent.top // Ces deux lignes permettent...
|
||||
verticalAlignment: Text.AlignTop // ... d'aligner le label avec le haut du Textarea qui suit (utile loesque le textarea est très long)
|
||||
}
|
||||
|
||||
Shipheart_formulaire_textarea {
|
||||
id: champ_formulaire_Emplacement
|
||||
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
|
||||
horizontalAlignment: Text.AlignJustify
|
||||
wrapMode: Label.Wrap
|
||||
}
|
||||
|
||||
Shipheart_formulaire_ligne_separation {
|
||||
haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Ligne de séparation :
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: 5
|
||||
color: "transparent"
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Ligne de formulaire : Commentaires
|
||||
Rectangle {
|
||||
width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2)
|
||||
implicitHeight: champ_formulaire_Commentaires.implicitHeight + 10
|
||||
color: "transparent"
|
||||
|
||||
Shipheart_formulaire_label {
|
||||
text: qsTr("Commentaires")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
anchors.top: parent.top // Ces deux lignes permettent...
|
||||
verticalAlignment: Text.AlignTop // ... d'aligner le label avec le haut du Textarea qui suit (utile loesque le textarea est très long)
|
||||
}
|
||||
|
||||
Shipheart_formulaire_textarea {
|
||||
id: champ_formulaire_Commentaires
|
||||
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
|
||||
horizontalAlignment: Text.AlignJustify
|
||||
wrapMode: Label.Wrap
|
||||
}
|
||||
|
||||
Shipheart_formulaire_ligne_separation {
|
||||
haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Ligne de formulaire : Courant de masses maxi
|
||||
Rectangle {
|
||||
width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2)
|
||||
height: visible ? hauteur_ligne_formulaire : 0
|
||||
color: "transparent"
|
||||
visible: (type_module === shipheart_type_module_shippower8DC)
|
||||
|
||||
Shipheart_formulaire_label { // Label :
|
||||
text: qsTr("Courant de masses max. sur réseau")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
}
|
||||
|
||||
Shipheart_formulaire_textfield { // Champ de saisie :
|
||||
id: champ_formulaire_Courant_masses_maxi
|
||||
width: parent.width * (1 - pourcentage_largeur_labels_formulaire - pourcentage_largeur_unites_formulaire)
|
||||
x: parent.width * pourcentage_largeur_labels_formulaire
|
||||
flag_num_only: true
|
||||
horizontalAlignment: Text.AlignRight
|
||||
rightPadding: 10
|
||||
}
|
||||
|
||||
Shipheart_formulaire_unite { // Unités :
|
||||
text: qsTr("A")
|
||||
width: parent.width * pourcentage_largeur_unites_formulaire
|
||||
}
|
||||
|
||||
Shipheart_formulaire_ligne_separation {
|
||||
haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Ligne d'extension pour laisser la liste remonter au-dessus de l'écran si besoin :
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: 100
|
||||
color: "transparent"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// 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 :
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: hauteur_bouton_droit
|
||||
color: shipheart_couleur_fond_bouton
|
||||
radius: shipheart_rayon_bouton
|
||||
// visible: !clavier.active // SDIR #255
|
||||
Text {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
font.pixelSize: 20
|
||||
text: qsTr("Enregistrer")
|
||||
color: couleur_blanc_casse
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
mise_a_jour();
|
||||
stackView.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Bandeau bas :
|
||||
//-------------------------------------------------------
|
||||
Row {
|
||||
x: 0
|
||||
y: shipheart_hauteur_page - shipheart_hauteur_bandeau_bas;
|
||||
width: shipheart_largeur_page;
|
||||
height: shipheart_hauteur_bandeau_bas;
|
||||
spacing: 5
|
||||
padding: 5
|
||||
|
||||
//.................................................
|
||||
// Bouton retour
|
||||
//.................................................
|
||||
Rectangle {
|
||||
id: bandeau_bas_zone_retour
|
||||
width: (parent.width * pourcentage_bandeau_bas_largeur_zone_retour) - (2 * parent.padding)
|
||||
height: shipheart_hauteur_bandeau_bas - parent.topPadding - parent.bottomPadding;
|
||||
radius: shipheart_rayon_bouton
|
||||
color: shipheart_couleur_fond_bouton
|
||||
|
||||
Image {
|
||||
source: "/images/icone_retour.png"
|
||||
sourceSize.height: 30
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea { // Zone d'interaction. On est obligé de la mettre dans la grille pour que Rectangle et MouseArea soient frères ou parent/enfant ET qu'on n'occupe qu'un espace dans la grille.
|
||||
id: mouse_area_bandeau_bas_zone_retour
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
stackView.pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
req = 'SELECT Type, Adresse_k_bus, Nom, Emplacement, Commentaires FROM TB_Modules_config WHERE Adresse_k_bus=' + adresse_module + ' ';
|
||||
res = bdd.requete_unique(req);
|
||||
|
||||
type_module = Number(res[0]);
|
||||
nom_module = Fonctions.nom_type_module(type_module);
|
||||
adresse_module = Number(res[1]);
|
||||
champ_formulaire_Nom.text = res[2];
|
||||
champ_formulaire_Emplacement.text = res[3];
|
||||
champ_formulaire_Commentaires.text = res[4];
|
||||
|
||||
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Courant_masses_maxi_sp8dc" ';
|
||||
res = bdd.requete_unique(req);
|
||||
champ_formulaire_Courant_masses_maxi.text = res[0];
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================================================
|
||||
// Mise à jour des valeurs saisies
|
||||
//=============================================================================================================
|
||||
function mise_a_jour()
|
||||
{
|
||||
var req;
|
||||
var val;
|
||||
var texte_nom;
|
||||
var texte_emplacement;
|
||||
var texte_commentaires;
|
||||
var courant_masses;
|
||||
|
||||
// Mise à jour des textes :
|
||||
texte_nom = champ_formulaire_Nom.text.replace(/\"/g, "\\\"");
|
||||
//console.log("Nom = [" + champ_formulaire_Nom.text + "] et texte modifié = [" + texte_nom + "]")
|
||||
texte_emplacement = champ_formulaire_Emplacement.text.replace(/\"/g, "\\\"");
|
||||
//console.log("Emplacement = [" + champ_formulaire_Emplacement.text + "] et texte modifié = [" + texte_emplacement + "]")
|
||||
texte_commentaires = champ_formulaire_Commentaires.text.replace(/\"/g, "\\\"");
|
||||
//console.log("Commentaires = [" + champ_formulaire_Commentaires.text + "] et texte modifié = [" + texte_commentaires + "]")
|
||||
|
||||
req = 'UPDATE TB_Modules_config SET Nom="' + texte_nom + '", Emplacement="' + texte_emplacement + '", Commentaires="' + texte_commentaires + '" WHERE Adresse_k_bus=' + adresse_module + ' ';
|
||||
//console.log("Requête = " + req)
|
||||
bdd.requete_unique(req);
|
||||
|
||||
|
||||
// Mise à jour de la valeur de 'Courant_masses_maxi_sp8dc' :
|
||||
courant_masses = Number(champ_formulaire_Courant_masses_maxi.text);
|
||||
if ((courant_masses >= 0) && (courant_masses <= shipheart_max_courant_masses_sp8dc))
|
||||
{
|
||||
req = 'UPDATE TB_Configuration SET Valeur=' + courant_masses + ' WHERE Nom="Courant_masses_maxi_sp8dc" ';
|
||||
//console.log("Requête = " + req)
|
||||
bdd.requete_unique(req);
|
||||
|
||||
|
||||
// Demande de reconfiguration système via la BDD car on a modifié des valeurs de configuration :
|
||||
synchro_bdd(shipheart_type_synchro_config);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,416 @@
|
||||
//========================================================================================================================================================================
|
||||
// CONFIG_MODULE.QML
|
||||
// Ce fichier traite la configuration d'un module (à la fois sur l'aspect physique et config)
|
||||
// La page est appelée depuis la page config_reseau_j_bus.qml, en cliquant sur un module dans la colonne 'config'
|
||||
//========================================================================================================================================================================
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
import QtQml.Models
|
||||
|
||||
import qt.koriolan.shipheart 1.0
|
||||
import"fonctions.js" as Fonctions
|
||||
|
||||
|
||||
|
||||
Shipheart_page {
|
||||
id: page_config_module
|
||||
|
||||
|
||||
// Mis en forme :
|
||||
readonly property double pourcentage_largeur_colonne_gauche: 0.75
|
||||
readonly property double espace_colonnes_principales: 20
|
||||
readonly property double pourcentage_hauteur_ligne_haut: 0
|
||||
readonly property double espace_lignes_principales: 20
|
||||
readonly property double affichage_hauteur_utile: shipheart_hauteur_page - shipheart_hauteur_bandeau_haut - shipheart_hauteur_bandeau_bas
|
||||
|
||||
readonly property int hauteur_ligne_formulaire: 50
|
||||
readonly property double pourcentage_largeur_labels_formulaire: 0.45
|
||||
|
||||
readonly property int hauteur_bouton_droit: 80
|
||||
|
||||
readonly property double pourcentage_bandeau_bas_largeur_zone_retour: 1
|
||||
|
||||
|
||||
readonly property int periode_init_raffraichissement_parametres: 1 // En ms
|
||||
readonly property int periode_raffraichissement_parametres: 1000 // En ms
|
||||
readonly property int step_timer_appui_long: 30 // en ms
|
||||
|
||||
|
||||
|
||||
// Données :
|
||||
property bool flag_init: true // Permet de bloquer certains affichage tant que l'init n'est pas terminée
|
||||
property int valeur_timer_appui_long: 0
|
||||
property int adresse_module;
|
||||
property int type_carte: 0
|
||||
property string titre_page: ""
|
||||
property int consigne_en_cours: 0 // Contient la commande en cours sur le module
|
||||
property int index_courant_masses: -1 // SDIR #321
|
||||
|
||||
|
||||
|
||||
// Modèles :
|
||||
// Note : les modèles chargés dans 'main.qml' n'ont pas à être rechargés dans les pages suivantes
|
||||
|
||||
|
||||
//===========================================================
|
||||
// Timer periode raffraichissement parametres :
|
||||
//===========================================================
|
||||
Timer {
|
||||
id: timer_raffraichissement_parametres
|
||||
interval: periode_init_raffraichissement_parametres
|
||||
triggeredOnStart: false
|
||||
running: true
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
if (interval == periode_init_raffraichissement_parametres) { // Premier passage, 1ms après le premier chargement
|
||||
interval = periode_raffraichissement_parametres;
|
||||
|
||||
init_page();
|
||||
}
|
||||
else
|
||||
{
|
||||
mise_a_jour();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//===========================================================
|
||||
// Lorsque la page est sur le point d'être affichée dans la pile :
|
||||
//===========================================================
|
||||
StackView.onActivating: {
|
||||
init_page(); // Permet un rafraichissement des champs qui ont pu être modifiés dans les pages en-dessous (Emplacement du module, Commentaires,...)
|
||||
}
|
||||
|
||||
//===========================================================
|
||||
// Titre de la page :
|
||||
//===========================================================
|
||||
Shipheart_titre_1 {titre:titre_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;
|
||||
color: "transparent"
|
||||
|
||||
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
|
||||
|
||||
// Cf Ship2net.qml pour ajouter ici des champs de saisie...
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Ecran Milieu - Gauche :
|
||||
//-------------------------------------------------------
|
||||
Rectangle {
|
||||
id: zone_affichage_milieu_gauche
|
||||
x: 0
|
||||
y: shipheart_hauteur_bandeau_haut + zone_affichage_haut_gauche.height + espace_lignes_principales;
|
||||
width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2)
|
||||
height: (affichage_hauteur_utile * (1 - pourcentage_hauteur_ligne_haut)) - espace_lignes_principales;
|
||||
color: "transparent"
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Grille pour afficher les valeurs des paramètres non configurables :
|
||||
ListView {
|
||||
id: grille_informations
|
||||
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
spacing: 5
|
||||
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_informations
|
||||
|
||||
delegate: ligne_champ
|
||||
|
||||
Component {
|
||||
id: ligne_champ
|
||||
|
||||
Rectangle {
|
||||
width: grille_informations.width
|
||||
height: undefined // Permet de faire fonctionner le 'implicitHeight' qui suit
|
||||
implicitHeight: (texte_valeur_champ.implicitHeight > hauteur_ligne_formulaire) ?
|
||||
texte_valeur_champ.implicitHeight :
|
||||
hauteur_ligne_formulaire
|
||||
color: "transparent"
|
||||
// visible: !flag_init
|
||||
|
||||
Shipheart_formulaire_label {
|
||||
text: nom_champ
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
}
|
||||
Shipheart_formulaire_valeur_fixe {
|
||||
id: texte_valeur_champ
|
||||
text: valeur_champ
|
||||
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
|
||||
x: parent.width * pourcentage_largeur_labels_formulaire
|
||||
padding: 10
|
||||
}
|
||||
Shipheart_formulaire_ligne_separation {
|
||||
haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse
|
||||
}
|
||||
}
|
||||
}
|
||||
ListModel {
|
||||
id: modele_grille_informations
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// 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 localiser le module :
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: hauteur_bouton_droit
|
||||
color: (consigne_en_cours !== 0) ? shipheart_couleur_fond_bouton_actif : shipheart_couleur_fond_bouton
|
||||
radius: shipheart_rayon_bouton
|
||||
visible: !clavier.active && (type_carte !== shipheart_type_module_shipbase)
|
||||
Text {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
font.pixelSize: 20
|
||||
text: qsTr("Localiser le module")
|
||||
color: couleur_blanc_casse
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
if (consigne_en_cours === 0) consigne_en_cours = 1;
|
||||
else consigne_en_cours = 0;
|
||||
commande_localisation_module(adresse_module, consigne_en_cours);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Bandeau bas :
|
||||
//-------------------------------------------------------
|
||||
Row {
|
||||
x: 0
|
||||
y: shipheart_hauteur_page - shipheart_hauteur_bandeau_bas;
|
||||
width: shipheart_largeur_page;
|
||||
height: shipheart_hauteur_bandeau_bas;
|
||||
spacing: 5
|
||||
padding: 5
|
||||
|
||||
//.................................................
|
||||
// Bouton retour
|
||||
//.................................................
|
||||
Rectangle {
|
||||
id: bandeau_bas_zone_retour
|
||||
width: (parent.width * pourcentage_bandeau_bas_largeur_zone_retour) - (2 * parent.padding)
|
||||
height: shipheart_hauteur_bandeau_bas - parent.topPadding - parent.bottomPadding;
|
||||
radius: shipheart_rayon_bouton
|
||||
color: shipheart_couleur_fond_bouton
|
||||
|
||||
Image {
|
||||
source: "/images/icone_retour.png"
|
||||
sourceSize.height: 30
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
}
|
||||
|
||||
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 (consigne_en_cours !== 0) commande_localisation_module(adresse_module, 0); // Coupure de la localisation du module si on quitte la page et que la localisation est en cours
|
||||
stackView.pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 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()
|
||||
{
|
||||
|
||||
mise_a_jour();
|
||||
|
||||
flag_init = false;
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================================================
|
||||
// Mise à jour des informations variables
|
||||
// NB : le choix est fait de relancer une init complète chaque seconde. Un peu lourd mais permet de raffraichir
|
||||
// automatiquement toutes les infos chaque seconde (utile en tests de cartes...) [SDIR #309]
|
||||
//=============================================================================================================
|
||||
function mise_a_jour()
|
||||
{
|
||||
var req, res;
|
||||
var i;
|
||||
var nom_champ, valeur_champ, flag_valide;
|
||||
var index = 0;
|
||||
var nom_champ_emplacement, valeur_champ_emplacement;
|
||||
var nom_champ_commentaires, valeur_champ_commentaires;
|
||||
|
||||
|
||||
modele_grille_informations.clear(); // RAZ des valeurs existantes
|
||||
|
||||
// La liste ci-dessous permet de définir les champs qui seront affichés ainsi que leur ordre d'affichage :
|
||||
// Attention : 'Type' est traité hors boucle et doit donc rester en première position !!
|
||||
var param = ["Type",
|
||||
"Adresse_k_bus",
|
||||
"Adresse_mac",
|
||||
// "Software_type",
|
||||
"Software_version",
|
||||
"Software_crc",
|
||||
"Hardware_version",
|
||||
"Flag_r_term",
|
||||
// "Cpu_unique_id",
|
||||
// "Cpu_flash_size",
|
||||
// "Cpu_package",
|
||||
"Date_maj"]; // Laissé actif en dernière position pour gérer les ',' lors de commentaires... Mais supprimé dans le switch...
|
||||
|
||||
req = 'SELECT ';
|
||||
req += param[0];
|
||||
for (i=1; i<(param.length - 1); i++) req += ', ' + param[i];
|
||||
req += ' FROM TB_Modules_physiques WHERE Adresse_k_bus=' + adresse_module + ' ';
|
||||
//console.log("req =[" + req + "]");
|
||||
res = bdd.requete_unique(req);
|
||||
|
||||
//=======================================================
|
||||
// Cas particulier du 'Type' qui est traité hors boucle :
|
||||
// NB : il doit donc rester en première position de la liste des paramètres !!
|
||||
type_carte = Number(res[0]);
|
||||
|
||||
//==================================================
|
||||
// Traitement de tous les autres paramètres :
|
||||
for (i=1; i<(param.length - 1); i++)
|
||||
{
|
||||
flag_valide = true;
|
||||
switch(param[i]) // NB : l'ordre de traitement dans le switch n'a aucun impact sur l'affichage....
|
||||
{
|
||||
case "Adresse_k_bus" :
|
||||
if (type_carte === shipheart_type_module_shipbase) titre_page = qsTr("Paramètres du module [%1]").arg(Fonctions.nom_type_module(type_carte))
|
||||
else titre_page = qsTr("Paramètres du module [%1] à l'adresse [%2]").arg(Fonctions.nom_type_module(type_carte)).arg(Number(res[i]));
|
||||
continue;
|
||||
case "Adresse_mac" : nom_champ = qsTr("N° de série"); valeur_champ = res[i]; break;
|
||||
case "Software_type" : nom_champ = qsTr("Nom du firmware"); valeur_champ = res[i]; break;
|
||||
case "Software_version" : nom_champ = qsTr("Version du firmware"); valeur_champ = res[i]; break;
|
||||
case "Hardware_version": nom_champ = qsTr("Version matérielle"); valeur_champ = res[i]; break;
|
||||
case "Flag_r_term" : if (adresse_module === 0) continue; nom_champ = qsTr("Résistance de terminaison"); valeur_champ = Number(res[i]) ? qsTr("Oui") : qsTr("Non"); break;
|
||||
// case "Cpu_unique_id": nom_champ = qsTr("ID unique du processeur"); valeur_champ = res[i]; break;
|
||||
// case "Cpu_flash_size": nom_champ = qsTr("Taille mémoire flash"); valeur_champ = res[i] + " kB"; break;
|
||||
// case "Cpu_package": nom_champ = qsTr("Code package processeur"); valeur_champ = res[i]; break;
|
||||
case "Software_crc": nom_champ = qsTr("CRC du firmware"); valeur_champ = res[i]; break;
|
||||
case "Date_maj":
|
||||
flag_valide = false;
|
||||
break;
|
||||
|
||||
default: nom_champ = param[i]; valeur_champ = res[i]; break;
|
||||
}
|
||||
|
||||
if (flag_valide)
|
||||
{
|
||||
valeur_champ = valeur_champ.replace(/\n/g, "<br />"); // Remplace les '\n' par '<br />'. Sinon, les '\n' ne sont pas pris en compte par le RichText d'affichage.
|
||||
|
||||
modele_grille_informations.append({"nom_champ": nom_champ, "valeur_champ": valeur_champ});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//==================================================
|
||||
// Cas particulier des SP8DC avec leur courant de masse :
|
||||
if (type_carte === shipheart_type_module_shippower8DC)
|
||||
{
|
||||
// Ajout de l'entrée dans le modèle :
|
||||
modele_grille_informations.append({"nom_champ": qsTr("Courant de masses sur réseau"), "valeur_champ": "0"});
|
||||
index_courant_masses = modele_grille_informations.count - 1; // Permet d'accéder ensuite à ce champ particulier pour mettre sa valeur à jour. Le '-1' permet d'avoir une valeur entre 0 et N car l'append précédent a positionné le COUNT à >= 1.
|
||||
}
|
||||
|
||||
|
||||
//=========================================================
|
||||
// Cas particulier du champ Version Processeur de ShipBase :
|
||||
if (adresse_module === 0) // Pour ShipBase, la version de Compute Module n'est pas dans TB_Modules_physiques mais dans TB_Systeme...
|
||||
{
|
||||
res = bdd.requete_unique('SELECT Valeur FROM TB_Systeme WHERE Nom="Version_cm" ');
|
||||
|
||||
modele_grille_informations.append({"nom_champ": qsTr("Version processeur"), "valeur_champ": res[0]});
|
||||
}
|
||||
|
||||
|
||||
//=========================================================
|
||||
// Courant de masse des SP8DC :
|
||||
if (index_courant_masses >= 0) // SDIR #321 : si l'index est toujours égal à -1, c'est que le champ n'est pas utilisé sur ce module et on ne fait pas de mises à jour.
|
||||
{
|
||||
req = 'SELECT Courant_masses FROM TB_Modules_config WHERE Adresse_k_bus=' + adresse_module + ' ';
|
||||
//console.log("req = [" + req + "]");
|
||||
res = bdd.requete_unique(req);
|
||||
modele_grille_informations.setProperty(index_courant_masses, "valeur_champ", Number(res[0]).toFixed(3).toString() + " A");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================================================
|
||||
// Emission d'une commande à destination d'une carte
|
||||
//=============================================================================================================
|
||||
function commande_localisation_module(id, consigne)
|
||||
{
|
||||
var req;
|
||||
|
||||
consigne_en_cours = consigne;
|
||||
req = "UPDATE TB_Modules_config SET New_cde='" + shipheart_commande_module_localisation + "/" + consigne + "' WHERE Adresse_k_bus=" + adresse_module + " ";
|
||||
bdd.requete_unique(req);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,709 @@
|
||||
//========================================================================================================================================================================
|
||||
// CONFIG_ORDRE_ELEMENTS.QML
|
||||
// Ce fichier traite l'ordre d'affichage d'éléments sur la page d'accueil (batteries, circuits, réservoirs, capteurs). La page permet modifier l'ordre d'affichage
|
||||
// en déplaçant (glisser/déposer) éléments configurés.
|
||||
// L'appel se fait en passant la propriété 'table' qui permet de connaitre le type d'éléments à traiter.
|
||||
// La page est appelée depuis la page CONFIG_XXXXXX_1, en cliquant sur l'icone des deux flèches inversés en bas de l'écran
|
||||
//========================================================================================================================================================================
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
import QtQml.Models 2.1
|
||||
|
||||
import qt.koriolan.shipheart 1.0
|
||||
|
||||
|
||||
|
||||
Shipheart_page {
|
||||
id: page_config_ordre_elements
|
||||
|
||||
|
||||
// Mis en forme :
|
||||
readonly property double affichage_hauteur_utile: shipheart_hauteur_page - shipheart_hauteur_bandeau_haut - shipheart_hauteur_bandeau_bas
|
||||
|
||||
readonly property int periode_init_raffraichissement_parametres: 1 // En ms
|
||||
readonly property int periode_raffraichissement_parametres: 1000 // En ms
|
||||
|
||||
|
||||
// Affichage :
|
||||
property string texte_titre: ""
|
||||
property string texte_aucun_groupe: ""
|
||||
property string texte_aucun_element: ""
|
||||
property bool bouton_bandeau_bas_zone_retour_actif: false
|
||||
|
||||
property bool flag_affichage_zone_groupe: false
|
||||
property double pourcentage_largeur_zone_groupes: 0.4
|
||||
property int nombre_groupes_affichees_sur_une_colonne: 8
|
||||
property int espace_zones: 10
|
||||
property int nombre_colonnes_affichage: 1
|
||||
property int nombre_elements_affichees_sur_une_colonne: 8
|
||||
property int espace_lignes_affichage: 10
|
||||
property int espace_colonnes_affichage: 300
|
||||
|
||||
// Données :
|
||||
property string table: ""
|
||||
property int type_source_groupe: shipheart_type_source_inconnu // 0
|
||||
property int id_groupe: 0 // Cle_primaire du groupe en cours (par défaut, 0 = sans famille)
|
||||
|
||||
|
||||
// Modèles :
|
||||
// Note : les modèles chargés dans 'main.qml' n'ont pas à être rechargés dans les pages suivantes
|
||||
|
||||
|
||||
//===========================================================
|
||||
// Timer periode raffraichissement parametres :
|
||||
//===========================================================
|
||||
Timer {
|
||||
id: timer_raffraichissement_parametres
|
||||
interval: periode_init_raffraichissement_parametres
|
||||
triggeredOnStart: false
|
||||
running: true
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
if (interval == periode_init_raffraichissement_parametres) // Premier passage, 1ms après le premier chargement
|
||||
{
|
||||
interval = periode_raffraichissement_parametres;
|
||||
init_page();
|
||||
}
|
||||
else if (!bouton_bandeau_bas_zone_retour_actif)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================
|
||||
// Lorsque la page est sur le point d'être affichée dans la pile :
|
||||
//===========================================================
|
||||
StackView.onActivating: {
|
||||
mise_a_jour_liste_groupes();
|
||||
mise_a_jour_liste_elements_groupe(id_groupe);
|
||||
}
|
||||
|
||||
|
||||
// Titre de la page :
|
||||
Shipheart_titre_1 {titre:texte_titre; hauteur: shipheart_hauteur_bandeau_haut}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Ecran Principal :
|
||||
//-------------------------------------------------------
|
||||
Rectangle {
|
||||
id: zone_affichage_principale
|
||||
x: 0
|
||||
y: shipheart_hauteur_bandeau_haut
|
||||
width: shipheart_largeur_page
|
||||
height: affichage_hauteur_utile
|
||||
color: "transparent"
|
||||
|
||||
//-------------------------------------------------
|
||||
// Liste des groupes
|
||||
Rectangle {
|
||||
id: zone_affichage_groupes
|
||||
x: 0
|
||||
y: 0
|
||||
width: (shipheart_largeur_page * pourcentage_largeur_zone_groupes) - (espace_zones / 2)
|
||||
height: affichage_hauteur_utile
|
||||
visible: flag_affichage_zone_groupe
|
||||
color: "transparent"
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Liste :
|
||||
ListView {
|
||||
property bool deplacement_en_cours: false // Indique si un déplacement (au global) est en cours ou pas
|
||||
property int save_current_index: 0 // Permet de garder le Current_index du début du déplacement et de compenser les changements qui sont fait automatiquement, notamment en début et fin de liste. Le principe est qu'une fois le mouvement déclenché, ON NE CHANGE PAS de CurrentIndex !!
|
||||
|
||||
id: grille_groupes
|
||||
|
||||
x: 0
|
||||
y: 0
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
|
||||
clip: true // Limite l'affichage des délégués dans la zone de ListView (sinon, on affiche au moins un délégué au-dessus et un en dessous...)
|
||||
highlightRangeMode: ListView.StrictlyEnforceRange // Permet de faire défiler la liste jusqu'à ne garder que le dernier élément affiché
|
||||
|
||||
model: modele_liste_groupes
|
||||
delegate: bouton_groupe
|
||||
|
||||
displaced: Transition { // Gère la transition lors d'un déplacement
|
||||
NumberAnimation{
|
||||
properties: "x,y" // Ici, on devrait pouvoir limiter à Y
|
||||
duration: 500 // Vitesse à laquelle se déplacent les boutons lorsqu'on les déplace
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: bouton_groupe
|
||||
|
||||
MouseArea {
|
||||
id: dragArea_groupe // Zone correspondant à un seul bouton (on est dans le Delegate)
|
||||
|
||||
width: grille_groupes.width
|
||||
height: grille_groupes.height / nombre_groupes_affichees_sur_une_colonne
|
||||
|
||||
property bool bouton_appuye: false // On ne peut pas utiliser la propriété globale "deplacement_en_cours" car il faut une propriété par délégué
|
||||
|
||||
pressAndHoldInterval: 500; // Temporise avant de passer en mode "déplacement"
|
||||
|
||||
drag.target: bouton_appuye ? contenu_bouton_groupe : undefined
|
||||
drag.axis: Drag.YAxis // On ne se déplace que sur l'axe Y
|
||||
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
mise_a_jour_ordre();
|
||||
id_groupe = modele_liste_groupes.get(index).id;
|
||||
mise_a_jour_liste_groupes();
|
||||
mise_a_jour_liste_elements_groupe(id_groupe);
|
||||
}
|
||||
onDoubleClicked: {
|
||||
shipheart_clic();
|
||||
stackView.push("config_groupe_elements.qml", {"table": type_source_groupe, "id_groupe":modele_liste_groupes.get(index).id})
|
||||
}
|
||||
|
||||
onPressAndHold: {
|
||||
shipheart_clic();
|
||||
bouton_appuye = true // Indication (au niveau du bouton seul) du début de l'appui long donc du déplacement
|
||||
grille_groupes.deplacement_en_cours = true // Indication (au niveau de ListView) du début du déplacement
|
||||
grille_groupes.save_current_index = grille_groupes.currentIndex; // Sauvegarde du CurrentIndex au début du déplacement
|
||||
}
|
||||
onReleased: {
|
||||
bouton_appuye = false // Indication (au niveau du bouton seul) de la fin de l'appui long donc du déplacement
|
||||
grille_groupes.deplacement_en_cours = false // Indication (au niveau de ListView) de la fin du déplacement
|
||||
grille_groupes.currentIndex = grille_groupes.save_current_index; // Restitution de la valeur initiale du CurrentIndex (a priori, pas nécessaire car mis à jour au fur et à mesure des changements dans "onCurrentIndexChanged")
|
||||
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: contenu_bouton_groupe
|
||||
|
||||
anchors {
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
width: dragArea_groupe.width - 10
|
||||
height: dragArea_groupe.height - 10
|
||||
radius: shipheart_rayon_bouton
|
||||
color: (id_groupe === model.id) ? shipheart_couleur_fond_bouton_actif : shipheart_couleur_fond_bouton // SDIR #245
|
||||
opacity: dragArea_groupe.bouton_appuye ? 0.6 : 1.0
|
||||
|
||||
Text {
|
||||
anchors.verticalCenter: contenu_bouton_groupe.verticalCenter
|
||||
anchors.left: contenu_bouton_groupe.left
|
||||
leftPadding: 20
|
||||
rightPadding: 20
|
||||
text: model.nom
|
||||
color: couleur_blanc_casse
|
||||
font.pixelSize: 18
|
||||
}
|
||||
|
||||
Drag.active: dragArea_groupe.bouton_appuye
|
||||
Drag.source: dragArea_groupe
|
||||
Drag.hotSpot.x: width / 2
|
||||
Drag.hotSpot.y: height / 2
|
||||
|
||||
states: State{
|
||||
when: dragArea_groupe.bouton_appuye
|
||||
ParentChange {
|
||||
target: contenu_bouton_groupe
|
||||
parent: grille_groupes
|
||||
}
|
||||
AnchorChanges {
|
||||
target: contenu_bouton_groupe
|
||||
anchors { // Necessaire pour autoriser le mouvement
|
||||
horizontalCenter: undefined
|
||||
verticalCenter: undefined
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DropArea {
|
||||
anchors.fill: parent
|
||||
onEntered: {
|
||||
|
||||
if (drag.source.DelegateModel.itemsIndex !== dragArea_groupe.DelegateModel.itemsIndex)
|
||||
{
|
||||
//console.log("\tMouvement de Source index = " + drag.source.DelegateModel.itemsIndex + " vers Dest index = " + dragArea.DelegateModel.itemsIndex)
|
||||
modele_liste_groupes.move(drag.source.DelegateModel.itemsIndex, dragArea_groupe.DelegateModel.itemsIndex, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
footer: Rectangle { // Ce premier rectangle sert juste à créer un espace un peu plus grand pour le bouton '+' et le décaler de 'spacing' vers le bas...
|
||||
width: grille_groupes.width
|
||||
height: grille_groupes.height / nombre_groupes_affichees_sur_une_colonne
|
||||
color: "transparent"
|
||||
|
||||
Rectangle { // c'est le bouton proprement dit...
|
||||
id: bouton_footer_plus
|
||||
width: parent.width - 10
|
||||
height: parent.height - 10
|
||||
x: 5
|
||||
color: shipheart_couleur_fond_bouton
|
||||
radius: shipheart_rayon_bouton
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
Text {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
text: "+"
|
||||
font.pixelSize: 40
|
||||
font.bold: true
|
||||
color: couleur_gris_moyen
|
||||
}
|
||||
MouseArea{
|
||||
anchors.fill : parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
stackView.push("config_groupe_elements.qml", {"table": type_source_groupe, "id_groupe":0})
|
||||
}
|
||||
}
|
||||
}
|
||||
Rectangle { // Texte d'info en-dessous du '+'
|
||||
width: parent.width - 10
|
||||
height: parent.height - 10
|
||||
x: 5
|
||||
y: bouton_footer_plus.height
|
||||
color: "transparent"
|
||||
anchors.top: parent.bottom
|
||||
anchors.topMargin: 30
|
||||
Text {
|
||||
anchors.top: parent.top
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
font.pixelSize: 12
|
||||
color: couleur_gris_moyen
|
||||
text: qsTr("Pour déplacer un groupe, le maintenir appuyé puis le faire glisser.<br />Pour modifier ou supprimer un groupe, double-cliquer sur le groupe.<br />Pour ajouter un groupe, cliquer sur '+'.<br /><br />Note : si un seul groupe, aucun onglet n'est affiché sur la page concernée...")
|
||||
}
|
||||
}
|
||||
|
||||
} // Fin de footer
|
||||
|
||||
ListModel {
|
||||
id: modele_liste_groupes
|
||||
}
|
||||
|
||||
onCurrentIndexChanged: {
|
||||
if (grille_groupes.deplacement_en_cours === false)
|
||||
{
|
||||
// grille_modules_physiques.positionViewAtIndex(currentIndex, ListView.Beginning); // Permet de faire défiler la liste des modules physiques "en face" des modules configurés. Mais uniquement en dehors de déplacements puisque, pendant les déplacements, on force CurrentIndex à rester fixe.
|
||||
}
|
||||
else
|
||||
{
|
||||
grille_groupes.currentIndex = grille_groupes.save_current_index; // Permet de compenser les changements de CurrentIndex 'imposés' par le ListView. Notamment lors des déplacements en début et fin de liste.
|
||||
}
|
||||
}
|
||||
|
||||
} // Fin de Listview des Groupes
|
||||
|
||||
|
||||
// Texte si liste de groupes est vide :
|
||||
Label {
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Qt.AlignHCenter
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
visible: parent.count === 0
|
||||
text: texte_aucun_groupe
|
||||
color: couleur_rouge_transparent
|
||||
font.pixelSize: 15
|
||||
font.bold: true
|
||||
wrapMode: Label.Wrap
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Ligne verticale de séparation entre groupes et éléments du groupe :
|
||||
Rectangle {
|
||||
x: zone_affichage_groupes.width + (espace_zones/2)
|
||||
y: 0
|
||||
width: 3
|
||||
height: affichage_hauteur_utile
|
||||
color: couleur_gris_tres_pale_transparent
|
||||
visible: flag_affichage_zone_groupe
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// Liste des éléments du groupe :
|
||||
Rectangle {
|
||||
id: zone_affichage_elements
|
||||
x: flag_affichage_zone_groupe ? (zone_affichage_groupes.width + espace_zones) : 0
|
||||
y: 0
|
||||
width: flag_affichage_zone_groupe ? (shipheart_largeur_page * (1 - pourcentage_largeur_zone_groupes)) - (espace_zones / 2) : shipheart_largeur_page
|
||||
height: affichage_hauteur_utile
|
||||
color: "transparent"
|
||||
|
||||
GridView {
|
||||
id: grille_elements
|
||||
|
||||
property int save_current_index: 0 // Permet de garder le Current_index du début du déplacement et de compenser les changements qui sont fait automatiquement, notamment en début et fin de liste. Le principe est qu'une fois le mouvement déclenché, ON NE CHANGE PAS de CurrentIndex !!
|
||||
|
||||
anchors.fill: parent
|
||||
cellWidth: (width / nombre_colonnes_affichage)
|
||||
cellHeight: parent.height / nombre_elements_affichees_sur_une_colonne
|
||||
|
||||
displaced: Transition { // Gère la transition lors d'un déplacement
|
||||
NumberAnimation{
|
||||
properties: "x,y" // Ici, on devrait pouvoir limiter à Y
|
||||
duration: 500 // Vitesse à laquelle se déplacent les boutons lorsqu'on les déplace
|
||||
}
|
||||
}
|
||||
|
||||
model: modele_liste_elements
|
||||
delegate: bouton_element
|
||||
|
||||
Component {
|
||||
id: bouton_element
|
||||
|
||||
MouseArea {
|
||||
id: dragArea_element // Zone correspondant à un seul bouton (on est dans le Delegate)
|
||||
|
||||
property bool bouton_appuye: false // On ne peut pas utiliser la propriété globale "deplacement_en_cours" car il faut une propriété par délégué
|
||||
|
||||
width: grille_elements.cellWidth
|
||||
height: grille_elements.cellHeight
|
||||
|
||||
pressAndHoldInterval: 500; // Temporise avant de passer en mode "déplacement"
|
||||
|
||||
drag.target: bouton_appuye ? contenu_bouton_element : undefined
|
||||
drag.axis: Drag.XandYAxis // On se déplace sur les 2 axes
|
||||
|
||||
onPressAndHold: {
|
||||
bouton_appuye = true // Indication (au niveau du bouton seul) du début de l'appui long donc du déplacement
|
||||
grille_elements.save_current_index = grille_elements.currentIndex; // Sauvegarde du CurrentIndex au début du déplacement
|
||||
}
|
||||
onReleased: {
|
||||
bouton_appuye = false // Indication (au niveau du bouton seul) de la fin de l'appui long donc du déplacement
|
||||
grille_elements.currentIndex = grille_elements.save_current_index; // Restitution de la valeur initiale du CurrentIndex (a priori, pas nécessaire car mis à jour au fur et à mesure des changements dans "onCurrentIndexChanged")
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: contenu_bouton_element
|
||||
|
||||
anchors {
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
width: dragArea_element.width - 10
|
||||
height: dragArea_element.height - 10
|
||||
radius: shipheart_rayon_bouton
|
||||
color: shipheart_couleur_fond_bouton
|
||||
opacity: dragArea_element.bouton_appuye ? 0.6 : 1.0
|
||||
|
||||
Text {
|
||||
anchors.verticalCenter: contenu_bouton_element.verticalCenter
|
||||
anchors.left: contenu_bouton_element.left
|
||||
leftPadding: 20
|
||||
rightPadding: 20
|
||||
text: model.nom
|
||||
color: couleur_blanc_casse
|
||||
font.pixelSize: 18
|
||||
}
|
||||
|
||||
Drag.active: dragArea_element.bouton_appuye
|
||||
Drag.source: dragArea_element
|
||||
Drag.hotSpot.x: width / 2
|
||||
Drag.hotSpot.y: height / 2
|
||||
|
||||
states: State{
|
||||
when: dragArea_element.bouton_appuye
|
||||
ParentChange {
|
||||
target: contenu_bouton_element
|
||||
parent: grille_elements
|
||||
}
|
||||
AnchorChanges {
|
||||
target: contenu_bouton_element
|
||||
anchors { // Necessaire pour autoriser le mouvement
|
||||
horizontalCenter: undefined
|
||||
verticalCenter: undefined
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DropArea {
|
||||
anchors.fill: parent
|
||||
onEntered: {
|
||||
if (drag.source.DelegateModel.itemsIndex !== dragArea_element.DelegateModel.itemsIndex)
|
||||
{
|
||||
//console.log("\tMouvement de Source index = " + drag.source.DelegateModel.itemsIndex + " vers Dest index = " + dragArea_element.DelegateModel.itemsIndex)
|
||||
modele_liste_elements.move(drag.source.DelegateModel.itemsIndex, dragArea_element.DelegateModel.itemsIndex, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ListModel {
|
||||
id: modele_liste_elements
|
||||
}
|
||||
|
||||
onCurrentIndexChanged: {
|
||||
grille_elements.currentIndex = grille_elements.save_current_index; // Permet de compenser les changements de CurrentIndex 'imposés' par le ListView. Notamment lors des déplacements en début et fin de liste.
|
||||
}
|
||||
|
||||
} // Fin de Gridview
|
||||
|
||||
// Texte si groupe vide :
|
||||
Label {
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Qt.AlignHCenter
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
visible: modele_liste_elements.count === 0
|
||||
text: texte_aucun_element
|
||||
color: couleur_rouge_transparent
|
||||
font.pixelSize: 15
|
||||
font.bold: true
|
||||
wrapMode: Label.Wrap
|
||||
}
|
||||
|
||||
} // Fin de zone affichage elements
|
||||
|
||||
} // Fin de Ecran Principal
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// 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 - (2 * parent.padding)
|
||||
height: shipheart_hauteur_bandeau_bas - parent.topPadding - parent.bottomPadding;
|
||||
radius: 5
|
||||
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();
|
||||
mise_a_jour_ordre();
|
||||
stackView.pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 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 nb;
|
||||
|
||||
|
||||
//console.log("Table = "+ table);
|
||||
|
||||
// Paramètres par défaut :
|
||||
flag_affichage_zone_groupe = false;
|
||||
nombre_colonnes_affichage = 1;
|
||||
nombre_elements_affichees_sur_une_colonne = 8;
|
||||
espace_lignes_affichage = 8;
|
||||
espace_colonnes_affichage = 300;
|
||||
type_source_groupe = shipheart_type_source_inconnu;
|
||||
texte_aucun_groupe = qsTr("Aucun groupe n'est actuellement configuré...");
|
||||
texte_aucun_element = qsTr("Aucun élément n'est actuellement configuré...");
|
||||
|
||||
// Paramètres spécifiques :
|
||||
switch(table)
|
||||
{
|
||||
//----------------------------------------------------------------------------------
|
||||
case "TB_Batteries":
|
||||
nombre_colonnes_affichage = 1;
|
||||
espace_colonnes_affichage = 20;
|
||||
texte_aucun_groupe = qsTr("Aucun groupe de batteries n'est actuellement configuré...");
|
||||
texte_aucun_element = qsTr("Aucune batterie n'est actuellement affectée à ce groupe...");
|
||||
texte_titre = qsTr("Affichage des batteries sur la page d'accueil");
|
||||
type_source_groupe = shipheart_type_source_batteries;
|
||||
break;
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
case "TB_Capteurs":
|
||||
nombre_colonnes_affichage = 3;
|
||||
espace_colonnes_affichage = 20;
|
||||
texte_aucun_groupe = qsTr("Aucun groupe de capteurs n'est actuellement configuré...");
|
||||
texte_aucun_element = qsTr("Aucun capteur n'est actuellement affecté ce groupe...");
|
||||
texte_titre = qsTr("Affichage des capteurs sur la page d'accueil");
|
||||
type_source_groupe = shipheart_type_source_capteurs;
|
||||
break;
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
case "TB_Circuits":
|
||||
nombre_colonnes_affichage = 2;
|
||||
espace_colonnes_affichage = 80;
|
||||
texte_aucun_groupe = qsTr("Aucun groupe de circuits n'est actuellement configuré...");
|
||||
texte_aucun_element = qsTr("Aucun circuit n'est actuellement affecté à ce groupe...");
|
||||
texte_titre = qsTr("Affichage des circuits sur la page d'accueil");
|
||||
type_source_groupe = shipheart_type_source_circuits;
|
||||
break;
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
case "TB_Reservoirs":
|
||||
nombre_colonnes_affichage = 1;
|
||||
nombre_elements_affichees_sur_une_colonne = 8;
|
||||
espace_colonnes_affichage = 20;
|
||||
texte_aucun_groupe = qsTr("Aucun groupe de réservoirs n'est actuellement configuré...");
|
||||
texte_aucun_element = qsTr("Aucun réservoir n'est actuellement affecté à ce groupe...");
|
||||
texte_titre = qsTr("Affichage des réservoirs sur la page d'accueil");
|
||||
type_source_groupe = shipheart_type_source_reservoirs;
|
||||
break;
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
default:
|
||||
}
|
||||
|
||||
// Traitement spécifique quand on traite les groupes :
|
||||
if (type_source_groupe !== shipheart_type_source_inconnu)
|
||||
{
|
||||
flag_affichage_zone_groupe = true; // Plus facile pour gérer l'affichage
|
||||
mise_a_jour_liste_groupes(); // Après la rcherche du premier groupe sinon il n'est pas sélectionné...
|
||||
}
|
||||
|
||||
mise_a_jour_liste_elements_groupe(id_groupe);
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================================================
|
||||
// Mise à jour des groupes
|
||||
//=============================================================================================================
|
||||
function mise_a_jour_liste_groupes()
|
||||
{
|
||||
var req, res, nb;
|
||||
var i;
|
||||
var actif;
|
||||
|
||||
//console.log("Table groupe = " +table_groupe);
|
||||
|
||||
modele_liste_groupes.clear();
|
||||
|
||||
|
||||
// Vérif que l'id froupe existe bien :
|
||||
req = 'SELECT Cle_primaire FROM TB_Familles WHERE Type_source=' + type_source_groupe + ' AND Cle_primaire=' + id_groupe + ' ';
|
||||
//console.log("Requête = [ " + req + "; ]")
|
||||
nb = bdd.requete(req);
|
||||
if (nb === 0) id_groupe = 0; // Sinon, on positionne l'ID à 0 pour que la première valeur soit enregistrée dans la boucle suivante.
|
||||
|
||||
|
||||
// Recherche des groupes :
|
||||
if (type_source_groupe !== shipheart_type_source_inconnu)
|
||||
{
|
||||
req = 'SELECT Nom, Cle_primaire, Priorite_affichage FROM TB_Familles WHERE Type_source=' + type_source_groupe + ' ORDER BY Priorite_affichage';
|
||||
//console.log("Requête = [ " + req + "; ]")
|
||||
nb = bdd.requete(req);
|
||||
|
||||
for (i = 0; i < nb; i ++)
|
||||
{
|
||||
res = bdd.lecture_ligne();
|
||||
if (!res.isEmpty)
|
||||
{
|
||||
if (id_groupe === 0) id_groupe = Number(res[1]); // Utile en retour de suppression d'un groupe qui n'est plus disponible => on prend le premier
|
||||
|
||||
if (id_groupe === Number(res[1])) actif = true;
|
||||
else actif = false;
|
||||
|
||||
modele_liste_groupes.append({"nom": res[0], "id": Number(res[1]), "actif": actif});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================================================
|
||||
// Mise à jour des éléments d'un groupe
|
||||
//=============================================================================================================
|
||||
function mise_a_jour_liste_elements_groupe(id_groupe)
|
||||
{
|
||||
var req, res, nb;
|
||||
var i;
|
||||
var filtre;
|
||||
|
||||
modele_liste_elements.clear();
|
||||
|
||||
// Filtre de sélection en fonction du fait qu'on gère les groupes ou pas :
|
||||
if (type_source_groupe !== shipheart_type_source_inconnu) filtre = ' AND ID_Famille=' + id_groupe + ' ';
|
||||
else filtre = "";
|
||||
|
||||
// Récupération des données correspondant au type dans la BDD + mise à jour du modèle :
|
||||
req = 'SELECT Nom, Cle_primaire FROM TB_Familles WHERE Type_source=' + type_source_groupe + ' ' + filtre + ' AND Priorite_affichage_accueil>0 ORDER BY Priorite_affichage_accueil';
|
||||
//console.log("Requête = [ " + req + "; ]")
|
||||
nb = bdd.requete(req);
|
||||
|
||||
for (i = 0; i < nb; i ++)
|
||||
{
|
||||
res = bdd.lecture_ligne();
|
||||
if (!res.isEmpty)
|
||||
{
|
||||
modele_liste_elements.append({"nom": res[0], "id_element": Number(res[1])});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================================================
|
||||
// Enregistrement des modifications dans la BDD
|
||||
//=============================================================================================================
|
||||
function mise_a_jour_ordre()
|
||||
{
|
||||
var req, res;
|
||||
var i;
|
||||
var nb;
|
||||
|
||||
//------------------------------------------------------------
|
||||
// Mise à jour de l'ordre d'affichage des familles (groupes) :
|
||||
if (type_source_groupe !== shipheart_type_source_inconnu)
|
||||
{
|
||||
for(i = 0; i < modele_liste_groupes.count; i++)
|
||||
{
|
||||
if (modele_liste_groupes.get(i).id === 0) continue; // C'est le groupe par défaut qui n'est pas stocké dans la BDD...
|
||||
|
||||
req = 'UPDATE TB_Familles SET Priorite_affichage=' + (i+1) + ' WHERE Type_source=' + type_source_groupe + ' AND Cle_primaire=' + modele_liste_groupes.get(i).id + ' ';
|
||||
//console.log("Requête = " + req)
|
||||
bdd.requete_unique(req);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Mise à jour de l'ordre des éléments dans le groupe actuellement affiché :
|
||||
for(i = 0; i < modele_liste_elements.count; i++)
|
||||
{
|
||||
// Important : il faut bien commencer la numérotation à 1 car si 0 (ou négatif), l'élément est considéré comme masqué sur la page d'accueil (il faut alors le démasquer dans sa page de config).
|
||||
req = 'UPDATE ' + table + ' SET Priorite_affichage_accueil=' + (i+1) + ' WHERE Cle_primaire=' + modele_liste_elements.get(i).id_element + ' ';
|
||||
//console.log("Requête = [ " + req + "; ]")
|
||||
bdd.requete_unique(req);
|
||||
}
|
||||
|
||||
// NB : il n'est pas utile de demander une synchro (2) car les éléments modifiés ne concernent que des sujets d'affichage qui n'influent en rien le fonctionnement en dehors de QT.
|
||||
}
|
||||
}
|
||||
+686
@@ -0,0 +1,686 @@
|
||||
//========================================================================================================================================================================
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,856 @@
|
||||
//========================================================================================================================================================================
|
||||
// CONFIG_PAGE_EDITION.QML
|
||||
// Ce fichier traite la configuration d'une page personnalisée.
|
||||
// La page est appelée depuis la page CONFIG_PAGE, en cliquant sur le bouton "Edition"
|
||||
//========================================================================================================================================================================
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
import QtQml.Models 2.1
|
||||
|
||||
import qt.koriolan.shipheart 1.0
|
||||
import"fonctions.js" as Fonctions
|
||||
|
||||
|
||||
Shipheart_page {
|
||||
id: page_config_page_edition
|
||||
|
||||
// Mis en forme :
|
||||
readonly property double pourcentage_largeur_colonne_gauche: 0.20
|
||||
readonly property double pourcentage_bandeau_bas_largeur_zone_retour: 1.0
|
||||
readonly property double espace_colonnes_principales: 20
|
||||
|
||||
readonly property double pourcentage_hauteur_ligne_haut: 0.75
|
||||
readonly property double affichage_hauteur_utile: shipheart_hauteur_page - shipheart_hauteur_bandeau_haut - shipheart_hauteur_bandeau_bas
|
||||
readonly property double espace_lignes_principales: 20
|
||||
|
||||
readonly property int nombre_lignes_points_visibles: 6
|
||||
readonly property int diametre_points_deplacables: 100
|
||||
|
||||
readonly property int periode_init_raffraichissement_parametres: 1 // En ms
|
||||
readonly property int periode_raffraichissement_parametres: 1000 // En ms
|
||||
|
||||
|
||||
// Affichage :
|
||||
property bool flag_aucun_points: true
|
||||
|
||||
property bool flag_init: true // Permet de bloquer certains affichage tant qu el'init n'est pas terminée
|
||||
property bool flag_alignement_demande: false
|
||||
property bool flag_nouvelles_valeurs: false
|
||||
property bool flag_affichage_ajout_point: true
|
||||
|
||||
|
||||
// Données :
|
||||
property int id_page: 0
|
||||
property string nom_page: ""
|
||||
property string fichier: ""
|
||||
property int opacite: 0
|
||||
property int taille: 0
|
||||
property int offset_x: 0
|
||||
property int offset_y: 0
|
||||
property string chaine_points: ""
|
||||
property int nb_points: 0
|
||||
property int index_point_en_cours: -1
|
||||
|
||||
property double ecart_maxi_detectable: 0.0001
|
||||
|
||||
|
||||
// Modèles :
|
||||
// Note : les modèles chargés dans 'main.qml' n'ont pas à être rechargés dans les pages suivantes
|
||||
|
||||
|
||||
//===========================================================
|
||||
// Signaux :
|
||||
//===========================================================
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Connexion au signaux de pages créées depuis celle-ci :
|
||||
Connections {
|
||||
target: stackView.currentItem // Pointe sur la page active de StackView (qui sera créée... bientôt, ou pas)
|
||||
ignoreUnknownSignals: true // Permet de ne pas déclencher d'erreur AVANT que la page ne soit créée par un StackView.push()
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Fonction d'enregistrement des nouvelles data provenant de 'config_page' :
|
||||
// ----------------------------------------------------------------------------
|
||||
function onEnregistrer_config_page(new_id_page)
|
||||
{
|
||||
//console.log("Mise à jour de l'ID de la page : new_id_page = "+new_id_page);
|
||||
|
||||
id_page = new_id_page;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------
|
||||
// Fonction d'enregistrement des nouvelles data provenant de 'config_page_point' :
|
||||
// ---------------------------------------------------------------------------------
|
||||
function onEnregistrer_config_page_point(new_flag_point_existant, new_type_source, new_id_source, new_type_point, new_taille_point)
|
||||
{
|
||||
//console.log("index_point_en_cours = " + index_point_en_cours + " | Mise à jour des nouvelles valeur : new_flag_point_existant = " + new_flag_point_existant + ", new_type_source = " + new_type_source + ", new_id_source = " + new_id_source + ", new_type_point = " + new_type_point + ", new_taille_point = " + new_taille_point);
|
||||
|
||||
//----------------------------------------
|
||||
// Cas d'une mise à jour :
|
||||
if (index_point_en_cours !== -1) // Le point existait avant l'appel :
|
||||
{
|
||||
if (new_flag_point_existant) // Il existe toujours = mise à jour des données du point sélectionné :
|
||||
{
|
||||
modele_liste_points.set(index_point_en_cours, {
|
||||
"type_source": new_type_source,
|
||||
"id_source": new_id_source,
|
||||
"type_point": new_type_point,
|
||||
"taille_point": new_taille_point } );
|
||||
}
|
||||
else // Il n'existe plus = suppression du point :
|
||||
{
|
||||
modele_liste_points.remove(index_point_en_cours, 1);
|
||||
index_point_en_cours = -1;
|
||||
}
|
||||
}
|
||||
//----------------------------------------
|
||||
// Cas de l'ajout d'un point :
|
||||
else // Le point n'existait pas avant l'appel :
|
||||
{
|
||||
if (new_flag_point_existant) // Il existe maintenant = insertion du nouveau point :
|
||||
{
|
||||
modele_liste_points.append({
|
||||
"validite": 1,
|
||||
"type_source": new_type_source,
|
||||
"id_source": new_id_source,
|
||||
"x": -0.5, // Insertion sur le bord gauche...
|
||||
"y": -0.5, // .... et en haut de la page pour être visible
|
||||
"x_initial": -0.5,
|
||||
"y_initial": -0.5,
|
||||
"type_point": new_type_point,
|
||||
"taille_point": new_taille_point,
|
||||
"actif": false,
|
||||
"changed": true });
|
||||
|
||||
flag_alignement_demande = true // Permet de déclencher un traitement au niveau du repeater pour mettre à jour la position du rectangle/cercle.
|
||||
flag_alignement_demande = false // La RAZ ne peut pas se faire dans le repeater. Donc on la fait ici car le front montant a déjà été détecté par le signe de changement.
|
||||
}
|
||||
else ; // Il n'existe toujours pas (création abandonnée)
|
||||
}
|
||||
enregistrer_points(); // Mémorise dans la BDD les éventuels changements faits dans 'config_page_point'. Obligatoire car, ensuite, une 'init_page()' sera fait et rechargera les points depuis la BDD... (sans ça, les modifs faites sont perdues !)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//===========================================================
|
||||
// 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
|
||||
{
|
||||
// Recherche s'il y a au moins un point qui a été modifié :
|
||||
let flag = false;
|
||||
for(let i = 0; i < modele_liste_points.count; i++) {
|
||||
if (modele_liste_points.get(i).changed) { flag = true; break; }
|
||||
}
|
||||
flag_nouvelles_valeurs = flag;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================
|
||||
// Lorsque la page est sur le point d'être affichée dans la pile :
|
||||
//===========================================================
|
||||
StackView.onActivating: {
|
||||
if (id_page !== 0) init_page(); // Permet que lors du retour sur la page, l'état des différentes variables soit mise à jour avant l'affichage proprement dit. Y compris lors de l'ouverture initiale...
|
||||
}
|
||||
|
||||
//===========================================================
|
||||
// Lorsque la page est affichée dans la pile :
|
||||
//===========================================================
|
||||
StackView.onActivated: {
|
||||
if (id_page === 0) init_page(); // Permet, lorsque l'ouverture est terminée, de rediriger si besoin vers una autre page ('config_page' lors de la création)
|
||||
}
|
||||
|
||||
// Titre de la page :
|
||||
Shipheart_titre_1 {titre: qsTr("Edition de la page [%1]").arg(nom_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)
|
||||
clip:true // Evite que le ListView suivant ne puisse dépasser du rectangle
|
||||
color: "transparent"
|
||||
|
||||
ListModel {
|
||||
id: modele_liste_points
|
||||
}
|
||||
|
||||
ListView {
|
||||
id: liste_points
|
||||
anchors.fill: parent
|
||||
model: modele_liste_points
|
||||
spacing: 5
|
||||
snapMode: GridView.SnapToRow // L'arret de l'affichage se fera sur une rangée entière
|
||||
highlightMoveDuration: 600 // défini la vitesse à laquelle on va se déplacer sur l'item sélectionné (utilisé avec l'affectation du 'currentIndex' quand on touche un rectangle/cercle)
|
||||
highlightMoveVelocity: -1 // -1 si le précedent est actif et réciproquement
|
||||
footerPositioning: ListView.InlineFooter // Positionne le footer à la fin des enregistrements (pratique pour le bouton MORE...)
|
||||
visible: flag_init ? false : true;
|
||||
opacity: Math.max(0.1, 1.0 - (Math.abs(verticalOvershoot) *3 / height)) // Permet de rendre transparent le contenu lorsqu'on dépasse la zone de défilement
|
||||
delegate: Rectangle {
|
||||
height: ((liste_points.height - ((nombre_lignes_points_visibles - 1) * liste_points.spacing)) / nombre_lignes_points_visibles)
|
||||
width:zone_affichage_haut_gauche.width
|
||||
color: model.actif ? shipheart_couleur_fond_bouton_actif : shipheart_couleur_fond_bouton
|
||||
radius: shipheart_rayon_bouton
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// N° du point :
|
||||
Text {
|
||||
id: no_point // Premier élément du bouton : n° de ligne
|
||||
width: parent.width * 0.1;
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
horizontalAlignment: Text.AlignRight
|
||||
rightPadding: 5
|
||||
text: index + 1
|
||||
font.pixelSize: 18
|
||||
font.bold: true
|
||||
color: couleur_blanc_casse
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Icone du point :
|
||||
Rectangle { // Le passage par un rectangle avant l'image permet de centrer l'image sur le rectangle et pas juste caler les images à gaiche (elles n'ont pas la même largeur donc elles n'étaient pas centrées les unes par rapport aux autres)
|
||||
id: icone_point
|
||||
width: parent.width * 0.1;
|
||||
height: parent.height
|
||||
x: no_point.width
|
||||
color: "transparent"
|
||||
|
||||
Image {
|
||||
source: "/images/" + model.icone
|
||||
sourceSize.height: parent.height * 0.4
|
||||
sourceSize.width: parent.width
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
visible: (model.icone !== "")
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Nom du point :
|
||||
Text {
|
||||
id: nom_point
|
||||
x: no_point.width + icone_point.width;
|
||||
width: parent.width - no_point.width - icone_point.width;
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
leftPadding: 5
|
||||
text: model.nom
|
||||
font.pixelSize: 15
|
||||
color: couleur_blanc_casse
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Triangle orange de modification :
|
||||
Image {
|
||||
id: image_changed // Affichage du coin inférieur-droit en orange si le point a été modifié
|
||||
source: "/images/coin_bas_droite_orange.png"
|
||||
sourceSize.height: 20
|
||||
anchors {
|
||||
bottom: parent.bottom
|
||||
right: parent.right
|
||||
}
|
||||
visible: model.changed
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
MouseArea{
|
||||
anchors.fill : parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
index_point_en_cours = index;
|
||||
stackView.push("config_page_point.qml", {
|
||||
"flag_point_existant" : true,
|
||||
"type_source": model.type_source,
|
||||
"id_source": model.id_source,
|
||||
"type_point": model.type_point,
|
||||
"taille_point": model.taille_point })
|
||||
}
|
||||
pressAndHoldInterval: shipheart_mouse_press_and_hold_interval_long;
|
||||
onPressAndHold: {
|
||||
shipheart_clic();
|
||||
|
||||
// Appui long = Remise en position initiale du point :
|
||||
modele_liste_points.setProperty(index, "x", model.x_initial) // Recopie des coordonnées originelles dans les coordonnées actuelles
|
||||
modele_liste_points.setProperty(index, "y", model.y_initial)
|
||||
flag_alignement_demande = true // Permet de déclencher un traitement au nivea du repeater pour mettre à jour la position du rectangle/cercle.
|
||||
flag_alignement_demande = false // La RAZ ne peut pas se faire dans le repeater. Donc on la fait ici car le front montant a déjà été détecté par le signe de changement.
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
footer: Rectangle { // Ce premier rectangle sert juste à créer un espace un peu plu sgrand pour le bouton '+' et le décaler de 'spacing' vers le bas...
|
||||
height: ((liste_points.height - ((nombre_lignes_points_visibles - 1) * liste_points.spacing)) / nombre_lignes_points_visibles) + liste_points.spacing
|
||||
width:parent.width
|
||||
color: "transparent"
|
||||
visible: flag_affichage_ajout_point
|
||||
|
||||
Rectangle { // c'est le bouton proprement dit...
|
||||
height: ((liste_points.height - ((nombre_lignes_points_visibles - 1) * liste_points.spacing)) / nombre_lignes_points_visibles)
|
||||
width:parent.width
|
||||
color: shipheart_couleur_fond_bouton
|
||||
radius: shipheart_rayon_bouton
|
||||
anchors.bottom: parent.bottom
|
||||
Text {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
text: "+"
|
||||
font.pixelSize: 40
|
||||
font.bold: true
|
||||
color: couleur_gris_moyen
|
||||
}
|
||||
MouseArea{
|
||||
anchors.fill : parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
index_point_en_cours = -1;
|
||||
stackView.push("config_page_point.qml", {"flag_point_existant" : false, "type_source": 0, "id_source": 0, "type_point": 0 })
|
||||
}
|
||||
onPressed: shipheart_clic();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Qt.AlignHCenter
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
visible: parent.count === 0
|
||||
text: qsTr("Aucun équipement n'est configuré sur cette page pour le moment...")
|
||||
color: couleur_rouge_transparent
|
||||
font.pixelSize: 15
|
||||
font.bold: true
|
||||
wrapMode: Label.Wrap
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Ecran Bas - Gauche :
|
||||
//-------------------------------------------------------
|
||||
Rectangle {
|
||||
id: zone_affichage_bas_gauche
|
||||
x: 0
|
||||
y: shipheart_hauteur_bandeau_haut + zone_affichage_haut_gauche.height + espace_lignes_principales;
|
||||
width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2)
|
||||
height: (affichage_hauteur_utile * (1 - pourcentage_hauteur_ligne_haut)) - (espace_lignes_principales * 3 / 2)
|
||||
color: "transparent"
|
||||
|
||||
Column {
|
||||
anchors.fill: parent
|
||||
spacing: 5
|
||||
|
||||
//-----------------------------
|
||||
// Config de la page :
|
||||
//-----------------------------
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: (parent.height/2) - (parent.spacing/2)
|
||||
color: shipheart_couleur_fond_bouton
|
||||
radius: shipheart_rayon_bouton
|
||||
Text {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
font.pixelSize: 20
|
||||
text: qsTr("Page")
|
||||
color: couleur_blanc_casse
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
stackView.push("config_page.qml", {"id_page": id_page})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------
|
||||
// Bouton Enregistrer/créer :
|
||||
//-----------------------------
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: (parent.height/2) - (parent.spacing/2)
|
||||
color: shipheart_couleur_fond_bouton
|
||||
radius: shipheart_rayon_bouton
|
||||
Text {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
font.pixelSize: 20
|
||||
text: qsTr("Enregistrer")
|
||||
color: flag_nouvelles_valeurs ? couleur_blanc_casse : couleur_gris_fonce
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
if (flag_nouvelles_valeurs) enregistrer_points();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Ecran Droite :
|
||||
//-------------------------------------------------------
|
||||
Rectangle {
|
||||
id: zone_affichage_droite
|
||||
x: zone_affichage_haut_gauche.width + espace_colonnes_principales
|
||||
y: shipheart_hauteur_bandeau_haut + ((affichage_hauteur_utile - height) / 2);
|
||||
width: (shipheart_largeur_page * (1 - pourcentage_largeur_colonne_gauche)) - (espace_colonnes_principales / 2)
|
||||
height: (affichage_hauteur_utile - espace_lignes_principales) * (zone_affichage_droite.width / shipheart_largeur_page) // Permet d'avoir le même ratio que lors de l'affichage dans 'page_personnalisee.qml'
|
||||
color: "transparent"
|
||||
border.color: couleur_gris_moyen
|
||||
|
||||
//==========================
|
||||
// Image de la silhouette :
|
||||
Image {
|
||||
id: image_silhouette
|
||||
anchors.fill: parent
|
||||
source: (fichier !== "")
|
||||
? "file://" + shipheart_repertoire_config + shipheart_sous_repertoire_images_silhouette + "/" + fichier
|
||||
: ""
|
||||
fillMode: Image.PreserveAspectFit
|
||||
opacity: (opacite / 100)
|
||||
visible: (fichier !== "")
|
||||
}
|
||||
|
||||
//==========================
|
||||
// Points :
|
||||
Repeater {
|
||||
model: modele_liste_points
|
||||
|
||||
Rectangle {
|
||||
id: point_deplacable
|
||||
|
||||
property bool flag_init_point_deplacable: flag_init // Recopie au niveau du delegate du flag général pour pouvoir utiliser onFlag_xxxChanged et déclencher l'appel à une fonction JS une seule fois en fin d'init
|
||||
property bool flag_align_point_deplacable: flag_alignement_demande // Idem lorsqu'une mise à jour directe des coordonnées a été fait (par exemple, dans le menu de gauche, la remise aux conditions initiales d'un point) et qu'il faut aligner le rectangle/cerlce sur ces nouvelles coordonnées.
|
||||
|
||||
radius: diametre_points_deplacables / 2 // Défini dans l'entete
|
||||
width: diametre_points_deplacables // Rectangle => devient cercle
|
||||
height: width
|
||||
color: couleur_bleu_koriolan_tres_transparent
|
||||
|
||||
// Principe de coordonnées X/Y d'un point :
|
||||
// Les valeurs X et Y stockées dans la chaine Points dans la BDD sont des valeurs décimales, calculées
|
||||
// à partir du CENTRE de l'image.
|
||||
// La valeur 0/0 représente donc le centre de l'image, 0.5/0.5 représente le coin en bas à droite de l'image,
|
||||
// le point -0.5/-0.5 le point en haut à gauche et 0.5/0.0, le point sur le bord droit de l'image et au milieu dans le sens vertical.
|
||||
// Important, les valeurs peuvent être supérieures à 0.5 en valeur absolue car le point peut être hors de l'image. Par exemple,
|
||||
// dans le cas d'une image large et peu haute, des points peuvent être posés au-dessus ou au-dessous (et réciproquement).
|
||||
// L'objectif de cette méthode est de pouvoir ensuite afficher la page dans n'importe quelle proportion avec des points
|
||||
// toujours correctement placés sur ou autour de l'image.
|
||||
|
||||
//-----------------------------------------------------
|
||||
// Croix de positionnement :
|
||||
// (actives lorsque le point est en cours de déplacement)
|
||||
Rectangle {
|
||||
y: diametre_points_deplacables / 2
|
||||
width: diametre_points_deplacables
|
||||
height: 1
|
||||
color: couleur_green_yellow
|
||||
visible: model.actif
|
||||
}
|
||||
Rectangle {
|
||||
x: diametre_points_deplacables / 2
|
||||
width: 1
|
||||
height: diametre_points_deplacables
|
||||
color: couleur_green_yellow
|
||||
visible: model.actif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------
|
||||
// Icone :
|
||||
// (remplacée par la croix de positionnement en cours de déplacement)
|
||||
Image {
|
||||
source: "/images/" + shipheart_page_personnalisee_type_point_icones[model.type_source][model.type_point]
|
||||
sourceSize.height: model.taille_point
|
||||
anchors {
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
visible: !model.actif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------
|
||||
// N° du point afin de faire le lien avec l'écran de gauche :
|
||||
Text {
|
||||
id: libelle_point // N° du point dans le modèle (qui est commun à l'écran de gauche et sur les points déplaçables
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
text: (index + 1)
|
||||
font.pixelSize: 20
|
||||
font.weight: Font.Bold
|
||||
color: couleur_blanc_casse
|
||||
}
|
||||
|
||||
//-----------------------------------------------------
|
||||
// Prise en compte des déplacements horizontaux :
|
||||
onXChanged: { // Si le rectangle/cercle a bougé (avec le doigt), on met à jour la valeur de X de 'modèle_liste_points'
|
||||
if (image_silhouette.visible) modele_liste_points.setProperty(index, "x", ((x + (point_deplacable.width / 2) - (zone_affichage_droite.width / 2)) / image_silhouette.paintedWidth) )
|
||||
else modele_liste_points.setProperty(index, "x", ((x + (point_deplacable.width / 2) - (zone_affichage_droite.width / 2)) / zone_affichage_droite.width) )
|
||||
|
||||
if ((Math.abs(model.x - model.x_initial) > ecart_maxi_detectable)
|
||||
|| (Math.abs(model.y - model.y_initial) > ecart_maxi_detectable)) { // On est obligé de tester X et Y à chaque fois car on pourrait dévalider un changed si X est revenu à sa position initiale et pas Y
|
||||
modele_liste_points.setProperty(index, "changed", true);
|
||||
}
|
||||
else modele_liste_points.setProperty(index, "changed", false);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------
|
||||
// Prise en compte des déplacements verticaux :
|
||||
onYChanged: { // Iem pour l'axe Y
|
||||
if (image_silhouette.visible) modele_liste_points.setProperty(index, "y", ((y + (point_deplacable.height / 2) - (zone_affichage_droite.height / 2)) / image_silhouette.paintedHeight) )
|
||||
else modele_liste_points.setProperty(index, "y", ((y + (point_deplacable.height / 2) - (zone_affichage_droite.height / 2)) / zone_affichage_droite.height) )
|
||||
|
||||
if ((Math.abs(model.x - model.x_initial) > ecart_maxi_detectable)
|
||||
|| (Math.abs(model.y - model.y_initial) > ecart_maxi_detectable)) { // On est obligé de tester X et Y à chaque fois car on pourrait dévalider un changed si Y est revenu à sa position initiale et pas X
|
||||
modele_liste_points.setProperty(index, "changed", true);
|
||||
}
|
||||
else modele_liste_points.setProperty(index, "changed", false);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------
|
||||
MouseArea {
|
||||
id: mouse_area_point_deplacable // Zone dragable
|
||||
anchors.fill: parent
|
||||
drag.target: point_deplacable
|
||||
drag.axis: Drag.XAndYAxis
|
||||
drag {
|
||||
// Note : Le 'point' est le coin haut-gauche du rectangle (retaillé en cercle).
|
||||
// Il faut donc décaler les références d'une demi-largeur de rectangle pour que
|
||||
// le centre du cercle arrive aux extrémités attendues...
|
||||
minimumX: 0 - (point_deplacable.width / 2)
|
||||
maximumX: zone_affichage_droite.width - (point_deplacable.width / 2)
|
||||
minimumY: 0 - (point_deplacable.width / 2)
|
||||
maximumY: zone_affichage_droite.height - (point_deplacable.width / 2)
|
||||
}
|
||||
preventStealing: true
|
||||
onPressed: {
|
||||
modele_liste_points.setProperty(index, "actif", true) // Permet d'informer le bouton correpondant sur la liste gauche de passer en "actif"
|
||||
liste_points.currentIndex = index // Permet de ramener le bouton correspondant dans la zone visible du ListView de gauche
|
||||
}
|
||||
onReleased: {
|
||||
modele_liste_points.setProperty(index, "actif", false) // Permet d'informer le bouton correpondant sur la liste gauche de repasser au "repos"
|
||||
}
|
||||
}
|
||||
onFlag_init_point_deplacableChanged: { // Activé en fin d'init : Positionne le rectangle/cercle sur la valeur initiale du modèle.
|
||||
if (image_silhouette.visible)
|
||||
{
|
||||
point_deplacable.x = (model.x * image_silhouette.paintedWidth) + (zone_affichage_droite.width / 2) - (point_deplacable.width / 2)
|
||||
point_deplacable.y = (model.y * image_silhouette.paintedHeight) + (zone_affichage_droite.height / 2) - (point_deplacable.height / 2)
|
||||
}
|
||||
else
|
||||
{
|
||||
point_deplacable.x = (model.x * zone_affichage_droite.width) + (zone_affichage_droite.width / 2) - (point_deplacable.width / 2)
|
||||
point_deplacable.y = (model.y * zone_affichage_droite.height) + (zone_affichage_droite.height / 2) - (point_deplacable.height / 2)
|
||||
}
|
||||
}
|
||||
|
||||
onFlag_align_point_deplacableChanged: {
|
||||
if (flag_alignement_demande) // Permet de limiter le traitement au front montant de 'flag_alignement_demande'
|
||||
{ // PS : ce traitement est fait pour tous les points de repeater, même si la plupart du temps, un seul point a été modifié...
|
||||
if (image_silhouette.visible)
|
||||
{
|
||||
point_deplacable.x = (model.x * image_silhouette.paintedWidth) + (zone_affichage_droite.width / 2) - (point_deplacable.width / 2)
|
||||
point_deplacable.y = (model.y * image_silhouette.paintedHeight) + (zone_affichage_droite.height / 2) - (point_deplacable.height / 2)
|
||||
}
|
||||
else
|
||||
{
|
||||
point_deplacable.x = (model.x * zone_affichage_droite.width) + (zone_affichage_droite.width / 2) - (point_deplacable.width / 2)
|
||||
point_deplacable.y = (model.y * zone_affichage_droite.height) + (zone_affichage_droite.height / 2) - (point_deplacable.height / 2)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// 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 (flag_nouvelles_valeurs) // Si on demande le retour alors que des points ont été modifiés et pas enregistrés :
|
||||
{
|
||||
boite_validation_sortie.imageTitreSource = "/images/attention.png";
|
||||
boite_validation_sortie.message = qsTr("Vous avez effectué des modifications qui n'ont pes été enregistrées<br />Cliquer sur Annuler pour revenir en arrière et les enregistrer.<br />Cliquer sur OK pour sortir sans enregistrer.")
|
||||
boite_validation_sortie.open();
|
||||
}
|
||||
else stackView.pop() // Si retour alors qu'il n'y a aucun point non enregistrés, on sort sans rien demander.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Boite de validation :
|
||||
// NB : il est important que ce composant soit directement
|
||||
// rattaché à la page pour qu'elle s'affiche en plein écran.
|
||||
//-------------------------------------------------------
|
||||
Shipheart_boite_dialogue {
|
||||
id: boite_validation_sortie
|
||||
niveau: 1
|
||||
boutonAnnuler: true
|
||||
onClicked: {
|
||||
switch(bouton)
|
||||
{
|
||||
case shipheart_boite_dialogue_bouton_1: // Si Ok, on sort sans chercher plus loin
|
||||
stackView.pop()
|
||||
break;
|
||||
case shipheart_boite_dialogue_bouton_2: // Si Annuler, on revient sur la page pour que l'on puisse enregistrer.
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 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 nb;
|
||||
|
||||
if (id_page === 0) stackView.push("config_page.qml", {"id_page": 0}); // Lors de la création, on va directement à la config de la page
|
||||
else
|
||||
{
|
||||
flag_nouvelles_valeurs = false;
|
||||
|
||||
|
||||
i = 0;
|
||||
// Récupération des infos correspondant à la page concernée :
|
||||
req = 'SELECT Nom, ';
|
||||
// req += ' Type, ';
|
||||
req += ' Fichier, ';
|
||||
req += ' Opacite, ';
|
||||
req += ' Taille, ';
|
||||
req += ' Offset_x, ';
|
||||
req += ' Offset_y, ';
|
||||
req += ' Points ';
|
||||
req += ' FROM TB_Pages ';
|
||||
req += ' WHERE Cle_primaire=' + id_page + ' ';
|
||||
//console.log("req = [ " + req + "; ]");
|
||||
res = bdd.requete_unique(req);
|
||||
|
||||
nom_page = res[i++];
|
||||
fichier = res[i++];
|
||||
opacite = Number(res[i++]);
|
||||
taille = Number(res[i++]);
|
||||
offset_x = Number(res[i++]);
|
||||
offset_y = Number(res[i++]);
|
||||
chaine_points = res[i++];
|
||||
|
||||
// Remplissage des courbes et modèles :
|
||||
if (chaine_points !== "") init_points(chaine_points.split(';'));
|
||||
else init_points(""); // L'appel avec un array vide (cas du résultat de split sur une chaine vide) donne des résultats pas très clairs...
|
||||
|
||||
|
||||
flag_init = false; // Indique que l'init est terminée
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================================================
|
||||
// Met à jour 'modele_liste_points', 'points_originaux' et 'points_nouveaux' avec les paramètres contenu dans 'chaines_points'
|
||||
//=============================================================================================================
|
||||
function init_points(chaines_points)
|
||||
{
|
||||
var req, res;
|
||||
var nb;
|
||||
var i;
|
||||
var chaine_point;
|
||||
var point;
|
||||
var validite;
|
||||
var type_source;
|
||||
var id_source;
|
||||
var x, y;
|
||||
var type_point;
|
||||
var taille_point;
|
||||
var icone;
|
||||
|
||||
// RAZ des courbes :
|
||||
nb_points = 0;
|
||||
modele_liste_points.clear();
|
||||
flag_aucun_points = true;
|
||||
|
||||
if (chaines_points === "")
|
||||
{
|
||||
console.log("La liste de points est vide")
|
||||
return; // Si le tableau est vide (aucun point), il ne faut pas faire de traitement supplémentaire...
|
||||
}
|
||||
|
||||
|
||||
// Ajout des points dans les modèles :
|
||||
for (chaine_point of chaines_points) // Chaque point est du type : [validite/type_source/id_source/x/y/type_point/taille_point]
|
||||
{
|
||||
point = chaine_point.split('/');
|
||||
i = 0;
|
||||
validite = Number(point[i++]);
|
||||
type_source = Number(point[i++]);
|
||||
id_source = Number(point[i++]);
|
||||
x = Number(point[i++]);
|
||||
y = Number(point[i++]);
|
||||
type_point = Number(point[i++]);
|
||||
taille_point = Number(point[i++]);
|
||||
|
||||
// Recherche des infos de l'équipement :
|
||||
switch(type_source)
|
||||
{
|
||||
case shipheart_type_source_circuits:
|
||||
req = ' SELECT Nom FROM TB_Circuits WHERE Cle_primaire=' + id_source + ' ';
|
||||
icone = "icone_consommation_electrique.png";
|
||||
break;
|
||||
|
||||
case shipheart_type_source_reservoirs:
|
||||
req = ' SELECT Nom FROM TB_Reservoirs WHERE Cle_primaire=' + id_source + ' ';
|
||||
icone = "reservoir_eau.png";
|
||||
break;
|
||||
|
||||
case shipheart_type_source_batteries:
|
||||
req = ' SELECT Nom FROM TB_Batteries WHERE Cle_primaire=' + id_source + ' ';
|
||||
icone = "batterie_moyen.png";
|
||||
break;
|
||||
|
||||
case shipheart_type_source_capteurs:
|
||||
req = ' SELECT Nom FROM TB_Capteurs WHERE Cle_primaire=' + id_source + ' ';
|
||||
icone = "icone_auxiliaires.png";
|
||||
break;
|
||||
|
||||
case shipheart_type_source_modules:
|
||||
req = ' SELECT Type FROM TB_Modules_config WHERE Adresse_k_bus=' + id_source + ' ';
|
||||
icone = "soh_sombre.png";
|
||||
break;
|
||||
}
|
||||
//console.log("req = [ " + req + "; ]");
|
||||
res = bdd.requete_unique(req);
|
||||
|
||||
modele_liste_points.append({
|
||||
"validite": validite,
|
||||
"type_source": type_source,
|
||||
"id_source": id_source,
|
||||
"x": x,
|
||||
"y": y,
|
||||
"x_initial": x,
|
||||
"y_initial": y,
|
||||
"type_point": type_point,
|
||||
"taille_point": taille_point,
|
||||
"nom": (type_source !== shipheart_type_source_modules) ? res[0] : Fonctions.nom_type_module(Number(res[0])),
|
||||
"icone": icone,
|
||||
"actif": false,
|
||||
"changed": false }); // Modèle pour la liste de gauche + les rectangle/cercles utilisés pour les bouger
|
||||
|
||||
|
||||
flag_aucun_points = false; // Utilisé pour afficher le message "aucune données...'
|
||||
|
||||
if (++nb_points >= shipheart_page_personnalisee_nb_max_points)
|
||||
{
|
||||
flag_affichage_ajout_point = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
flag_alignement_demande = true // Permet de déclencher un traitement au niveau du repeater pour mettre à jour la position du rectangle/cercle.
|
||||
flag_alignement_demande = false // La RAZ ne peut pas se faire dans le repeater. Donc on la fait ici car le front montant a déjà été détecté par le signe de changement.
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================================================
|
||||
// Enregistre dans la BDD les nouvelles valeurs
|
||||
//=============================================================================================================
|
||||
function enregistrer_points()
|
||||
{
|
||||
var i;
|
||||
var req;
|
||||
var chaine = "";
|
||||
|
||||
// Génération de la chaine de points [validite/type_source/id_source/x/y/type_point/taille_point] :
|
||||
for(i = 0; i < modele_liste_points.count; i++) {
|
||||
if (chaine !== "") chaine += ";";
|
||||
chaine += (modele_liste_points.get(i).validite) ? "1" : "0";
|
||||
chaine += "/";
|
||||
chaine += (modele_liste_points.get(i).type_source);
|
||||
chaine += "/";
|
||||
chaine += (modele_liste_points.get(i).id_source);
|
||||
chaine += "/";
|
||||
chaine += (modele_liste_points.get(i).x).toFixed(4);
|
||||
chaine += "/";
|
||||
chaine += (modele_liste_points.get(i).y).toFixed(4);
|
||||
chaine += "/";
|
||||
chaine += (modele_liste_points.get(i).type_point);
|
||||
chaine += "/";
|
||||
chaine += (modele_liste_points.get(i).taille_point);
|
||||
|
||||
modele_liste_points.setProperty(i, "changed", false) // On en profite pour RAZ tous les flags Changed
|
||||
}
|
||||
flag_nouvelles_valeurs = false; // ainsi que le flag de nouvelles valeurs
|
||||
|
||||
// Mise à jour de l'entrée dans la table :
|
||||
req = 'UPDATE TB_Pages SET Points="' + chaine + '" WHERE Cle_primaire=' + id_page + ' '
|
||||
//console.log("req = [ " + req + "; ]");
|
||||
bdd.requete_unique(req);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,741 @@
|
||||
//========================================================================================================================================================================
|
||||
// CONFIG_PAGE_POINT.QML
|
||||
// Ce fichier traite la configuration d'un point dans une page. La page permet notamment de :
|
||||
// - Modifier la config du point (ou de le créer la première fois),
|
||||
// - Supprimer le point
|
||||
// La page est appelée depuis la page config_page_edition.qml, en cliquant sur le point à modifier (ou sur le '+' en vue d'une création)
|
||||
//========================================================================================================================================================================
|
||||
import QtQuick 2.12
|
||||
import QtQml.Models
|
||||
|
||||
import qt.koriolan.shipheart 1.0
|
||||
import"fonctions.js" as Fonctions
|
||||
|
||||
|
||||
Shipheart_page {
|
||||
id: page_config_page_point
|
||||
|
||||
|
||||
// Mise en forme - Largeur :
|
||||
readonly property double pourcentage_largeur_colonne_gauche: 0.75
|
||||
readonly property double espace_colonnes_principales: 20
|
||||
readonly property double pourcentage_largeur_labels_formulaire: 0.5
|
||||
readonly property double pourcentage_largeur_unites_formulaire: 0.1
|
||||
readonly property int largeur_bouton_suite: 15
|
||||
readonly property double pourcentage_bandeau_bas_largeur_zone_retour: 1
|
||||
|
||||
readonly property int nombre_widgets_heure_par_ligne: 12
|
||||
|
||||
// Mise en forme - Hauteur :
|
||||
readonly property double pourcentage_hauteur_ligne_haut: 1
|
||||
readonly property int hauteur_ligne_formulaire: 60
|
||||
readonly property int hauteur_bouton_droit: 80
|
||||
readonly property int espace_lignes_principales: 20
|
||||
readonly property double affichage_hauteur_utile: shipheart_hauteur_page - shipheart_hauteur_bandeau_haut - shipheart_hauteur_bandeau_bas
|
||||
|
||||
// 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 bool flag_point_existant: false
|
||||
property int type_source: 0
|
||||
property int id_source: -1
|
||||
property int type_point: 0
|
||||
property int taille_point: 25
|
||||
|
||||
|
||||
// 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_point(bool new_flag_point_existant, int new_type_source, int new_id_source, int type_point, int taille_point) // 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;
|
||||
|
||||
init_page();
|
||||
}
|
||||
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;
|
||||
|
||||
if (mousearea_bouton_supprimer.pressed)
|
||||
{
|
||||
shipheart_clic();
|
||||
page_config_page_point.enregistrer_config_page_point(false, type_source, id_source, type_point, taille_point);
|
||||
stackView.pop(); // Retour à la page d'édition de la page
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Titre de la page :
|
||||
Shipheart_titre_1 {titre: (type_source === -1) ? qsTr("Création d'un point") : qsTr("Configuration du point"); 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"
|
||||
|
||||
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: affichage_hauteur_utile - hauteur_ligne_formulaire // Cette valeur permet de bien remonter les drniers champs (utile dans le cas de Textarea notamment) en laissant toujours une hauteur de lugne de formulaire au moins (évite qu'on "perde" l'affichage qui serait trop décalé vers le haut)
|
||||
color: "transparent"
|
||||
}
|
||||
|
||||
ObjectModel {
|
||||
id: modele_grille_principale
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Ligne de formulaire : Type_source
|
||||
Rectangle {
|
||||
id: ligne_type_source
|
||||
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("Type de la source")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
couleur: (champ_formulaire_Type_source.currentIndex !== 0)
|
||||
? shipheart_formulaire_couleur_texte_par_defaut
|
||||
: shipheart_formulaire_couleur_texte_en_erreur
|
||||
}
|
||||
|
||||
Shipheart_formulaire_combobox {
|
||||
id: champ_formulaire_Type_source
|
||||
model: ListModel { }
|
||||
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
|
||||
|
||||
onActivated: {
|
||||
shipheart_clic();
|
||||
if (type_source !== champ_formulaire_Type_source.model.get(champ_formulaire_Type_source.currentIndex).valeur)
|
||||
{
|
||||
type_source = champ_formulaire_Type_source.model.get(champ_formulaire_Type_source.currentIndex).valeur;
|
||||
id_source = -1;
|
||||
type_point = 0;
|
||||
if (type_source > 0) mise_a_jour_source();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Shipheart_formulaire_ligne_separation {
|
||||
haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Ligne de formulaire : ID_Source
|
||||
Rectangle {
|
||||
id: ligne_source
|
||||
width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2)
|
||||
height: visible ? hauteur_ligne_formulaire : 0
|
||||
color: "transparent"
|
||||
visible: (type_source !== 0)
|
||||
|
||||
Shipheart_formulaire_label {
|
||||
text: qsTr("Source")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
couleur: (champ_formulaire_Source.currentIndex !== 0)
|
||||
? shipheart_formulaire_couleur_texte_par_defaut
|
||||
: shipheart_formulaire_couleur_texte_en_erreur
|
||||
}
|
||||
|
||||
Shipheart_formulaire_combobox {
|
||||
id: champ_formulaire_Source
|
||||
model: ListModel { }
|
||||
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
|
||||
|
||||
onActivated: {
|
||||
shipheart_clic();
|
||||
id_source = champ_formulaire_Source.model.get(champ_formulaire_Source.currentIndex).valeur;
|
||||
mise_a_jour_type_point();
|
||||
}
|
||||
}
|
||||
|
||||
Shipheart_formulaire_ligne_separation {
|
||||
haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Ligne de formulaire : Type_point
|
||||
Rectangle {
|
||||
id: ligne_type_point
|
||||
width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2)
|
||||
height: visible ? hauteur_ligne_formulaire : 0
|
||||
color: "transparent"
|
||||
visible: (type_source !== 0)
|
||||
&& (id_source !== -1)
|
||||
&& (type_source !== shipheart_type_source_modules)
|
||||
// && (champ_formulaire_Type_point.model.count > 1)
|
||||
|
||||
Shipheart_formulaire_label {
|
||||
text: qsTr("Type de point")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
couleur: shipheart_formulaire_couleur_texte_par_defaut
|
||||
}
|
||||
|
||||
Shipheart_formulaire_combobox_icones {
|
||||
id: champ_formulaire_Type_point
|
||||
model: ListModel { }
|
||||
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
|
||||
|
||||
onActivated: {
|
||||
shipheart_clic();
|
||||
type_point = champ_formulaire_Type_point.model.get(champ_formulaire_Type_point.currentIndex).valeur;
|
||||
}
|
||||
}
|
||||
|
||||
Shipheart_formulaire_ligne_separation {
|
||||
haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Ligne de formulaire : Taille_point
|
||||
Rectangle {
|
||||
id: ligne_taille_point
|
||||
width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2)
|
||||
height: visible ? hauteur_ligne_formulaire : 0
|
||||
color: "transparent"
|
||||
visible: (type_source !== 0)
|
||||
&& (id_source !== -1)
|
||||
// && (champ_formulaire_Taille_point.model.count > 1)
|
||||
|
||||
Shipheart_formulaire_label {
|
||||
text: qsTr("Taille du point")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
couleur: shipheart_formulaire_couleur_texte_par_defaut
|
||||
}
|
||||
|
||||
Shipheart_formulaire_combobox {
|
||||
id: champ_formulaire_Taille_point
|
||||
model: ListModel { }
|
||||
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
|
||||
|
||||
onActivated: {
|
||||
shipheart_clic();
|
||||
taille_point = champ_formulaire_Taille_point.model.get(champ_formulaire_Taille_point.currentIndex).valeur;
|
||||
}
|
||||
}
|
||||
|
||||
Shipheart_formulaire_ligne_separation {
|
||||
haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse
|
||||
}
|
||||
}
|
||||
|
||||
} // Fin de Grille principale
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// 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: (champ_formulaire_Type_source.currentIndex !== 0)
|
||||
&& (champ_formulaire_Source.currentIndex !== 0)
|
||||
|
||||
Text {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
font.pixelSize: 20
|
||||
text: flag_point_existant ? qsTr("Enregistrer") : qsTr("Créer le point")
|
||||
color: couleur_blanc_casse
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
page_config_page_point.enregistrer_config_page_point(true, type_source, id_source, type_point, taille_point);
|
||||
stackView.pop(); // Retour à la page d'édition de la page
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//.......................................................
|
||||
// Bouton de suppression
|
||||
//.......................................................
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: hauteur_bouton_droit
|
||||
color: shipheart_couleur_fond_bouton
|
||||
radius: shipheart_rayon_bouton
|
||||
visible: flag_point_existant
|
||||
|
||||
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();
|
||||
page_config_page_point.enregistrer_config_page_point(flag_point_existant, type_source, id_source, type_point, taille_point);
|
||||
stackView.pop(); // Retour à la page d'édition de la page
|
||||
}
|
||||
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) - (2 * parent.padding)
|
||||
height: shipheart_hauteur_bandeau_bas - parent.topPadding - parent.bottomPadding;
|
||||
radius: shipheart_rayon_bouton
|
||||
color: shipheart_couleur_fond_bouton
|
||||
|
||||
Image {
|
||||
source: "/images/icone_retour.png"
|
||||
sourceSize.height: 30
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea { // Zone d'interaction. On est obligé de la mettre dans la grille pour que Rectangle et MouseArea soient frères ou parent/enfant ET qu'on n'occupe qu'un espace dans la grille.
|
||||
id: mouse_area_bandeau_bas_zone_retour
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
stackView.pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Boite de validation :
|
||||
//-------------------------------------------------------
|
||||
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;
|
||||
|
||||
// Remplissage des différents modèles, dans l'ordre des priorités :
|
||||
mise_a_jour_type_source();
|
||||
|
||||
// Mise à jour du modèle de taille sans attendre car elle est indépendante du type de source ou de point :
|
||||
mise_a_jour_taille_point();
|
||||
|
||||
flag_init = false; // Indique que l'init est terminée
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================================================
|
||||
// MAJ du type de source
|
||||
//=============================================================================================================
|
||||
function mise_a_jour_type_source()
|
||||
{
|
||||
var i;
|
||||
|
||||
// Effacement du modèle et premier enregistrement avec 'Non défini' :
|
||||
champ_formulaire_Type_source.model.clear();
|
||||
champ_formulaire_Type_source.model.append( {
|
||||
"valeur": -1,
|
||||
"texte": qsTr("Non défini"),
|
||||
"actif": true });
|
||||
champ_formulaire_Type_source.model.append( {
|
||||
"valeur": shipheart_type_source_capteurs,
|
||||
"texte": qsTr("Capteur"),
|
||||
"actif": true });
|
||||
champ_formulaire_Type_source.model.append( {
|
||||
"valeur": shipheart_type_source_circuits,
|
||||
"texte": qsTr("Circuit"),
|
||||
"actif": true });
|
||||
champ_formulaire_Type_source.model.append( {
|
||||
"valeur": shipheart_type_source_reservoirs,
|
||||
"texte": qsTr("Réservoir"),
|
||||
"actif": true });
|
||||
champ_formulaire_Type_source.model.append( {
|
||||
"valeur": shipheart_type_source_batteries,
|
||||
"texte": qsTr("Batterie"),
|
||||
"actif": true });
|
||||
champ_formulaire_Type_source.model.append( {
|
||||
"valeur": shipheart_type_source_modules,
|
||||
"texte": qsTr("Modules"),
|
||||
"actif": true });
|
||||
|
||||
// Mise à jour de l'index courant du modèle champ_formulaire_Type_source :
|
||||
i = recherche_index_valeur_modele(type_source, champ_formulaire_Type_source.model, "Type_source");
|
||||
if (i === -1) champ_formulaire_Type_source.currentIndex = recherche_index_valeur_modele(-1, champ_formulaire_Type_source.model, "Type_source");
|
||||
else champ_formulaire_Type_source.currentIndex = i;
|
||||
|
||||
|
||||
// Appel du remplissage des modèles de niveau inférieur si cela est possible :
|
||||
if (type_source > 0) mise_a_jour_source();
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================================================
|
||||
// MAJ de la source
|
||||
//=============================================================================================================
|
||||
function mise_a_jour_source()
|
||||
{
|
||||
var req, res;
|
||||
var nb;
|
||||
var i;
|
||||
|
||||
// Effacement du modèle et premier enregistrement avec 'Non défini' :
|
||||
champ_formulaire_Source.model.clear();
|
||||
champ_formulaire_Source.model.append( {
|
||||
"valeur": -1,
|
||||
"texte": qsTr("Non défini"),
|
||||
"actif": true });
|
||||
switch(type_source)
|
||||
{
|
||||
case shipheart_type_source_circuits:
|
||||
req = 'SELECT Cle_primaire, ';
|
||||
req += 'Nom, ';
|
||||
req += 'Nom_famille ';
|
||||
req += 'FROM TB_Circuits, ';
|
||||
req += ' (SELECT Cle_primaire AS Cle_famille, Nom AS Nom_famille, Priorite_affichage AS Priorite_famille FROM TB_Familles WHERE Type_source=' + shipheart_type_source_circuits + ') AS TB_Familles ';
|
||||
req += ' WHERE ID_Famille=Cle_famille ';
|
||||
req += ' ORDER BY Priorite_famille, ABS(Priorite_affichage_accueil)';
|
||||
|
||||
break;
|
||||
|
||||
case shipheart_type_source_capteurs:
|
||||
req = 'SELECT Cle_primaire, ';
|
||||
req += 'Nom, ';
|
||||
req += 'Nom_famille ';
|
||||
req += 'FROM TB_Capteurs, ';
|
||||
req += ' (SELECT Cle_primaire AS Cle_famille, Nom AS Nom_famille, Priorite_affichage AS Priorite_famille FROM TB_Familles WHERE Type_source=' + shipheart_type_source_capteurs + ') AS TB_Familles ';
|
||||
req += ' WHERE ID_Famille=Cle_famille ';
|
||||
req += ' ORDER BY Priorite_famille, ABS(Priorite_affichage_accueil)';
|
||||
|
||||
break;
|
||||
|
||||
case shipheart_type_source_reservoirs:
|
||||
req = 'SELECT Cle_primaire, ';
|
||||
req += 'Nom, ';
|
||||
req += 'Nom_famille ';
|
||||
req += 'FROM TB_Reservoirs, ';
|
||||
req += ' (SELECT Cle_primaire AS Cle_famille, Nom AS Nom_famille, Priorite_affichage AS Priorite_famille FROM TB_Familles WHERE Type_source=' + shipheart_type_source_reservoirs + ') AS TB_Familles ';
|
||||
req += ' WHERE ID_Famille=Cle_famille ';
|
||||
req += ' ORDER BY Priorite_famille, ABS(Priorite_affichage_accueil)';
|
||||
|
||||
break;
|
||||
|
||||
case shipheart_type_source_batteries:
|
||||
req = 'SELECT Cle_primaire, ';
|
||||
req += 'Nom, ';
|
||||
req += 'Nom_famille ';
|
||||
req += 'FROM TB_Batteries, ';
|
||||
req += ' (SELECT Cle_primaire AS Cle_famille, Nom AS Nom_famille, Priorite_affichage AS Priorite_famille FROM TB_Familles WHERE Type_source=' + shipheart_type_source_batteries + ') AS TB_Familles ';
|
||||
req += ' WHERE ID_Famille=Cle_famille ';
|
||||
req += ' ORDER BY Priorite_famille, ABS(Priorite_affichage_accueil)';
|
||||
|
||||
break;
|
||||
|
||||
case shipheart_type_source_modules:
|
||||
req = 'SELECT Adresse_k_bus, ';
|
||||
req += 'Type, ';
|
||||
req += '"" AS Nom_famille '; // Permet de passer le traitement des familles sans erreur et ajout de ligne inutile (les batteries n'ont pas de notion de famille)
|
||||
req += 'FROM TB_Modules_config ';
|
||||
req += ' ORDER BY Adresse_k_bus';
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
table = "";
|
||||
break;
|
||||
}
|
||||
|
||||
if (req !== "")
|
||||
{
|
||||
//console.log("Requête = [ " + req + "; ]");
|
||||
nb = bdd.requete(req);
|
||||
|
||||
var prec_famille = "";
|
||||
for (i = 0; i < nb; i ++)
|
||||
{
|
||||
res = bdd.lecture_ligne();
|
||||
if (!res.isEmpty)
|
||||
{
|
||||
// Ajout de le ligne de famille :
|
||||
if (prec_famille !== res[2])
|
||||
{
|
||||
champ_formulaire_Source.model.append( {
|
||||
"groupe": true,
|
||||
"valeur": 0,
|
||||
"texte": res[2],
|
||||
"actif": false });
|
||||
prec_famille = res[2];
|
||||
}
|
||||
|
||||
// Ajout de la ligne normale :
|
||||
var texte;
|
||||
if (type_source === shipheart_type_source_modules)
|
||||
{
|
||||
texte = Fonctions.nom_type_module(Number(res[1]));
|
||||
if (Number(res[0]) !== 0) texte += " @" + res[0];
|
||||
}
|
||||
else texte = res[1];
|
||||
|
||||
|
||||
champ_formulaire_Source.model.append( {
|
||||
"groupe": false,
|
||||
"valeur": Number(res[0]),
|
||||
"texte": texte,
|
||||
"actif": true });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Mise à jour de l'index courant du modèle :
|
||||
i = recherche_index_valeur_modele(id_source, champ_formulaire_Source.model, "id_source");
|
||||
if (i === -1) champ_formulaire_Source.currentIndex = recherche_index_valeur_modele(0, champ_formulaire_Source.model, "id_source");
|
||||
else champ_formulaire_Source.currentIndex = i;
|
||||
|
||||
|
||||
// Appel du remplissage des modèles de niveau inférieur si cela est possible :
|
||||
if (id_source !== -1) mise_a_jour_type_point();
|
||||
|
||||
}
|
||||
|
||||
//=============================================================================================================
|
||||
// MAJ du type de point
|
||||
//=============================================================================================================
|
||||
function mise_a_jour_type_point()
|
||||
{
|
||||
var req, res;
|
||||
var i;
|
||||
var libelle;
|
||||
|
||||
// Effacement du modèle :
|
||||
champ_formulaire_Type_point.model.clear();
|
||||
|
||||
// Boucle sur toutes les entrées du tableau des types de points correspondant au 'type_source' (cf dans 'main.qml') :
|
||||
for (i = 0; i < shipheart_page_personnalisee_type_point_icones[type_source].length; i ++)
|
||||
{
|
||||
if ((type_source === shipheart_type_source_circuits) && (i === 0)) continue; // Pour les circuits, on n'autorise pas le premier élément qui correspond à l'icone OFF
|
||||
|
||||
champ_formulaire_Type_point.model.append( {
|
||||
"valeur": i,
|
||||
"texte": "",
|
||||
"icone": shipheart_page_personnalisee_type_point_icones[type_source][i],
|
||||
"actif": true });
|
||||
}
|
||||
|
||||
// Mise à jour de l'index courant du modèle :
|
||||
i = recherche_index_valeur_modele(type_point, champ_formulaire_Type_point.model, "type_point");
|
||||
if (i === -1) champ_formulaire_Type_point.currentIndex = recherche_index_valeur_modele(1, champ_formulaire_Type_point.model, "type_point");
|
||||
else champ_formulaire_Type_point.currentIndex = i;
|
||||
|
||||
// Cas particulier des modules : on ne laisse pas le choix de l'icone à afficher...
|
||||
if (type_source === shipheart_type_source_modules)
|
||||
{
|
||||
req = 'SELECT Type FROM TB_Modules_config WHERE Adresse_k_bus=' + id_source + ' ';
|
||||
//console.log("Requête = [ " + req + "; ]");
|
||||
res = bdd.requete_unique(req);
|
||||
|
||||
type_point = Number(res[0]); // Pour les modules, on a autant de fichiers que de type, classés dans l'ordre des Type.
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================================================
|
||||
// MAJ de la taille de point
|
||||
//=============================================================================================================
|
||||
function mise_a_jour_taille_point()
|
||||
{
|
||||
var i;
|
||||
|
||||
// Effacement du modèle ::
|
||||
champ_formulaire_Taille_point.model.clear();
|
||||
|
||||
for (i = 2; i <= 16; i ++)
|
||||
{
|
||||
champ_formulaire_Taille_point.model.append( {
|
||||
"valeur": (i * 5),
|
||||
"texte": (i * 5),
|
||||
"actif": true });
|
||||
}
|
||||
|
||||
// Mise à jour de l'index courant du modèle :
|
||||
i = recherche_index_valeur_modele(taille_point, champ_formulaire_Taille_point.model, "taille_point");
|
||||
if (i === -1) champ_formulaire_Taille_point.currentIndex = recherche_index_valeur_modele(25, champ_formulaire_Taille_point.model, "taille_point");
|
||||
else champ_formulaire_Taille_point.currentIndex = i;
|
||||
|
||||
}
|
||||
|
||||
//=============================================================================================================
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,528 @@
|
||||
//========================================================================================================================================================================
|
||||
// CONFIG_PAGES.QML
|
||||
// Ce fichier traite la configuration des pages. La page permet notamment de :
|
||||
// - Afficher, pour toutes les pages déjà configurées (et donc d'accéder à la configuration détaillée de l'une d'elle ; ou sa création)
|
||||
// - valider/dévalider l'affichage d'une page via un bouton en bout de ligne basculable par clic-droit
|
||||
// - Changer l'ordre d'affichage sur la page d'accueil
|
||||
// La page est appelée depuis la page PARAMETRES_AVANCES, en cliquant sur "Batteries"
|
||||
//========================================================================================================================================================================
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
import QtQml.Models 2.1
|
||||
|
||||
import qt.koriolan.shipheart 1.0
|
||||
|
||||
|
||||
Shipheart_page {
|
||||
id: page_config_pages
|
||||
|
||||
|
||||
// Mis en forme :
|
||||
readonly property double affichage_hauteur_utile: shipheart_hauteur_page - shipheart_hauteur_bandeau_haut - shipheart_hauteur_bandeau_bas
|
||||
readonly property int hauteur_bouton_droit: 80
|
||||
|
||||
readonly property double pourcentage_largeur_colonne_gauche: 0.75
|
||||
readonly property double pourcentage_bandeau_bas_largeur_zone_retour: 1.0
|
||||
readonly property int espace_colonnes_principales: 20
|
||||
readonly property double pourcentage_largeur_bouton_affichage_dans_colonne_gauche: 0.15
|
||||
|
||||
readonly property int nombre_pages_affiches_sur_une_colonne: 8
|
||||
|
||||
readonly property int periode_init_raffraichissement_parametres: 1 // En ms
|
||||
readonly property int periode_raffraichissement_parametres: 100 // En ms
|
||||
|
||||
// Affichage :
|
||||
property int niveau_page: 0
|
||||
|
||||
// Modèles :
|
||||
// Note : les modèles chargés dans 'main.qml' n'ont pas à être rechargés dans les pages suivantes
|
||||
|
||||
|
||||
//===========================================================
|
||||
// Timer periode raffraichissement parametres :
|
||||
//===========================================================
|
||||
Timer {
|
||||
id: timer_raffraichissement_parametres
|
||||
interval: periode_init_raffraichissement_parametres
|
||||
triggeredOnStart: false
|
||||
running: true
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
if (interval == periode_init_raffraichissement_parametres) // Premier passage, 1ms après le premier chargement
|
||||
{
|
||||
interval = periode_raffraichissement_parametres;
|
||||
}
|
||||
else {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================
|
||||
// Lorsque la page est sur le point d'être affichée dans la pile :
|
||||
//===========================================================
|
||||
StackView.onActivating: {
|
||||
init_page(); // Permet que lors du retour sur la page, l'état des différentes variables soit mise à jour avant l'affichage proprement dit. Y compris lors de l'ouverture initiale...
|
||||
}
|
||||
|
||||
// Titre de la page :
|
||||
Shipheart_titre_1 {titre:qsTr("Configuration des pages"); hauteur: shipheart_hauteur_bandeau_haut}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Ecran de gauche (liste des pages) :
|
||||
//-------------------------------------------------------
|
||||
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 pages :
|
||||
ListView {
|
||||
id: grille_principale
|
||||
|
||||
property bool deplacement_en_cours: false // Indique si un déplacement (au global) est en cours ou pas
|
||||
property int save_current_index: 0 // Permet de garder le Current_index du début du déplacement et de compenser les changements qui sont fait automatiquement, notamment en début et fin de liste. Le principe est qu'une fois le mouvement déclenché, ON NE CHANGE PAS de CurrentIndex !!
|
||||
|
||||
x: 0
|
||||
y: 0
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
|
||||
clip: true // Limite l'affichage des délégués dans la zone de ListView (sinon, on affiche au moins un délégué au-dessus et un en dessous...)
|
||||
highlightRangeMode: ListView.StrictlyEnforceRange // Permet de faire défiler la liste jusqu'à ne garder que le dernier élément affiché
|
||||
|
||||
displaced: Transition { // Gère la transition lors d'un déplacement
|
||||
NumberAnimation{
|
||||
properties: "x,y" // Ici, on devrait pouvoir limiter à Y
|
||||
duration: 500 // Vitesse à laquelle se déplacent les boutons lorsqu'on les déplace
|
||||
}
|
||||
}
|
||||
|
||||
model: modele_grille_principale
|
||||
delegate: bouton_page
|
||||
|
||||
Component {
|
||||
id: bouton_page
|
||||
|
||||
MouseArea {
|
||||
id: dragArea_groupe // Zone correspondant à un seul bouton (on est dans le Delegate)
|
||||
|
||||
width: grille_principale.width
|
||||
height: grille_principale.height / nombre_pages_affiches_sur_une_colonne
|
||||
|
||||
property bool bouton_appuye: false // On ne peut pas utiliser la propriété globale "deplacement_en_cours" car il faut une propriété par délégué
|
||||
|
||||
pressAndHoldInterval: 500; // Temporise avant de passer en mode "déplacement"
|
||||
|
||||
drag.target: bouton_appuye ? contenu_bouton_page : undefined
|
||||
drag.axis: Drag.YAxis // On ne se déplace que sur l'axe Y
|
||||
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
if (model.configurable) stackView.push("config_page_edition.qml", {"id_page": model.id})
|
||||
}
|
||||
|
||||
onPressAndHold: {
|
||||
shipheart_clic();
|
||||
bouton_appuye = true // Indication (au niveau du bouton seul) du début de l'appui long donc du déplacement
|
||||
grille_principale.deplacement_en_cours = true // Indication (au niveau de ListView) du début du déplacement
|
||||
grille_principale.save_current_index = grille_principale.currentIndex; // Sauvegarde du CurrentIndex au début du déplacement
|
||||
}
|
||||
onReleased: {
|
||||
bouton_appuye = false // Indication (au niveau du bouton seul) de la fin de l'appui long donc du déplacement
|
||||
grille_principale.deplacement_en_cours = false // Indication (au niveau de ListView) de la fin du déplacement
|
||||
grille_principale.currentIndex = grille_principale.save_current_index; // Restitution de la valeur initiale du CurrentIndex (a priori, pas nécessaire car mis à jour au fur et à mesure des changements dans "onCurrentIndexChanged")
|
||||
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: contenu_bouton_page
|
||||
|
||||
anchors {
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
width: dragArea_groupe.width - 5
|
||||
height: dragArea_groupe.height - 5
|
||||
color: "transparent"
|
||||
opacity: dragArea_groupe.bouton_appuye ? 0.6 : 1.0
|
||||
|
||||
//------------------------------------
|
||||
// Bouton avec le nom de la page :
|
||||
//------------------------------------
|
||||
Rectangle {
|
||||
height: parent.height - 5
|
||||
width: (model.masquable) ?
|
||||
((parent.width * (1 - pourcentage_largeur_bouton_affichage_dans_colonne_gauche)) - 10) :
|
||||
parent.width
|
||||
color: model.configurable ?
|
||||
shipheart_couleur_fond_bouton :
|
||||
"transparent"
|
||||
border.width: 2
|
||||
border.color: shipheart_couleur_fond_bouton
|
||||
radius: shipheart_rayon_bouton
|
||||
anchors {
|
||||
left: parent.left
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Icone du bouton :
|
||||
Rectangle { // Le passage par un rectangle avant l'image permet de centrer l'image sur le rectangle et pas juste caler les images à gauche (elles n'ont pas la même largeur donc elles n'étaient pas centrées les unes par rapport aux autres)
|
||||
width: 35
|
||||
height: parent.height
|
||||
x: 20
|
||||
color: "transparent"
|
||||
visible: (model.type < shipheart_type_page_personnalisee_non_masquable)
|
||||
Image {
|
||||
source: (model.icone !== "") ? ("/images/" + model.icone) : "" // Sans le test, on génère un warning lorsque 'icone' est vide
|
||||
sourceSize.height: parent.height * 0.5
|
||||
sourceSize.width: parent.width
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
visible: (model.icone !== "")
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Texte du bouton :
|
||||
Text {
|
||||
visible: (model.type >= shipheart_type_page_personnalisee_non_masquable)
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Qt.AlignLeft
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
leftPadding: 20
|
||||
text: model.nom
|
||||
color: couleur_blanc_casse
|
||||
font.pixelSize: 18
|
||||
wrapMode: Label.Wrap
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------
|
||||
// Bouton Visible :
|
||||
//------------------------------------
|
||||
Rectangle {
|
||||
x: (parent.width * (1 - pourcentage_largeur_bouton_affichage_dans_colonne_gauche))
|
||||
height: parent.height - 10
|
||||
width:(parent.width * pourcentage_largeur_bouton_affichage_dans_colonne_gauche)
|
||||
anchors {
|
||||
right: parent.right
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
radius: shipheart_rayon_bouton
|
||||
color: shipheart_couleur_fond_bouton
|
||||
visible: model.masquable
|
||||
|
||||
//----------------------------
|
||||
// Coche verte ou croix rouge :
|
||||
Image {
|
||||
source: (model.priorite_affichage <= 0) ? "/images/faux.png" : "/images/vrai.png"
|
||||
sourceSize.height: parent.height * 0.5
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------
|
||||
MouseArea {
|
||||
id: mouse_area_cdes_auto
|
||||
x: 0
|
||||
y: 0
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
pressAndHoldInterval: shipheart_mouse_press_and_hold_interval_long
|
||||
|
||||
onPressAndHold: {
|
||||
shipheart_clic();
|
||||
toggle_validite(model.index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Drag.active: dragArea_groupe.bouton_appuye
|
||||
Drag.source: dragArea_groupe
|
||||
Drag.hotSpot.x: width / 2
|
||||
Drag.hotSpot.y: height / 2
|
||||
|
||||
states: State{
|
||||
when: dragArea_groupe.bouton_appuye
|
||||
ParentChange {
|
||||
target: contenu_bouton_page
|
||||
parent: grille_principale
|
||||
}
|
||||
AnchorChanges {
|
||||
target: contenu_bouton_page
|
||||
anchors { // Necessaire pour autoriser le mouvement
|
||||
horizontalCenter: undefined
|
||||
verticalCenter: undefined
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DropArea {
|
||||
enabled: (index !== 0) // On interdit de bouger la première ligne (Ephéméride)
|
||||
anchors.fill: parent
|
||||
onEntered: {
|
||||
|
||||
if (drag.source.DelegateModel.itemsIndex !== dragArea_groupe.DelegateModel.itemsIndex)
|
||||
{
|
||||
//console.log("\tMouvement de Source index = " + drag.source.DelegateModel.itemsIndex + " vers Dest index = " + dragArea.DelegateModel.itemsIndex)
|
||||
modele_grille_principale.move(drag.source.DelegateModel.itemsIndex, dragArea_groupe.DelegateModel.itemsIndex, 1)
|
||||
mise_a_jour_ordre_pages();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ListModel {
|
||||
id: modele_grille_principale
|
||||
}
|
||||
|
||||
Label {
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Qt.AlignHCenter
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
visible: parent.count === 0
|
||||
text: qsTr("Aucune page n'est encore configurée...")
|
||||
color: couleur_rouge_transparent
|
||||
font.pixelSize: 15
|
||||
font.bold: true
|
||||
wrapMode: Label.Wrap
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Ecran Droite :
|
||||
//-------------------------------------------------------
|
||||
Rectangle {
|
||||
id: zone_affichage_droite
|
||||
x: zone_affichage_gauche.width + espace_colonnes_principales
|
||||
y: shipheart_hauteur_bandeau_haut + 5; // Le +5 permet d'aligner le haut du premier bouton de droite avec le haut du premier bouton de la liste de gauche (
|
||||
width: (shipheart_largeur_page * (1 - pourcentage_largeur_colonne_gauche)) - (espace_colonnes_principales / 2)
|
||||
height: affichage_hauteur_utile
|
||||
color: "transparent"
|
||||
|
||||
Column {
|
||||
anchors.fill: parent
|
||||
spacing: 10
|
||||
|
||||
//----------------------
|
||||
// Bouton + :
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: hauteur_bouton_droit
|
||||
color: shipheart_couleur_fond_bouton
|
||||
radius: shipheart_rayon_bouton
|
||||
visible: !clavier.active
|
||||
Text {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
font.pixelSize: 40
|
||||
text: qsTr("+")
|
||||
color: couleur_blanc_casse
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
stackView.push("config_page_edition.qml", {"id_page": 0})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Bandeau bas :
|
||||
//-------------------------------------------------------
|
||||
Row {
|
||||
x: 0
|
||||
y: shipheart_hauteur_page - shipheart_hauteur_bandeau_bas;
|
||||
width: shipheart_largeur_page;
|
||||
height: shipheart_hauteur_bandeau_bas;
|
||||
padding: 5
|
||||
spacing: 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();
|
||||
stackView.pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 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()
|
||||
{
|
||||
niveau_page = stackView.depth - 1; // Permet de stocker le niveau de la page dans la Stackview
|
||||
|
||||
mise_a_jour_donnees();
|
||||
}
|
||||
|
||||
//=============================================================================================================
|
||||
// Mise à jour des données
|
||||
//=============================================================================================================
|
||||
function mise_a_jour_donnees()
|
||||
{
|
||||
var req, res;
|
||||
var i;
|
||||
var nb_pages;
|
||||
var type;
|
||||
var configurable;
|
||||
var masquable;
|
||||
|
||||
modele_grille_principale.clear(); // RAZ des valeurs existantes
|
||||
|
||||
req = 'SELECT Cle_primaire, ';
|
||||
req += ' Nom, ';
|
||||
req += ' Type, ';
|
||||
req += ' Fichier, ';
|
||||
req += ' Priorite_affichage ';
|
||||
req += ' FROM TB_Pages ORDER BY ABS(Priorite_affichage), Cle_primaire';
|
||||
//console.log("Requête = [ " + req + "; ]");
|
||||
nb_pages = bdd.requete(req);
|
||||
|
||||
for (i = 0; i < nb_pages; i ++)
|
||||
{
|
||||
res = bdd.lecture_ligne();
|
||||
if (!res.isEmpty)
|
||||
{
|
||||
// Recherche du caractère configurable et/ou masquable de la page :
|
||||
type = Number(res[2]);
|
||||
switch(type)
|
||||
{
|
||||
//-------------------------------------------------
|
||||
case shipheart_type_page_preconfiguree_ephemeride:
|
||||
configurable = false;
|
||||
masquable = false;
|
||||
break;
|
||||
|
||||
//-------------------------------------------------
|
||||
case shipheart_type_page_preconfiguree_chronometre:
|
||||
case shipheart_type_page_personnalisee_minuteur:
|
||||
case shipheart_type_page_preconfiguree_reveil:
|
||||
configurable = false;
|
||||
masquable = true;
|
||||
break;
|
||||
|
||||
//-------------------------------------------------
|
||||
case shipheart_type_page_personnalisee_non_masquable:
|
||||
configurable = true;
|
||||
masquable = false;
|
||||
break;
|
||||
|
||||
//-------------------------------------------------
|
||||
case shipheart_type_page_personnalisee_masquable:
|
||||
configurable = true;
|
||||
masquable = true;
|
||||
break;
|
||||
|
||||
//-------------------------------------------------
|
||||
case shipheart_type_page_inconnu:
|
||||
continue;
|
||||
}
|
||||
|
||||
// Mise à jour du modèle :
|
||||
modele_grille_principale.append({
|
||||
"id": Number(res[0]),
|
||||
"nom": res[1],
|
||||
"type": type,
|
||||
"configurable": configurable,
|
||||
"masquable": masquable,
|
||||
"icone": (Number(res[2]) >= shipheart_type_page_personnalisee_non_masquable) ? "" : res[3], // On n'utilise les icones que pour les pages préconfigurées (et il faut bien faire la distinctions car les fichiers icones sont stockées dans 'images' alors que les fichiers silhouette sont stockées dans 'docs/images_silhouette')
|
||||
"priorite_affichage": Number(res[4]) });
|
||||
|
||||
}
|
||||
else break; // Ne devrait pas arriver....
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================================================
|
||||
// Mise à jour de l'ordre des pages
|
||||
//=============================================================================================================
|
||||
function mise_a_jour_ordre_pages()
|
||||
{
|
||||
var req;
|
||||
var i;
|
||||
var new_priorite_affichage;
|
||||
|
||||
for (i = 0; i < modele_grille_principale.count; i++)
|
||||
{
|
||||
new_priorite_affichage = i + 1; // Nouvelle valeur arbitraire
|
||||
|
||||
if (modele_grille_principale.get(i).priorite_affichage < 0) new_priorite_affichage *= (-1); // Passage en négatif pour les pages déjà dévalidées
|
||||
|
||||
// Mise à jour dans le modele :
|
||||
modele_grille_principale.set(i, { "priorite_affichage": new_priorite_affichage } );
|
||||
|
||||
// Mis à jour de la nouvelle valeur dans la BDD :
|
||||
req = 'UPDATE TB_Pages SET Priorite_affichage=' + new_priorite_affichage + ' WHERE Cle_primaire=' + modele_grille_principale.get(i).id + ' ';
|
||||
//console.log("Requête = [ " + req + "; ]");
|
||||
bdd.requete_unique(req);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================================================
|
||||
// Bascule de la visibilité d'une page
|
||||
//=============================================================================================================
|
||||
function toggle_validite(index)
|
||||
{
|
||||
var req;
|
||||
var priorite_affichage;
|
||||
|
||||
// Recherche de la valeur actuelle et calcul de la nouvelle :
|
||||
priorite_affichage = modele_grille_principale.get(index).priorite_affichage * (-1);
|
||||
|
||||
// Mise à jour de la nouvelle valeur dans le modèle :
|
||||
modele_grille_principale.set(index, {"priorite_affichage": priorite_affichage});
|
||||
|
||||
// Mis à jour de la nouvelle valeur dans la BDD :
|
||||
req = 'UPDATE TB_Pages SET Priorite_affichage=' + priorite_affichage + ' WHERE Cle_primaire=' + modele_grille_principale.get(index).id + ' ';
|
||||
//console.log("Requête = [ " + req + "; ]");
|
||||
bdd.requete_unique(req);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,509 @@
|
||||
//========================================================================================================================================================================
|
||||
// CONFIG_RESEAU_ETHERNET.QML
|
||||
// Ce fichier traite la configuration du réseau Ethernet
|
||||
// La page est appelée depuis la page parametres_avances.qml
|
||||
//========================================================================================================================================================================
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
import QtQml.Models
|
||||
|
||||
import qt.koriolan.shipheart 1.0
|
||||
|
||||
|
||||
|
||||
Shipheart_page {
|
||||
id: page_config_reseau_ethernet_wifi
|
||||
|
||||
|
||||
// Mis en forme :
|
||||
readonly property double pourcentage_largeur_colonne_gauche: 0.75
|
||||
readonly property double espace_colonnes_principales: 20
|
||||
readonly property double pourcentage_hauteur_ligne_haut: 0
|
||||
readonly property double espace_lignes_principales: 20
|
||||
readonly property double affichage_hauteur_utile: shipheart_hauteur_page - shipheart_hauteur_bandeau_haut - shipheart_hauteur_bandeau_bas
|
||||
|
||||
readonly property int hauteur_ligne_formulaire: 60
|
||||
readonly property double pourcentage_largeur_labels_formulaire: 0.45
|
||||
|
||||
readonly property int hauteur_bouton_droit: 80
|
||||
|
||||
readonly property double pourcentage_bandeau_bas_largeur_zone_retour: 1
|
||||
|
||||
|
||||
readonly property int periode_init_raffraichissement_parametres: 1 // En ms
|
||||
readonly property int periode_raffraichissement_parametres: 1000 // En ms
|
||||
|
||||
|
||||
|
||||
// Affichage :
|
||||
property bool bouton_bandeau_bas_zone_retour_actif: false
|
||||
property int protection_mode: 0
|
||||
property bool flag_init: true // Permet de bloquer certains affichage tant que l'init n'est pas terminée
|
||||
property int position_wifi_sta: 0
|
||||
property int position_wifi_ap: 0
|
||||
|
||||
// Données :
|
||||
property string bssid_wifi_sta: ""
|
||||
|
||||
// Modèles :
|
||||
// Note : les modèles chargés dans 'main.qml' n'ont pas à être rechargés dans les pages suivantes
|
||||
|
||||
|
||||
//===========================================================
|
||||
// Timer periode raffraichissement parametres :
|
||||
//===========================================================
|
||||
Timer {
|
||||
id: timer_raffraichissement_parametres
|
||||
interval: periode_init_raffraichissement_parametres
|
||||
triggeredOnStart: false
|
||||
running: true
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
if (interval == periode_init_raffraichissement_parametres) { // Premier passage, 1ms après le premier chargement
|
||||
interval = periode_raffraichissement_parametres;
|
||||
|
||||
init_page();
|
||||
}
|
||||
else if (!bouton_bandeau_bas_zone_retour_actif)
|
||||
{
|
||||
mise_a_jour();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================
|
||||
// Lorsque la page est sur le point d'être affichée dans la pile :
|
||||
//===========================================================
|
||||
StackView.onActivating: {
|
||||
mise_a_jour();
|
||||
}
|
||||
|
||||
// Titre de la page :
|
||||
Shipheart_titre_1 {titre:qsTr("Réseau Ethernet & Wifi"); 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;
|
||||
color: "transparent"
|
||||
|
||||
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
|
||||
|
||||
// Cf Ship2net.qml pour ajouter ici des champs de saisie...
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Ecran Milieu - Gauche :
|
||||
//-------------------------------------------------------
|
||||
Rectangle {
|
||||
id: zone_affichage_milieu_gauche
|
||||
x: 0
|
||||
y: shipheart_hauteur_bandeau_haut + zone_affichage_haut_gauche.height + espace_lignes_principales;
|
||||
width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2)
|
||||
height: (affichage_hauteur_utile * (1 - pourcentage_hauteur_ligne_haut)) - espace_lignes_principales;
|
||||
color: "transparent"
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Grille pour afficher les valeurs des paramètres non configurables :
|
||||
GridView {
|
||||
id: grille_informations
|
||||
|
||||
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_grille_informations
|
||||
delegate: Rectangle {
|
||||
width: zone_affichage_milieu_gauche.width
|
||||
height: visible ? hauteur_ligne_formulaire : 0
|
||||
color: "transparent"
|
||||
visible: !flag_init
|
||||
|
||||
// Sous-titre :
|
||||
Shipheart_titre_2 {
|
||||
titre: model.titre
|
||||
hauteur: shipheart_hauteur_bandeau_haut
|
||||
visible: !flag_init && (model.titre !== "")
|
||||
}
|
||||
|
||||
// Champ d'info :
|
||||
Shipheart_formulaire_label {
|
||||
text: model.nom_champ
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
visible: (model.titre === "")
|
||||
}
|
||||
Shipheart_formulaire_valeur_fixe {
|
||||
text: model.valeur_champ
|
||||
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
|
||||
x: parent.width * pourcentage_largeur_labels_formulaire
|
||||
visible: (model.titre === "")
|
||||
color: (model.etat === "NORMAL") ?
|
||||
couleur_blanc_casse :
|
||||
(model.etat === "OK") ? couleur_vert : couleur_rouge
|
||||
}
|
||||
Shipheart_formulaire_ligne_separation {
|
||||
haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse
|
||||
visible: (model.titre === "")
|
||||
}
|
||||
Shipheart_formulaire_ligne_separation {
|
||||
haut_bas_hautbas: shipheart_formulaire_ligne_separation_haute
|
||||
epaisseur_ligne: 2
|
||||
force: shipheart_formulaire_ligne_separation_force_elevee
|
||||
visible: (model.titre !== "")
|
||||
}
|
||||
}
|
||||
ListModel {
|
||||
id: modele_grille_informations
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// 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"
|
||||
|
||||
// ATTENTION : cette barre latérale n'est pas "standard", la 'column' habituelle a été supprimée pour permettre le positionnement des boutons à certaines hauteur...
|
||||
|
||||
// Bouton Wifi STA :
|
||||
Rectangle {
|
||||
y: position_wifi_sta * hauteur_ligne_formulaire
|
||||
width: parent.width
|
||||
height: hauteur_bouton_droit
|
||||
color: shipheart_couleur_fond_bouton
|
||||
radius: shipheart_rayon_bouton
|
||||
Text {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
font.pixelSize: 20
|
||||
text: qsTr("Modifier")
|
||||
color: couleur_blanc_casse
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
stackView.push("config_reseau_wifi_sta.qml");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Bouton Wifi AP :
|
||||
Rectangle {
|
||||
y: position_wifi_ap * hauteur_ligne_formulaire
|
||||
width: parent.width
|
||||
height: hauteur_bouton_droit
|
||||
color: shipheart_couleur_fond_bouton
|
||||
radius: shipheart_rayon_bouton
|
||||
Text {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
font.pixelSize: 20
|
||||
text: qsTr("Modifier")
|
||||
color: couleur_blanc_casse
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
stackView.push("config_reseau_wifi_ap.qml");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Bandeau bas :
|
||||
//-------------------------------------------------------
|
||||
Row {
|
||||
x: 0
|
||||
y: shipheart_hauteur_page - shipheart_hauteur_bandeau_bas;
|
||||
width: shipheart_largeur_page;
|
||||
height: shipheart_hauteur_bandeau_bas;
|
||||
spacing: 5
|
||||
padding: 5
|
||||
|
||||
//.................................................
|
||||
// Bouton retour
|
||||
//.................................................
|
||||
Rectangle {
|
||||
id: bandeau_bas_zone_retour
|
||||
width: (parent.width * pourcentage_bandeau_bas_largeur_zone_retour) - (2 * parent.padding)
|
||||
height: shipheart_hauteur_bandeau_bas - parent.topPadding - parent.bottomPadding;
|
||||
radius: shipheart_rayon_bouton
|
||||
color: shipheart_couleur_fond_bouton
|
||||
|
||||
Image {
|
||||
source: "/images/icone_retour.png"
|
||||
sourceSize.height: 30
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea { // Zone d'interaction. On est obligé de la mettre dans la grille pour que Rectangle et MouseArea soient frères ou parent/enfant ET qu'on n'occupe qu'un espace dans la grille.
|
||||
id: mouse_area_bandeau_bas_zone_retour
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
stackView.pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 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 mode_validation_maj;
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
// Mise à jour des informations non configurables :
|
||||
mise_a_jour();
|
||||
|
||||
flag_init = false;
|
||||
}
|
||||
|
||||
//=============================================================================================================
|
||||
// Mise à jour des valeurs courantes
|
||||
//=============================================================================================================
|
||||
function mise_a_jour()
|
||||
{
|
||||
var req, res;
|
||||
var nb;
|
||||
var i;
|
||||
var nom_champ, valeur_champ;
|
||||
var flag_valide;
|
||||
var wifi_sta_cde;
|
||||
var wifi_ap_cde;
|
||||
|
||||
modele_grille_informations.clear();
|
||||
|
||||
//=======================================================================================
|
||||
// Ethernet:
|
||||
//=======================================================================================
|
||||
modele_grille_informations.append({ "titre": qsTr("Ethernet"), "nom_champ": "", "valeur_champ": "" });
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
// Adresse IP Ethernet:
|
||||
req = 'SELECT Valeur FROM TB_Systeme WHERE Nom="Adresse_ip_ethernet" ';
|
||||
res = bdd.requete_unique(req);
|
||||
modele_grille_informations.append({ "titre": "",
|
||||
"nom_champ":qsTr("Adresse IP"),
|
||||
"valeur_champ": (res[0] === shipheart_adresse_ip_inconnue) ? qsTr("Non connecté") : res[0],
|
||||
"etat": (res[0] === shipheart_adresse_ip_inconnue) ? "NOK" : "OK"
|
||||
});
|
||||
|
||||
//=======================================================================================
|
||||
// Wifi STA :
|
||||
//=======================================================================================
|
||||
position_wifi_sta = modele_grille_informations.count;
|
||||
modele_grille_informations.append({ "titre": "Wifi STA [STAtion - " + qsTr("Connexion à un réseau existant") + "]", "nom_champ": "", "valeur_champ": "" });
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
// Commande_sta:
|
||||
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Wifi_sta_cde" ';
|
||||
res = bdd.requete_unique(req);
|
||||
wifi_sta_cde = Number(res[0]);
|
||||
modele_grille_informations.append({ "titre": "",
|
||||
"nom_champ":qsTr("Etat"),
|
||||
"valeur_champ": (wifi_sta_cde !== 0) ? qsTr("On") : qsTr("Off"),
|
||||
"etat": (wifi_sta_cde === 0) ? "NOK" : "NORMAL"
|
||||
});
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
// BSSID_STA :
|
||||
if (wifi_sta_cde !== 0)
|
||||
{
|
||||
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="BSSID_Wifi_sta" ';
|
||||
res = bdd.requete_unique(req);
|
||||
bssid_wifi_sta = res[0];
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
// SSid_STA & Pwd_STA :
|
||||
if (wifi_sta_cde !== 0)
|
||||
{
|
||||
var nom_reseau_wifi_sta = "--";
|
||||
var psk_reseau_wifi_sta = "--";
|
||||
if (bssid_wifi_sta !== "")
|
||||
{
|
||||
req = 'SELECT Nom, Psk FROM TB_Wifi_sta WHERE Bssid="' + bssid_wifi_sta + '" ';
|
||||
res = bdd.requete_unique(req);
|
||||
|
||||
nom_reseau_wifi_sta = res[0];
|
||||
psk_reseau_wifi_sta = res[1];
|
||||
}
|
||||
|
||||
modele_grille_informations.append({ "titre": "",
|
||||
"nom_champ":qsTr("Nom du réseau [SSID]"),
|
||||
"valeur_champ": nom_reseau_wifi_sta,
|
||||
"etat": "NORMAL"
|
||||
});
|
||||
/* modele_grille_informations.append({ "titre": "",
|
||||
"nom_champ":qsTr("Mot de passe d'accès au réseau"),
|
||||
"valeur_champ": psk_reseau_wifi_sta,
|
||||
"etat": "NORMAL"
|
||||
});
|
||||
*/
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
// Ip_STA :
|
||||
if (wifi_sta_cde !== 0)
|
||||
{
|
||||
req = 'SELECT Valeur FROM TB_Systeme WHERE Nom="Adresse_ip_wifi_sta" ';
|
||||
res = bdd.requete_unique(req);
|
||||
modele_grille_informations.append({ "titre": "",
|
||||
"nom_champ":qsTr("Adresse IP"),
|
||||
"valeur_champ": (res[0] === shipheart_adresse_ip_inconnue) ? qsTr("Non connecté") : res[0],
|
||||
"etat": (res[0] === shipheart_adresse_ip_inconnue) ? "NOK" : "OK"
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
//=======================================================================================
|
||||
// Wifi AP :
|
||||
//=======================================================================================
|
||||
position_wifi_ap = modele_grille_informations.count;
|
||||
modele_grille_informations.append({ "titre": "Wifi AP [Access Point - " + qsTr("Génération d'un réseau spécifique") + "]", "nom_champ": "", "valeur_champ": "" });
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
// Commande AP :
|
||||
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Wifi_ap_cde" ';
|
||||
res = bdd.requete_unique(req);
|
||||
wifi_ap_cde = Number(res[0]);
|
||||
modele_grille_informations.append({ "titre": "",
|
||||
"nom_champ":qsTr("Etat"),
|
||||
"valeur_champ": (wifi_ap_cde !== 0) ? qsTr("On") : qsTr("Off"),
|
||||
"etat": (wifi_ap_cde === 0) ? "NOK" : "NORMAL"
|
||||
});
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
// SSid_AP :
|
||||
if (wifi_ap_cde !== 0)
|
||||
{
|
||||
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Wifi_ap_ssid" ';
|
||||
res = bdd.requete_unique(req);
|
||||
modele_grille_informations.append({ "titre": "",
|
||||
"nom_champ":qsTr("Nom du réseau [SSID]"),
|
||||
"valeur_champ": res[0],
|
||||
"etat": "NORMAL"
|
||||
});
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
// Pwd_AP :
|
||||
/* if (wifi_ap_cde !== 0)
|
||||
{
|
||||
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Wifi_ap_pwd" ';
|
||||
res = bdd.requete_unique(req);
|
||||
modele_grille_informations.append({ "titre": "",
|
||||
"nom_champ":qsTr("Mot de passe d'accès au réseau"),
|
||||
"valeur_champ": res[0],
|
||||
"etat": "NORMAL"
|
||||
});
|
||||
}
|
||||
*/
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
// Canal :
|
||||
if (wifi_ap_cde !== 0)
|
||||
{
|
||||
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Wifi_ap_canal" ';
|
||||
res = bdd.requete_unique(req);
|
||||
|
||||
var canal = Number(res[0]);
|
||||
var freq;
|
||||
if (canal < 36) freq = "2.4";
|
||||
else freq = "5";
|
||||
|
||||
modele_grille_informations.append({ "titre": "",
|
||||
"nom_champ": qsTr("Canal"),
|
||||
"valeur_champ": canal + " [" + freq + "GHz]",
|
||||
"etat": "NORMAL"
|
||||
});
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
// Ip_AP :
|
||||
if (wifi_ap_cde !== 0)
|
||||
{
|
||||
req = 'SELECT Valeur FROM TB_Systeme WHERE Nom="Adresse_ip_wifi_ap" ';
|
||||
res = bdd.requete_unique(req);
|
||||
modele_grille_informations.append({ "titre": "",
|
||||
"nom_champ":qsTr("Adresse IP"),
|
||||
"valeur_champ": (res[0] === shipheart_adresse_ip_inconnue) ? qsTr("Non connecté") : res[0],
|
||||
"etat": (res[0] === shipheart_adresse_ip_inconnue) ? "NOK" : "OK"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================================================
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,346 @@
|
||||
//========================================================================================================================================================================
|
||||
// CONFIG_RESEAU_NMEA.QML
|
||||
// Ce fichier traite la configuration de PGNs NMEA2000. La page permet notamment de :
|
||||
// - Afficher tous les PGN/Field déjà configurés (présents ou absent mais utilisés sur un capteur)
|
||||
// - Afficher tous les PGN que ShipHeart peut traiter et qu'il a vu passer sur le réseau "récemment"
|
||||
// La page est appelée depuis la page PARAMETRES_AVANCES.
|
||||
//========================================================================================================================================================================
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
import qt.koriolan.shipheart 1.0
|
||||
import"fonctions_date_heure.js" as Fonctions_date_heure
|
||||
|
||||
|
||||
|
||||
Shipheart_page {
|
||||
id: page_config_reseau_nmea
|
||||
|
||||
|
||||
// Mis en forme :
|
||||
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.5
|
||||
readonly property int nombre_capteurs_affiches_sur_une_colonne: 8
|
||||
readonly property int nombre_sondes_affichees_sur_une_colonne: 8
|
||||
|
||||
readonly property double pourcentage_largeur_colonne_gauche: 0.75
|
||||
readonly property int espace_colonnes_principales: 20
|
||||
readonly property double pourcentage_bandeau_bas_largeur_zone_retour: 1.0
|
||||
|
||||
readonly property int periode_init_raffraichissement_parametres: 1 // En ms
|
||||
readonly property int periode_raffraichissement_parametres: 1000 // En ms /!\ Laisser à 1s afin que le compteur secondes fonctionne correctement...
|
||||
|
||||
|
||||
// Affichage :
|
||||
property int niveau_page: 0
|
||||
property int defaut_bus_ow: 0
|
||||
|
||||
|
||||
|
||||
// Modèles :
|
||||
// Note : les modèles chargés dans 'main.qml' n'ont pas à être rechargés dans les pages suivantes
|
||||
|
||||
|
||||
//===========================================================
|
||||
// Timer periode raffraichissement parametres :
|
||||
//===========================================================
|
||||
Timer {
|
||||
id: timer_raffraichissement_parametres
|
||||
interval: periode_init_raffraichissement_parametres
|
||||
triggeredOnStart: false
|
||||
running: true
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
if (interval == periode_init_raffraichissement_parametres) // Premier passage, 1ms après le premier chargement
|
||||
{
|
||||
interval = periode_raffraichissement_parametres;
|
||||
init_page();
|
||||
}
|
||||
else
|
||||
{
|
||||
mise_a_jour_donnees();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Titre de la page :
|
||||
Shipheart_titre_1 {titre:qsTr("Réseau NMEA2000"); hauteur: shipheart_hauteur_bandeau_haut}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Ecran de gauche (liste des PGNs) :
|
||||
//-------------------------------------------------------
|
||||
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 PGNs :
|
||||
GridView {
|
||||
id: grille_principale
|
||||
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
cellWidth: parent.width;
|
||||
cellHeight: affichage_hauteur_utile / nombre_sondes_affichees_sur_une_colonne
|
||||
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
|
||||
|
||||
delegate: Rectangle {
|
||||
width: grille_principale.cellWidth
|
||||
height: grille_principale.cellHeight
|
||||
color: "transparent"
|
||||
|
||||
Rectangle {
|
||||
width: parent.width - 10
|
||||
height: parent.height - 10
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
radius: shipheart_rayon_bouton
|
||||
color: shipheart_couleur_fond_bouton
|
||||
border.color: couleur_blanc_casse
|
||||
border.width: (actif === 0) ? 1 : 0
|
||||
|
||||
Text {
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Qt.AlignLeft
|
||||
verticalAlignment: Qt.AlignTop
|
||||
topPadding: 10
|
||||
leftPadding: 20
|
||||
text: "PGN : " + pgn + " - Field : " + field
|
||||
color: (actif === 1) ? couleur_gris_moyen : couleur_blanc_casse
|
||||
font.pixelSize: 14
|
||||
wrapMode: Label.Wrap
|
||||
}
|
||||
Text {
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Qt.AlignLeft
|
||||
verticalAlignment: Qt.AlignTop
|
||||
topPadding: 10
|
||||
leftPadding: parent.width / 4
|
||||
text: nom
|
||||
color: (actif === 1) ? couleur_gris_moyen : couleur_blanc_casse
|
||||
font.pixelSize: 16
|
||||
font.weight: Font.Bold
|
||||
wrapMode: Label.Wrap
|
||||
}
|
||||
Text {
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Qt.AlignRight
|
||||
verticalAlignment: Qt.AlignTop
|
||||
topPadding: 10
|
||||
rightPadding: 20
|
||||
text: Fonctions_date_heure.chaine_duree(age *1000) // age + " s"
|
||||
color: (actif === 1) ? couleur_gris_moyen : couleur_blanc_casse
|
||||
font.pixelSize: 14
|
||||
wrapMode: Label.Wrap
|
||||
}
|
||||
|
||||
Text {
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Qt.AlignLeft
|
||||
verticalAlignment: Qt.AlignBottom
|
||||
bottomPadding: 10
|
||||
leftPadding: 20
|
||||
text: nom_capteur
|
||||
color: (actif === 1) ? couleur_gris_moyen : couleur_blanc_casse
|
||||
font.pixelSize: 18
|
||||
font.weight: Font.Bold
|
||||
wrapMode: Label.Wrap
|
||||
}
|
||||
Text {
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Qt.AlignRight
|
||||
verticalAlignment: Qt.AlignBottom
|
||||
bottomPadding: 10
|
||||
rightPadding: 20
|
||||
visible: valeur_valide
|
||||
text: valeur
|
||||
color: (actif === 1) ? couleur_gris_moyen : couleur_blanc_casse
|
||||
font.pixelSize: 18
|
||||
font.bold: true
|
||||
}
|
||||
|
||||
}
|
||||
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.
|
||||
anchors.fill: parent
|
||||
enabled: actif === 0
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
stackView.push("config_capteur.qml", {"type_entrees": shipheart_capteur_type_entrees_nmea, "entrees": pgn + ":" + field});
|
||||
}
|
||||
}
|
||||
}
|
||||
ListModel {
|
||||
id: modele_grille_principale
|
||||
}
|
||||
Label {
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Qt.AlignHCenter
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
visible: parent.count === 0
|
||||
text: qsTr("Aucun PGN n'a encore été détecté sur le réseau NMEA2000...")
|
||||
color: couleur_rouge_transparent
|
||||
font.pixelSize: 15
|
||||
font.bold: true
|
||||
wrapMode: Label.Wrap
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Ecran de droite (liste des sondes de température) :
|
||||
//-------------------------------------------------------
|
||||
Rectangle {
|
||||
id: zone_affichage_droite
|
||||
x: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) + (espace_colonnes_principales / 2)
|
||||
y: shipheart_hauteur_bandeau_haut;
|
||||
width: (shipheart_largeur_page * (1 - pourcentage_largeur_colonne_gauche)) - (espace_colonnes_principales / 2)
|
||||
height: affichage_hauteur_utile
|
||||
color: "transparent"
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Bandeau bas :
|
||||
//-------------------------------------------------------
|
||||
Row {
|
||||
x: 0
|
||||
y: shipheart_hauteur_page - shipheart_hauteur_bandeau_bas;
|
||||
width: shipheart_largeur_page;
|
||||
height: shipheart_hauteur_bandeau_bas;
|
||||
padding: 5
|
||||
spacing: 5
|
||||
|
||||
//.................................................
|
||||
// Bouton retour
|
||||
//.................................................
|
||||
Rectangle {
|
||||
id: bandeau_bas_zone_retour
|
||||
width: (parent.width * pourcentage_bandeau_bas_largeur_zone_retour) - (2 * parent.padding)
|
||||
height: shipheart_hauteur_bandeau_bas - parent.topPadding - parent.bottomPadding;
|
||||
radius: shipheart_rayon_bouton
|
||||
color: shipheart_couleur_fond_bouton
|
||||
|
||||
Image {
|
||||
source: "/images/icone_retour.png"
|
||||
sourceSize.height: 30
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea { // Zone d'interaction. On est obligé de la mettre dans la grille pour que Rectangle et MouseArea soient frères ou parent/enfant ET qu'on n'occupe qu'un espace dans la grille.
|
||||
id: mouse_area_bandeau_bas_zone_retour
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
stackView.pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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()
|
||||
{
|
||||
niveau_page = stackView.depth - 1; // Permet de stocker le niveau de la page dans la Stackview
|
||||
|
||||
mise_a_jour_donnees();
|
||||
}
|
||||
|
||||
//=============================================================================================================
|
||||
// Mise à jour des données
|
||||
//=============================================================================================================
|
||||
function mise_a_jour_donnees()
|
||||
{
|
||||
var req, res;
|
||||
var i;
|
||||
var nb;
|
||||
|
||||
|
||||
//=======================================================================
|
||||
// Grille principale (liste des sondes de température configurées) :
|
||||
|
||||
modele_grille_principale.clear(); // RAZ des valeurs existantes
|
||||
|
||||
req = 'SELECT ';
|
||||
req += ' Pgn, ';
|
||||
req += ' Field, '
|
||||
req += ' Nom, ';
|
||||
req += ' Actif, ';
|
||||
req += ' (SELECT Unite FROM TB_Variables WHERE Cle_primaire=ID_Variable) AS Unite, ';
|
||||
req += ' Valeur, ';
|
||||
req += ' Precision_affichage_mesures,'
|
||||
req += ' (UNIX_TIMESTAMP() - UNIX_TIMESTAMP(Date_maj)) AS Age ';
|
||||
req += ' FROM TB_Nmea2000 ';
|
||||
req += ' ORDER BY Pgn, Field';
|
||||
//console.log("Requête = [ " + req + "; ]");
|
||||
nb = bdd.requete(req);
|
||||
|
||||
for (i = 0; i < nb; i ++)
|
||||
{
|
||||
res = bdd.lecture_ligne();
|
||||
if (!res.isEmpty)
|
||||
{
|
||||
modele_grille_principale.append({ "pgn": Number(res[0]),
|
||||
"field": Number(res[1]),
|
||||
"nom": res[2],
|
||||
"actif": Number(res[3]),
|
||||
"valeur": Number(res[5]).toFixed(Number(res[6])) + ((res[4] !== "") ? (" " + res[4]) : ""),
|
||||
"valeur_valide": true,
|
||||
"age": Number(res[7]),
|
||||
"nom_capteur": qsTr("PGN non affecté") });
|
||||
}
|
||||
}
|
||||
|
||||
// Mise à jour du nom des capteurs utilisant ces sondes :
|
||||
for (i = 0; i < modele_grille_principale.count; i ++)
|
||||
{
|
||||
if (modele_grille_principale.get(i).actif > 0)
|
||||
{
|
||||
req = 'SELECT Nom FROM TB_Capteurs WHERE Adresse_module=0 AND Type_entrees=' + shipheart_capteur_type_entrees_nmea + ' AND Entrees="' + modele_grille_principale.get(i).pgn + ':' + modele_grille_principale.get(i).field + '" ';
|
||||
//console.log("Requête = [ " + req + "; ]");
|
||||
var n = bdd.requete(req);
|
||||
if (n > 0)
|
||||
{
|
||||
res = bdd.lecture_ligne();
|
||||
modele_grille_principale.setProperty(i, "nom_capteur", res[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Mise à jour du champ 'valeur_valide' : :
|
||||
for (i = 0; i < modele_grille_principale.count; i ++)
|
||||
{
|
||||
if (modele_grille_principale.get(i).actif === 0) // On ne teste que les entrées qui sont Inactive (les Actives ont forcément une valeur valide)
|
||||
{
|
||||
// Recherche su au moins un PGN/Field pointe sur le même PGN et est actif (dans ce cas, le Compagnon et l'Appli maintiennent à jour les valeurs de tous les Fields, même ceux qui ne sont pas valides)
|
||||
req = 'SELECT COUNT(*) FROM TB_Nmea2000 WHERE Pgn=' + modele_grille_principale.get(i).pgn + ' AND Actif=1 ';
|
||||
//console.log("Requête = [ " + req + "; ]");
|
||||
res = bdd.requete_unique(req);
|
||||
if (Number(res[0]) === 0) modele_grille_principale.setProperty(i, "valeur_valide", false); // Si aucun PGN/Field pointant sur le même PGN n'est actif, alors la valeur ne sera jamais mise à jour et il vaut mieux ne pas l'afficher...
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,490 @@
|
||||
//========================================================================================================================================================================
|
||||
// CONFIG_RESEAU_ONE_WIRE.QML
|
||||
// Ce fichier traite la configuration des devices One Wire. La page permet notamment de :
|
||||
// - Afficher tous les capteurs déjà configurés (présents ou absent mais utilisés sur un capteur)
|
||||
// - Déclencher la recherche de nouveaux capteurs OW
|
||||
// La page est appelée depuis la page PARAMETRES_AVANCES.
|
||||
//========================================================================================================================================================================
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
import qt.koriolan.shipheart 1.0
|
||||
|
||||
|
||||
Shipheart_page {
|
||||
id: page_config_reseau_one_wire
|
||||
|
||||
|
||||
// Mis en forme :
|
||||
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.5
|
||||
readonly property int nombre_capteurs_affiches_sur_une_colonne: 8
|
||||
readonly property int nombre_sondes_affichees_sur_une_colonne: 8
|
||||
|
||||
readonly property double pourcentage_largeur_colonne_gauche: 0.75
|
||||
readonly property int espace_colonnes_principales: 20
|
||||
readonly property double pourcentage_bandeau_bas_largeur_zone_retour: 1.0
|
||||
|
||||
readonly property int periode_init_raffraichissement_parametres: 1 // En ms
|
||||
readonly property int periode_raffraichissement_parametres: 1000 // En ms /!\ Laisser à 1s afin que le compteur secondes fonctionne correctement...
|
||||
readonly property int periode_decouverte_reseau_ow: 10 // En secondes
|
||||
|
||||
// Affichage :
|
||||
property int niveau_page: 0
|
||||
property int defaut_bus_ow: 0
|
||||
property int compteur_secondes: periode_decouverte_reseau_ow // Cette init permet de débuter par une découverte réseau
|
||||
|
||||
|
||||
|
||||
// Modèles :
|
||||
// Note : les modèles chargés dans 'main.qml' n'ont pas à être rechargés dans les pages suivantes
|
||||
|
||||
|
||||
//===========================================================
|
||||
// Timer periode raffraichissement parametres :
|
||||
//===========================================================
|
||||
Timer {
|
||||
id: timer_raffraichissement_parametres
|
||||
interval: periode_init_raffraichissement_parametres
|
||||
triggeredOnStart: false
|
||||
running: true
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
if (interval == periode_init_raffraichissement_parametres) // Premier passage, 1ms après le premier chargement
|
||||
{
|
||||
interval = periode_raffraichissement_parametres;
|
||||
init_page();
|
||||
}
|
||||
|
||||
if (stackView.depth === (niveau_page + 1)) // Désactive le raffraichissement quand la page n'est pas activée dans la pile
|
||||
{
|
||||
|
||||
compteur_secondes ++;
|
||||
if (compteur_secondes >= periode_decouverte_reseau_ow)
|
||||
{
|
||||
compteur_secondes = 0;
|
||||
demande_decouverte_ow(); // On fait une découverte OW toutes les 10 secondes tant qu'on est sur cette page (et uniquement quand on est sur cette page !)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (compteur_secondes >= 2) mise_a_jour_donnees(); // La mise à jour des données se fait toutes les secondes, sauf entre 0 et 2s (pour laisser le temps à la découverte réseau de se terminer et ainsi éviter les affichages tronqués)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Titre de la page :
|
||||
Shipheart_titre_1 {titre:qsTr("Réseau One Wire"); hauteur: shipheart_hauteur_bandeau_haut}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Ecran de gauche (liste des capteurs) :
|
||||
//-------------------------------------------------------
|
||||
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 devices :
|
||||
GridView {
|
||||
id: grille_principale
|
||||
|
||||
width: parent.width
|
||||
height: affichage_hauteur_utile - (affichage_hauteur_utile / nombre_sondes_affichees_sur_une_colonne)
|
||||
cellWidth: parent.width;
|
||||
cellHeight: affichage_hauteur_utile / nombre_sondes_affichees_sur_une_colonne
|
||||
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
|
||||
visible: (defaut_bus_ow === 0)
|
||||
delegate: Rectangle {
|
||||
width: grille_principale.cellWidth
|
||||
height: grille_principale.cellHeight
|
||||
color: "transparent"
|
||||
|
||||
Rectangle {
|
||||
width: parent.width - 10
|
||||
height: parent.height - 10
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
radius: shipheart_rayon_bouton
|
||||
color: (erreur === 0) ? shipheart_couleur_fond_bouton : couleur_rouge_transparent
|
||||
border.color: couleur_blanc_casse
|
||||
border.width: ((affecte === 0) && (erreur === 0)) ? 1 : 0
|
||||
|
||||
Text {
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Qt.AlignLeft
|
||||
verticalAlignment: Qt.AlignTop
|
||||
topPadding: 10
|
||||
leftPadding: 20
|
||||
text: "ID : " + rom_code
|
||||
color: ((affecte === 1) && (erreur === 0)) ? couleur_gris_moyen : couleur_blanc_casse
|
||||
font.pixelSize: 14
|
||||
wrapMode: Label.Wrap
|
||||
}
|
||||
Text {
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Qt.AlignLeft
|
||||
verticalAlignment: Qt.AlignTop
|
||||
topPadding: 10
|
||||
leftPadding: parent.width / 2
|
||||
text: device_family + " [" + device_family_description + "]"
|
||||
color: ((affecte === 1) && (erreur === 0)) ? couleur_gris_moyen : couleur_blanc_casse
|
||||
font.pixelSize: 14
|
||||
wrapMode: Label.Wrap
|
||||
}
|
||||
Text {
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Qt.AlignLeft
|
||||
verticalAlignment: Qt.AlignBottom
|
||||
bottomPadding: 10
|
||||
leftPadding: 20
|
||||
text: nom
|
||||
color: ((affecte === 1) && (erreur === 0)) ? couleur_gris_moyen : couleur_blanc_casse
|
||||
font.pixelSize: 18
|
||||
font.weight: Font.Bold
|
||||
wrapMode: Label.Wrap
|
||||
}
|
||||
Text {
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Qt.AlignLeft
|
||||
verticalAlignment: Qt.AlignBottom
|
||||
bottomPadding: 10
|
||||
leftPadding: parent.width / 2
|
||||
text: emplacement
|
||||
color: ((affecte === 1) && (erreur === 0)) ? couleur_gris_moyen : couleur_blanc_casse
|
||||
font.pixelSize: 14
|
||||
wrapMode: Label.Wrap
|
||||
}
|
||||
Text {
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Qt.AlignRight
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
rightPadding: 20
|
||||
text: valeur
|
||||
color: ((affecte === 1) && (erreur === 0)) ? couleur_gris_moyen : couleur_blanc_casse
|
||||
font.pixelSize: 18
|
||||
font.bold: true
|
||||
// wrapMode: Label.Wrap
|
||||
}
|
||||
}
|
||||
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.
|
||||
anchors.fill: parent
|
||||
onPressAndHold: {
|
||||
shipheart_clic();
|
||||
stackView.push("config_reseau_one_wire_modification.qml", {"rom_code": rom_code});
|
||||
}
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
if (affecte === 0) stackView.push("config_capteur.qml", {"type_entrees": shipheart_capteur_type_entrees_ow, "entrees": rom_code});
|
||||
}
|
||||
}
|
||||
}
|
||||
ListModel {
|
||||
id: modele_grille_principale
|
||||
}
|
||||
Label {
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Qt.AlignHCenter
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
visible: parent.count === 0
|
||||
text: qsTr("Aucune sonde n'est encore installée...")
|
||||
color: couleur_rouge_transparent
|
||||
font.pixelSize: 15
|
||||
font.bold: true
|
||||
wrapMode: Label.Wrap
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: message_defaut_bus_ow
|
||||
|
||||
anchors.fill: parent
|
||||
color: "transparent"
|
||||
border.width: 3
|
||||
border.color: couleur_orange
|
||||
radius: shipheart_rayon_bouton
|
||||
visible: (defaut_bus_ow !== 0)
|
||||
|
||||
Text { // Affiche parfaitement 1, 2 ou 3 lignes de texte. A partir de 4 et 5, ça mort sur le contour du rectangle mais c'est encore lisible.
|
||||
id: etat_circuit
|
||||
width: parent.width - anchors.leftMargin;
|
||||
wrapMode: Text.Wrap
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
text: qsTr("Le bus One Wire est actuellement détecté en court-circuit. <br />Cet état ne présente aucun danger mais l'empêche de fonctionner. <br /><br />Vérifier le câblage correspondant jusqu'à ce que ce message disparaisse.");
|
||||
anchors {
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
font.pixelSize: 18
|
||||
color: couleur_blanc_casse
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Ecran de droite (liste des sondes de température) :
|
||||
//-------------------------------------------------------
|
||||
Rectangle {
|
||||
id: zone_affichage_droite
|
||||
x: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) + (espace_colonnes_principales / 2)
|
||||
y: shipheart_hauteur_bandeau_haut;
|
||||
width: (shipheart_largeur_page * (1 - pourcentage_largeur_colonne_gauche)) - (espace_colonnes_principales / 2)
|
||||
height: affichage_hauteur_utile
|
||||
color: "transparent"
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Bandeau bas :
|
||||
//-------------------------------------------------------
|
||||
Row {
|
||||
x: 0
|
||||
y: shipheart_hauteur_page - shipheart_hauteur_bandeau_bas;
|
||||
width: shipheart_largeur_page;
|
||||
height: shipheart_hauteur_bandeau_bas;
|
||||
padding: 5
|
||||
spacing: 5
|
||||
|
||||
//.................................................
|
||||
// Bouton retour
|
||||
//.................................................
|
||||
Rectangle {
|
||||
id: bandeau_bas_zone_retour
|
||||
width: (parent.width * pourcentage_bandeau_bas_largeur_zone_retour) - (2 * parent.padding)
|
||||
height: shipheart_hauteur_bandeau_bas - parent.topPadding - parent.bottomPadding;
|
||||
radius: shipheart_rayon_bouton
|
||||
color: shipheart_couleur_fond_bouton
|
||||
|
||||
Image {
|
||||
source: "/images/icone_retour.png"
|
||||
sourceSize.height: 30
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea { // Zone d'interaction. On est obligé de la mettre dans la grille pour que Rectangle et MouseArea soient frères ou parent/enfant ET qu'on n'occupe qu'un espace dans la grille.
|
||||
id: mouse_area_bandeau_bas_zone_retour
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
stackView.pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 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'.
|
||||
|
||||
|
||||
|
||||
|
||||
// Principes :
|
||||
// L'état de chaque device est caractérisé par 3 indicateurs :
|
||||
// - Affectation : indique si le device est utilisé par un capteur (ou un équipement en général).
|
||||
// - si 0 : le device n'est PAS utilisé
|
||||
// - si 1 : le device est utilisé
|
||||
// - Présence : indique si le device est physiquement présent (et donc qu'il a communiqué correctement lors de la dernière communication de la part du Compagnon)
|
||||
// - si 0 : le device est absent
|
||||
// - si 1 : le device est présent
|
||||
// - Etat : indique l'état du device lui-même ou, par extension, l'état du réseau.
|
||||
// - si 0 : le device fonctionne correctement
|
||||
// - si -1 : le device comporte une erreur interne
|
||||
// - si -2 : l'ensemble du bus est en erreur (cf alors également 'Defaut_bus_ow' dans TB_Système)
|
||||
//
|
||||
// Dans TB_One_wire, il n'y a JAMAIS d'entrée avec Présence=0 et Affectation=0. En effet, dans ce cas, l'entrée est supprimée.
|
||||
//
|
||||
// L'indicateur d'erreur est calculé comme la synthèse entre 'Etat<0' OU 'Affecté=1 ET Présence=0'. Si l'une de ces condition est vraie, l'indicateur d'erreur est vrai.
|
||||
// Au-delà de 'erreur' qui prévaut pour l'affichage, on utilise 'Affectation' pour indiquer si le device est occupé ou pas.
|
||||
//
|
||||
// En synthèse, on gère 3 états distincts pour un device :
|
||||
// 1. Erreur=0 et Affecté=1 : cas normal d'un device utilisé
|
||||
// 2. Erreur=0 et Affecté=0 : cas normal d'un device non utilisé
|
||||
// 3. Erreur=1 : cas d'un device en erreur (et a priori, utilisé car sinon, il est peu probabe qu'il soit dans la liste)
|
||||
// A noter qu'un 4ème état existe mais il est global : si TB_Systeme.defaut_bus_ow=1, une page dédiée est affichée sur tout l'écran pour indiquer un défaut bus global.
|
||||
|
||||
|
||||
//=============================================================================================================
|
||||
// Init de la page
|
||||
//=============================================================================================================
|
||||
function init_page()
|
||||
{
|
||||
niveau_page = stackView.depth - 1; // Permet de stocker le niveau de la page dans la Stackview
|
||||
|
||||
mise_a_jour_donnees();
|
||||
}
|
||||
|
||||
//=============================================================================================================
|
||||
// Mise à jour des données
|
||||
//=============================================================================================================
|
||||
function mise_a_jour_donnees()
|
||||
{
|
||||
var req, res;
|
||||
var i;
|
||||
var nb_sondes;
|
||||
var device_family;
|
||||
var device_family_description;
|
||||
var erreur;
|
||||
|
||||
|
||||
|
||||
//=======================================================================
|
||||
// Grille principale (liste des sondes de température configurées) :
|
||||
|
||||
modele_grille_principale.clear(); // RAZ des valeurs existantes
|
||||
|
||||
req = 'SELECT Valeur FROM TB_Systeme WHERE Nom="Defaut_bus_ow" ';
|
||||
res = bdd.requete_unique(req);
|
||||
defaut_bus_ow = Number(res[0]);
|
||||
|
||||
if (defaut_bus_ow === 0) // Si un défaut de bus OW est en cours, il est inutile d'afficher quoi que ce soit...
|
||||
{
|
||||
|
||||
req = 'SELECT ';
|
||||
req += ' Rom_code, ';
|
||||
req += ' CONV(substring_index(Rom_code,":",1), 16, 10) AS Type, ' // Extrait le premier octet du Rom_Code qui contient le Device-Family puis le convertit de Hexa en Décimal
|
||||
req += ' Affecte, ';
|
||||
req += ' Presence, ';
|
||||
req += ' Etat, ';
|
||||
req += ' Valeur, ';
|
||||
req += ' Emplacement ';
|
||||
req += ' FROM TB_One_wire ';
|
||||
req += ' ORDER BY Rom_code';
|
||||
nb_sondes = bdd.requete(req);
|
||||
//console.log("Requête =" + req + " et nb réponses = " + nb_sondes);
|
||||
|
||||
for (i = 0; i < nb_sondes; i ++)
|
||||
{
|
||||
res = bdd.lecture_ligne();
|
||||
if (!res.isEmpty)
|
||||
{
|
||||
// Recherche du type de device en fonction de ROM_CODE_0 :
|
||||
switch(Number(res[1]))
|
||||
{
|
||||
case 0x01: device_family = "DS1990A, DS1990R, DS2401, DS2411"; device_family_description= "Serial number"; break;
|
||||
case 0x02: device_family = "DS1991"; device_family_description= "Secure memory"; break;
|
||||
case 0x04: device_family = "DS2404"; device_family_description= "EconoRAM time chip"; break;
|
||||
case 0x05: device_family = "DS2405"; device_family_description= "Addressable switch"; break;
|
||||
case 0x06: device_family = "DS1993"; device_family_description= "4Kb Memory button"; break;
|
||||
case 0x08: device_family = "DS1992"; device_family_description= "1kb memory button"; break;
|
||||
case 0x0A: device_family = "DS1995"; device_family_description= "16kb memory button"; break;
|
||||
case 0x0B: device_family = "DS1985, DS2505"; device_family_description= "16kb add-only memory"; break;
|
||||
case 0x0C: device_family = "DS1996"; device_family_description= "64kb memory button"; break;
|
||||
case 0x0F: device_family = "DS1986, DS2506"; device_family_description= "64kb add-only memory"; break;
|
||||
case 0x10: device_family = "DS18S20"; device_family_description= "Temperature sensor"; break;
|
||||
case 0x12: device_family = "DS2406, DS2407"; device_family_description= "Dual addressable switch"; break;
|
||||
case 0x14: device_family = "DS1971, DS2430A"; device_family_description= "256b EEPROM"; break;
|
||||
case 0x16: device_family = "DS1954, DS1957"; device_family_description= "Coprocessor ibutton"; break;
|
||||
case 0x18: device_family = "DS1962, DS1963S"; device_family_description= "4kb monetary device with SHA"; break;
|
||||
case 0x1A: device_family = "DS1963L"; device_family_description= "4kb monetary device"; break;
|
||||
case 0x1B: device_family = "DS2436"; device_family_description= "Battery ID/monitor"; break;
|
||||
case 0x1C: device_family = "DS28E04-100"; device_family_description= "4kb EEPROM with PIO"; break;
|
||||
case 0x1D: device_family = "DS2423"; device_family_description= "4kb 1Wire RAM with counter"; break;
|
||||
case 0x1E: device_family = "DS2437"; device_family_description= "Smart battery monitor IC"; break;
|
||||
case 0x1F: device_family = "DS2409"; device_family_description= "Microlan coupler"; break;
|
||||
case 0x20: device_family = "DS2450"; device_family_description= "Quad ADC"; break;
|
||||
case 0x21: device_family = "DS1921G, DS1921H, DS1921Z"; device_family_description= "Thermochron loggers"; break;
|
||||
case 0x22: device_family = "DS1822"; device_family_description= "Econo digital thermometer"; break;
|
||||
case 0x23: device_family = "DS1973, DS2433"; device_family_description= "4kb EEPROM"; break;
|
||||
case 0x24: device_family = "DS2415"; device_family_description= "Time chip"; break;
|
||||
case 0x26: device_family = "DS2438"; device_family_description= "Smart battery monitor"; break;
|
||||
case 0x27: device_family = "DS2417"; device_family_description= "Time chip"; break;
|
||||
case 0x28: device_family = "DS18B20"; device_family_description= "Temperature sensor"; break; // Cas des DS18B20
|
||||
case 0x29: device_family = "DS2408"; device_family_description= "8-channel switch"; break;
|
||||
case 0x2C: device_family = "DS2890"; device_family_description= "Digital potentiometer"; break;
|
||||
case 0x2D: device_family = "DS1972, DS2431"; device_family_description= "1024b memory"; break;
|
||||
case 0x2E: device_family = "DS2770"; device_family_description= "Battery monitor/charge controller"; break;
|
||||
case 0x30: device_family = "DS2760"; device_family_description= "Precision li+ battery monitor"; break;
|
||||
case 0x31: device_family = "DS2720"; device_family_description= "Single cell li+ protection IC"; break;
|
||||
case 0x32: device_family = "DS2780"; device_family_description= "Fuel gauge IC"; break;
|
||||
case 0x33: device_family = "DS1961S, DS2432"; device_family_description= "1kb memory with SHA"; break;
|
||||
case 0x34: device_family = "DS2703"; device_family_description= "Sha battery authentication"; break;
|
||||
case 0x35: device_family = "DS2755"; device_family_description= "Fuel gauge"; break;
|
||||
case 0x36: device_family = "DS2740"; device_family_description= "Coulomb counter"; break;
|
||||
case 0x37: device_family = "DS1977"; device_family_description= "32kb memory"; break;
|
||||
case 0x3D: device_family = "DS2781"; device_family_description= "Fuel gauge IC"; break;
|
||||
case 0x3A: device_family = "DS2413"; device_family_description= "Two-channel switch"; break;
|
||||
case 0x3B: device_family = "DS1825, MAX31826, MAX31850"; device_family_description= "Temperature sensor, TC reader"; break;
|
||||
case 0x41: device_family = "DS1923, DS1922E, DS1922L, DS1922T"; device_family_description= "Hygrochrons"; break;
|
||||
case 0x42: device_family = "DS28EA00"; device_family_description= "Digital thermometer with sequence detect"; break;
|
||||
case 0x43: device_family = "DS28EC20"; device_family_description= "20kb memory"; break;
|
||||
case 0x44: device_family = "DS28E10"; device_family_description= "Sha1 authenticator"; break;
|
||||
case 0x51: device_family = "DS2751"; device_family_description= "Battery fuel gauge"; break;
|
||||
case 0x7E: device_family = "EDS00xx"; device_family_description= "EDS sensor adapter"; break;
|
||||
case 0x81: device_family = "USBID, DS1420"; device_family_description= "ID"; break;
|
||||
case 0x82: device_family = "DS1425"; device_family_description= "ID and pw protected RAM"; break;
|
||||
|
||||
default: device_family = "<i>" + qsTr("Type inconnu") + "</i>"; break;
|
||||
}
|
||||
|
||||
erreur = 0;
|
||||
if (Number(res[4]) < 0) erreur = 1;
|
||||
else
|
||||
{
|
||||
if ((Number(res[2]) === 1) && (Number(res[3]) === 0)) erreur = 1;
|
||||
}
|
||||
|
||||
//console.log("Sonde OW trouvée : ROM_Code = [" + res[0] + "] donc Device_type = " + device_family_description);
|
||||
modele_grille_principale.append({
|
||||
"rom_code": res[0],
|
||||
"nom": qsTr("Sonde non affectée"),
|
||||
"device_family": device_family,
|
||||
"device_family_description": device_family_description,
|
||||
"affecte": Number(res[2]),
|
||||
"presence": Number(res[3]),
|
||||
"erreur": erreur,
|
||||
"valeur": Number(res[5]).toFixed(2) + " °C",
|
||||
"emplacement": res[6] });
|
||||
console.log("ID:" + res[0] + " est " + Number(res[2]));
|
||||
}
|
||||
}
|
||||
|
||||
// Mise à jour du nom des capteurs utilisant ces sondes :
|
||||
for (i = 0; i < modele_grille_principale.count; i ++)
|
||||
{
|
||||
if (modele_grille_principale.get(i).affecte > 0)
|
||||
{
|
||||
req = 'SELECT Nom FROM TB_Capteurs WHERE Adresse_module=0 AND Type_entrees=' + shipheart_capteur_type_entrees_ow + ' AND Entrees="' + modele_grille_principale.get(i).rom_code + '" ';
|
||||
//console.log("Requête = [ " + req + "; ]");
|
||||
var nb = bdd.requete(req);
|
||||
if (nb > 0)
|
||||
{
|
||||
res = bdd.lecture_ligne();
|
||||
modele_grille_principale.setProperty(i, "nom", res[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================================================
|
||||
// Demande de découverte OW
|
||||
//=============================================================================================================
|
||||
function demande_decouverte_ow()
|
||||
{
|
||||
var req, res;
|
||||
var i;
|
||||
var nb;
|
||||
|
||||
req = 'UPDATE TB_Systeme SET Valeur=1 WHERE Nom="Demande_decouverte_ow" ';
|
||||
//console.log("req =" + req);
|
||||
bdd.requete_unique(req);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,264 @@
|
||||
//========================================================================================================================================================================
|
||||
// CONFIG_RESEAU_ONE_WIRE_MODIFICATION.QML
|
||||
// Ce fichier traite la configuration d'un device OW
|
||||
// La page est appelée depuis la page config_reseau_one_wire.qml, en cliquant sur un device
|
||||
//========================================================================================================================================================================
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
import QtQml.Models
|
||||
|
||||
import qt.koriolan.shipheart 1.0
|
||||
|
||||
|
||||
|
||||
Shipheart_page {
|
||||
id: page_config_reseau_one_wire_modification
|
||||
|
||||
|
||||
// Mis en forme :
|
||||
readonly property double pourcentage_largeur_colonne_gauche: 0.75
|
||||
readonly property double espace_colonnes_principales: 20
|
||||
readonly property double pourcentage_hauteur_ligne_haut: 1
|
||||
readonly property double espace_lignes_principales: 20
|
||||
readonly property double affichage_hauteur_utile: shipheart_hauteur_page - shipheart_hauteur_bandeau_haut - shipheart_hauteur_bandeau_bas
|
||||
|
||||
readonly property int hauteur_ligne_formulaire: 60
|
||||
readonly property double pourcentage_largeur_labels_formulaire: 0.4
|
||||
|
||||
readonly property int hauteur_bouton_droit: 80
|
||||
|
||||
readonly property double pourcentage_bandeau_bas_largeur_zone_retour: 1
|
||||
|
||||
readonly property int periode_init_raffraichissement_parametres: 1 // En ms
|
||||
readonly property int periode_raffraichissement_parametres: 1000 // En ms
|
||||
|
||||
// Affichage :
|
||||
|
||||
|
||||
// Données :
|
||||
property string rom_code;
|
||||
|
||||
// Modèles :
|
||||
// Note : les modèles chargés dans 'main.qml' n'ont pas à être rechargés dans les pages suivantes
|
||||
|
||||
|
||||
|
||||
//===========================================================
|
||||
// Timer periode raffraichissement parametres :
|
||||
//===========================================================
|
||||
Timer {
|
||||
id: timer_raffraichissement_parametres
|
||||
interval: periode_init_raffraichissement_parametres
|
||||
triggeredOnStart: false
|
||||
running: true
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
if (interval == periode_init_raffraichissement_parametres) { // Premier passage, 1ms après le premier chargement
|
||||
interval = periode_raffraichissement_parametres;
|
||||
|
||||
init_page();
|
||||
}
|
||||
else {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Titre de la page :
|
||||
Shipheart_titre_1 {titre:qsTr("Configuration de la sonde [%1]").arg(rom_code); 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"
|
||||
|
||||
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 : Emplacement
|
||||
Rectangle {
|
||||
width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2)
|
||||
implicitHeight: champ_formulaire_Emplacement.implicitHeight
|
||||
color: "transparent"
|
||||
|
||||
Shipheart_formulaire_label {
|
||||
text: qsTr("Emplacement de la sonde")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
}
|
||||
|
||||
Shipheart_formulaire_textarea {
|
||||
id: champ_formulaire_Emplacement
|
||||
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
|
||||
horizontalAlignment: Text.AlignJustify
|
||||
wrapMode: Label.Wrap
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Ligne d'extension pour laisser la liste remonter au-dessus de l'écran si besoin :
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: 100
|
||||
color: "transparent"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// 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 :
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: hauteur_bouton_droit
|
||||
color: shipheart_couleur_fond_bouton
|
||||
radius: shipheart_rayon_bouton
|
||||
// visible: !clavier.active // SDIR #255
|
||||
Text {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
font.pixelSize: 20
|
||||
text: qsTr("Enregistrer")
|
||||
color: couleur_blanc_casse
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
mise_a_jour();
|
||||
stackView.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Bandeau bas :
|
||||
//-------------------------------------------------------
|
||||
Row {
|
||||
x: 0
|
||||
y: shipheart_hauteur_page - shipheart_hauteur_bandeau_bas;
|
||||
width: shipheart_largeur_page;
|
||||
height: shipheart_hauteur_bandeau_bas;
|
||||
spacing: 5
|
||||
padding: 5
|
||||
|
||||
//.................................................
|
||||
// Bouton retour
|
||||
//.................................................
|
||||
Rectangle {
|
||||
id: bandeau_bas_zone_retour
|
||||
width: (parent.width * pourcentage_bandeau_bas_largeur_zone_retour) - (2 * parent.padding)
|
||||
height: shipheart_hauteur_bandeau_bas - parent.topPadding - parent.bottomPadding;
|
||||
radius: shipheart_rayon_bouton
|
||||
color: shipheart_couleur_fond_bouton
|
||||
|
||||
Image {
|
||||
source: "/images/icone_retour.png"
|
||||
sourceSize.height: 30
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea { // Zone d'interaction. On est obligé de la mettre dans la grille pour que Rectangle et MouseArea soient frères ou parent/enfant ET qu'on n'occupe qu'un espace dans la grille.
|
||||
id: mouse_area_bandeau_bas_zone_retour
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
stackView.pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 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;
|
||||
|
||||
//console.log("Rom_code = " + rom_code)
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
// Emplacement :
|
||||
req = 'SELECT Emplacement FROM TB_One_wire WHERE Rom_code="' + rom_code + '" ';
|
||||
//console.log("Requête = [ " + req + "; ]")
|
||||
res = bdd.requete_unique(req);
|
||||
|
||||
champ_formulaire_Emplacement.text = res[0];
|
||||
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================================================
|
||||
// Mise à jour des valeurs saisies
|
||||
//=============================================================================================================
|
||||
function mise_a_jour()
|
||||
{
|
||||
var req;
|
||||
var val;
|
||||
var texte_emplacement;
|
||||
var texte_commentaires;
|
||||
|
||||
texte_emplacement = champ_formulaire_Emplacement.text.replace(/\"/g, "\\\"");
|
||||
//console.log("Emplacement = [" + champ_formulaire_Emplacement.text + "] et texte modifié = [" + texte_emplacement + "]")
|
||||
|
||||
req = 'UPDATE TB_One_wire SET Emplacement="' + texte_emplacement + '" WHERE Rom_code="' + rom_code + '" ';
|
||||
//console.log("Requête = [ " + req + "; ]")
|
||||
bdd.requete_unique(req);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,555 @@
|
||||
//========================================================================================================================================================================
|
||||
// CONFIG_RESEAU_WIFI_AP.QML
|
||||
// Ce fichier traite la configuration du Wifi en mode AP
|
||||
// La page est appelée depuis la page parametres_avances.qml
|
||||
//========================================================================================================================================================================
|
||||
import QtQuick 2.12
|
||||
import QtQml.Models
|
||||
|
||||
import qt.koriolan.shipheart 1.0
|
||||
|
||||
|
||||
|
||||
Shipheart_page {
|
||||
id: page_config_reseau_wifi_ap
|
||||
|
||||
|
||||
// Mis en forme :
|
||||
readonly property double pourcentage_largeur_colonne_gauche: 0.75
|
||||
readonly property double espace_colonnes_principales: 20
|
||||
readonly property double espace_lignes_principales: 20
|
||||
readonly property double affichage_hauteur_utile: shipheart_hauteur_page - shipheart_hauteur_bandeau_haut - shipheart_hauteur_bandeau_bas
|
||||
|
||||
readonly property int hauteur_ligne_formulaire: 60
|
||||
readonly property double pourcentage_largeur_labels_formulaire: 0.4
|
||||
|
||||
readonly property int hauteur_bouton_droit: 80
|
||||
|
||||
readonly property double pourcentage_bandeau_bas_largeur_zone_retour: 1
|
||||
|
||||
|
||||
readonly property int periode_init_raffraichissement_parametres: 1 // En ms
|
||||
readonly property int periode_raffraichissement_parametres: 1000 // En ms
|
||||
|
||||
|
||||
|
||||
// Affichage :
|
||||
property int protection_mode: 0
|
||||
property bool flag_init: true // Permet de bloquer certains affichage tant que l'init n'est pas terminée
|
||||
|
||||
// Données :
|
||||
property string ip_ap: ""
|
||||
|
||||
|
||||
// Modèles :
|
||||
// Note : les modèles chargés dans 'main.qml' n'ont pas à être rechargés dans les pages suivantes
|
||||
|
||||
|
||||
//===========================================================
|
||||
// Timer periode raffraichissement parametres :
|
||||
//===========================================================
|
||||
Timer {
|
||||
id: timer_raffraichissement_parametres
|
||||
interval: periode_init_raffraichissement_parametres
|
||||
triggeredOnStart: false
|
||||
running: true
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
if (interval == periode_init_raffraichissement_parametres) { // Premier passage, 1ms après le premier chargement
|
||||
interval = periode_raffraichissement_parametres;
|
||||
|
||||
init_page();
|
||||
}
|
||||
else
|
||||
{
|
||||
mise_a_jour();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Titre de la page :
|
||||
Shipheart_titre_1 {titre:qsTr("Configuration Wifi en mode AP"); 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 - espace_lignes_principales;
|
||||
color: "transparent"
|
||||
|
||||
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 : Ap_Commande
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: visible ? hauteur_ligne_formulaire : 0
|
||||
color: "transparent"
|
||||
//visible: false
|
||||
|
||||
Shipheart_formulaire_label {
|
||||
text: qsTr("Etat")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
}
|
||||
|
||||
Shipheart_formulaire_combobox {
|
||||
id: champ_formulaire_Ap_commande
|
||||
model: ListModel { }
|
||||
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
|
||||
onActivated: {
|
||||
shipheart_clic();
|
||||
}
|
||||
}
|
||||
|
||||
Shipheart_formulaire_ligne_separation {
|
||||
haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Ligne de formulaire : AP_SSID
|
||||
Rectangle {
|
||||
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_Ap_commande.model.get(champ_formulaire_Ap_commande.currentIndex).valeur === 1)
|
||||
|
||||
Shipheart_formulaire_label {
|
||||
text: qsTr("Nom du réseau (SSID)")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
}
|
||||
|
||||
Shipheart_formulaire_textfield {
|
||||
id: champ_formulaire_Ap_ssid
|
||||
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 : AP_PWD
|
||||
Rectangle {
|
||||
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_Ap_commande.model.get(champ_formulaire_Ap_commande.currentIndex).valeur === 1)
|
||||
|
||||
Shipheart_formulaire_label {
|
||||
text: qsTr("Mot de passe d'accès au réseau")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
}
|
||||
|
||||
Shipheart_formulaire_textfield {
|
||||
id: champ_formulaire_Ap_pwd
|
||||
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 : AP_Canal
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: visible ? hauteur_ligne_formulaire : 0
|
||||
color: "transparent"
|
||||
visible: !flag_init && (champ_formulaire_Ap_commande.model.get(champ_formulaire_Ap_commande.currentIndex).valeur === 1)
|
||||
//visible: false
|
||||
|
||||
Shipheart_formulaire_label {
|
||||
text: qsTr("Canal")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
}
|
||||
|
||||
Shipheart_formulaire_combobox {
|
||||
id: champ_formulaire_Ap_canal
|
||||
model: ListModel { }
|
||||
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
|
||||
onActivated: {
|
||||
shipheart_clic();
|
||||
}
|
||||
}
|
||||
|
||||
Shipheart_formulaire_ligne_separation {
|
||||
haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Ligne de formulaire : Ip_AP
|
||||
Rectangle {
|
||||
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_Ap_commande.model.get(champ_formulaire_Ap_commande.currentIndex).valeur === 1)
|
||||
//visible: false
|
||||
|
||||
Shipheart_formulaire_label {
|
||||
text: qsTr("Adresse IP")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
}
|
||||
Shipheart_formulaire_valeur_fixe {
|
||||
text: (ip_ap === shipheart_adresse_ip_inconnue) ? qsTr("Non connecté") : ip_ap
|
||||
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
|
||||
x: parent.width * pourcentage_largeur_labels_formulaire
|
||||
padding: 10
|
||||
}
|
||||
Shipheart_formulaire_ligne_separation {
|
||||
haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// 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 - (espace_lignes_principales / 2);
|
||||
color: "transparent"
|
||||
|
||||
|
||||
Column {
|
||||
anchors.fill: parent
|
||||
spacing: 10
|
||||
|
||||
// Bouton Enregistrer :
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: hauteur_bouton_droit
|
||||
color: shipheart_couleur_fond_bouton
|
||||
radius: shipheart_rayon_bouton
|
||||
// visible: !clavier.active // SDIR #255
|
||||
Text {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
font.pixelSize: 20
|
||||
text: qsTr("Enregistrer")
|
||||
color: couleur_blanc_casse
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
var texte_erreur = check_saisie();
|
||||
if (texte_erreur === "")
|
||||
{
|
||||
enregistrement(); // Mise à jour des données saisies dans la BDD et reconfiguration par l'application pour prise en compte.
|
||||
stackView.pop(); // Retour aux Paramètres Avancés
|
||||
}
|
||||
else
|
||||
{
|
||||
boite_validation.niveau = 2
|
||||
boite_validation.imageTitreSource = "/images/attention.png"
|
||||
boite_validation.message = texte_erreur;
|
||||
boite_validation.open();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Bandeau bas :
|
||||
//-------------------------------------------------------
|
||||
Row {
|
||||
x: 0
|
||||
y: shipheart_hauteur_page - shipheart_hauteur_bandeau_bas;
|
||||
width: shipheart_largeur_page;
|
||||
height: shipheart_hauteur_bandeau_bas;
|
||||
spacing: 5
|
||||
padding: 5
|
||||
|
||||
//.................................................
|
||||
// Bouton retour
|
||||
//.................................................
|
||||
Rectangle {
|
||||
id: bandeau_bas_zone_retour
|
||||
width: (parent.width * pourcentage_bandeau_bas_largeur_zone_retour) - (2 * parent.padding)
|
||||
height: shipheart_hauteur_bandeau_bas - parent.topPadding - parent.bottomPadding;
|
||||
radius: shipheart_rayon_bouton
|
||||
color: shipheart_couleur_fond_bouton
|
||||
|
||||
Image {
|
||||
source: "/images/icone_retour.png"
|
||||
sourceSize.height: 30
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea { // Zone d'interaction. On est obligé de la mettre dans la grille pour que Rectangle et MouseArea soient frères ou parent/enfant ET qu'on n'occupe qu'un espace dans la grille.
|
||||
id: mouse_area_bandeau_bas_zone_retour
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
stackView.pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Boite de validation :
|
||||
// NB : il est important que ce composant soit directement
|
||||
// rattaché à la page pour qu'elle s'affiche en plein écran.
|
||||
//-------------------------------------------------------
|
||||
Shipheart_boite_dialogue {
|
||||
id: boite_validation
|
||||
boutonAnnuler: true
|
||||
onClicked: {
|
||||
switch(bouton)
|
||||
{
|
||||
case shipheart_boite_dialogue_bouton_1:
|
||||
break;
|
||||
case shipheart_boite_dialogue_bouton_2:
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 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;
|
||||
var commande_ap;
|
||||
var mode;
|
||||
var ap_canal;
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
// Commande AP :
|
||||
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Wifi_ap_cde" ';
|
||||
res = bdd.requete_unique(req);
|
||||
commande_ap = Number(res[0]);
|
||||
|
||||
champ_formulaire_Ap_commande.model.clear();
|
||||
champ_formulaire_Ap_commande.model.append({"valeur": 0, "texte": qsTr("Off") });
|
||||
champ_formulaire_Ap_commande.model.append({"valeur": 1, "texte": qsTr("On") });
|
||||
|
||||
// Positionnement de l'index sur la valeur en cours :
|
||||
i = recherche_index_valeur_modele(commande_ap, champ_formulaire_Ap_commande.model, "commande_ap");
|
||||
if (i === -1) champ_formulaire_Ap_commande.currentIndex = recherche_index_valeur_modele(1, champ_formulaire_Ap_commande.model, "commande_ap");
|
||||
else champ_formulaire_Ap_commande.currentIndex = i;
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
// SSid_AP :
|
||||
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Wifi_ap_ssid" ';
|
||||
res = bdd.requete_unique(req);
|
||||
champ_formulaire_Ap_ssid.text = res[0];
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
// Pwd_AP :
|
||||
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Wifi_ap_pwd" ';
|
||||
res = bdd.requete_unique(req);
|
||||
champ_formulaire_Ap_pwd.text = res[0];
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
// Canal :
|
||||
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Wifi_ap_canal" ';
|
||||
res = bdd.requete_unique(req);
|
||||
ap_canal = Number(res[0]);
|
||||
|
||||
champ_formulaire_Ap_canal.model.clear();
|
||||
var canaux = [];
|
||||
if (shipheart_generation_shipbase === shipheart_generation_shipbase_v1)
|
||||
{
|
||||
for (i=1; i <= 11; i ++) canaux.push(i); // Canaux accessibles en 2.4GHz
|
||||
}
|
||||
else if (shipheart_generation_shipbase === shipheart_generation_shipbase_v2)
|
||||
{
|
||||
for (i=1; i <= 13; i ++) canaux.push(i); // Canaux accessibles en 2.4GHz
|
||||
canaux.push(36); // Canaux accessibles en 5GHz (sans "logique" permettant d'éviter l'enregistrement manuel...)
|
||||
canaux.push(40);
|
||||
canaux.push(44);
|
||||
canaux.push(48);
|
||||
// Les canaux > 48 déclenchent une erreur... Ils apparaissent effectivement avec la mention '(no IR, radar detection)' dans le retour de 'iw list'.
|
||||
/* canaux.push(52);
|
||||
canaux.push(56);
|
||||
canaux.push(60);
|
||||
canaux.push(64);
|
||||
canaux.push(100);
|
||||
canaux.push(104);
|
||||
canaux.push(108);
|
||||
canaux.push(112);
|
||||
canaux.push(116);
|
||||
canaux.push(120);
|
||||
canaux.push(124);
|
||||
canaux.push(128);
|
||||
canaux.push(132);
|
||||
canaux.push(136);
|
||||
canaux.push(140);
|
||||
*/
|
||||
}
|
||||
// Remplissage du modèle :
|
||||
var freq;
|
||||
for (const canal of canaux)
|
||||
{
|
||||
if (canal < 36) freq = "2.4";
|
||||
else freq = "5";
|
||||
champ_formulaire_Ap_canal.model.append({"valeur": canal, "texte": qsTr("Canal %1 - [%2GHz]").arg(canal).arg(freq) });
|
||||
}
|
||||
|
||||
|
||||
// Positionnement de l'index sur la valeur en cours :
|
||||
i = recherche_index_valeur_modele(ap_canal, champ_formulaire_Ap_canal.model, "Canal");
|
||||
if (i === -1) champ_formulaire_Ap_canal.currentIndex = recherche_index_valeur_modele(11, champ_formulaire_Ap_canal.model, "Canal");
|
||||
else champ_formulaire_Ap_canal.currentIndex = i;
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
// Ip_AP :
|
||||
req = 'SELECT Valeur FROM TB_Systeme WHERE Nom="Adresse_ip_wifi_ap" ';
|
||||
res = bdd.requete_unique(req);
|
||||
ip_ap = res[0];
|
||||
|
||||
|
||||
flag_init = false; // Indique que l'init est terminée
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================================================
|
||||
// Mise à jour
|
||||
//=============================================================================================================
|
||||
function mise_a_jour()
|
||||
{
|
||||
var req, res;
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Mode AP
|
||||
//-------------------------------------------------------------------------------
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
// Ip_AP :
|
||||
req = 'SELECT Valeur FROM TB_Systeme WHERE Nom="Adresse_ip_wifi_ap" ';
|
||||
res = bdd.requete_unique(req);
|
||||
ip_ap = res[0];
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================================================
|
||||
// Check des valeurs saisies
|
||||
// Retourne une chaine vide si Ok, le message d'erreur si NOK
|
||||
//=============================================================================================================
|
||||
function check_saisie()
|
||||
{
|
||||
|
||||
if (champ_formulaire_Ap_commande.model.get(champ_formulaire_Ap_commande.currentIndex).valeur > 0)
|
||||
{
|
||||
var liste_caracteres_autorisés_ssid_ap = "-."; // En plus des chiffres et des lettres majuscules et minuscules
|
||||
var regex_ssid_ap = new RegExp("(^[0-9A-Za-z]+$)");
|
||||
var liste_caracteres_autorisés_pwd_ap = "-_./="; // En plus des chiffres et des lettres majuscules et minuscules
|
||||
var regex_pwd_ap = new RegExp("(^[0-9A-Za-z" + liste_caracteres_autorisés_pwd_ap + "]+$)");
|
||||
|
||||
if ((champ_formulaire_Ap_ssid.text.length < 1) || (champ_formulaire_Ap_ssid.text.length > 32)) return(qsTr("Le nom du réseau (SSID) doit comprendre entre 1 et 32 caractères. <br />Merci d'entrer un nom valide."));
|
||||
if ((champ_formulaire_Ap_pwd.text.length < 8) || (champ_formulaire_Ap_pwd.text.length > 63)) return(qsTr("Le mot de passe d'accès au réseau doit comprendre entre 8 et 63 caractères. <br />Merci d'entrer un mot de passe valide."));
|
||||
if (! regex_ssid_ap.test(champ_formulaire_Ap_ssid.text)) // S'il y a autre chose que le regex
|
||||
{
|
||||
return(qsTr("Le nom du réseau (SSID) doit comprendre uniquement :<br />- des lettres majuscules [A - Z],<br />- des lettres minuscules [a - z],<br />- des chiffres [0 - 9]<br />- les caractères spéciaux [%1].<br /><br />Merci d'entrer un nom valide.").arg(liste_caracteres_autorisés_ssid_ap));
|
||||
}
|
||||
if (! regex_pwd_ap.test(champ_formulaire_Ap_pwd.text)) // S'il y a autre chose que le regex
|
||||
{
|
||||
return(qsTr("Le mot de passe d'accès au réseau doit comprendre uniquement :<br />- des lettres majuscules [A - Z],<br />- des lettres minuscules [a - z],<br />- des chiffres [0 - 9]<br />- les caractères spéciaux [%1].<br /><br />Merci d'entrer un nom valide.").arg(liste_caracteres_autorisés_pwd_ap));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return("");
|
||||
}
|
||||
|
||||
//=============================================================================================================
|
||||
// Mise à jour des valeurs saisies
|
||||
//=============================================================================================================
|
||||
function enregistrement()
|
||||
{
|
||||
var req;
|
||||
|
||||
// Mise à jour des nouvelles valeurs dans la BDD :
|
||||
req = 'UPDATE TB_Configuration SET Valeur="' + champ_formulaire_Ap_commande.model.get(champ_formulaire_Ap_commande.currentIndex).valeur + '" WHERE Nom="Wifi_ap_cde" ';
|
||||
bdd.requete_unique(req);
|
||||
req = 'UPDATE TB_Configuration SET Valeur="' + champ_formulaire_Ap_ssid.text + '" WHERE Nom="Wifi_ap_ssid" ';
|
||||
bdd.requete_unique(req);
|
||||
req = 'UPDATE TB_Configuration SET Valeur="' + champ_formulaire_Ap_pwd.text + '" WHERE Nom="Wifi_ap_pwd" ';
|
||||
bdd.requete_unique(req);
|
||||
req = 'UPDATE TB_Configuration SET Valeur="' + champ_formulaire_Ap_canal.model.get(champ_formulaire_Ap_canal.currentIndex).valeur + '" WHERE Nom="Wifi_ap_canal" ';
|
||||
bdd.requete_unique(req);
|
||||
|
||||
// Demande de rechargement de la config du Wifi :
|
||||
req = 'UPDATE TB_Configuration SET Valeur=1 WHERE Nom="Wifi_new_config" ';
|
||||
bdd.requete_unique(req);
|
||||
}
|
||||
|
||||
//=============================================================================================================
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,591 @@
|
||||
//========================================================================================================================================================================
|
||||
// CONFIG_RESEAU_WIFI_STA.QML
|
||||
// Ce fichier traite la configuration du Wifi en mode STA
|
||||
// La page est appelée depuis la page parametres_avances.qml
|
||||
//========================================================================================================================================================================
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
import QtQml.Models
|
||||
|
||||
import qt.koriolan.shipheart 1.0
|
||||
|
||||
|
||||
|
||||
Shipheart_page {
|
||||
id: page_config_reseau_wifi_sta
|
||||
|
||||
|
||||
// Mis en forme :
|
||||
readonly property double pourcentage_largeur_colonne_gauche: 0.75
|
||||
readonly property double espace_colonnes_principales: 20
|
||||
readonly property double espace_lignes_principales: 20
|
||||
readonly property double affichage_hauteur_utile: shipheart_hauteur_page - shipheart_hauteur_bandeau_haut - shipheart_hauteur_bandeau_bas
|
||||
|
||||
readonly property int hauteur_ligne_formulaire: 60
|
||||
readonly property double pourcentage_largeur_labels_formulaire: 0.4
|
||||
|
||||
readonly property int hauteur_bouton_droit: 80
|
||||
|
||||
readonly property double pourcentage_bandeau_bas_largeur_zone_retour: 1
|
||||
|
||||
|
||||
readonly property int periode_init_raffraichissement_parametres: 1 // En ms
|
||||
readonly property int periode_raffraichissement_parametres: 1000 // En ms
|
||||
readonly property int step_timer_appui_long: 30 // en ms
|
||||
readonly property int periode_scan_wifi_sta: 15 // en s
|
||||
|
||||
|
||||
|
||||
// Affichage :
|
||||
property int protection_mode: 0
|
||||
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 compteur_scan_wifi_sta: 0
|
||||
property int stackview_niveau_page: 0
|
||||
property string bssid: ""
|
||||
property bool flag_pwd_visible: false
|
||||
property bool flag_wifi_sta_up: false
|
||||
|
||||
|
||||
// Modèles :
|
||||
// Note : les modèles chargés dans 'main.qml' n'ont pas à être rechargés dans les pages suivantes
|
||||
|
||||
|
||||
|
||||
//===========================================================
|
||||
// Timer periode raffraichissement parametres :
|
||||
//===========================================================
|
||||
Timer {
|
||||
id: timer_raffraichissement_parametres
|
||||
interval: periode_init_raffraichissement_parametres
|
||||
triggeredOnStart: false
|
||||
running: true
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
if (interval == periode_init_raffraichissement_parametres) { // Premier passage, 1ms après le premier chargement
|
||||
interval = periode_raffraichissement_parametres;
|
||||
|
||||
init_page();
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (stackView.depth === stackview_niveau_page) // Permet d'éviter les raffraichissements si on est sur la page de liste des réseaux
|
||||
{
|
||||
mise_a_jour();
|
||||
|
||||
if (-- compteur_scan_wifi_sta <= 0) // Une demande est faite au démarrage de la page
|
||||
{
|
||||
if (flag_wifi_sta_up) demande_de_scan(); // Si le réseau est down, ce n'est pas la peine de faire un scan (yne erreur est émise par le shell dans ce cas mais rien de bloquant)
|
||||
compteur_scan_wifi_sta = periode_scan_wifi_sta ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================
|
||||
// Lorsque la page est sur le point d'être affichée dans la pile :
|
||||
//===========================================================
|
||||
StackView.onActivating: {
|
||||
compteur_scan_wifi_sta = 0;
|
||||
}
|
||||
|
||||
// Titre de la page :
|
||||
Shipheart_titre_1 {titre:qsTr("Configuration Wifi en mode STA"); 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 - espace_lignes_principales;
|
||||
color: "transparent"
|
||||
|
||||
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 : STA_Commande
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: visible ? hauteur_ligne_formulaire : 0
|
||||
color: "transparent"
|
||||
//visible: false
|
||||
|
||||
Shipheart_formulaire_label {
|
||||
text: qsTr("Etat")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
}
|
||||
|
||||
Shipheart_formulaire_combobox {
|
||||
id: champ_formulaire_Sta_commande
|
||||
model: ListModel { }
|
||||
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
|
||||
onActivated: {
|
||||
shipheart_clic();
|
||||
}
|
||||
}
|
||||
|
||||
Shipheart_formulaire_ligne_separation {
|
||||
haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Ligne de formulaire : STA_Liste_ssid
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: visible ? hauteur_ligne_formulaire : 0
|
||||
color: "transparent"
|
||||
visible: !flag_init && (champ_formulaire_Sta_commande.model.get(champ_formulaire_Sta_commande.currentIndex).valeur === 1)
|
||||
|
||||
Shipheart_formulaire_label {
|
||||
text: qsTr("Réseau")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
}
|
||||
|
||||
Shipheart_formulaire_combobox {
|
||||
id: champ_formulaire_Sta_liste_ssid
|
||||
model: ListModel { }
|
||||
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
|
||||
onActivated: {
|
||||
shipheart_clic();
|
||||
// Mémorisation du BSSID choisit (permet que les mise à jour de la liste de scan ne remette pas en cause ce choix) :
|
||||
bssid = champ_formulaire_Sta_liste_ssid.model.get(champ_formulaire_Sta_liste_ssid.currentIndex).bssid;
|
||||
// Pré-remplissage du Psk du nouveau réseau sélectionné (s'il était déjà connu) :
|
||||
champ_formulaire_Sta_psk.text = champ_formulaire_Sta_liste_ssid.model.get(champ_formulaire_Sta_liste_ssid.currentIndex).psk;
|
||||
// Mise à jour du flag de masquage de Pwd :
|
||||
flag_pwd_visible = champ_formulaire_Sta_liste_ssid.model.get(champ_formulaire_Sta_liste_ssid.currentIndex).connu;
|
||||
}
|
||||
}
|
||||
|
||||
Shipheart_formulaire_ligne_separation {
|
||||
haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Ligne de formulaire : STA_PSK
|
||||
Rectangle {
|
||||
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_Sta_commande.model.get(champ_formulaire_Sta_commande.currentIndex).valeur === 1) &&
|
||||
(champ_formulaire_Sta_liste_ssid.currentIndex !== 0)
|
||||
|
||||
Shipheart_formulaire_label {
|
||||
text: qsTr("Mot de passe d'accès au réseau")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
}
|
||||
|
||||
Shipheart_formulaire_textfield {
|
||||
id: champ_formulaire_Sta_psk
|
||||
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
|
||||
x: parent.width * pourcentage_largeur_labels_formulaire
|
||||
password_type: flag_pwd_visible
|
||||
}
|
||||
|
||||
Shipheart_formulaire_ligne_separation {
|
||||
haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// 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 - (espace_lignes_principales / 2);
|
||||
color: "transparent"
|
||||
|
||||
|
||||
Column {
|
||||
anchors.fill: parent
|
||||
spacing: 10
|
||||
|
||||
//.......................................................
|
||||
// Bouton Enregistrer :
|
||||
//.......................................................
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: hauteur_bouton_droit
|
||||
color: shipheart_couleur_fond_bouton
|
||||
radius: shipheart_rayon_bouton
|
||||
visible: !flag_init
|
||||
// && !clavier.active // SDIR #255
|
||||
/* &&
|
||||
(
|
||||
(champ_formulaire_Sta_commande.model.get(champ_formulaire_Sta_commande.currentIndex).valeur === 0) // Commande OFF
|
||||
|| // OU
|
||||
( (champ_formulaire_Sta_liste_ssid.currentIndex !== 0) // Réseau existant choisit
|
||||
&& // ET
|
||||
(champ_formulaire_Sta_psk.text.length > 0) ) // Psk non vide (il sera validé au moment de l'enregistrement pour le contenu)
|
||||
)
|
||||
*/
|
||||
Text {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
font.pixelSize: 20
|
||||
text: qsTr("Enregistrer")
|
||||
color: couleur_blanc_casse
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
var texte_erreur = check_saisie();
|
||||
if (texte_erreur === "")
|
||||
{
|
||||
enregistrement(); // Mise à jour des données saisies dans la BDD et reconfiguration par l'application pour prise en compte.
|
||||
stackView.pop(); // Retour aux Paramètres Avancés
|
||||
}
|
||||
else
|
||||
{
|
||||
boite_validation.niveau = 2
|
||||
boite_validation.imageTitreSource = "/images/attention.png"
|
||||
boite_validation.message = texte_erreur;
|
||||
boite_validation.open();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//.......................................................
|
||||
// Bouton Liste des réseaux :
|
||||
//.......................................................
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: hauteur_bouton_droit
|
||||
color: shipheart_couleur_fond_bouton
|
||||
radius: shipheart_rayon_bouton
|
||||
visible: !flag_init && !clavier.active
|
||||
Text {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
font.pixelSize: 20
|
||||
text: qsTr("Réseaux connus")
|
||||
color: couleur_blanc_casse
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
stackView.push("config_reseau_wifi_sta_liste.qml");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Bandeau bas :
|
||||
//-------------------------------------------------------
|
||||
Row {
|
||||
x: 0
|
||||
y: shipheart_hauteur_page - shipheart_hauteur_bandeau_bas;
|
||||
width: shipheart_largeur_page;
|
||||
height: shipheart_hauteur_bandeau_bas;
|
||||
spacing: 5
|
||||
padding: 5
|
||||
|
||||
//.................................................
|
||||
// Bouton retour
|
||||
//.................................................
|
||||
Rectangle {
|
||||
id: bandeau_bas_zone_retour
|
||||
width: (parent.width * pourcentage_bandeau_bas_largeur_zone_retour) - (2 * parent.padding)
|
||||
height: shipheart_hauteur_bandeau_bas - parent.topPadding - parent.bottomPadding;
|
||||
radius: shipheart_rayon_bouton
|
||||
color: shipheart_couleur_fond_bouton
|
||||
|
||||
Image {
|
||||
source: "/images/icone_retour.png"
|
||||
sourceSize.height: 30
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea { // Zone d'interaction. On est obligé de la mettre dans la grille pour que Rectangle et MouseArea soient frères ou parent/enfant ET qu'on n'occupe qu'un espace dans la grille.
|
||||
id: mouse_area_bandeau_bas_zone_retour
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
stackView.pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Boite de validation :
|
||||
// NB : il est important que ce composant soit directement
|
||||
// rattaché à la page pour qu'elle s'affiche en plein écran.
|
||||
//-------------------------------------------------------
|
||||
Shipheart_boite_dialogue {
|
||||
id: boite_validation
|
||||
boutonAnnuler: true
|
||||
onClicked: {
|
||||
switch(bouton)
|
||||
{
|
||||
case shipheart_boite_dialogue_bouton_1:
|
||||
break;
|
||||
case shipheart_boite_dialogue_bouton_2:
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 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;
|
||||
var commande_sta;
|
||||
var commande_ap;
|
||||
var mode;
|
||||
var ap_canal;
|
||||
|
||||
|
||||
|
||||
stackview_niveau_page = stackView.depth;
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Mode STA
|
||||
//-------------------------------------------------------------------------------
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
// Bssid_sta:
|
||||
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="BSSID_Wifi_sta" ';
|
||||
res = bdd.requete_unique(req);
|
||||
bssid = res[0];
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
// Commande_sta:
|
||||
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Wifi_sta_cde" ';
|
||||
res = bdd.requete_unique(req);
|
||||
commande_sta = Number(res[0]);
|
||||
|
||||
champ_formulaire_Sta_commande.model.clear();
|
||||
champ_formulaire_Sta_commande.model.append({"valeur": 0, "texte": qsTr("Off") });
|
||||
champ_formulaire_Sta_commande.model.append({"valeur": 1, "texte": qsTr("On") });
|
||||
|
||||
// Positionnement de l'index sur la valeur en cours :
|
||||
i = recherche_index_valeur_modele(commande_sta, champ_formulaire_Sta_commande.model, "commande_sta");
|
||||
if (i === -1) champ_formulaire_Sta_commande.currentIndex = recherche_index_valeur_modele(1, champ_formulaire_Sta_commande.model, "commande_sta");
|
||||
else champ_formulaire_Sta_commande.currentIndex = i;
|
||||
|
||||
|
||||
mise_a_jour();
|
||||
|
||||
flag_init = false; // Indique que l'init est terminée
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================================================
|
||||
// Mise à jour
|
||||
//=============================================================================================================
|
||||
function mise_a_jour()
|
||||
{
|
||||
var req, res;
|
||||
var nb;
|
||||
var i;
|
||||
var index_en_cours;
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
// Wifi STA Up :
|
||||
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Wifi_sta_cde" ';
|
||||
res = bdd.requete_unique(req);
|
||||
flag_wifi_sta_up = (Number(res[0]) !== 0);
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
// Sta_liste_ssid :
|
||||
index_en_cours = 0;
|
||||
champ_formulaire_Sta_liste_ssid.model.clear();
|
||||
champ_formulaire_Sta_liste_ssid.model.append({
|
||||
"texte": qsTr("Aucun réseau..."),
|
||||
"bssid": "",
|
||||
"nom_ssid": "",
|
||||
"psk": "",
|
||||
"canal_ssid": 0,
|
||||
"qualite_ssid": 0,
|
||||
"connu": false });
|
||||
|
||||
req = 'SELECT Bssid, Presence, Nom, Psk, Canal, Qualite, Connu FROM TB_Wifi_sta ORDER BY Qualite DESC ';
|
||||
//console.log("req = [ " + req + " ;]");
|
||||
nb = bdd.requete(req);
|
||||
|
||||
for (i = 0; i < nb; i ++)
|
||||
{
|
||||
res = bdd.lecture_ligne();
|
||||
if (!res.isEmpty)
|
||||
{
|
||||
if (bssid === res[0])
|
||||
{
|
||||
index_en_cours = champ_formulaire_Sta_liste_ssid.model.count;
|
||||
if (flag_init) champ_formulaire_Sta_psk.text = res[3]; // On précharge le Psk à l'init (ensuite, c'est uniquement si changement de BSSID)
|
||||
}
|
||||
else if (Number(res[1]) === 0) continue; // Si le réseau n'est pas présent et n'est pas celui en cours, on ne le présente pas
|
||||
|
||||
champ_formulaire_Sta_liste_ssid.model.append({
|
||||
"texte": "<table width='95%'><tbody><tr><td colspan='3'><b>" + res[2] + "</b></td></tr> <tr style=\"font-size:14px\"><td>" + res[0] + "</td><td align='center'>" + ((Number(res[4]) < 20) ? "2.4GHz" : "5GHz") + " - Channel " + res[4] + "</td><td align='right'>[" + Number(res[5]) + " %]</td></tr> <tbody></table>",
|
||||
"bssid": res[0],
|
||||
"nom_ssid": res[2],
|
||||
"psk": res[3],
|
||||
"canal_ssid": Number(res[4]),
|
||||
"qualite_ssid": Number(res[5]),
|
||||
"connu": (Number(res[6]) === 1)});
|
||||
}
|
||||
else break; // Ne devrait pas arriver....
|
||||
}
|
||||
|
||||
//console.log("index en cours = " + index_en_cours);
|
||||
champ_formulaire_Sta_liste_ssid.currentIndex = index_en_cours;
|
||||
flag_pwd_visible = champ_formulaire_Sta_liste_ssid.model.get(index_en_cours).connu;
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================================================
|
||||
// Check des valeurs saisies
|
||||
// Retourne une chaine vide si Ok, le message d'erreur si NOK
|
||||
//=============================================================================================================
|
||||
function check_saisie()
|
||||
{
|
||||
|
||||
if (champ_formulaire_Sta_commande.model.get(champ_formulaire_Sta_commande.currentIndex).valeur > 0)
|
||||
{
|
||||
|
||||
// NOTE : la mise en commentaires ci-dessosu vient du fait qu'il y a peu d'intérêt à verrouiller le contenu et la taille du SSID comme du PSK.
|
||||
// L'idée est en effet que l'on s'adapte à des réseaux existants donc, si les valeurs entrées leur conviennent, à nous aussi...
|
||||
/* var liste_caracteres_autorisés_ssid_sta = "-. "; // En plus des chiffres et des lettres majuscules et minuscules
|
||||
var regex_ssid_sta = new RegExp("(^[0-9A-Za-z" + liste_caracteres_autorisés_ssid_sta + "]+$)");
|
||||
var liste_caracteres_autorisés_pwd_sta = "-_./="; // En plus des chiffres et des lettres majuscules et minuscules
|
||||
var regex_pwd_sta = new RegExp("(^[0-9A-Za-z" + liste_caracteres_autorisés_pwd_sta + "]+$)");
|
||||
|
||||
if ((champ_formulaire_Sta_liste_ssid.model.get(champ_formulaire_Sta_liste_ssid.currentIndex).nom_ssid.length < 1) || (champ_formulaire_Sta_liste_ssid.model.get(champ_formulaire_Sta_liste_ssid.currentIndex).nom_ssid.length > 32)) return(qsTr("Le nom du réseau (SSID) doit comprendre entre 1 et 32 caractères. <br />Merci d'entrer un nom valide."));
|
||||
if ((champ_formulaire_Sta_psk.text.length < 8) || (champ_formulaire_Sta_psk.text.length > 63)) return(qsTr("Le mot de passe d'accès au réseau doit comprendre entre 8 et 63 caractères. <br />Merci d'entrer un mot de passe valide."));
|
||||
if (! regex_ssid_sta.test(champ_formulaire_Sta_liste_ssid.model.get(champ_formulaire_Sta_liste_ssid.currentIndex).nom_ssid)) // S'il y a autre chose que le regex
|
||||
{
|
||||
return(qsTr("Le nom du réseau (SSID) doit comprendre uniquement :<br />- des lettres majuscules [A - Z],<br />- des lettres minuscules [a - z],<br />- des chiffres [0 - 9]<br />- les caractères spéciaux [%1].<br /><br />Merci d'entrer un nom valide.").arg(liste_caracteres_autorisés_ssid_sta));
|
||||
}
|
||||
if (! regex_pwd_sta.test(champ_formulaire_Sta_psk.text)) // S'il y a autre chose que le regex
|
||||
{
|
||||
return(qsTr("Le mot de passe d'accès au réseau doit comprendre uniquement :<br />- des lettres majuscules [A - Z],<br />- des lettres minuscules [a - z],<br />- des chiffres [0 - 9]<br />- les caractères spéciaux [%1].<br /><br />Merci d'entrer un nom valide.").arg(liste_caracteres_autorisés_pwd_sta));
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
return("");
|
||||
}
|
||||
|
||||
//=============================================================================================================
|
||||
// Mise à jour des valeurs saisies
|
||||
//=============================================================================================================
|
||||
function enregistrement()
|
||||
{
|
||||
var req;
|
||||
|
||||
// Mise à jour dans TB_Configuration :
|
||||
req = 'UPDATE TB_Configuration SET Valeur="' + champ_formulaire_Sta_commande.model.get(champ_formulaire_Sta_commande.currentIndex).valeur + '" WHERE Nom="Wifi_sta_cde" ';
|
||||
bdd.requete_unique(req);
|
||||
req = 'UPDATE TB_Configuration SET Valeur="' + champ_formulaire_Sta_liste_ssid.model.get(champ_formulaire_Sta_liste_ssid.currentIndex).bssid + '" WHERE Nom="BSSID_Wifi_sta" ';
|
||||
bdd.requete_unique(req);
|
||||
|
||||
// Mise à jour des données du réseau choisit dans TB_Wifi_sta (si le BSSID est autre que AUCUN) :
|
||||
if (champ_formulaire_Sta_liste_ssid.model.get(champ_formulaire_Sta_liste_ssid.currentIndex).bssid !== "")
|
||||
{
|
||||
req = 'UPDATE TB_Wifi_sta SET ';
|
||||
req += ' Psk="' + champ_formulaire_Sta_psk.text + '", ';
|
||||
req += ' Connu=1 ';
|
||||
req += ' WHERE Bssid="' + bssid + '" ';
|
||||
console.log("req = [ " + req + " ;]");
|
||||
bdd.requete_unique(req);
|
||||
}
|
||||
|
||||
// Demande de rechargement de la config du Wifi :
|
||||
req = 'UPDATE TB_Configuration SET Valeur=1 WHERE Nom="Wifi_new_config" ';
|
||||
bdd.requete_unique(req);
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================================================
|
||||
// Demande de scan de Wifi STA
|
||||
//=============================================================================================================
|
||||
function demande_de_scan()
|
||||
{
|
||||
var req;
|
||||
|
||||
// Demande de scan :
|
||||
req = 'UPDATE TB_Configuration SET Valeur=2 WHERE Nom="Wifi_new_config" ';
|
||||
bdd.requete_unique(req);
|
||||
}
|
||||
|
||||
//=============================================================================================================
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,376 @@
|
||||
//========================================================================================================================================================================
|
||||
// CONFIG_RESEAU_WIFI_STA_LISTE.QML
|
||||
// Ce fichier traite la gestion de la liste des SSID du Wifi en mode STA
|
||||
// La page est appelée depuis la page config_reseau_wifi_sta.qml
|
||||
//========================================================================================================================================================================
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
import qt.koriolan.shipheart 1.0
|
||||
|
||||
|
||||
|
||||
Shipheart_page {
|
||||
id: page_config_reseau_wifi_sta_liste
|
||||
|
||||
|
||||
// Mis en forme :
|
||||
readonly property double pourcentage_largeur_colonne_gauche: 0.75
|
||||
readonly property double espace_colonnes_principales: 20
|
||||
readonly property double espace_lignes_principales: 20
|
||||
readonly property double affichage_hauteur_utile: shipheart_hauteur_page - shipheart_hauteur_bandeau_haut - shipheart_hauteur_bandeau_bas
|
||||
|
||||
readonly property int hauteur_ligne_reseau: 80
|
||||
readonly property double pourcentage_largeur_labels_formulaire: 0.4
|
||||
|
||||
readonly property int hauteur_bouton_droit: 80
|
||||
|
||||
readonly property double pourcentage_bandeau_bas_largeur_zone_retour: 1
|
||||
|
||||
|
||||
readonly property int periode_init_raffraichissement_parametres: 1 // En ms
|
||||
readonly property int periode_raffraichissement_parametres: 1000 // En ms
|
||||
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 compteur_scan_wifi_sta: 0
|
||||
property string bssid_en_cours: ""
|
||||
|
||||
|
||||
// Modèles :
|
||||
// Note : les modèles chargés dans 'main.qml' n'ont pas à être rechargés dans les pages suivantes
|
||||
|
||||
|
||||
|
||||
//===========================================================
|
||||
// Timer periode raffraichissement parametres :
|
||||
//===========================================================
|
||||
Timer {
|
||||
id: timer_raffraichissement_parametres
|
||||
interval: periode_init_raffraichissement_parametres
|
||||
triggeredOnStart: false
|
||||
running: true
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
if (interval == periode_init_raffraichissement_parametres) { // Premier passage, 1ms après le premier chargement
|
||||
interval = periode_raffraichissement_parametres;
|
||||
|
||||
init_page();
|
||||
|
||||
}
|
||||
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;
|
||||
|
||||
if (mousearea_bouton_oublier_reseau.pressed)
|
||||
{
|
||||
oublier_reseaux();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Titre de la page :
|
||||
Shipheart_titre_1 {titre:qsTr("Liste des réseaux Wifi connus"); 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 - espace_lignes_principales;
|
||||
color: "transparent"
|
||||
|
||||
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
|
||||
highlightRangeMode: ListView.StrictlyEnforceRange // Permet de faire défiler la liste jusqu'à ne garder que le dernier élément affiché (et comme la liste des modules physiques est obligée d'utiliser ce paramètre, on fait pareil sur cette liste pour que les deux soient synchro)
|
||||
|
||||
model: modele_grille_principale
|
||||
delegate: Rectangle {
|
||||
width: zone_affichage_haut_gauche.width
|
||||
height: hauteur_ligne_reseau
|
||||
color: "transparent"
|
||||
|
||||
Rectangle {
|
||||
width: parent.width - 10
|
||||
height: parent.height - 10
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
radius: shipheart_rayon_bouton
|
||||
color: (bssid_en_cours === model.bssid) ? shipheart_couleur_fond_bouton_actif : shipheart_couleur_fond_bouton
|
||||
|
||||
Text {
|
||||
id: reseau_nom
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Qt.AlignLeft
|
||||
verticalAlignment: Qt.AlignTop
|
||||
topPadding: 10
|
||||
leftPadding: 20
|
||||
text: nom
|
||||
color: model.presence ? couleur_blanc_casse : couleur_gris_moyen
|
||||
font.pixelSize: 22
|
||||
font.weight: Font.Bold
|
||||
}
|
||||
Text {
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Qt.AlignLeft
|
||||
verticalAlignment: Qt.AlignBottom
|
||||
bottomPadding: 10
|
||||
leftPadding: 20
|
||||
text: model.bssid
|
||||
color: reseau_nom.color
|
||||
font.pixelSize: 18
|
||||
}
|
||||
Text {
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Qt.AlignRight
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
rightPadding: 20
|
||||
text: ((model.canal < 20) ? "2.4GHz" : "5GHz") + " - Channel " + model.canal
|
||||
color: reseau_nom.color
|
||||
font.pixelSize: 18
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
if (bssid_en_cours === model.bssid) bssid_en_cours = "";
|
||||
else bssid_en_cours = model.bssid
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ListModel {
|
||||
id: modele_grille_principale
|
||||
}
|
||||
|
||||
Label {
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Qt.AlignHCenter
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
visible: parent.count === 0
|
||||
text: qsTr("Aucun réseau n'a été détecté...")
|
||||
color: couleur_rouge_transparent
|
||||
font.pixelSize: 15
|
||||
font.bold: true
|
||||
wrapMode: Label.Wrap
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// 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 - (espace_lignes_principales / 2);
|
||||
color: "transparent"
|
||||
|
||||
|
||||
Column {
|
||||
anchors.fill: parent
|
||||
spacing: 10
|
||||
|
||||
|
||||
|
||||
//.......................................................
|
||||
// Bouton de suppression
|
||||
//.......................................................
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: hauteur_bouton_droit
|
||||
color: shipheart_couleur_fond_bouton
|
||||
radius: shipheart_rayon_bouton
|
||||
visible: true
|
||||
|
||||
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_oublier_reseau.pressed
|
||||
}
|
||||
Text {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
font.pixelSize: 20
|
||||
text: (bssid_en_cours === "") ? qsTr("Oublier tous les réseaux") : qsTr("Oublier ce réseau")
|
||||
color: couleur_blanc_casse
|
||||
}
|
||||
MouseArea {
|
||||
id: mousearea_bouton_oublier_reseau
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Bandeau bas :
|
||||
//-------------------------------------------------------
|
||||
Row {
|
||||
x: 0
|
||||
y: shipheart_hauteur_page - shipheart_hauteur_bandeau_bas;
|
||||
width: shipheart_largeur_page;
|
||||
height: shipheart_hauteur_bandeau_bas;
|
||||
spacing: 5
|
||||
padding: 5
|
||||
|
||||
//.................................................
|
||||
// Bouton retour
|
||||
//.................................................
|
||||
Rectangle {
|
||||
id: bandeau_bas_zone_retour
|
||||
width: (parent.width * pourcentage_bandeau_bas_largeur_zone_retour) - (2 * parent.padding)
|
||||
height: shipheart_hauteur_bandeau_bas - parent.topPadding - parent.bottomPadding;
|
||||
radius: shipheart_rayon_bouton
|
||||
color: shipheart_couleur_fond_bouton
|
||||
|
||||
Image {
|
||||
source: "/images/icone_retour.png"
|
||||
sourceSize.height: 30
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea { // Zone d'interaction. On est obligé de la mettre dans la grille pour que Rectangle et MouseArea soient frères ou parent/enfant ET qu'on n'occupe qu'un espace dans la grille.
|
||||
id: mouse_area_bandeau_bas_zone_retour
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
stackView.pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 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;
|
||||
|
||||
modele_grille_principale.clear(); // RAZ des valeurs existantes
|
||||
|
||||
req = 'SELECT Bssid, Presence, Connu, Nom, Psk, Canal, Qualite FROM TB_Wifi_sta WHERE Connu=1 ORDER BY Nom ';
|
||||
//console.log("req = [ " + req + " ;]");
|
||||
nb = bdd.requete(req);
|
||||
|
||||
for (i = 0; i < nb; i ++)
|
||||
{
|
||||
res = bdd.lecture_ligne();
|
||||
if (!res.isEmpty)
|
||||
{
|
||||
modele_grille_principale.append({
|
||||
"bssid": res[0],
|
||||
"presence": (Number(res[1]) !== 0),
|
||||
"connu": (Number(res[2]) !== 0),
|
||||
"nom": res[3],
|
||||
"psk": res[4],
|
||||
"canal": Number(res[5]),
|
||||
"qualite": Number(res[6]) });
|
||||
}
|
||||
else break; // Ne devrait pas arriver....
|
||||
}
|
||||
|
||||
flag_init = false; // Indique que l'init est terminée
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================================================
|
||||
// Requête de suppression des réseaux à oublier
|
||||
//=============================================================================================================
|
||||
function oublier_reseaux()
|
||||
{
|
||||
var req;
|
||||
var i;
|
||||
|
||||
if (bssid_en_cours === "") // Oubli de tous les réseaux
|
||||
{
|
||||
req = 'DELETE FROM TB_Wifi_sta ';
|
||||
bdd.requete_unique(req);
|
||||
|
||||
stackView.pop(); // Si on les a tous supprimés, autant revenir au menu précédent
|
||||
}
|
||||
else // Oubli du seul réseau sélectionné :
|
||||
{
|
||||
req = 'DELETE FROM TB_Wifi_sta WHERE Bssid="' + bssid_en_cours + '" ';
|
||||
bdd.requete_unique(req);
|
||||
|
||||
for (i=0; i<modele_grille_principale.count; i++)
|
||||
{
|
||||
if (modele_grille_principale.get(i).bssid === bssid_en_cours)
|
||||
{
|
||||
modele_grille_principale.remove(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
bssid_en_cours = ""; // Déselection du réseau qui vient d'être supprimé
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,311 @@
|
||||
//========================================================================================================================================================================
|
||||
// CONFIG_RESERVOIRS.QML
|
||||
// Ce fichier traite la configuration des réservoirs. La page permet notamment de :
|
||||
// - Afficher, pour tous les réservoirs déjà configurés (et donc d'accéder à la configuration détaillée de l'un d'eux ; ou sa création)
|
||||
// - Accéder au menu de changement de l'ordre d'affichage sur la page d'accueil
|
||||
// La page est appelée depuis la page PARAMETRES_AVANCES, en cliquant sur "Réservoirs"
|
||||
//========================================================================================================================================================================
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
import qt.koriolan.shipheart 1.0
|
||||
|
||||
|
||||
|
||||
Shipheart_page {
|
||||
id: page_config_reservoirs
|
||||
|
||||
|
||||
// Mis en forme :
|
||||
readonly property double affichage_hauteur_utile: shipheart_hauteur_page - shipheart_hauteur_bandeau_haut - shipheart_hauteur_bandeau_bas
|
||||
readonly property int hauteur_bouton_droit: 80
|
||||
|
||||
readonly property double pourcentage_largeur_colonne_gauche: 0.75
|
||||
readonly property int espace_colonnes_principales: 20
|
||||
readonly property double pourcentage_bandeau_bas_largeur_zone_retour: 1.0
|
||||
|
||||
readonly property int nombre_reservoirs_affiches_sur_une_colonne: 8
|
||||
|
||||
readonly property int periode_init_raffraichissement_parametres: 1 // En ms
|
||||
readonly property int periode_raffraichissement_parametres: 100 // En ms
|
||||
|
||||
|
||||
// Affichage :
|
||||
property int niveau_page: 0
|
||||
property bool bouton_bandeau_bas_zone_retour_actif: false
|
||||
|
||||
|
||||
// Modèles :
|
||||
// Note : les modèles chargés dans 'main.qml' n'ont pas à être rechargés dans les pages suivantes
|
||||
|
||||
|
||||
//===========================================================
|
||||
// Timer periode raffraichissement parametres :
|
||||
//===========================================================
|
||||
Timer {
|
||||
id: timer_raffraichissement_parametres
|
||||
interval: periode_init_raffraichissement_parametres
|
||||
triggeredOnStart: false
|
||||
running: true
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
if (interval == periode_init_raffraichissement_parametres) // Premier passage, 1ms après le premier chargement
|
||||
{
|
||||
interval = periode_raffraichissement_parametres;
|
||||
init_page();
|
||||
}
|
||||
|
||||
if (stackView.depth === (niveau_page + 1)) // Désactive le raffraichissement quand la page n'est pas activée dans la pile
|
||||
{
|
||||
if (!bouton_bandeau_bas_zone_retour_actif)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================
|
||||
// Lorsque la page est sur le point d'être affichée dans la pile :
|
||||
//===========================================================
|
||||
StackView.onActivating: {
|
||||
mise_a_jour_donnees(); // Permet que lors du retour sur la page, l'état des différentes variables soit mise à jour avant l'affichage proprement dit.
|
||||
}
|
||||
|
||||
// Titre de la page :
|
||||
Shipheart_titre_1 {titre:qsTr("Configuration des réservoirs"); hauteur: shipheart_hauteur_bandeau_haut}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Ecran de gauche (liste des réservoirs) :
|
||||
//-------------------------------------------------------
|
||||
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 réservoirs :
|
||||
GridView {
|
||||
id: grille_principale
|
||||
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
cellWidth: parent.width;
|
||||
cellHeight: height / nombre_reservoirs_affiches_sur_une_colonne
|
||||
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
|
||||
delegate: Rectangle {
|
||||
width: grille_principale.cellWidth
|
||||
height: grille_principale.cellHeight
|
||||
color: "transparent"
|
||||
Rectangle { // c'est le bouton proprement dit...
|
||||
height: parent.height - 10
|
||||
width:parent.width - 10
|
||||
color: shipheart_couleur_fond_bouton
|
||||
border.color: couleur_rouge
|
||||
border.width: (model.etat_systeme === 0) ? 0 : 3
|
||||
radius: shipheart_rayon_bouton
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
Text {
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Qt.AlignLeft
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
leftPadding: 20
|
||||
text: model.nom
|
||||
color: couleur_blanc_casse
|
||||
font.pixelSize: 18
|
||||
wrapMode: Label.Wrap
|
||||
}
|
||||
MouseArea{
|
||||
anchors.fill : parent
|
||||
enabled : !grille_principale.moving // Permet de bloquer le Mousearea pendant le déplacement de la grille
|
||||
onReleased: { // Permet déclencher à la fin d'un clic (court) sans mouvement
|
||||
shipheart_clic();
|
||||
stackView.push("config_reservoir.qml", {"id_reservoir": model.id})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ListModel {
|
||||
id: modele_grille_principale
|
||||
}
|
||||
|
||||
Label {
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Qt.AlignHCenter
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
visible: parent.count === 0
|
||||
text: qsTr("Aucun réservoir n'est encore configuré...")
|
||||
color: couleur_rouge_transparent
|
||||
font.pixelSize: 15
|
||||
font.bold: true
|
||||
wrapMode: Label.Wrap
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Ecran Droite :
|
||||
//-------------------------------------------------------
|
||||
Rectangle {
|
||||
id: zone_affichage_droite
|
||||
x: zone_affichage_gauche.width + espace_colonnes_principales
|
||||
y: shipheart_hauteur_bandeau_haut + 5; // Le +5 permet d'aligner le haut du premier bouton de droite avec le haut du premier bouton de la liste de gauche (
|
||||
width: (shipheart_largeur_page * (1 - pourcentage_largeur_colonne_gauche)) - (espace_colonnes_principales / 2)
|
||||
height: affichage_hauteur_utile
|
||||
color: "transparent"
|
||||
|
||||
|
||||
Column {
|
||||
anchors.fill: parent
|
||||
spacing: 10
|
||||
|
||||
//----------------------
|
||||
// Bouton + :
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: hauteur_bouton_droit
|
||||
color: shipheart_couleur_fond_bouton
|
||||
radius: shipheart_rayon_bouton
|
||||
visible: !clavier.active
|
||||
Text {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
font.pixelSize: 40
|
||||
text: qsTr("+")
|
||||
color: couleur_blanc_casse
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
stackView.push("config_reservoir.qml");
|
||||
}
|
||||
}
|
||||
}
|
||||
//----------------------
|
||||
// Bouton tri :
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: hauteur_bouton_droit
|
||||
color: shipheart_couleur_fond_bouton
|
||||
radius: shipheart_rayon_bouton
|
||||
visible: !clavier.active // && (modele_grille_principale.count > 1) // SDIR #258
|
||||
Image {
|
||||
id: image_parametres
|
||||
source: "/images/tri.png"
|
||||
sourceSize.height: 25
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
stackView.push("config_ordre_elements.qml", {"table": "TB_Reservoirs"})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Bandeau bas :
|
||||
//-------------------------------------------------------
|
||||
Row {
|
||||
x: 0
|
||||
y: shipheart_hauteur_page - shipheart_hauteur_bandeau_bas;
|
||||
width: shipheart_largeur_page;
|
||||
height: shipheart_hauteur_bandeau_bas;
|
||||
padding: 5
|
||||
spacing: 5
|
||||
|
||||
//.................................................
|
||||
// Bouton retour
|
||||
//.................................................
|
||||
Rectangle {
|
||||
id: bandeau_bas_zone_retour
|
||||
width: (parent.width * pourcentage_bandeau_bas_largeur_zone_retour) - (2 * parent.padding)
|
||||
height: shipheart_hauteur_bandeau_bas - parent.topPadding - parent.bottomPadding;
|
||||
radius: shipheart_rayon_bouton
|
||||
color: shipheart_couleur_fond_bouton
|
||||
Image {
|
||||
source: "/images/icone_retour.png"
|
||||
sourceSize.height: 30
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
}
|
||||
MouseArea { // Zone d'interaction. On est obligé de la mettre dans la grille pour que Rectangle et MouseArea soient frères ou parent/enfant ET qu'on n'occupe qu'un espace dans la grille.
|
||||
id: mouse_area_bandeau_bas_zone_retour
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
stackView.pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 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()
|
||||
{
|
||||
niveau_page = stackView.depth - 1; // Permet de stocker le niveau de la page dans la Stackview
|
||||
|
||||
mise_a_jour_donnees();
|
||||
}
|
||||
|
||||
//=============================================================================================================
|
||||
// Mise à jour des données
|
||||
//=============================================================================================================
|
||||
function mise_a_jour_donnees()
|
||||
{
|
||||
var req, res;
|
||||
var i;
|
||||
var nb_reservoirs;
|
||||
|
||||
|
||||
modele_grille_principale.clear(); // RAZ des valeurs existantes
|
||||
|
||||
req = 'SELECT Cle_primaire, ';
|
||||
req += ' Etat_systeme, ';
|
||||
req += ' Nom ';
|
||||
req += ' FROM TB_Reservoirs ORDER BY Priorite_affichage_accueil';
|
||||
//console.log("req = [ " + req + '; ]');
|
||||
nb_reservoirs = bdd.requete(req);
|
||||
|
||||
for (i = 0; i < nb_reservoirs; i ++)
|
||||
{
|
||||
res = bdd.lecture_ligne();
|
||||
if (!res.isEmpty)
|
||||
{
|
||||
modele_grille_principale.append({"id": Number(res[0]), "etat_systeme": Number(res[1]), "nom": res[2] });
|
||||
}
|
||||
else break; // Ne devrait pas arriver....
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,746 @@
|
||||
//========================================================================================================================================================================
|
||||
// CONFIG_SHIP2NET.QML
|
||||
// Ce fichier traite la configuration de Ship2net et de la liaison 4G-LTE en particulier
|
||||
// La page est appelée depuis la page parametres_avances.qml, en cliquant sur "Ship2net" depuis la colonne "Vos paramètres"
|
||||
//========================================================================================================================================================================
|
||||
import QtQuick 2.12
|
||||
import QtQml.Models
|
||||
|
||||
import qt.koriolan.shipheart 1.0
|
||||
|
||||
|
||||
|
||||
Shipheart_page {
|
||||
id: page_config_ship2net
|
||||
|
||||
|
||||
// Mis en forme :
|
||||
readonly property double pourcentage_largeur_colonne_gauche: 0.75
|
||||
readonly property double espace_colonnes_principales: 20
|
||||
readonly property double pourcentage_hauteur_ligne_haut: 1
|
||||
readonly property double espace_lignes_principales: 20
|
||||
readonly property double affichage_hauteur_utile: shipheart_hauteur_page - shipheart_hauteur_bandeau_haut - shipheart_hauteur_bandeau_bas
|
||||
|
||||
readonly property int hauteur_ligne_formulaire: 60
|
||||
readonly property double pourcentage_largeur_labels_formulaire: 0.45
|
||||
|
||||
readonly property int hauteur_bouton_droit: 80
|
||||
|
||||
readonly property double pourcentage_bandeau_bas_largeur_zone_retour: 1
|
||||
|
||||
|
||||
readonly property int periode_init_raffraichissement_parametres: 1 // En ms
|
||||
readonly property int periode_raffraichissement_parametres: 1000 // En ms
|
||||
|
||||
|
||||
|
||||
// Affichage :
|
||||
property bool bouton_bandeau_bas_zone_retour_actif: false
|
||||
property int protection_mode: 0
|
||||
property bool flag_init: true // Permet de bloquer certains affichage tant que l'init n'est pas terminée
|
||||
|
||||
// Données :
|
||||
property int acces_webgl_1_validation: 0
|
||||
property string acces_webgl_1_parametres: ""
|
||||
property int acces_webgl_2_validation: 0
|
||||
property string acces_webgl_2_parametres: ""
|
||||
property int acces_webgl_3_validation: 0
|
||||
property string acces_webgl_3_parametres: ""
|
||||
|
||||
|
||||
// Modèles :
|
||||
// Note : les modèles chargés dans 'main.qml' n'ont pas à être rechargés dans les pages suivantes
|
||||
|
||||
|
||||
//===========================================================
|
||||
// Timer periode raffraichissement parametres :
|
||||
//===========================================================
|
||||
Timer {
|
||||
id: timer_raffraichissement_parametres
|
||||
interval: periode_init_raffraichissement_parametres
|
||||
triggeredOnStart: false
|
||||
running: true
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
if (interval == periode_init_raffraichissement_parametres) { // Premier passage, 1ms après le premier chargement
|
||||
interval = periode_raffraichissement_parametres;
|
||||
|
||||
init_page();
|
||||
}
|
||||
else if (!bouton_bandeau_bas_zone_retour_actif)
|
||||
{
|
||||
mise_a_jour();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Titre de la page :
|
||||
Shipheart_titre_1 {titre:qsTr("Ship2net"); 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;
|
||||
color: "transparent"
|
||||
|
||||
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 : Periode_sauvegarde_bdd
|
||||
Rectangle {
|
||||
width: grille_principale.width
|
||||
height: visible ? hauteur_ligne_formulaire : 0
|
||||
color: "transparent"
|
||||
visible : (shipheart_generation_shipbase === shipheart_generation_shipbase_v2) // Ce champ n'est pas configurable sur V1
|
||||
|
||||
Shipheart_formulaire_label {
|
||||
text: qsTr("Période des sauvegardes")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
}
|
||||
|
||||
Shipheart_formulaire_combobox {
|
||||
id: champ_formulaire_Periode_sauvegarde_bdd
|
||||
model: ListModel { }
|
||||
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
|
||||
onActivated: {
|
||||
shipheart_clic();
|
||||
}
|
||||
}
|
||||
|
||||
Shipheart_formulaire_ligne_separation {
|
||||
haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Ligne de formulaire : Periode_connexion_ship2net
|
||||
Rectangle {
|
||||
width: grille_principale.width
|
||||
height: visible ? hauteur_ligne_formulaire : 0
|
||||
color: "transparent"
|
||||
visible : (shipheart_generation_shipbase === shipheart_generation_shipbase_v2) // Ce champ n'est pas configurable sur V1
|
||||
|
||||
Shipheart_formulaire_label {
|
||||
text: qsTr("Période de connexion à Ship2net")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
}
|
||||
|
||||
Shipheart_formulaire_combobox {
|
||||
id: champ_formulaire_Periode_connexion_ship2net
|
||||
model: ListModel { }
|
||||
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
|
||||
onActivated: {
|
||||
shipheart_clic();
|
||||
}
|
||||
}
|
||||
|
||||
Shipheart_formulaire_ligne_separation {
|
||||
haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Ligne de formulaire : Mode_validation_maj
|
||||
Rectangle {
|
||||
width: grille_principale.width
|
||||
height: visible ? hauteur_ligne_formulaire : 0
|
||||
color: "transparent"
|
||||
|
||||
Shipheart_formulaire_label {
|
||||
text: qsTr("Mode de validation des mises à jour")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
}
|
||||
|
||||
Shipheart_formulaire_combobox {
|
||||
id: champ_formulaire_Mode_validation_maj
|
||||
model: ListModel { }
|
||||
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
|
||||
onActivated: {
|
||||
shipheart_clic();
|
||||
}
|
||||
}
|
||||
|
||||
Shipheart_formulaire_ligne_separation {
|
||||
haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Ligne de formulaire : Acces_webgl_1_validation
|
||||
Rectangle {
|
||||
width: grille_principale.width
|
||||
height: visible ? hauteur_ligne_formulaire : 0
|
||||
color: "transparent"
|
||||
|
||||
Shipheart_formulaire_label {
|
||||
text: qsTr("Accès distant WebGL #1")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
}
|
||||
|
||||
Shipheart_formulaire_combobox {
|
||||
id: champ_formulaire_Acces_webgl_1_validation
|
||||
model: ListModel { }
|
||||
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
|
||||
onActivated: {
|
||||
shipheart_clic();
|
||||
acces_webgl_1_validation = champ_formulaire_Acces_webgl_1_validation.model.get(champ_formulaire_Acces_webgl_1_validation.currentIndex).valeur;
|
||||
}
|
||||
}
|
||||
|
||||
Shipheart_formulaire_ligne_separation {
|
||||
haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Ligne de formulaire : Acces_webgl_2_validation
|
||||
Rectangle {
|
||||
width: grille_principale.width
|
||||
height: visible ? hauteur_ligne_formulaire : 0
|
||||
color: "transparent"
|
||||
|
||||
Shipheart_formulaire_label {
|
||||
text: qsTr("Accès distant WebGL #2")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
}
|
||||
|
||||
Shipheart_formulaire_combobox {
|
||||
id: champ_formulaire_Acces_webgl_2_validation
|
||||
model: ListModel { }
|
||||
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
|
||||
onActivated: {
|
||||
shipheart_clic();
|
||||
acces_webgl_2_validation = champ_formulaire_Acces_webgl_2_validation.model.get(champ_formulaire_Acces_webgl_2_validation.currentIndex).valeur;
|
||||
}
|
||||
}
|
||||
|
||||
Shipheart_formulaire_ligne_separation {
|
||||
haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Ligne de formulaire : Acces_webgl_3_validation
|
||||
Rectangle {
|
||||
width: grille_principale.width
|
||||
height: visible ? hauteur_ligne_formulaire : 0
|
||||
color: "transparent"
|
||||
|
||||
Shipheart_formulaire_label {
|
||||
text: qsTr("Accès distant WebGL #3")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
}
|
||||
|
||||
Shipheart_formulaire_combobox {
|
||||
id: champ_formulaire_Acces_webgl_3_validation
|
||||
model: ListModel { }
|
||||
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
|
||||
onActivated: {
|
||||
shipheart_clic();
|
||||
acces_webgl_3_validation = champ_formulaire_Acces_webgl_3_validation.model.get(champ_formulaire_Acces_webgl_3_validation.currentIndex).valeur;
|
||||
}
|
||||
}
|
||||
|
||||
Shipheart_formulaire_ligne_separation {
|
||||
haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Ecran Milieu - Gauche :
|
||||
//-------------------------------------------------------
|
||||
Rectangle {
|
||||
id: zone_affichage_milieu_gauche
|
||||
x: 0
|
||||
y: shipheart_hauteur_bandeau_haut + zone_affichage_haut_gauche.height + espace_lignes_principales;
|
||||
width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2)
|
||||
height: (affichage_hauteur_utile * (1 - pourcentage_hauteur_ligne_haut)) - espace_lignes_principales;
|
||||
color: "transparent"
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Grille pour afficher les valeurs des paramètres non configurables :
|
||||
GridView {
|
||||
id: grille_informations
|
||||
|
||||
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_grille_informations
|
||||
delegate: Rectangle {
|
||||
width: zone_affichage_milieu_gauche.width
|
||||
height: visible ? hauteur_ligne_formulaire : 0
|
||||
color: "transparent"
|
||||
visible: !flag_init
|
||||
|
||||
Shipheart_formulaire_label {
|
||||
text: model.nom_champ
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
}
|
||||
Shipheart_formulaire_valeur_fixe {
|
||||
text: model.valeur_champ
|
||||
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
|
||||
}
|
||||
}
|
||||
ListModel {
|
||||
id: modele_grille_informations
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// 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 {
|
||||
width: parent.width
|
||||
height: hauteur_bouton_droit
|
||||
color: shipheart_couleur_fond_bouton
|
||||
radius: shipheart_rayon_bouton
|
||||
// visible: !clavier.active // SDIR #255
|
||||
Text {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
font.pixelSize: 20
|
||||
text: qsTr("Enregistrer")
|
||||
color: couleur_blanc_casse
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
enregistrement(); // Mise à jour des données saisies dans la BDD et reconfiguration par l'application pour prise en compte.
|
||||
timer_tempo_reconfiguration.restart();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//.......................................................
|
||||
// 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();
|
||||
stackView.pop(); // Retour à la page de config des évènements
|
||||
}
|
||||
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) - (2 * parent.padding)
|
||||
height: shipheart_hauteur_bandeau_bas - parent.topPadding - parent.bottomPadding;
|
||||
radius: shipheart_rayon_bouton
|
||||
color: shipheart_couleur_fond_bouton
|
||||
|
||||
Image {
|
||||
source: "/images/icone_retour.png"
|
||||
sourceSize.height: 30
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea { // Zone d'interaction. On est obligé de la mettre dans la grille pour que Rectangle et MouseArea soient frères ou parent/enfant ET qu'on n'occupe qu'un espace dans la grille.
|
||||
id: mouse_area_bandeau_bas_zone_retour
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
stackView.pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//===========================================================
|
||||
// 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 periode_sauvegarde_bdd;
|
||||
var periode_connexion_ship2net;
|
||||
var mode_validation_maj;
|
||||
var cle;
|
||||
var deb, fin;
|
||||
var port;
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
// Mise à jour des informations non configurables :
|
||||
mise_a_jour();
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
// Periode sauvegarde BDD :
|
||||
|
||||
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Periode_sauvegarde_bdd" ';
|
||||
res = bdd.requete_unique(req);
|
||||
periode_sauvegarde_bdd = Number(res[0]);
|
||||
|
||||
champ_formulaire_Periode_sauvegarde_bdd.model.clear();
|
||||
champ_formulaire_Periode_sauvegarde_bdd.model.append({"valeur": 0, "texte": qsTr("Jamais") });
|
||||
if (shipheart_niveau_acces_en_cours >= 10)
|
||||
{
|
||||
champ_formulaire_Periode_sauvegarde_bdd.model.append({"valeur": (2*60), "texte": qsTr("2 minutes") });
|
||||
champ_formulaire_Periode_sauvegarde_bdd.model.append({"valeur": (10*60), "texte": qsTr("10 minutes") });
|
||||
}
|
||||
champ_formulaire_Periode_sauvegarde_bdd.model.append({"valeur": (30*60), "texte": qsTr("30 minutes") });
|
||||
champ_formulaire_Periode_sauvegarde_bdd.model.append({"valeur": (1*60*60), "texte": qsTr("1 heure") });
|
||||
champ_formulaire_Periode_sauvegarde_bdd.model.append({"valeur": (2*60*60), "texte": qsTr("2 heures") });
|
||||
champ_formulaire_Periode_sauvegarde_bdd.model.append({"valeur": (4*60*60), "texte": qsTr("4 heures") });
|
||||
champ_formulaire_Periode_sauvegarde_bdd.model.append({"valeur": (12*60*60), "texte": qsTr("12 heures") });
|
||||
champ_formulaire_Periode_sauvegarde_bdd.model.append({"valeur": (24*60*60), "texte": qsTr("24 heures") });
|
||||
|
||||
// Positionnement de l'index sur la valeur en cours :
|
||||
i = recherche_index_valeur_modele(periode_sauvegarde_bdd, champ_formulaire_Periode_sauvegarde_bdd.model, "periode_sauvegarde_bdd");
|
||||
if (i === -1) champ_formulaire_Periode_sauvegarde_bdd.currentIndex = recherche_index_valeur_modele((2*60*60), champ_formulaire_Periode_sauvegarde_bdd.model, "periode_sauvegarde_bdd");
|
||||
else champ_formulaire_Periode_sauvegarde_bdd.currentIndex = i;
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
// Periode connexion Ship2net :
|
||||
|
||||
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Periode_connexion_ship2net" ';
|
||||
res = bdd.requete_unique(req);
|
||||
periode_connexion_ship2net = Number(res[0]);
|
||||
|
||||
champ_formulaire_Periode_connexion_ship2net.model.clear();
|
||||
champ_formulaire_Periode_connexion_ship2net.model.append({"valeur": 0, "texte": qsTr("Jamais") });
|
||||
champ_formulaire_Periode_connexion_ship2net.model.append({"valeur": (2*60), "texte": qsTr("2 minutes") });
|
||||
champ_formulaire_Periode_connexion_ship2net.model.append({"valeur": (10*60), "texte": qsTr("10 minutes") });
|
||||
champ_formulaire_Periode_connexion_ship2net.model.append({"valeur": (30*60), "texte": qsTr("30 minutes") });
|
||||
champ_formulaire_Periode_connexion_ship2net.model.append({"valeur": (1*60*60), "texte": qsTr("1 heure") });
|
||||
champ_formulaire_Periode_connexion_ship2net.model.append({"valeur": (4*60*60), "texte": qsTr("4 heures") });
|
||||
champ_formulaire_Periode_connexion_ship2net.model.append({"valeur": (12*60*60), "texte": qsTr("12 heures") });
|
||||
champ_formulaire_Periode_connexion_ship2net.model.append({"valeur": (24*60*60), "texte": qsTr("24 heures") });
|
||||
|
||||
// Positionnement de l'index sur la valeur en cours :
|
||||
i = recherche_index_valeur_modele(periode_connexion_ship2net, champ_formulaire_Periode_connexion_ship2net.model, "periode_connexion_ship2net");
|
||||
if (i === -1) champ_formulaire_Periode_connexion_ship2net.currentIndex = recherche_index_valeur_modele((2*60*60), champ_formulaire_Periode_connexion_ship2net.model, "periode_connexion_ship2net");
|
||||
else champ_formulaire_Periode_connexion_ship2net.currentIndex = i;
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
// Mode_validation_maj :
|
||||
|
||||
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Mode_validation_maj" ';
|
||||
res = bdd.requete_unique(req);
|
||||
mode_validation_maj = Number(res[0]);
|
||||
|
||||
champ_formulaire_Mode_validation_maj.model.clear();
|
||||
champ_formulaire_Mode_validation_maj.model.append({"valeur": 0, "texte": qsTr("Aucune mise à jour") });
|
||||
champ_formulaire_Mode_validation_maj.model.append({"valeur": 1, "texte": qsTr("Validation manuelle des mises à jour reçues") });
|
||||
champ_formulaire_Mode_validation_maj.model.append({"valeur": 2, "texte": qsTr("Validation automatique des mises à jour reçues") });
|
||||
|
||||
// Positionnement de l'index sur la valeur en cours :
|
||||
i = recherche_index_valeur_modele(mode_validation_maj, champ_formulaire_Mode_validation_maj.model, "mode_validation_maj");
|
||||
if (i === -1) champ_formulaire_Mode_validation_maj.currentIndex = recherche_index_valeur_modele(2, champ_formulaire_Mode_validation_maj.model, "mode_validation_maj");
|
||||
else champ_formulaire_Mode_validation_maj.currentIndex = i;
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
// Acces_webgl_1_validation :
|
||||
|
||||
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Acces_webgl_1_validation" ';
|
||||
res = bdd.requete_unique(req);
|
||||
acces_webgl_1_validation = Number(res[0]);
|
||||
|
||||
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Acces_webgl_1_parametres" ';
|
||||
res = bdd.requete_unique(req);
|
||||
acces_webgl_1_parametres = res[0]; // Par exemple : '-platform webgl:port=8081:wsserverport=8082'. NB : ne PAS mettre d'espace à la fin car cela peut poser des soucis à l'Appli pour détecter le process en cours d'exécution.
|
||||
|
||||
cle = ":port=";
|
||||
deb = acces_webgl_1_parametres.indexOf(cle) + cle.length;
|
||||
fin = acces_webgl_1_parametres.indexOf(":", deb);
|
||||
//console.log("parametres = [" + acces_webgl_1_parametres + "], deb = " + deb + " et fin = " + fin);
|
||||
port = acces_webgl_1_parametres.slice(deb, fin);
|
||||
|
||||
champ_formulaire_Acces_webgl_1_validation.model.clear();
|
||||
champ_formulaire_Acces_webgl_1_validation.model.append({"valeur": 0, "texte": qsTr("Dévalidé") });
|
||||
champ_formulaire_Acces_webgl_1_validation.model.append({"valeur": 1, "texte": qsTr("Valide [port %1]").arg(port) });
|
||||
|
||||
// Positionnement de l'index sur la valeur en cours :
|
||||
if (acces_webgl_1_validation === 1) champ_formulaire_Acces_webgl_1_validation.currentIndex = 1;
|
||||
else champ_formulaire_Acces_webgl_1_validation.currentIndex = 0;
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
// Acces_webgl_2_validation :
|
||||
|
||||
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Acces_webgl_2_validation" ';
|
||||
res = bdd.requete_unique(req);
|
||||
acces_webgl_2_validation = Number(res[0]);
|
||||
|
||||
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Acces_webgl_2_parametres" ';
|
||||
res = bdd.requete_unique(req);
|
||||
acces_webgl_2_parametres = res[0];
|
||||
|
||||
cle = ":port=";
|
||||
deb = acces_webgl_2_parametres.indexOf(cle) + cle.length;
|
||||
fin = acces_webgl_2_parametres.indexOf(":", deb);
|
||||
//console.log("parametres = [" + acces_webgl_2_parametres + "], deb = " + deb + " et fin = " + fin);
|
||||
port = acces_webgl_2_parametres.slice(deb, fin);
|
||||
|
||||
champ_formulaire_Acces_webgl_2_validation.model.clear();
|
||||
champ_formulaire_Acces_webgl_2_validation.model.append({"valeur": 0, "texte": qsTr("Dévalidé") });
|
||||
champ_formulaire_Acces_webgl_2_validation.model.append({"valeur": 1, "texte": qsTr("Valide [port %1]").arg(port) });
|
||||
|
||||
// Positionnement de l'index sur la valeur en cours :
|
||||
if (acces_webgl_2_validation === 1) champ_formulaire_Acces_webgl_2_validation.currentIndex = 1;
|
||||
else champ_formulaire_Acces_webgl_2_validation.currentIndex = 0;
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
// Acces_webgl_3_validation :
|
||||
|
||||
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Acces_webgl_3_validation" ';
|
||||
res = bdd.requete_unique(req);
|
||||
acces_webgl_3_validation = Number(res[0]);
|
||||
|
||||
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Acces_webgl_3_parametres" ';
|
||||
res = bdd.requete_unique(req);
|
||||
acces_webgl_3_parametres = res[0];
|
||||
|
||||
cle = ":port=";
|
||||
deb = acces_webgl_3_parametres.indexOf(cle) + cle.length;
|
||||
fin = acces_webgl_3_parametres.indexOf(":", deb);
|
||||
//console.log("parametres = [" + acces_webgl_3_parametres + "], deb = " + deb + " et fin = " + fin);
|
||||
port = acces_webgl_3_parametres.slice(deb, fin);
|
||||
|
||||
champ_formulaire_Acces_webgl_3_validation.model.clear();
|
||||
champ_formulaire_Acces_webgl_3_validation.model.append({"valeur": 0, "texte": qsTr("Dévalidé") });
|
||||
champ_formulaire_Acces_webgl_3_validation.model.append({"valeur": 1, "texte": qsTr("Valide [port %1]").arg(port) });
|
||||
|
||||
// Positionnement de l'index sur la valeur en cours :
|
||||
if (acces_webgl_3_validation === 1) champ_formulaire_Acces_webgl_3_validation.currentIndex = 1;
|
||||
else champ_formulaire_Acces_webgl_3_validation.currentIndex = 0;
|
||||
|
||||
|
||||
flag_init = false;
|
||||
}
|
||||
|
||||
//=============================================================================================================
|
||||
// Mise à jour des valeurs courantes
|
||||
//=============================================================================================================
|
||||
function mise_a_jour()
|
||||
{
|
||||
var req, res;
|
||||
var nb;
|
||||
var i;
|
||||
var nom_champ, valeur_champ;
|
||||
var mode_validation_maj;
|
||||
var flag_valide;
|
||||
|
||||
modele_grille_informations.clear();
|
||||
|
||||
/* req = 'SELECT Nom, Valeur FROM TB_Systeme ORDER BY Cle_primaire';
|
||||
//console.log("req =" + req);
|
||||
nb = bdd.requete(req);
|
||||
|
||||
for (i = 0; i < nb; i ++)
|
||||
{
|
||||
res = bdd.lecture_ligne();
|
||||
if (!res.isEmpty)
|
||||
{
|
||||
flag_valide = true;
|
||||
switch(res[0])
|
||||
{
|
||||
case "Adresse_ip_ethernet":
|
||||
nom_champ = qsTr("Adresse IP sur réseau Ethernet");
|
||||
valeur_champ = (res[1] === shipheart_adresse_ip_inconnue) ? qsTr("Non connecté") : res[1];
|
||||
if (shipheart_generation_shipbase < shipheart_generation_shipbase_v2) flag_valide = false;
|
||||
break;
|
||||
case "Adresse_ip_wifi_sta":
|
||||
nom_champ = qsTr("Adresse IP sur réseau Wifi (STA)");
|
||||
valeur_champ = (res[1] === shipheart_adresse_ip_inconnue) ? qsTr("Non connecté") : res[1];
|
||||
if (shipheart_generation_shipbase < shipheart_generation_shipbase_v2) flag_valide = false;
|
||||
break;
|
||||
case "Adresse_ip_wifi_ap":
|
||||
nom_champ = qsTr("Adresse IP sur réseau Wifi ShipHeart (AP)");
|
||||
valeur_champ = (res[1] === shipheart_adresse_ip_inconnue) ? qsTr("Non connecté") : res[1];
|
||||
if (shipheart_generation_shipbase < shipheart_generation_shipbase_v2) flag_valide = false;
|
||||
break;
|
||||
|
||||
default: continue;
|
||||
}
|
||||
if (flag_valide) modele_grille_informations.append({"commande": false, "nom_champ": nom_champ, "valeur_champ": valeur_champ});
|
||||
}
|
||||
else break; // Ne devrait pas arriver....
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
//=============================================================================================================
|
||||
// Enregistrement des valeurs saisies
|
||||
//=============================================================================================================
|
||||
function enregistrement()
|
||||
{
|
||||
var req;
|
||||
|
||||
// Mise à jour de la nouvelle valeur de 'Periode_sauvegarde_bdd' dans la BDD :
|
||||
req = 'UPDATE TB_Configuration SET Valeur="' + champ_formulaire_Periode_sauvegarde_bdd.model.get(champ_formulaire_Periode_sauvegarde_bdd.currentIndex).valeur + '" ';
|
||||
req += ' WHERE Nom="Periode_sauvegarde_bdd" '
|
||||
//console.log("Requête = [ " + req + " ]")
|
||||
bdd.requete_unique(req);
|
||||
|
||||
// Mise à jour de la nouvelle valeur de 'Periode_connexion_ship2net' dans la BDD :
|
||||
req = 'UPDATE TB_Configuration SET Valeur="' + champ_formulaire_Periode_connexion_ship2net.model.get(champ_formulaire_Periode_connexion_ship2net.currentIndex).valeur + '" ';
|
||||
req += ' WHERE Nom="Periode_connexion_ship2net" '
|
||||
//console.log("Requête = [ " + req + " ]")
|
||||
bdd.requete_unique(req);
|
||||
|
||||
// Mise à jour de la nouvelle valeur de 'Mode_validation_maj' dans la BDD :
|
||||
req = 'UPDATE TB_Configuration SET Valeur="' + champ_formulaire_Mode_validation_maj.model.get(champ_formulaire_Mode_validation_maj.currentIndex).valeur + '" ';
|
||||
req += ' WHERE Nom="Mode_validation_maj" '
|
||||
//console.log("Requête = [ " + req + " ]")
|
||||
bdd.requete_unique(req);
|
||||
|
||||
|
||||
// Note : la logique aurait voulu que l'on traite ici le lancement et l'arrêt des processus 'WebGL'. Malheureusement, les tentatives de
|
||||
// lancement via 'systeme.commande_shell()' n'ont pas fonctionné... En conséquence, on ne fait que mettre à jour les champs et l'Appli
|
||||
// se charge ensuite de lancer/arreter les process correspondants.
|
||||
|
||||
// Mise à jour des nouvelles valeurs relatives à l'accès WebGL #1 dans la BDD :
|
||||
req = 'UPDATE TB_Configuration SET Valeur="' + acces_webgl_1_validation + '" WHERE Nom="Acces_webgl_1_validation" '
|
||||
//console.log("Requête = [ " + req + " ]")
|
||||
bdd.requete_unique(req);
|
||||
|
||||
req = 'UPDATE TB_Configuration SET Valeur="' + acces_webgl_1_parametres + '" WHERE Nom="Acces_webgl_1_parametres" '
|
||||
//console.log("Requête = [ " + req + " ]")
|
||||
bdd.requete_unique(req);
|
||||
|
||||
// Mise à jour des nouvelles valeurs relatives à l'accès WebGL #2 dans la BDD :
|
||||
req = 'UPDATE TB_Configuration SET Valeur="' + acces_webgl_2_validation + '" WHERE Nom="Acces_webgl_2_validation" '
|
||||
//console.log("Requête = [ " + req + " ]")
|
||||
bdd.requete_unique(req);
|
||||
|
||||
req = 'UPDATE TB_Configuration SET Valeur="' + acces_webgl_2_parametres + '" WHERE Nom="Acces_webgl_2_parametres" '
|
||||
//console.log("Requête = [ " + req + " ]")
|
||||
bdd.requete_unique(req);
|
||||
|
||||
// Mise à jour des nouvelles valeurs relatives à l'accès WebGL #3 dans la BDD :
|
||||
req = 'UPDATE TB_Configuration SET Valeur="' + acces_webgl_3_validation + '" WHERE Nom="Acces_webgl_3_validation" '
|
||||
//console.log("Requête = [ " + req + " ]")
|
||||
bdd.requete_unique(req);
|
||||
|
||||
req = 'UPDATE TB_Configuration SET Valeur="' + acces_webgl_3_parametres + '" WHERE Nom="Acces_webgl_3_parametres" '
|
||||
//console.log("Requête = [ " + req + " ]")
|
||||
bdd.requete_unique(req);
|
||||
|
||||
|
||||
// Demande de reconfiguration système via la BDD car on a modifié des valeurs de configuration :
|
||||
synchro_bdd(shipheart_type_synchro_config);
|
||||
}
|
||||
|
||||
//=============================================================================================================
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,518 @@
|
||||
//========================================================================================================================================================================
|
||||
// CONFIG_SHIPRS.QML
|
||||
// La page est appelée depuis la page 'parametres_avances'home_attente.qml' lorsque la connexion a la BDD n'a pu être effectuée
|
||||
//========================================================================================================================================================================
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
import QtQml.Models
|
||||
|
||||
import qt.koriolan.shipheart 1.0
|
||||
import"fonctions.js" as Fonctions
|
||||
|
||||
|
||||
|
||||
Shipheart_page {
|
||||
id: page_config_shiprs
|
||||
|
||||
|
||||
// Mis en forme :
|
||||
readonly property double pourcentage_largeur_colonne_gauche: 0.75
|
||||
readonly property double espace_colonnes_principales: 20
|
||||
readonly property double pourcentage_hauteur_message_alerte: 0.45
|
||||
readonly property double espace_lignes_principales: 20
|
||||
readonly property double affichage_hauteur_utile: shipheart_hauteur_page - shipheart_hauteur_bandeau_haut - shipheart_hauteur_bandeau_bas
|
||||
|
||||
readonly property int hauteur_ligne_formulaire: 60
|
||||
readonly property double pourcentage_largeur_labels_formulaire: 0.45
|
||||
|
||||
readonly property int hauteur_bouton_droit: 80
|
||||
|
||||
readonly property double pourcentage_bandeau_bas_largeur_zone_retour: 1
|
||||
|
||||
|
||||
readonly property int periode_init_raffraichissement_parametres: 1 // En ms
|
||||
readonly property int periode_raffraichissement_parametres: 1000 // En ms
|
||||
|
||||
readonly property int step_timer_sortie: 10 // en ms
|
||||
|
||||
|
||||
// Affichage :
|
||||
property bool bouton_bandeau_bas_zone_retour_actif: false
|
||||
property bool flag_init: true // Permet de bloquer certains affichage tant que l'init n'est pas terminée
|
||||
|
||||
// Données :
|
||||
property bool connexion_impossible: false
|
||||
property string adresse_ip_shipbase: "inconnue<br /><i>unknown</i>"
|
||||
property int taille_ecran_shiprs: 10
|
||||
property bool configuration_modifiee: false
|
||||
property string message_erreur: ""
|
||||
property string message_info: ""
|
||||
property int valeur_timer_sortie: 0
|
||||
|
||||
// Modèles :
|
||||
// Note : les modèles chargés dans 'main.qml' n'ont pas à être rechargés dans les pages suivantes
|
||||
|
||||
|
||||
//===========================================================
|
||||
// Timer periode raffraichissement parametres :
|
||||
//===========================================================
|
||||
Timer {
|
||||
id: timer_raffraichissement_parametres
|
||||
interval: periode_init_raffraichissement_parametres
|
||||
triggeredOnStart: false
|
||||
running: true
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
if (interval == periode_init_raffraichissement_parametres) { // Premier passage, 1ms après le premier chargement
|
||||
interval = periode_raffraichissement_parametres;
|
||||
|
||||
init_page();
|
||||
}
|
||||
else if (!bouton_bandeau_bas_zone_retour_actif)
|
||||
{
|
||||
// mise_a_jour();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================
|
||||
// Timer pour gérer l'appui long du reboot :
|
||||
//===========================================================
|
||||
Timer {
|
||||
id: timer_sortie
|
||||
interval: step_timer_sortie
|
||||
triggeredOnStart: false
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
if (valeur_timer_sortie < shipheart_mouse_press_and_hold_interval_tres_long) valeur_timer_sortie+= step_timer_sortie;
|
||||
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_sortie.running = false;
|
||||
valeur_timer_sortie = 0;
|
||||
|
||||
// Demande de Reset (via linux si on est sur un ShipRS !) :
|
||||
let commande = "sudo sh -c \"sudo reboot now\" ";
|
||||
//console.log("Commande shell : [" + commande + "]");
|
||||
systeme.commande_shell(commande, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Titre de la p"/images/ak14.png"age :
|
||||
Shipheart_titre_1 {titre:"ShipRS"; hauteur: shipheart_hauteur_bandeau_haut}
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Ecran Haut :
|
||||
//-------------------------------------------------------
|
||||
Rectangle {
|
||||
id: zone_affichage_message_alerte
|
||||
x: 0
|
||||
y: shipheart_hauteur_bandeau_haut;
|
||||
width: shipheart_largeur_page;
|
||||
height: visible ? (shipheart_hauteur_page - shipheart_hauteur_bandeau_haut) * pourcentage_hauteur_message_alerte : 0;
|
||||
color: "transparent"
|
||||
border.width: 3
|
||||
border.color: couleur_rouge
|
||||
radius: shipheart_rayon_bouton
|
||||
visible: connexion_impossible
|
||||
|
||||
Image {
|
||||
id: picto_alerte
|
||||
source: "/images/ak14.png"
|
||||
sourceSize.height: 100;
|
||||
anchors {
|
||||
left: parent.left
|
||||
leftMargin: 20
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
Text { // Affiche parfaitement 1, 2 ou 3 lignes de texte. A partir de 4 et 5, ça mort sur le contour du rectangle mais c'est encore lisible.
|
||||
id: message_alerte
|
||||
width: parent.width - picto_alerte.width - picto_alerte.anchors.leftMargin - anchors.leftMargin;
|
||||
wrapMode: Text.Wrap
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
leftPadding: 10 // Dégage le pictogramme sur la gauche
|
||||
rightPadding: 10 // Evite de se caler sur le bord droit du rectangle
|
||||
text: "La connexion à ShipBase a échoué.<br />\
|
||||
Vérifiez avant tout que ShipBase est bien sous tension et qu'il est bien connecté au réseau local.<br />\
|
||||
Vérifiez ensuite que ShipRS est également connecté au réseau local via son port Ethernet.<br />\
|
||||
Enfin, assurez-vous que l'adresse IP de ShipBase sur le réseau local est bien celle renseignée ci-dessous.<br />\
|
||||
Dans le cas contraire, vous pouvez la mettre à jour puis cliquer sur [Enregistrer].<br />\
|
||||
<b>Attention : La prise en compte de cette nouvelle adresse ne sera prise en compte qu'après un redémarrage de ShipRS.</b><br /><br />
|
||||
<i>The connection to ShipBase has failed.<br />
|
||||
First of all, check that ShipBase is switched on and connected to the local network.<br />
|
||||
Then check that ShipRS is also connected to the local network via its Ethernet port.<br />
|
||||
Finally, make sure that the IP address of ShipBase on the local network is the one given below.<br />
|
||||
If not, you can update it and click on [Save].<br />
|
||||
<b>Please note: The new address will only be taken into account after a restart of ShipRS.</b></i>";
|
||||
anchors {
|
||||
left: picto_alerte.right
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
font.pixelSize: 18
|
||||
color: couleur_blanc_casse
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Ecran Bas - Gauche :
|
||||
//-------------------------------------------------------
|
||||
Rectangle {
|
||||
id: zone_affichage_saisie_parametres
|
||||
x: 0
|
||||
y: shipheart_hauteur_bandeau_haut + zone_affichage_message_alerte.height + espace_lignes_principales;
|
||||
width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2);
|
||||
height: ((shipheart_hauteur_page - shipheart_hauteur_bandeau_haut) * (1 - pourcentage_hauteur_message_alerte)) - espace_lignes_principales;
|
||||
color: "transparent"
|
||||
|
||||
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 : Adresse IP
|
||||
Rectangle {
|
||||
width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2)
|
||||
height: visible ? hauteur_ligne_formulaire : 0
|
||||
color: "transparent"
|
||||
|
||||
Shipheart_formulaire_label {
|
||||
text: "Adresse IP de ShipBase sur le réseau local<br /><i>ShipBase IP address on local network</i>"
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
}
|
||||
|
||||
Shipheart_formulaire_textfield {
|
||||
id: champ_formulaire_Adresse_ip
|
||||
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 : Taille écran
|
||||
Rectangle {
|
||||
width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2)
|
||||
height: visible ? hauteur_ligne_formulaire : 0
|
||||
color: "transparent"
|
||||
|
||||
Shipheart_formulaire_label {
|
||||
text: "Taille de l'écran<br /><i>Screen size</i>"
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
}
|
||||
|
||||
Shipheart_formulaire_combobox {
|
||||
id: champ_formulaire_Taille_ecran
|
||||
model: ListModel { }
|
||||
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
|
||||
onActivated: {
|
||||
shipheart_clic();
|
||||
}
|
||||
}
|
||||
|
||||
Shipheart_formulaire_ligne_separation {
|
||||
haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Message d'erreur si adresse IP invalide :
|
||||
Rectangle {
|
||||
width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2)
|
||||
height: visible ? hauteur_ligne_formulaire : 0
|
||||
color: "transparent"
|
||||
visible: (message_erreur !== "") || (message_info !== "")
|
||||
|
||||
Text {
|
||||
// height: parent.height * proportion_hauteur_texte_droite
|
||||
width: parent.width;
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
topPadding: 20 // Cette valeur permet d'être aligné avec la version courante...
|
||||
bottomPadding: 50
|
||||
font.pixelSize: 18
|
||||
text: (message_erreur !== "") ? message_erreur : message_info
|
||||
color: (message_erreur !== "") ? couleur_rouge : couleur_blanc_casse
|
||||
wrapMode: Text.Wrap
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Ecran Bas - Droite :
|
||||
//-------------------------------------------------------
|
||||
Rectangle {
|
||||
id: zone_affichage_droite
|
||||
x: zone_affichage_saisie_parametres.width + espace_colonnes_principales
|
||||
y: shipheart_hauteur_bandeau_haut + zone_affichage_message_alerte.height + espace_lignes_principales;
|
||||
width: (shipheart_largeur_page * (1 - pourcentage_largeur_colonne_gauche)) - (espace_colonnes_principales / 2);
|
||||
height: ((shipheart_hauteur_page - shipheart_hauteur_bandeau_haut) * (1 - pourcentage_hauteur_message_alerte)) - espace_lignes_principales;
|
||||
color: "transparent"
|
||||
visible: !clavier.active
|
||||
|
||||
Column {
|
||||
anchors.fill: parent
|
||||
spacing: 10
|
||||
|
||||
// Bouton Enregistrer :
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: hauteur_bouton_droit
|
||||
color: shipheart_couleur_fond_bouton
|
||||
radius: shipheart_rayon_bouton
|
||||
Text {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
font.pixelSize: 20
|
||||
text: "Enregistrer<br /><i>Save</i>"
|
||||
color: couleur_blanc_casse
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
enregistrement();
|
||||
if ((!connexion_impossible) && (message_erreur === ""))
|
||||
{
|
||||
shipheart_clic();
|
||||
stackView.pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Bouton Rebooter :
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: hauteur_bouton_droit
|
||||
color: shipheart_couleur_fond_bouton
|
||||
radius: shipheart_rayon_bouton
|
||||
visible: connexion_impossible && configuration_modifiee
|
||||
|
||||
Label {
|
||||
anchors.centerIn: parent
|
||||
text: "Redémarrer ShipRS<br /><i>Restart ShipRS</i>"
|
||||
color: couleur_blanc_casse
|
||||
font.pixelSize:20
|
||||
}
|
||||
|
||||
// Barre grandissante pour montrer durée d'appui vs tempo nécessaire :
|
||||
Rectangle {
|
||||
width: (valeur_timer_sortie / shipheart_mouse_press_and_hold_interval_tres_long) * parent.width
|
||||
height: parent.height
|
||||
color: couleur_rouge_transparent
|
||||
radius: shipheart_rayon_bouton
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onPressed: { // Déclenché lors de l'appui inital
|
||||
valeur_timer_sortie = 0;
|
||||
timer_sortie.running = true;
|
||||
}
|
||||
onClicked: { // Déclenché si l'appui n'a pas été suffisement long pour avoir un Press&Hold :
|
||||
timer_sortie.running = false;
|
||||
valeur_timer_sortie = 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_sortie.running = false;
|
||||
valeur_timer_sortie = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// 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
|
||||
visible: !connexion_impossible
|
||||
|
||||
//.................................................
|
||||
// Bouton retour
|
||||
//.................................................
|
||||
Rectangle {
|
||||
id: bandeau_bas_zone_retour
|
||||
width: (parent.width * pourcentage_bandeau_bas_largeur_zone_retour) - (2 * parent.padding)
|
||||
height: shipheart_hauteur_bandeau_bas - parent.topPadding - parent.bottomPadding;
|
||||
radius: shipheart_rayon_bouton
|
||||
color: shipheart_couleur_fond_bouton
|
||||
|
||||
Image {
|
||||
source: "/images/icone_retour.png"
|
||||
sourceSize.height: 30
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea { // Zone d'interaction. On est obligé de la mettre dans la grille pour que Rectangle et MouseArea soient frères ou parent/enfant ET qu'on n'occupe qu'un espace dans la grille.
|
||||
id: mouse_area_bandeau_bas_zone_retour
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
stackView.pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//=============================================================================================================
|
||||
// Init de la page
|
||||
//=============================================================================================================
|
||||
function init_page()
|
||||
{
|
||||
var i;
|
||||
var lignes;
|
||||
|
||||
lignes = systeme.lecture_fichier(shipheart_nom_complet_fichier_shiprs_conf);
|
||||
// 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 de 'shiprs.conf' = " + lignes[0]);
|
||||
console.log("Adresse IP de ShipBase dans 'shiprs.conf' = " + lignes[1]);
|
||||
console.log("Taille écran dans 'shiprs.conf' = " + lignes[2]);
|
||||
|
||||
if (lignes[0] === "Ok")
|
||||
{
|
||||
adresse_ip_shipbase = lignes[1];
|
||||
taille_ecran_shiprs = lignes[2];
|
||||
}
|
||||
else
|
||||
{
|
||||
adresse_ip_shipbase = "???.???.???.???";
|
||||
taille_ecran_shiprs = 10;
|
||||
|
||||
message_erreur = "/!\\ La lecture du fichier 'shiprs.conf' est impossible<br /><i>/!\\ ShipRS config file can't be accessed</i>";
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------------
|
||||
champ_formulaire_Adresse_ip.text = adresse_ip_shipbase;
|
||||
|
||||
//-----------------------------------------------------------------------------------------
|
||||
champ_formulaire_Taille_ecran.model.clear();
|
||||
champ_formulaire_Taille_ecran.model.append({"valeur": 7, "texte": "7\" " });
|
||||
champ_formulaire_Taille_ecran.model.append({"valeur": 10, "texte": "10\" " });
|
||||
champ_formulaire_Taille_ecran.model.append({"valeur": 22, "texte": "22\" " });
|
||||
|
||||
// Positionnement de l'index sur la valeur en cours :
|
||||
i = recherche_index_valeur_modele(taille_ecran_shiprs, champ_formulaire_Taille_ecran.model, "taille_ecran_shiprs");
|
||||
if (i === -1) champ_formulaire_Taille_ecran.currentIndex = recherche_index_valeur_modele(10, champ_formulaire_Taille_ecran.model, "taille_ecran_shiprs");
|
||||
else champ_formulaire_Taille_ecran.currentIndex = i;
|
||||
|
||||
|
||||
flag_init = false;
|
||||
}
|
||||
|
||||
//=============================================================================================================
|
||||
// Enregistrement des valeurs saisies
|
||||
//=============================================================================================================
|
||||
function enregistrement()
|
||||
{
|
||||
var lignes = [];
|
||||
|
||||
message_erreur = ""; // Nécessaire si une erreur était présente au préalable.
|
||||
message_info = ""; // Nécessaire si un message était présent au préalable.
|
||||
|
||||
// Vérification de la validité du format de l'adresse IP saisie :
|
||||
if (Fonctions.test_format_adresse_ip_v4(champ_formulaire_Adresse_ip.text))
|
||||
//-----------------------------------------------------------
|
||||
// Cas où le format est valide :
|
||||
{
|
||||
if(champ_formulaire_Adresse_ip.text !== "192.168.4.1")
|
||||
{
|
||||
|
||||
adresse_ip_shipbase = champ_formulaire_Adresse_ip.text;
|
||||
taille_ecran_shiprs = champ_formulaire_Taille_ecran.model.get(champ_formulaire_Taille_ecran.currentIndex).valeur;
|
||||
|
||||
lignes.push(adresse_ip_shipbase);
|
||||
lignes.push(taille_ecran_shiprs);
|
||||
|
||||
if (systeme.ecriture_fichier(shipheart_nom_complet_fichier_shiprs_conf, lignes) === -1)
|
||||
{
|
||||
message_erreur = "/!\\ L'écriture du fichier 'shiprs.conf' est impossible.<br /><i>/!\\ 'shiprs.conf' file cannot be written to</i>";
|
||||
}
|
||||
else
|
||||
{
|
||||
configuration_modifiee = true;
|
||||
message_info = "Les nouveaux paramètres ont été enregistrés.<br />Vous pouvez maintenant maintenir appuyé le bouton [Redémarrer ShipRS] jusqu'au redémarrage pour que ces nouveaux paramètres soient pris en compte.<br /><i>The new settings have been saved.<br />You can now press and hold the [Restart ShipRS] button until the system restarts to take these new settings into account.</i>";
|
||||
}
|
||||
//console.log("Format d'adresse IP valide...")
|
||||
}
|
||||
else message_erreur = "L'adresse IP [192.168.4.1] n'est pas autorisée. Merci d'entrer une adresse différente...<br /><i>The [192.168.4.1] IP address is not authorized. Please enter a different address...</i>";
|
||||
|
||||
|
||||
}
|
||||
//-----------------------------------------------------------
|
||||
// Cas où le format est invalide :
|
||||
else
|
||||
{
|
||||
message_erreur = "L'adresse IP saisie n'est pas valide et ne peut pas être enregistrée. Merci d'entrer une chaine valide...<br /><i>The IP address entered is invalid and cannot be saved. Please enter a valid string...</i>";
|
||||
|
||||
// champ_formulaire_Adresse_ip.text = adresse_ip_shipbase; // Retour à la valeur précédente
|
||||
//console.log("Format d'adresse IP invalide !")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//=============================================================================================================
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,476 @@
|
||||
//========================================================================================================================================================================
|
||||
// CONFIG_SPECIFIQUE_CLIENT_SUNCY.QML
|
||||
// Ce fichier traite la configuration des paramètres spécifiques au client Suncy Concept
|
||||
// La page est appelée depuis la page parametres_avances.qml, en cliquant sur "Vos paramètres" > "Spécifique xxxx" (ce bouton n'est visible que si l'option Spécifique_client
|
||||
// contient la valeur adéquate dans TB_COnfiguration)
|
||||
//========================================================================================================================================================================
|
||||
import QtQuick 2.12
|
||||
import QtQml.Models
|
||||
|
||||
import qt.koriolan.shipheart 1.0
|
||||
|
||||
|
||||
|
||||
Shipheart_page {
|
||||
id: page_config_specifique_client_suncy
|
||||
|
||||
|
||||
// Mis en forme :
|
||||
readonly property double pourcentage_largeur_colonne_gauche: 0.75
|
||||
readonly property double espace_colonnes_principales: 20
|
||||
readonly property double pourcentage_hauteur_ligne_haut: 1
|
||||
readonly property double espace_lignes_principales: 20
|
||||
readonly property double affichage_hauteur_utile: shipheart_hauteur_page - shipheart_hauteur_bandeau_haut - shipheart_hauteur_bandeau_bas
|
||||
|
||||
readonly property int hauteur_ligne_formulaire: 60
|
||||
readonly property double pourcentage_largeur_labels_formulaire: 0.4
|
||||
|
||||
readonly property int hauteur_bouton_droit: 80
|
||||
|
||||
readonly property double pourcentage_bandeau_bas_largeur_zone_retour: 1
|
||||
|
||||
readonly property int periode_init_raffraichissement_parametres: 1 // En ms
|
||||
readonly property int periode_raffraichissement_parametres: 1000 // En ms
|
||||
|
||||
// Affichage :
|
||||
property bool bouton_bandeau_bas_zone_retour_actif: false
|
||||
property int protection_mode: 0
|
||||
|
||||
|
||||
// Données :
|
||||
property int min_taille_code: 6
|
||||
property int max_taille_code: 8
|
||||
|
||||
// Modèles :
|
||||
// Note : les modèles chargés dans 'main.qml' n'ont pas à être rechargés dans les pages suivantes
|
||||
|
||||
|
||||
|
||||
//===========================================================
|
||||
// Timer periode raffraichissement parametres :
|
||||
//===========================================================
|
||||
Timer {
|
||||
id: timer_raffraichissement_parametres
|
||||
interval: periode_init_raffraichissement_parametres
|
||||
triggeredOnStart: false
|
||||
running: true
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
if (interval == periode_init_raffraichissement_parametres) { // Premier passage, 1ms après le premier chargement
|
||||
interval = periode_raffraichissement_parametres;
|
||||
|
||||
init_page();
|
||||
}
|
||||
else if (!bouton_bandeau_bas_zone_retour_actif) {
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Titre de la page :
|
||||
Shipheart_titre_1 {titre:qsTr("Configuration spécifique à Suncy Concept"); 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"
|
||||
|
||||
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 : Sortie activation moteur
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: visible ? hauteur_ligne_formulaire : 0
|
||||
color: "transparent"
|
||||
|
||||
Shipheart_formulaire_label {
|
||||
text: qsTr("Circuit d'activation moteur")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
}
|
||||
|
||||
Shipheart_formulaire_combobox {
|
||||
id: champ_formulaire_Circuit_activation_moteur
|
||||
model: ListModel { }
|
||||
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
|
||||
onActivated: {
|
||||
shipheart_clic();
|
||||
}
|
||||
}
|
||||
|
||||
Shipheart_formulaire_ligne_separation {
|
||||
haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Espace :
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: 50
|
||||
color: "transparent"
|
||||
}
|
||||
// Sous-titre :
|
||||
Shipheart_titre_2 {titre:qsTr("Nouveau code"); hauteur: shipheart_hauteur_bandeau_haut}
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Ligne de formulaire : Code
|
||||
Rectangle {
|
||||
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("Code d'accès au bateau")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
}
|
||||
|
||||
Shipheart_formulaire_textfield {
|
||||
id: champ_formulaire_Code
|
||||
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
|
||||
x: parent.width * pourcentage_largeur_labels_formulaire
|
||||
flag_num_only: true
|
||||
password_type: true
|
||||
maximumLength: max_taille_code_pattern
|
||||
}
|
||||
}
|
||||
//-------------------------------------------------------------------------------
|
||||
// Ligne de formulaire : Répéter Code
|
||||
Rectangle {
|
||||
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("Répéter le code d'accès")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
}
|
||||
|
||||
Shipheart_formulaire_textfield {
|
||||
id: champ_formulaire_Code_repetition
|
||||
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
|
||||
x: parent.width * pourcentage_largeur_labels_formulaire
|
||||
flag_num_only: true
|
||||
password_type: true
|
||||
maximumLength: max_taille_code_pattern
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// 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 :
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: hauteur_bouton_droit
|
||||
color: shipheart_couleur_fond_bouton
|
||||
radius: shipheart_rayon_bouton
|
||||
// visible: !clavier.active // SDIR #255
|
||||
Text {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
font.pixelSize: 20
|
||||
text: qsTr("Enregistrer")
|
||||
color: couleur_blanc_casse
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
if (mise_a_jour() !== -1) stackView.pop(); // On ne revient à la page précédente que si la saisie est valide...
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Bandeau bas :
|
||||
//-------------------------------------------------------
|
||||
Row {
|
||||
x: 0
|
||||
y: shipheart_hauteur_page - shipheart_hauteur_bandeau_bas;
|
||||
width: shipheart_largeur_page;
|
||||
height: shipheart_hauteur_bandeau_bas;
|
||||
spacing: 5
|
||||
padding: 5
|
||||
|
||||
//.................................................
|
||||
// Bouton retour
|
||||
//.................................................
|
||||
Rectangle {
|
||||
id: bandeau_bas_zone_retour
|
||||
width: (parent.width * pourcentage_bandeau_bas_largeur_zone_retour) - (2 * parent.padding)
|
||||
height: shipheart_hauteur_bandeau_bas - parent.topPadding - parent.bottomPadding;
|
||||
radius: shipheart_rayon_bouton
|
||||
color: shipheart_couleur_fond_bouton
|
||||
|
||||
Image {
|
||||
source: "/images/icone_retour.png"
|
||||
sourceSize.height: 30
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea { // Zone d'interaction. On est obligé de la mettre dans la grille pour que Rectangle et MouseArea soient frères ou parent/enfant ET qu'on n'occupe qu'un espace dans la grille.
|
||||
id: mouse_area_bandeau_bas_zone_retour
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
stackView.pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Boite d'information :
|
||||
//-------------------------------------------------------
|
||||
Shipheart_boite_dialogue {
|
||||
id: boite_information
|
||||
}
|
||||
|
||||
|
||||
// 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_circuits;
|
||||
var i, j;
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
// Taille du code :
|
||||
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Min_taille_code" ';
|
||||
res = bdd.requete_unique(req);
|
||||
min_taille_code = Number(res[0]);
|
||||
|
||||
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Max_taille_code" ';
|
||||
res = bdd.requete_unique(req);
|
||||
max_taille_code = Number(res[0]);
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
// Paramètres spécifiques :
|
||||
for (i = 1; i < shipheart_specifique_client.length; i ++)
|
||||
{
|
||||
var parametre = shipheart_specifique_client[i].split('=');
|
||||
switch(parametre[0])
|
||||
{
|
||||
//--------------------------------------------------------
|
||||
case 'id_circuit_activation_moteur':
|
||||
champ_formulaire_Circuit_activation_moteur.model.clear();
|
||||
champ_formulaire_Circuit_activation_moteur.model.append({"valeur": 0, "texte": qsTr("Aucune") });
|
||||
|
||||
req = 'SELECT Cle_primaire, Nom, Adresse_module, No_circuit FROM TB_Circuits ORDER BY Adresse_module, No_circuit';
|
||||
//console.log("req =" + req);
|
||||
nb_circuits = bdd.requete(req);
|
||||
|
||||
for (j = 0; j < nb_circuits; j ++)
|
||||
{
|
||||
res = bdd.lecture_ligne();
|
||||
if (!res.isEmpty)
|
||||
{
|
||||
champ_formulaire_Circuit_activation_moteur.model.append({"valeur": Number(res[0]), "texte": qsTr(" [module %1 - circuit %2] %3").arg(Number(res[2])).arg(Number(res[3]) + 1).arg(res[1])});
|
||||
}
|
||||
else break; // Ne devrait pas arriver....
|
||||
}
|
||||
|
||||
// Positionnement de l'index sur la valeur en cours :
|
||||
var defaut_circuit_activation_moteur = 0
|
||||
j = recherche_index_valeur_modele(Number(parametre[1]), champ_formulaire_Circuit_activation_moteur.model, "Circuit_activation_moteur");
|
||||
if (j === -1) champ_formulaire_Circuit_activation_moteur.currentIndex = recherche_index_valeur_modele(defaut_circuit_activation_moteur, champ_formulaire_Circuit_activation_moteur.model, "Circuit_activation_moteur");
|
||||
else champ_formulaire_Circuit_activation_moteur.currentIndex = j;
|
||||
|
||||
break;
|
||||
|
||||
//--------------------------------------------------------
|
||||
default:
|
||||
console.log("paramètre spécifique client inconnu : [" + parametre[0] + "] = [" + parametre[1] + "]");
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================================================
|
||||
// Mise à jour des valeurs saisies
|
||||
//=============================================================================================================
|
||||
function mise_a_jour()
|
||||
{
|
||||
var req;
|
||||
var i;
|
||||
var chaine_specifique_client;
|
||||
|
||||
//=============================================
|
||||
// Configuration du code d'accès :
|
||||
var nouveau_code_saisi, nouveau_code_repetition_saisi;
|
||||
var nouveau_code_saisi_encrypte;
|
||||
var erreur = false;
|
||||
|
||||
nouveau_code_saisi = champ_formulaire_Code.text
|
||||
nouveau_code_repetition_saisi = champ_formulaire_Code_repetition.text
|
||||
do { // Fake loop
|
||||
|
||||
//.........................................
|
||||
// Si aucune valeur de code n'est saisie :
|
||||
if ((nouveau_code_saisi === "") && (nouveau_code_repetition_saisi === "")) break;
|
||||
|
||||
//.................................................
|
||||
// Si la répétition n'est pas égale à l'original :
|
||||
if (nouveau_code_repetition_saisi !== nouveau_code_saisi)
|
||||
{
|
||||
boite_information.niveau = 1
|
||||
boite_information.imageTitreSource = "/images/attention.png"
|
||||
boite_information.message = qsTr("Les deux valeurs saisies doivent être identiques !\n\nDe plus, le code doit contenir :\n- %1 chiffres au minimum\n- %2 chiffres au maximum.").arg(min_taille_code).arg(max_taille_code);
|
||||
boite_information.open();
|
||||
|
||||
erreur = true;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
//.................................................
|
||||
// Si le format du nouveau code n'est pas correct :
|
||||
if ((nouveau_code_saisi.length < min_taille_code) || (nouveau_code_saisi.length > max_taille_code))
|
||||
{
|
||||
//console.log("Le code saisie a une longueur anormale [" + nouveau_code_saisi.length + "]")
|
||||
boite_information.niveau = 1
|
||||
boite_information.imageTitreSource = "/images/attention.png";
|
||||
boite_information.message = qsTr("Le nouveau code doit contenir :\n- %1 chiffres au minimum\n- %2 chiffres au maximum.\n\nLe code saisi ne répond pas à ces critères et sa mise à jour n'est donc pas effectuée.\n\nMerci de saisir un code au format valide si vous souhaitez le modifier.").arg(min_taille_code).arg(max_taille_code);
|
||||
boite_information.open();
|
||||
|
||||
erreur = true;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
//.................................................
|
||||
// Si tout est Ok :
|
||||
nouveau_code_saisi_encrypte = bdd.sha256(nouveau_code_saisi);
|
||||
req = 'UPDATE TB_Configuration SET Valeur="' + nouveau_code_saisi_encrypte + '" WHERE Nom="Code_client" ';
|
||||
//console.log("Requête = " + req)
|
||||
bdd.requete_unique(req);
|
||||
|
||||
shipheart_code_client = nouveau_code_saisi_encrypte;
|
||||
|
||||
} while (0);
|
||||
|
||||
|
||||
|
||||
if (erreur === false)
|
||||
{
|
||||
//=============================================
|
||||
// Mise à jour des paramètres spécifiques :
|
||||
chaine_specifique_client = shipheart_specifique_client[0]; // Premier champ toujours présent = n° de client spécifique
|
||||
|
||||
for (i = 1; i < shipheart_specifique_client.length; i ++) // On commence à 1 car le premier champ est déjà renseigné...
|
||||
{
|
||||
var parametre = shipheart_specifique_client[i].split('=');
|
||||
switch(parametre[0])
|
||||
{
|
||||
//--------------------------------------------------------
|
||||
case 'id_circuit_activation_moteur':
|
||||
var val = Number(champ_formulaire_Circuit_activation_moteur.model.get(champ_formulaire_Circuit_activation_moteur.currentIndex).valeur);
|
||||
if (val !== Number(parametre[1]))
|
||||
{
|
||||
bdd.requete_unique("UPDATE TB_Circuits SET New_consigne=0 WHERE Cle_primaire='" + Number(parametre[1]) + "'"); // Coupure de l'ancien circuit
|
||||
if (val > 0) bdd.requete_unique("UPDATE TB_Circuits SET New_consigne=100 WHERE Cle_primaire='" + val + "'"); // Activation du nouveau circuit (sauf si le nouveau circuit est 'Aucun')
|
||||
}
|
||||
shipheart_specifique_client[i] = parametre[0]; // Mise à jour de la propriété reconstituer l'ensemble de la chaine dans tous les cas
|
||||
shipheart_specifique_client[i] += "=" + val;
|
||||
|
||||
break;
|
||||
|
||||
//--------------------------------------------------------
|
||||
default :
|
||||
break;
|
||||
}
|
||||
|
||||
chaine_specifique_client += ";" + shipheart_specifique_client[i]; // Remplissage de la chaine complète pour mise à jour de la BDD
|
||||
}
|
||||
|
||||
// Mise à jour de la BDD :
|
||||
req = 'UPDATE TB_Configuration SET Valeur="' + chaine_specifique_client + '" WHERE Nom="Specifique_client" ';
|
||||
//console.log("Requête = " + req)
|
||||
bdd.requete_unique(req);
|
||||
}
|
||||
|
||||
if (erreur === false) return(0);
|
||||
else return(-1);
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================================================
|
||||
// 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,773 @@
|
||||
//========================================================================================================================================================================
|
||||
// CONFIG_VERSION.QML
|
||||
// Ce fichier traite les informations de versions de ShipHeart
|
||||
// La page est appelée depuis la page parametres_avances.qml, en cliquant sur "Version"
|
||||
//========================================================================================================================================================================
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
import qt.koriolan.shipheart 1.0
|
||||
|
||||
|
||||
|
||||
Shipheart_page {
|
||||
id: page_config_version
|
||||
|
||||
|
||||
// Mis en forme :
|
||||
readonly property double pourcentage_largeur_colonne_gauche: 0.50
|
||||
readonly property double espace_colonnes_principales: 20
|
||||
readonly property double pourcentage_hauteur_ligne_haut: 0.7
|
||||
readonly property double espace_lignes_principales: 20
|
||||
readonly property double affichage_hauteur_utile: shipheart_hauteur_page - shipheart_hauteur_bandeau_haut - shipheart_hauteur_bandeau_bas
|
||||
|
||||
readonly property int hauteur_ligne_formulaire: 60
|
||||
readonly property double pourcentage_largeur_labels_formulaire: 0.4
|
||||
|
||||
readonly property double proportion_hauteur_texte_droite: 0.4
|
||||
readonly property int hauteur_bouton_droit: 80
|
||||
readonly property int largeur_bouton_droit: 200
|
||||
|
||||
readonly property double pourcentage_bandeau_bas_largeur_zone_retour: 0.86
|
||||
|
||||
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 int protection_mode: 0
|
||||
|
||||
|
||||
// Données :
|
||||
property int valeur_timer_appui_long: 0
|
||||
property string version_actuelle: ""
|
||||
property string date_version_actuelle: ""
|
||||
property string version_nouvelle: ""
|
||||
property int type_version_nouvelle: 0 // 0: aucune, 1= à valider, 2= à charger
|
||||
property int demande_maj_soft_en_cours: shipheart_demande_maj_soft_aucune
|
||||
property bool flag_demande_factory_reset_en_cours: false
|
||||
property bool flag_demande_factory_reset: false
|
||||
|
||||
// Modèles :
|
||||
// Note : les modèles chargés dans 'main.qml' n'ont pas à être rechargés dans les pages suivantes
|
||||
|
||||
|
||||
//===========================================================
|
||||
// Timer periode raffraichissement parametres :
|
||||
//===========================================================
|
||||
Timer {
|
||||
id: timer_raffraichissement_parametres
|
||||
interval: periode_init_raffraichissement_parametres
|
||||
triggeredOnStart: false
|
||||
running: true
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
if (interval == periode_init_raffraichissement_parametres) { // Premier passage, 1ms après le premier chargement
|
||||
interval = periode_raffraichissement_parametres;
|
||||
|
||||
init_page();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Si on est en cours de Factory Reset et qu'un fichier '.enc' est dispo, c'est que ça doit être le fichier
|
||||
// de Factory Reset généré par sauvegarde.php qui est prêt :
|
||||
if ((flag_demande_factory_reset) &&
|
||||
(shipheart_nb_fichiers_a_charger > 0)) // On ne peut pas utiliser (shipheart_fichier_a_charger != "") car on ne prend pas en compte les fichiers de type 'new' (ni 'restore).
|
||||
{
|
||||
busy_indicator.running = false;
|
||||
rebooter();
|
||||
}
|
||||
|
||||
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;
|
||||
shipheart_clic();
|
||||
|
||||
if (mousearea_installer_now.pressed)
|
||||
{
|
||||
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("<b>Mise à jour immédiate</b><br /><br />Si vous confirmez, cette mise à jour peut nécessiter <u>quelques minutes</u> pendant lesquelles <b>votre système ShipHeart ne sera pas accessible</b>.<br /><br />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 !<br /><br />Cliquez sur Annuler pour revenir en arrière et effectuer cette installation ultérieurement.")
|
||||
boite_validation_securisee.alignementMessage = Text.AlignHCenter
|
||||
boite_validation_securisee.affichageAscenseur = true;
|
||||
boite_validation_securisee.open();
|
||||
}
|
||||
else if (mousearea_installer_next_start.pressed)
|
||||
{
|
||||
boite_validation_securisee.niveau = 1;
|
||||
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("Si vous confirmez, cette mise à jour sera marquée pour être chargée au prochain démarrage de ShipHeart.<br />Cliquez sur Annuler pour revenir en arrière et la conserver.")
|
||||
boite_validation_securisee.alignementMessage = Text.AlignHCenter
|
||||
boite_validation_securisee.affichageAscenseur = true;
|
||||
boite_validation_securisee.open();
|
||||
}
|
||||
else if (mousearea_installer_never.pressed)
|
||||
{
|
||||
boite_validation_securisee.niveau = 1;
|
||||
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("<b>Suppression de version</b><br /><br />Si vous confirmez, cette mise à jour sera définitivement supprimée.<br />Cliquez sur Annuler pour revenir en arrière et la conserver.")
|
||||
boite_validation_securisee.alignementMessage = Text.AlignHCenter
|
||||
boite_validation_securisee.affichageAscenseur = true;
|
||||
boite_validation_securisee.open();
|
||||
}
|
||||
else if (mousearea_factory_reset.pressed)
|
||||
{
|
||||
flag_demande_factory_reset_en_cours = true;
|
||||
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("Réinitialiser");
|
||||
boite_validation_securisee.imageTitreSource = "/images/attention.png";
|
||||
boite_validation_securisee.message = qsTr("<b>Réinitialisation Usine</b><br /><br />Si vous confirmez, tous les paramètres de ShipHeart seront complètement et définitivement effacés !<br /><br />Aucune sauvegarde ne sera conservée et tout retour en arrière sera impossible... <br /><br />Cliquez sur Annuler pour revenir en arrière si vous n'êtes pas certain de votre décision.<br /><br />Note : En cas de doute, vous pouvez effectuer une Sauvegarde et <u>la stocker sur une clé externe</u> avant d'effectuer cette réinitialisation usine.")
|
||||
boite_validation_securisee.alignementMessage = Text.AlignHCenter
|
||||
boite_validation_securisee.affichageAscenseur = true;
|
||||
boite_validation_securisee.open();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Titre de la page :
|
||||
Shipheart_titre_1 {titre:qsTr("Version"); 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"
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Grille pour afficher les paramètres :
|
||||
GridView {
|
||||
id: grille_informations
|
||||
|
||||
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_grille_informations
|
||||
delegate: Rectangle {
|
||||
width: grille_informations.cellWidth - 10
|
||||
height: grille_informations.cellHeight - 5
|
||||
color: "transparent"
|
||||
Rectangle { // c'est le bouton proprement dit...
|
||||
height: parent.height
|
||||
width:parent.width
|
||||
color: "transparent"
|
||||
radius: shipheart_rayon_bouton
|
||||
anchors.bottom: parent.bottom
|
||||
Text {
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Qt.AlignLeft
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
leftPadding: 20
|
||||
text: model.nom_champ + " : " + model.valeur_champ
|
||||
color: couleur_blanc_casse
|
||||
font.pixelSize: 18
|
||||
font.bold: false
|
||||
wrapMode: Label.Wrap
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ListModel {
|
||||
id: modele_grille_informations
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// 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"
|
||||
border.color: couleur_blanc_casse_transparent
|
||||
border.width: 2
|
||||
visible: (type_version_nouvelle > 0)
|
||||
|
||||
Column {
|
||||
|
||||
anchors.fill: parent
|
||||
spacing: 20
|
||||
|
||||
//=========================================================================
|
||||
// Texte d'introduction
|
||||
//=========================================================================
|
||||
Text {
|
||||
// height: parent.height * proportion_hauteur_texte_droite
|
||||
width: parent.width;
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
topPadding: 20 // Cette valeur permet d'être aligné avec la version courante...
|
||||
bottomPadding: 50
|
||||
font.pixelSize: 18
|
||||
text: {
|
||||
let message;
|
||||
switch (type_version_nouvelle)
|
||||
{
|
||||
//-----------------------------
|
||||
// Fichier dans A_VALIDER :
|
||||
case shipheart_demande_maj_soft_validation:
|
||||
message = qsTr("La version <b>%1</b> est disponible.<br /><br />Souhaitez-vous : ").arg(version_nouvelle);
|
||||
break;
|
||||
|
||||
//-----------------------------
|
||||
// Fichier dans A_CHARGER :
|
||||
case shipheart_demande_maj_soft_chargement:
|
||||
message = qsTr("La version <b>%1</b> est disponible.<br /><br />Elle sera automatiquement installée lors du prochain démarrage de ShipHeart.<br />A moins que vous ne choisissiez l'une des options ci-dessous :").arg(version_nouvelle)
|
||||
break;
|
||||
|
||||
//-----------------------------
|
||||
// Aucun fichier ni dans A_CHARGER, ni dans A_VALIDER :
|
||||
case shipheart_demande_maj_soft_aucune:
|
||||
default:
|
||||
message = "";
|
||||
}
|
||||
return message;
|
||||
}
|
||||
color: couleur_blanc_casse
|
||||
wrapMode: Text.Wrap
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// Boutons :
|
||||
//=========================================================================
|
||||
Row {
|
||||
height: hauteur_bouton_droit
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
spacing: 20
|
||||
|
||||
//---------------------------------------------------------------
|
||||
Rectangle {
|
||||
id: bouton_installer_now
|
||||
height: hauteur_bouton_droit
|
||||
width:largeur_bouton_droit
|
||||
color: shipheart_couleur_fond_bouton
|
||||
radius: shipheart_rayon_bouton
|
||||
visible: (type_version_nouvelle > 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_installer_now.pressed
|
||||
}
|
||||
Text {
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Qt.AlignHCenter
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
text: qsTr("L'installer\nmaintenant")
|
||||
color: couleur_blanc_casse
|
||||
font.pixelSize: 16
|
||||
wrapMode: Label.Wrap
|
||||
padding: 10
|
||||
}
|
||||
MouseArea {
|
||||
id: mousearea_installer_now
|
||||
anchors.fill: parent
|
||||
|
||||
onPressed: { // Déclenché lors de l'appui inital
|
||||
timer_appui_long.running = true;
|
||||
valeur_timer_appui_long = 0;
|
||||
demande_maj_soft_en_cours = shipheart_demande_maj_soft_chargement;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
Rectangle {
|
||||
id: bouton_installer_next_start
|
||||
height: hauteur_bouton_droit
|
||||
width:largeur_bouton_droit
|
||||
color: shipheart_couleur_fond_bouton
|
||||
radius: shipheart_rayon_bouton
|
||||
visible: (type_version_nouvelle === 1)
|
||||
|
||||
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_installer_next_start.pressed
|
||||
}
|
||||
Text {
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Qt.AlignHCenter
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
text: qsTr("L'installer au prochain démarrage de ShipHeart")
|
||||
color: couleur_blanc_casse
|
||||
font.pixelSize: 16
|
||||
wrapMode: Label.Wrap
|
||||
padding: 10
|
||||
}
|
||||
MouseArea {
|
||||
id: mousearea_installer_next_start
|
||||
anchors.fill: parent
|
||||
onPressed: { // Déclenché lors de l'appui inital
|
||||
timer_appui_long.running = true;
|
||||
valeur_timer_appui_long = 0;
|
||||
demande_maj_soft_en_cours = shipheart_demande_maj_soft_validation;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
Rectangle {
|
||||
id: bouton_installer_never
|
||||
height: hauteur_bouton_droit
|
||||
width:largeur_bouton_droit
|
||||
color: shipheart_couleur_fond_bouton
|
||||
radius: shipheart_rayon_bouton
|
||||
visible: (type_version_nouvelle > 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_installer_never.pressed
|
||||
}
|
||||
Text {
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Qt.AlignHCenter
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
text: qsTr("Ne jamais l'installer")
|
||||
color: couleur_blanc_casse
|
||||
font.pixelSize: 16
|
||||
wrapMode: Label.Wrap
|
||||
padding: 10
|
||||
}
|
||||
MouseArea {
|
||||
id: mousearea_installer_never
|
||||
anchors.fill: parent
|
||||
onPressed: { // Déclenché lors de l'appui inital
|
||||
timer_appui_long.running = true;
|
||||
valeur_timer_appui_long = 0;
|
||||
demande_maj_soft_en_cours = shipheart_demande_maj_soft_annulation;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Ecran Bas :
|
||||
//-------------------------------------------------------
|
||||
Rectangle {
|
||||
id: zone_affichage_bas
|
||||
x: 0
|
||||
y: shipheart_hauteur_bandeau_haut + zone_affichage_haut_gauche.height + espace_lignes_principales;
|
||||
width: shipheart_largeur_page
|
||||
height: (affichage_hauteur_utile * (1 - pourcentage_hauteur_ligne_haut)) - espace_lignes_principales;
|
||||
color: "transparent"
|
||||
|
||||
Text {
|
||||
width: parent.width;
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
horizontalAlignment: Text.AlignJustify
|
||||
padding: 20 // Cette valeur permet d'être aligné avec la version courante...
|
||||
font.pixelSize: 16
|
||||
text: qsTr("Le présent produit est conçu et fabriqué par la société Koriolan qui dispose de toutes les licences et droits d'exploitation sur les images, \
|
||||
logiciels et brevets utilisés tant pour sa conception que pour son fonctionnement. \
|
||||
ShipHeart™, Ship2net™ et Koriolan™ sont des marques déposées par la société Koriolan. \
|
||||
Pour toute question relative à ce produit, merci de vous rendre sur le site 'koriolan.tech' ou de nous contacter à l'adresse 'contact@koriolan.tech'.");
|
||||
color: couleur_blanc_casse
|
||||
wrapMode: Text.Wrap
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// 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: (bandeau_bas_zone_bouton_factory_reset.visible) ?
|
||||
(parent.width * pourcentage_bandeau_bas_largeur_zone_retour - (parent.spacing / 2)) :
|
||||
(parent.width - (2 * parent.padding))
|
||||
height: shipheart_hauteur_bandeau_bas - parent.topPadding - parent.bottomPadding;
|
||||
radius: shipheart_rayon_bouton
|
||||
color: shipheart_couleur_fond_bouton
|
||||
|
||||
Image {
|
||||
source: "/images/icone_retour.png"
|
||||
sourceSize.height: 30
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: mouse_area_bandeau_bas_zone_retour
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
|
||||
shipheart_compteur_time_out_niveau_acces = shipheart_time_out_niveau_acces; // Rechargement au moment de la sortie (SDIR #187)
|
||||
shipheart_flag_blocage_compteurs_pendant_config = false; // Déblocage du comptage (SDIR #187)
|
||||
|
||||
stackView.pop(stackView.get(shipheart_niveau_home)); // Retour direct à la Home Page quand on quitte les Paramètres Avancés...
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//.................................................
|
||||
// Bouton Factory Reset :
|
||||
//.................................................
|
||||
Rectangle {
|
||||
id: bandeau_bas_zone_bouton_factory_reset
|
||||
width: (parent.width * (1 - pourcentage_bandeau_bas_largeur_zone_retour)) - (parent.spacing / 2)
|
||||
height: shipheart_hauteur_bandeau_bas - parent.topPadding - parent.bottomPadding;
|
||||
radius: shipheart_rayon_bouton
|
||||
color: shipheart_couleur_fond_bouton
|
||||
visible: (shipheart_type_installation === shipheart_type_installation_shipbase)
|
||||
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_factory_reset.pressed
|
||||
}
|
||||
Image {
|
||||
source: mousearea_factory_reset.pressed ? "/images/factory_reset_actif.png" : "/images/factory_reset_sombre.png"
|
||||
sourceSize.height: 40
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
}
|
||||
MouseArea {
|
||||
id: mousearea_factory_reset
|
||||
anchors.fill: parent
|
||||
onPressed: { // Déclenché lors de l'appui inital
|
||||
valeur_timer_appui_long = 0;
|
||||
timer_appui_long.running = true;
|
||||
}
|
||||
onClicked: { // Déclenché si l'appui n'a pas été suffisement long pour avoir un Press&Hold :
|
||||
valeur_timer_appui_long = 0;
|
||||
timer_appui_long.running = false;
|
||||
}
|
||||
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 !!)
|
||||
valeur_timer_appui_long = 0;
|
||||
timer_appui_long.running = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//---------------------------
|
||||
// Busy Indicator :
|
||||
Shipheart_busy_indicator {
|
||||
id: busy_indicator
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// 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 :
|
||||
if (demande_maj_soft_en_cours !== shipheart_demande_maj_soft_aucune)
|
||||
{
|
||||
demande_maj(demande_maj_soft_en_cours);
|
||||
demande_maj_soft_en_cours = shipheart_demande_maj_soft_aucune;
|
||||
}
|
||||
else if (flag_demande_factory_reset_en_cours)
|
||||
{
|
||||
demande_factory_reset();
|
||||
}
|
||||
break;
|
||||
|
||||
case shipheart_boite_dialogue_bouton_2: // Annuler : on revient sur la page pour que l'on puisse enregistrer.
|
||||
demande_maj_soft_en_cours = shipheart_demande_maj_soft_aucune;
|
||||
flag_demande_factory_reset_en_cours = false;
|
||||
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;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Mise à jour des informations sur les différentes versions sous-jacentes :
|
||||
modele_grille_informations.clear();
|
||||
|
||||
req = 'SELECT Nom, Valeur FROM TB_Systeme ORDER BY Cle_primaire';
|
||||
//console.log("req =" + req);
|
||||
nb = bdd.requete(req);
|
||||
|
||||
for (i = 0; i < nb; i ++)
|
||||
{
|
||||
res = bdd.lecture_ligne();
|
||||
if (!res.isEmpty)
|
||||
{
|
||||
switch(res[0])
|
||||
{
|
||||
// case "Version_soft_package": nom_champ = qsTr("Version du package logiciel"); valeur_champ = res[1]; break;
|
||||
case "Version_soft_no_package":
|
||||
version_actuelle = res[1];
|
||||
nom_champ = qsTr("Version du package logiciel");
|
||||
valeur_champ = res[1];
|
||||
break;
|
||||
case "Version_soft_application_cm3p":
|
||||
nom_champ = qsTr("Version de l'application");
|
||||
valeur_champ = res[1];
|
||||
break;
|
||||
case "Version_soft_application_qt":
|
||||
nom_champ = qsTr("Version de l'interface graphique");
|
||||
valeur_champ = res[1];
|
||||
break;
|
||||
case "Version_soft_modem":
|
||||
if (shipheart_generation_shipbase >= shipheart_generation_shipbase_v2) continue;
|
||||
nom_champ = qsTr("Version du firmware du modem");
|
||||
valeur_champ = res[1].replace("Revision:", "");
|
||||
break;
|
||||
case "No_imei":
|
||||
if (shipheart_generation_shipbase >= shipheart_generation_shipbase_v2) continue;
|
||||
nom_champ = qsTr("Numéro d'IMEI");
|
||||
valeur_champ = res[1];
|
||||
break;
|
||||
case "No_iccid":
|
||||
if (shipheart_generation_shipbase >= shipheart_generation_shipbase_v2) continue;
|
||||
nom_champ = qsTr("Numéro d'ICCID");
|
||||
valeur_champ = res[1].replace("f", "");
|
||||
break;
|
||||
case "No_imsi":
|
||||
if (shipheart_generation_shipbase >= shipheart_generation_shipbase_v2) continue;
|
||||
nom_champ = qsTr("Numéro d'IMSI");
|
||||
valeur_champ = res[1];
|
||||
break;
|
||||
|
||||
default: continue;
|
||||
}
|
||||
modele_grille_informations.append({"nom_champ": nom_champ, "valeur_champ": valeur_champ});
|
||||
}
|
||||
else break; // Ne devrait pas arriver....
|
||||
}
|
||||
|
||||
|
||||
mise_a_jour();
|
||||
}
|
||||
|
||||
//=============================================================================================================
|
||||
// Mise à jour de l'état des fichiers disponibles :
|
||||
//=============================================================================================================
|
||||
function mise_a_jour()
|
||||
{
|
||||
var i;
|
||||
var fragments_new_version;
|
||||
|
||||
version_nouvelle = "";
|
||||
|
||||
if (shipheart_fichier_a_charger !== "") // Si un fichier a chargé existe, on ne considère que celui-ci :
|
||||
{
|
||||
let c = shipheart_fichier_a_charger.split('.'); // Extraction de la partie avant le premier '.'
|
||||
fragments_new_version = c[0].split('_'); // Extractions des fragments de version
|
||||
type_version_nouvelle = shipheart_demande_maj_soft_chargement;
|
||||
|
||||
}
|
||||
else if(shipheart_fichier_a_valider !== "") // ... sinon, on regarde si un fichier à valider existe et on le traite :
|
||||
{
|
||||
let c = shipheart_fichier_a_valider.split('.'); // Extraction de la partie avant le premier '.'
|
||||
fragments_new_version = c[0].split('_'); // Extractions des fragments de version
|
||||
type_version_nouvelle = shipheart_demande_maj_soft_validation;
|
||||
}
|
||||
else type_version_nouvelle = shipheart_demande_maj_soft_aucune;
|
||||
|
||||
if (type_version_nouvelle > shipheart_demande_maj_soft_aucune) version_nouvelle = fragments_new_version[2] + "." + fragments_new_version[3] + "." + fragments_new_version[4];
|
||||
else version_nouvelle = "";
|
||||
//console.log("Version nouvelle = " + version_nouvelle)
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================================================
|
||||
// Mise à jour de la valeur de Demande_maj_soft dans TB_Systeme
|
||||
//=============================================================================================================
|
||||
function demande_maj(demande_maj_soft)
|
||||
{
|
||||
var commande;
|
||||
|
||||
switch (demande_maj_soft)
|
||||
{
|
||||
//-----------------------------
|
||||
// Fichier dans A_VALIDER :
|
||||
// Note : l'utilisation de 'sudo sh -c "commande" ' permet de lancer un shell en sudo qui, ensuite exécute la commande (en sudo donc)
|
||||
// Sans passer par cette astuce, l'appel se fait depuis le shell qui a lancé Qt (non-sudo donc) et le fait d'ajouter 'sudo' DANS la commande
|
||||
// n'est pas prise en compte. La commandes est alors exécutée en non-sudo en, selon, les droits nécessaires, peut échouer.
|
||||
case shipheart_demande_maj_soft_validation:
|
||||
commande = 'sudo sh -c "mv ' + shipheart_repertoire_versions_a_valider + '/' + shipheart_fichier_a_valider + ' ' + shipheart_repertoire_versions_a_charger + '/' + shipheart_fichier_a_valider + '" ';
|
||||
//console.log("Exécution de la commande [ " + commande + " ]");
|
||||
systeme.commande_shell_non_bloquante(commande);
|
||||
|
||||
break;
|
||||
|
||||
//-----------------------------
|
||||
// Fichier dans A_CHARGER :
|
||||
case shipheart_demande_maj_soft_chargement:
|
||||
rebooter();
|
||||
break;
|
||||
|
||||
//------------------------------------------------------------
|
||||
// Demande d'annulation :
|
||||
case shipheart_demande_maj_soft_annulation:
|
||||
|
||||
// Vidage du répertoire A_VALIDER :
|
||||
commande = 'sudo sh -c "rm -f ' + shipheart_repertoire_versions_a_valider + '/*" ';
|
||||
//console.log("Exécution de la commande [ " + commande + " ]");
|
||||
systeme.commande_shell(commande, "");
|
||||
|
||||
// Vidage du répertoire A_CHARGER :
|
||||
commande = 'sudo sh -c "rm -f ' + shipheart_repertoire_versions_a_charger + '/*" ';
|
||||
//console.log("Exécution de la commande [ " + commande + " ]");
|
||||
systeme.commande_shell(commande, "");
|
||||
|
||||
break;
|
||||
|
||||
//-----------------------------
|
||||
// Aucun fichier ni dans A_CHARGER, ni dans A_VALIDER :
|
||||
case shipheart_demande_maj_soft_aucune:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Dermande de synchro rapide de l'appli :
|
||||
synchro_bdd(shipheart_type_synchro_data);
|
||||
|
||||
}
|
||||
|
||||
//=============================================================================================================
|
||||
// Traitement de la demande de Factory Reset :
|
||||
//=============================================================================================================
|
||||
function demande_factory_reset()
|
||||
{
|
||||
var commande;
|
||||
|
||||
flag_demande_factory_reset_en_cours = false;
|
||||
|
||||
// Vidage du répertoire A_CHARGER :
|
||||
commande = 'sudo sh -c "rm -f ' + shipheart_repertoire_versions_a_charger + '/*" ';
|
||||
//console.log("Exécution de la commande [ " + commande + " ]");
|
||||
systeme.commande_shell(commande, "");
|
||||
|
||||
// Vidage du répertoire A_VALIDER :
|
||||
// Peut être utile pour le fonctionnement après le Factory Reset.
|
||||
commande = 'sudo sh -c "rm -f ' + shipheart_repertoire_versions_a_valider + '/*" ';
|
||||
//console.log("Exécution de la commande [ " + commande + " ]");
|
||||
systeme.commande_shell(commande, "");
|
||||
|
||||
// Commande d'exécution du script :
|
||||
commande = 'sudo sh -c "php ' + shipheart_repertoire_utils + '/' + shipheart_nom_fichier_sauvegarde + ' Factory_reset" ';
|
||||
//console.log("Exécution de la commande [ " + commande + " ]");
|
||||
systeme.commande_shell_non_bloquante(commande); // On doit sortir sans attendre la fin de l'exécution pour que le sablier fonctionne.
|
||||
|
||||
flag_demande_factory_reset = true; // Permet de valider la recherche d'un fichier 'enc' de fin de sauvegarde
|
||||
busy_indicator.running = true; // Lance le sablier.
|
||||
}
|
||||
}
|
||||
|
||||
+311
@@ -0,0 +1,311 @@
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Layouts 1.12
|
||||
|
||||
import qt.koriolan.shipheart 1.0
|
||||
import"fonctions.js" as Fonctions
|
||||
import"fonctions_date_heure.js" as Fonctions_date_heure
|
||||
import"suncalc.js" as Suncalc
|
||||
|
||||
|
||||
Shipheart_page {
|
||||
id: page_ephemeride
|
||||
|
||||
// Mis en forme :
|
||||
readonly property double pourcentage_largeur_page_affichage_date_heure: 0.6
|
||||
readonly property double espace_colonnes_principales: 30
|
||||
|
||||
// Affichage :
|
||||
property bool bouton_bandeau_bas_zone_zone_retour_actif: false
|
||||
|
||||
// Données :
|
||||
property string jour_semaine_courant
|
||||
property string date_courante
|
||||
property string heure_courante
|
||||
property string langue: "FR"
|
||||
|
||||
property double test:0
|
||||
|
||||
// Modèles :
|
||||
// Note : les modèles chargés dans 'main.qml' n'ont pas à être rechargés dans les pages suivantes
|
||||
|
||||
|
||||
//===========================================================
|
||||
// Timer 1 seconde :
|
||||
//===========================================================
|
||||
Timer {
|
||||
id: timer_secondes
|
||||
interval: 1000
|
||||
triggeredOnStart: true
|
||||
running: true
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
// Calcul de la date et de l'heure + mise en forme
|
||||
var date = Fonctions_date_heure.date_courante(null, shipheart_fuseau_horaire, shipheart_heure_ete);
|
||||
jour_semaine_courant = Fonctions_date_heure.chaine_jour_semaine(date)
|
||||
date_courante = Fonctions_date_heure.chaine_date_longue(date, shipheart_langue)
|
||||
heure_courante = Fonctions_date_heure.chaine_heure(date);
|
||||
|
||||
// Position :
|
||||
mise_a_jour();
|
||||
}
|
||||
}
|
||||
|
||||
// Titre de la page :
|
||||
Shipheart_titre_1 {titre:qsTr("Ephéméride"); hauteur: shipheart_hauteur_bandeau_haut}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Ecran de gauche :
|
||||
//-------------------------------------------------------
|
||||
Rectangle {
|
||||
x: 0
|
||||
y: shipheart_hauteur_bandeau_haut;
|
||||
width: (shipheart_largeur_page * pourcentage_largeur_page_affichage_date_heure) - (espace_colonnes_principales / 2);
|
||||
height: shipheart_hauteur_page - shipheart_hauteur_bandeau_haut - shipheart_hauteur_bandeau_bas;
|
||||
color: "transparent"
|
||||
|
||||
Text {
|
||||
id: texte_jour_semaine
|
||||
text: jour_semaine_courant
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
verticalCenterOffset: -200
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
// font.family: "Montserrat"
|
||||
font.pixelSize: 60
|
||||
color: couleur_blanc_casse
|
||||
}
|
||||
Text {
|
||||
id: texte_date
|
||||
text: date_courante
|
||||
textFormat: Text.RichText // Autorise la prise en compte de <sup> par exemple...
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
verticalCenterOffset: -100
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
font.pixelSize: 60
|
||||
color: couleur_blanc_casse
|
||||
}
|
||||
Text {
|
||||
id: texte_heure
|
||||
text: heure_courante
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
verticalCenterOffset: 100
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
font.pixelSize: 100
|
||||
// font.weight: Font.Bold
|
||||
color: couleur_blanc_casse
|
||||
}
|
||||
Text {
|
||||
id: texte_fuseau
|
||||
text: (shipheart_fuseau_horaire > 0) ? "[ UTC +" + shipheart_fuseau_horaire + " ]" : ((shipheart_fuseau_horaire < 0) ? "[ UTC " + shipheart_fuseau_horaire + " ]" : "[ UTC ]" )
|
||||
// NB : Il n'y a pas de '-' dans le second cas car il est mis automatiquement par la valeur numérique (qui est négative).
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
verticalCenterOffset: 250
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
font.pixelSize: 20
|
||||
color: couleur_blanc_casse
|
||||
}
|
||||
|
||||
|
||||
Text {
|
||||
id: texte_heure_ete
|
||||
text: (shipheart_heure_ete === 0) ? qsTr("Heure d'hiver") : qsTr("Heure d'été")
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
verticalCenterOffset: 250 + texte_fuseau.height + 10
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
font.pixelSize: 16
|
||||
// font.italic: true
|
||||
color: couleur_gris_fonce
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Ecran de droite :
|
||||
//-------------------------------------------------------
|
||||
Rectangle {
|
||||
x: (shipheart_largeur_page * pourcentage_largeur_page_affichage_date_heure) + espace_colonnes_principales;
|
||||
y: shipheart_hauteur_bandeau_haut;
|
||||
width: ((shipheart_largeur_page * (1 - pourcentage_largeur_page_affichage_date_heure)) - (espace_colonnes_principales / 2)) * 0.8;
|
||||
height: shipheart_hauteur_page - shipheart_hauteur_bandeau_haut - shipheart_hauteur_bandeau_bas;
|
||||
color: "transparent"
|
||||
|
||||
ColumnLayout {
|
||||
width: parent.width
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
spacing: 0
|
||||
|
||||
ListModel {
|
||||
id: modele_ephemeride
|
||||
ListElement { evenement: qsTr("Aube nautique"); heure: "00:00"; ligne_sup: 1; ligne_inf: 1; hauteur:40; image: ""; }
|
||||
ListElement { evenement: qsTr("Lever du soleil"); heure: "00:00"; ligne_sup: 0; ligne_inf: 1; hauteur:40; image: ""; }
|
||||
ListElement { evenement: qsTr("Zénith"); heure: "00:00"; ligne_sup: 0; ligne_inf: 1; hauteur:40; image: ""; }
|
||||
ListElement { evenement: qsTr("Coucher du soleil"); heure: "00:00"; ligne_sup: 0; ligne_inf: 1; hauteur:40; image: ""; }
|
||||
ListElement { evenement: qsTr("Crépuscule nautique"); heure: "00:00"; ligne_sup: 0; ligne_inf: 1; hauteur:40; image: ""; }
|
||||
ListElement { evenement: ""; heure: ""; ligne_sup: 0; ligne_inf: 1; hauteur:60; image: ""; }
|
||||
ListElement { evenement: qsTr("Lune"); heure: ""; ligne_sup: 0; ligne_inf: 1; hauteur:60; image: "/images/lune_1.png"; }
|
||||
ListElement { evenement: ""; heure: ""; ligne_sup: 0; ligne_inf: 1; hauteur:60; image: ""; }
|
||||
ListElement { evenement: qsTr("Latitude"); heure: "Inconnue"; ligne_sup: 0; ligne_inf: 1; hauteur:40; image: ""; }
|
||||
ListElement { evenement: qsTr("Longitude"); heure: "Inconnue"; ligne_sup: 0; ligne_inf: 1; hauteur:40; image: ""; }
|
||||
}
|
||||
|
||||
Repeater {
|
||||
model: modele_ephemeride
|
||||
|
||||
Rectangle {
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
Layout.preferredWidth: parent.width
|
||||
Layout.preferredHeight: model.hauteur
|
||||
color: "transparent"
|
||||
|
||||
Rectangle {
|
||||
id: ligne_sup
|
||||
height:1
|
||||
width:parent.width
|
||||
color: couleur_gris_tres_fonce_transparent
|
||||
visible: model.ligne_sup ? 1 : 0;
|
||||
}
|
||||
Text {
|
||||
id: titre_ligne
|
||||
width: parent.width / 2;
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
leftPadding: 10
|
||||
text: model.evenement
|
||||
font.pixelSize: 18
|
||||
color: couleur_blanc_casse
|
||||
}
|
||||
Text {
|
||||
x: titre_ligne.width;
|
||||
width: parent.width - titre_ligne.width;
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
horizontalAlignment: Text.AlignRight
|
||||
rightPadding: 10
|
||||
text: model.heure
|
||||
font.pixelSize: 18
|
||||
color: couleur_blanc_casse
|
||||
visible: (model.image === "") ? true : false;
|
||||
}
|
||||
Image {
|
||||
visible: (model.image === "") ? false : true;
|
||||
source: model.image;
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 20
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
sourceSize.height: 40;
|
||||
}
|
||||
Rectangle {
|
||||
id: ligne_inf
|
||||
anchors.top: parent.bottom;
|
||||
height:1
|
||||
width:parent.width
|
||||
color: couleur_gris_tres_fonce_transparent
|
||||
visible: model.ligne_inf ? 1 : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// 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 - (2 * parent.padding)
|
||||
height: shipheart_hauteur_bandeau_bas - parent.topPadding - parent.bottomPadding;
|
||||
radius: 5
|
||||
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();
|
||||
stackView.pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//===========================================================
|
||||
// Economiseur : Doit être placé en fin de page pour fonctionner
|
||||
//===========================================================
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
preventStealing: true // Permet que cela fonctionne même si un élément flickable (notamment) soit derrière et "vole" le click
|
||||
enabled: flag_economiseur_actif
|
||||
onClicked: {
|
||||
mise_en_veille(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================================================
|
||||
// Mise à jour de la position
|
||||
//=============================================================================================================
|
||||
function mise_a_jour()
|
||||
{
|
||||
var req, res
|
||||
var lat, lon;
|
||||
var altitude = 0;
|
||||
|
||||
// Latitude :
|
||||
modele_ephemeride.set(8, {"heure": Fonctions.chaine_latitude(shipheart_latitude) })
|
||||
|
||||
// Longitude :
|
||||
modele_ephemeride.set(9, {"heure": Fonctions.chaine_longitude(shipheart_longitude) })
|
||||
|
||||
// Informations sur le soleil :
|
||||
modele_ephemeride.set(0, {"heure": shipheart_heure_aube_nautique });
|
||||
modele_ephemeride.set(1, {"heure": shipheart_heure_lever_soleil });
|
||||
modele_ephemeride.set(2, {"heure": shipheart_heure_zenith });
|
||||
modele_ephemeride.set(3, {"heure": shipheart_heure_coucher_soleil });
|
||||
modele_ephemeride.set(4, {"heure": shipheart_heure_crepuscule_nautique });
|
||||
|
||||
// Ajout du calcul de la hauteur du soleil au zénith :
|
||||
// NON TESTE !! A Tester !!
|
||||
//var sun_positions = Suncalc.SunCalc.getPosition(Fonctions_date_heure.date_courante(null, shipheart_fuseau_horaire, shipheart_heure_ete), lat, lon);
|
||||
//console.log("Hauteur du soleil au Zénith : " + (sun_positions.altitude * (180/3.141592653)).toFixed(1) + "°"); // La valeur d'altitude est retournée en radians
|
||||
//console.log("Azimuth du soleil au Zénith : " + (sun_positions.azimuth * (180/3.141592653)).toFixed(1) + "°"); // La valeur d'azimuth est retournée en radians
|
||||
|
||||
// Informations sur la lune :
|
||||
//console.time('calcul_heures_lune')
|
||||
var moon_status = Suncalc.SunCalc.getMoonIllumination(Fonctions_date_heure.date_courante(null, shipheart_fuseau_horaire, shipheart_heure_ete));
|
||||
//console.timeEnd('calcul_heures_lune')
|
||||
var phase = Number(moon_status.phase);
|
||||
|
||||
modele_ephemeride.set(6, {"image": "/images/lune_" + Number(Math.trunc(phase * 16) + 1) + ".png" }) // Sélection d'une image entre 'lune_1.png' et 'lune_16.png'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,378 @@
|
||||
//========================================================================================================================================================================
|
||||
// ETALONNAGE_CAPTEUR.QML
|
||||
// Ce fichier traite l'étalonnage d'une carte. La page affiche notamment :
|
||||
// - La valeur brute actuelle
|
||||
// - la valeur corrigée actuelle (rensignée manuellement)
|
||||
// - l'offset actuel
|
||||
// La page est appelée depuis la page config_capteur.qml, en cliquant sur le bouton ETALONNAGE lorsqu'il est disponible.
|
||||
//========================================================================================================================================================================
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQml.Models
|
||||
|
||||
import qt.koriolan.shipheart 1.0
|
||||
|
||||
|
||||
|
||||
|
||||
Shipheart_page {
|
||||
id: page_etalonnage_capteur
|
||||
|
||||
|
||||
// Mis en forme :
|
||||
readonly property double pourcentage_largeur_colonne_gauche: 0.75
|
||||
readonly property double espace_colonnes_principales: 20
|
||||
readonly property double pourcentage_hauteur_ligne_haut: 1
|
||||
readonly property double espace_lignes_principales: 20
|
||||
readonly property double affichage_hauteur_utile: shipheart_hauteur_page - shipheart_hauteur_bandeau_haut - shipheart_hauteur_bandeau_bas
|
||||
|
||||
readonly property int hauteur_ligne_formulaire: 60
|
||||
readonly property double pourcentage_largeur_labels_formulaire: 0.4
|
||||
|
||||
readonly property int hauteur_bouton_droit: 80
|
||||
|
||||
readonly property double pourcentage_bandeau_bas_largeur_zone_retour: 1
|
||||
|
||||
readonly property int periode_init_raffraichissement_parametres: 1 // En ms
|
||||
readonly property int periode_raffraichissement_parametres: 1000 // En ms
|
||||
|
||||
// Affichage :
|
||||
property bool bouton_bandeau_bas_zone_retour_actif: false
|
||||
property int protection_mode: 0
|
||||
property bool flag_init: true // Permet de bloquer certains affichage tant que l'init n'est pas terminée
|
||||
|
||||
// Données :
|
||||
property int id_capteur: -1
|
||||
property string nom_capteur: "---"
|
||||
property double valeur_old: 0
|
||||
property double valeur_brute: 0
|
||||
property double valeur_new: 0
|
||||
property double offset_old: 0
|
||||
property double offset_new: 0
|
||||
property string symbole_unite: ""
|
||||
property int precision_affichage: 1
|
||||
property int nouvelle_unite: 0
|
||||
|
||||
// Modèles :
|
||||
// Note : les modèles chargés dans 'main.qml' n'ont pas à être rechargés dans les pages suivantes
|
||||
|
||||
|
||||
|
||||
//===========================================================
|
||||
// Timer periode raffraichissement parametres capteur :
|
||||
//===========================================================
|
||||
Timer {
|
||||
id: timer_raffraichissement_parametres
|
||||
interval: periode_init_raffraichissement_parametres
|
||||
triggeredOnStart: false
|
||||
running: true
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
if (interval == periode_init_raffraichissement_parametres) // Premier passage, 1ms après le premier chargement
|
||||
{
|
||||
interval = periode_raffraichissement_parametres;
|
||||
init_page();
|
||||
}
|
||||
else if (!clavier.active) mise_a_jour(); // Permet la mise à jour en temps réel du moment que le clavier n'est pas actif.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Titre de la page :
|
||||
Shipheart_titre_1 {titre:qsTr("Etalonnage du capteur [%1]").arg(nom_capteur); 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"
|
||||
|
||||
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 : Valeur brute actuelle
|
||||
Rectangle {
|
||||
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("Valeur brute actuelle")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
}
|
||||
|
||||
Shipheart_formulaire_valeur_fixe {
|
||||
text: valeur_brute.toFixed(precision_affichage) + " " + symbole_unite
|
||||
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 : Valeur_corrigee
|
||||
Rectangle {
|
||||
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("Valeur corrigée actuelle (%1)").arg(symbole_unite)
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
}
|
||||
|
||||
Shipheart_formulaire_textfield {
|
||||
id: champ_formulaire_Valeur_corrigee
|
||||
text: valeur_new.toFixed(precision_affichage)
|
||||
width: parent.width * (1 - pourcentage_largeur_labels_formulaire)
|
||||
x: parent.width * pourcentage_largeur_labels_formulaire
|
||||
flag_num_only: true
|
||||
onAccepted: { // Mise à jour à l'appui sur RETURN mais PAS en repliant le clavier (avec le bouton du clavier et la flèche vers le bas).
|
||||
mise_a_jour(); // Dans tous les cas, la MAJ sera faite à l'enregistrement.
|
||||
}
|
||||
}
|
||||
|
||||
Shipheart_formulaire_ligne_separation {
|
||||
haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Ligne de formulaire : Offset
|
||||
Rectangle {
|
||||
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("Correction")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
}
|
||||
|
||||
Shipheart_formulaire_valeur_fixe {
|
||||
text: ((offset_new > 0) ? "+" : "") + offset_new.toFixed(precision_affichage) + " " + symbole_unite
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// 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 :
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: hauteur_bouton_droit
|
||||
color: shipheart_couleur_fond_bouton
|
||||
radius: shipheart_rayon_bouton
|
||||
// visible: !clavier.active // SDIR #255
|
||||
Text {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
font.pixelSize: 20
|
||||
text: qsTr("Enregistrer")
|
||||
color: couleur_blanc_casse
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
enregistrement();
|
||||
stackView.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Bandeau bas :
|
||||
//-------------------------------------------------------
|
||||
Row {
|
||||
x: 0
|
||||
y: shipheart_hauteur_page - shipheart_hauteur_bandeau_bas;
|
||||
width: shipheart_largeur_page;
|
||||
height: shipheart_hauteur_bandeau_bas;
|
||||
spacing: 5
|
||||
padding: 5
|
||||
|
||||
//.................................................
|
||||
// Bouton retour
|
||||
//.................................................
|
||||
Rectangle {
|
||||
id: bandeau_bas_zone_retour
|
||||
width: (parent.width * pourcentage_bandeau_bas_largeur_zone_retour) - (2 * parent.padding)
|
||||
height: shipheart_hauteur_bandeau_bas - parent.topPadding - parent.bottomPadding;
|
||||
radius: shipheart_rayon_bouton
|
||||
color: shipheart_couleur_fond_bouton
|
||||
|
||||
Image {
|
||||
source: "/images/icone_retour.png"
|
||||
sourceSize.height: 30
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea { // Zone d'interaction. On est obligé de la mettre dans la grille pour que Rectangle et MouseArea soient frères ou parent/enfant ET qu'on n'occupe qu'un espace dans la grille.
|
||||
id: mouse_area_bandeau_bas_zone_retour
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
stackView.pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//===========================================================
|
||||
// Economiseur : Doit être placé en fin de page pour fonctionner
|
||||
//===========================================================
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
preventStealing: true // Permet que cela fonctionne même si un élément flickable (notamment) soit derrière et "vole" le click
|
||||
enabled: flag_economiseur_actif
|
||||
onClicked: {
|
||||
mise_en_veille(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=============================================================================================================
|
||||
// Initialistion de la page
|
||||
//=============================================================================================================
|
||||
function init_page()
|
||||
{
|
||||
var i;
|
||||
var res;
|
||||
var id_variable;
|
||||
var tmp;
|
||||
|
||||
if (id_capteur > 0) res = bdd.requete_unique('SELECT Nom, Valeur, Offset, Precision_affichage_accueil, ID_Variable FROM TB_Capteurs WHERE Cle_primaire=' + id_capteur + ' ');
|
||||
else
|
||||
{
|
||||
console.log("La page 'etalonnage_capteur.qml' a été appelée sans 'id_capteur' valide. L'affichage de la page est impossible");
|
||||
stackView.pop();
|
||||
}
|
||||
|
||||
i = 0;
|
||||
nom_capteur = res[i++];
|
||||
valeur_old = Number(res[i++]); // La Valeur en BDD est une valeur corrigée avec l'offset BDD
|
||||
offset_old = Number(res[i++]);
|
||||
precision_affichage = Number(res[i++]);
|
||||
id_variable = Number(res[i++]);
|
||||
|
||||
valeur_brute = valeur_old - offset_old;
|
||||
valeur_new = valeur_old;
|
||||
offset_new = offset_old;
|
||||
|
||||
res = bdd.requete_unique('SELECT Unite, Conversion_unite FROM TB_Variables WHERE Cle_primaire=' + id_variable + ' ');
|
||||
symbole_unite = res[0];
|
||||
|
||||
// Non utilisé pour le moment...
|
||||
/* switch(Number(res[1]))
|
||||
{
|
||||
case shipheart_type_unite_volume:
|
||||
nouvelle_unite = shipheart_unite_volume;
|
||||
symbole_unite = shipheart_unite_volume_symbole;
|
||||
break;
|
||||
case shipheart_type_unite_temperature:
|
||||
nouvelle_unite = shipheart_unite_temperature;
|
||||
symbole_unite = shipheart_unite_temperature_symbole;
|
||||
break;
|
||||
default:
|
||||
nouvelle_unite = 0;
|
||||
symbole_unite = unite;
|
||||
break;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
//=============================================================================================================
|
||||
// Mise à jour de la valeur instantannée
|
||||
//=============================================================================================================
|
||||
function mise_a_jour()
|
||||
{
|
||||
var res
|
||||
|
||||
valeur_new = Number(champ_formulaire_Valeur_corrigee.text);
|
||||
offset_new = valeur_new - valeur_brute;
|
||||
|
||||
/* // Mise à jour avec dernière valeur en cours :
|
||||
res = bdd.requete_unique('SELECT Valeur FROM TB_Capteurs WHERE Cle_primaire="' + id_capteur + '" ');
|
||||
valeur_brute = Number(res[0]);
|
||||
valeur_corrigee = valeur_brute + offset;
|
||||
*/
|
||||
}
|
||||
|
||||
//=============================================================================================================
|
||||
// Enregistrement de la nouvelle valeur d'offset
|
||||
//=============================================================================================================
|
||||
function enregistrement()
|
||||
{
|
||||
var req, res
|
||||
|
||||
mise_a_jour(); // Pour avoir la dernière valeur d'offset
|
||||
|
||||
// Mise à jour de l'offset de correction :
|
||||
req = 'UPDATE TB_Capteurs SET Offset=' + offset_new + ' WHERE Cle_primaire="' + id_capteur + '" ';
|
||||
res = bdd.requete_unique(req);
|
||||
|
||||
// Demande de reconfiguration système via la BDD car on a modifié des valeurs de configuration :
|
||||
synchro_bdd(shipheart_type_synchro_config);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,904 @@
|
||||
//========================================================================================================================================================================
|
||||
// ETALONNAGE_CARTE.QML
|
||||
// Ce fichier traite l'étalonnage d'une carte. La page affiche notamment :
|
||||
// - La valeur brute actuelle
|
||||
// - la valeur corrigée actuelle (rensignée manuellement)
|
||||
// - l'offset actuel
|
||||
// La page est appelée depuis la page information_materiel.qml, en cliquant sur le bouton ETALONNAGE lorsqu'il est disponible.
|
||||
//========================================================================================================================================================================
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
import qt.koriolan.shipheart 1.0
|
||||
|
||||
|
||||
|
||||
Shipheart_page {
|
||||
id: page_etalonnage_carte
|
||||
|
||||
|
||||
// Mis en forme :
|
||||
readonly property double pourcentage_largeur_colonne_gauche: 0.75
|
||||
readonly property double espace_colonnes_principales: 20
|
||||
readonly property double pourcentage_hauteur_ligne_haut: 1
|
||||
readonly property double espace_lignes_principales: 20
|
||||
readonly property double affichage_hauteur_utile: shipheart_hauteur_page - shipheart_hauteur_bandeau_haut - shipheart_hauteur_bandeau_bas
|
||||
|
||||
readonly property int hauteur_ligne_formulaire: 60
|
||||
readonly property double pourcentage_largeur_labels_formulaire: 0.4
|
||||
readonly property double nombre_colonnes_secondaires: 2 // Cette valeur permet de découper les (1.0 - pourcentage_largeur_labels_formulaire) x pourcentage_largeur_colonne_gauche pour afficher les infos de chaque point d'étalonnage
|
||||
readonly property double espace_colonnes_secondaires: 20
|
||||
|
||||
readonly property int nombre_circuits_affiches_sur_une_colonne: 5
|
||||
|
||||
readonly property int hauteur_bouton_droit: 80
|
||||
|
||||
readonly property double pourcentage_bandeau_bas_largeur_zone_retour: 1
|
||||
|
||||
readonly property int periode_init_raffraichissement_parametres: 1 // En ms
|
||||
readonly property int periode_raffraichissement_parametres: 1000 // En ms
|
||||
|
||||
// Affichage :
|
||||
property bool bouton_bandeau_bas_zone_retour_actif: false
|
||||
property int protection_mode: 0
|
||||
property bool flag_init: true // Permet de bloquer certains affichage tant que l'init n'est pas terminée
|
||||
|
||||
// Données :
|
||||
property int adresse_module: -1
|
||||
property string nom_carte: "---"
|
||||
property int id_batterie: -1 // Cle_primaire de la batterie à laquelle le module est affecté (cas d'un ShipBS)
|
||||
property string eeprom: ""
|
||||
|
||||
property double courant_differentiel: 0
|
||||
property double courant_decharge: 0
|
||||
property double tension: 0
|
||||
property double resistance: 0
|
||||
|
||||
property bool flag_point_memorise_1: false
|
||||
property double courant_differentiel_1: 0
|
||||
property double courant_decharge_1: 0
|
||||
property double tension_1: 0
|
||||
property bool flag_point_memorise_2: false
|
||||
property double courant_differentiel_2: 0
|
||||
property double courant_decharge_2: 0
|
||||
property double tension_2: 0
|
||||
|
||||
|
||||
// Modèles :
|
||||
// Note : les modèles chargés dans 'main.qml' n'ont pas à être rechargés dans les pages suivantes
|
||||
|
||||
|
||||
|
||||
//===========================================================
|
||||
// Timer periode raffraichissement parametres capteur :
|
||||
//===========================================================
|
||||
Timer {
|
||||
id: timer_raffraichissement_parametres
|
||||
interval: periode_init_raffraichissement_parametres
|
||||
triggeredOnStart: false
|
||||
running: true
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
if (interval == periode_init_raffraichissement_parametres) // Premier passage, 1ms après le premier chargement
|
||||
{
|
||||
interval = periode_raffraichissement_parametres;
|
||||
init_page();
|
||||
}
|
||||
else if (!clavier.active) mise_a_jour(); // Permet la mise à jour en temps réel du moment que le clavier n'est pas actif.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Titre de la page :
|
||||
Shipheart_titre_1 {titre:qsTr("Etalonnage du module [%1 - #%2]").arg(nom_carte).arg(adresse_module); 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"
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Ligne de formulaire : N° des points d'étalonnage
|
||||
Rectangle {
|
||||
width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2)
|
||||
height: visible ? hauteur_ligne_formulaire : 0
|
||||
color: "transparent"
|
||||
|
||||
// Label de la ligne :
|
||||
Shipheart_formulaire_label {
|
||||
id: label_no_points
|
||||
text: ""
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
}
|
||||
|
||||
// Première valeur d'étalonnage :
|
||||
Rectangle {
|
||||
id: val_1_no_points
|
||||
width: (parent.width * (1 - pourcentage_largeur_labels_formulaire) / nombre_colonnes_secondaires) - (espace_colonnes_secondaires / 2)
|
||||
height: parent.height
|
||||
anchors {
|
||||
left: label_no_points.right
|
||||
leftMargin: 0
|
||||
}
|
||||
color: "transparent"
|
||||
Label {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
font.pixelSize: 18
|
||||
color: couleur_blanc_casse
|
||||
font.weight: Font.Bold
|
||||
text: qsTr("Point 1");
|
||||
}
|
||||
}
|
||||
|
||||
// Deuxième valeur d'étalonnage :
|
||||
Rectangle {
|
||||
id: val_2_no_points
|
||||
width: (parent.width * (1 - pourcentage_largeur_labels_formulaire) / nombre_colonnes_secondaires) - (espace_colonnes_secondaires / 2)
|
||||
height: parent.height
|
||||
anchors {
|
||||
left: val_1_no_points.right
|
||||
leftMargin: espace_colonnes_secondaires
|
||||
}
|
||||
color: "transparent"
|
||||
Label {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
|
||||
font.pixelSize: 18
|
||||
color: couleur_blanc_casse
|
||||
font.weight: Font.Bold
|
||||
text: qsTr("Point 2");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Ligne de formulaire : Courant de décharge
|
||||
Rectangle {
|
||||
y: hauteur_ligne_formulaire
|
||||
width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2)
|
||||
height: visible ? hauteur_ligne_formulaire : 0
|
||||
color: "transparent"
|
||||
|
||||
// Label de la ligne :
|
||||
Shipheart_formulaire_label {
|
||||
id: label_courant_decharge
|
||||
text: qsTr("Courant de décharge")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
}
|
||||
|
||||
// Première valeur d'étalonnage :
|
||||
Rectangle {
|
||||
id: val_1_courant_decharge
|
||||
width: (parent.width * (1 - pourcentage_largeur_labels_formulaire) / nombre_colonnes_secondaires) - (espace_colonnes_secondaires / 2)
|
||||
height: parent.height
|
||||
anchors {
|
||||
left: label_courant_decharge.right
|
||||
leftMargin: 0
|
||||
}
|
||||
color: "transparent"
|
||||
Label {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
font.pixelSize: 18
|
||||
color: couleur_blanc_casse
|
||||
text: courant_decharge_1.toFixed(3) + " A"
|
||||
}
|
||||
}
|
||||
|
||||
// Deuxième valeur d'étalonnage :
|
||||
Rectangle {
|
||||
id: val_2_courant_decharge
|
||||
width: (parent.width * (1 - pourcentage_largeur_labels_formulaire) / nombre_colonnes_secondaires) - (espace_colonnes_secondaires / 2)
|
||||
height: parent.height
|
||||
anchors {
|
||||
left: val_1_courant_decharge.right
|
||||
leftMargin: espace_colonnes_secondaires
|
||||
}
|
||||
color: "transparent"
|
||||
Label {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
|
||||
font.pixelSize: 18
|
||||
color: couleur_blanc_casse
|
||||
text: courant_decharge_2.toFixed(3) + " A"
|
||||
}
|
||||
}
|
||||
|
||||
// Ligne de séparation :
|
||||
Shipheart_formulaire_ligne_separation {
|
||||
haut_bas_hautbas: shipheart_formulaire_ligne_separation_haute
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Ligne de formulaire : Courant différentiel
|
||||
Rectangle {
|
||||
y: 2 * hauteur_ligne_formulaire
|
||||
width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2)
|
||||
height: visible ? hauteur_ligne_formulaire : 0
|
||||
color: "transparent"
|
||||
|
||||
// Label de la ligne :
|
||||
Shipheart_formulaire_label {
|
||||
id: label_courant_differentiel
|
||||
text: qsTr("Courant différentiel")
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
}
|
||||
|
||||
// Première valeur d'étalonnage :
|
||||
Rectangle {
|
||||
id: val_1_courant_differentiel
|
||||
width: (parent.width * (1 - pourcentage_largeur_labels_formulaire) / nombre_colonnes_secondaires) - (espace_colonnes_secondaires / 2)
|
||||
height: parent.height
|
||||
anchors {
|
||||
left: label_courant_differentiel.right
|
||||
leftMargin: 0
|
||||
}
|
||||
color: "transparent"
|
||||
Label {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
font.pixelSize: 18
|
||||
color: couleur_blanc_casse
|
||||
text: courant_differentiel_1.toFixed(3) + " A"
|
||||
}
|
||||
}
|
||||
|
||||
// Deuxième valeur d'étalonnage :
|
||||
Rectangle {
|
||||
id: val_2_courant_differentiel
|
||||
width: (parent.width * (1 - pourcentage_largeur_labels_formulaire) / nombre_colonnes_secondaires) - (espace_colonnes_secondaires / 2)
|
||||
height: parent.height
|
||||
anchors {
|
||||
left: val_1_courant_differentiel.right
|
||||
leftMargin: espace_colonnes_secondaires
|
||||
}
|
||||
color: "transparent"
|
||||
Label {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
|
||||
font.pixelSize: 18
|
||||
color: couleur_blanc_casse
|
||||
text: courant_differentiel_2.toFixed(3) + " A"
|
||||
}
|
||||
}
|
||||
|
||||
// Ligne de séparation :
|
||||
Shipheart_formulaire_ligne_separation {
|
||||
haut_bas_hautbas: shipheart_formulaire_ligne_separation_haute
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Ligne de formulaire : Boutons de mémorisation
|
||||
Rectangle {
|
||||
y: 3 * hauteur_ligne_formulaire
|
||||
width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2)
|
||||
height: visible ? hauteur_bouton_droit : 0
|
||||
color: "transparent"
|
||||
|
||||
// Label de la ligne :
|
||||
Shipheart_formulaire_label {
|
||||
id: label_boutons
|
||||
text: ""
|
||||
width: parent.width * pourcentage_largeur_labels_formulaire
|
||||
}
|
||||
|
||||
// Première valeur d'étalonnage :
|
||||
Rectangle {
|
||||
id: val_1_boutons
|
||||
width: (parent.width * (1 - pourcentage_largeur_labels_formulaire) / nombre_colonnes_secondaires) - (espace_colonnes_secondaires / 2)
|
||||
height: parent.height - 10
|
||||
radius: shipheart_rayon_bouton
|
||||
anchors {
|
||||
left: label_boutons.right
|
||||
leftMargin: 0
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
color: shipheart_couleur_fond_bouton
|
||||
Label {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
font.pixelSize: 18
|
||||
color: flag_point_memorise_1 ? couleur_gris_fonce : couleur_blanc_casse
|
||||
text: flag_point_memorise_1 ? qsTr("Recalculer ce point") : qsTr("Mémoriser ce point")
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
if (flag_point_memorise_1) flag_point_memorise_1 = false;
|
||||
else
|
||||
{
|
||||
if (flag_point_memorise_2)
|
||||
{
|
||||
if ((courant_differentiel_1 === courant_differentiel_2) ||
|
||||
(courant_decharge_1 === courant_decharge_2))
|
||||
{
|
||||
boite_alerte.open();
|
||||
}
|
||||
else flag_point_memorise_1 = true;
|
||||
}
|
||||
else flag_point_memorise_1 = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Deuxième valeur d'étalonnage :
|
||||
Rectangle {
|
||||
id: val_2_boutons
|
||||
width: (parent.width * (1 - pourcentage_largeur_labels_formulaire) / nombre_colonnes_secondaires) - (espace_colonnes_secondaires / 2)
|
||||
height: parent.height - 10
|
||||
radius: shipheart_rayon_bouton
|
||||
anchors {
|
||||
left: val_1_boutons.right
|
||||
leftMargin: espace_colonnes_secondaires
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
color: shipheart_couleur_fond_bouton
|
||||
Label {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
|
||||
font.pixelSize: 18
|
||||
color: flag_point_memorise_2 ? couleur_gris_fonce : couleur_blanc_casse
|
||||
text: flag_point_memorise_2 ? qsTr("Recalculer ce point") : qsTr("Mémoriser ce point")
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
if (flag_point_memorise_2) flag_point_memorise_2 = false;
|
||||
else
|
||||
{
|
||||
if (flag_point_memorise_1)
|
||||
{
|
||||
if ((courant_differentiel_1 === courant_differentiel_2) ||
|
||||
(courant_decharge_1 === courant_decharge_2))
|
||||
{
|
||||
boite_alerte.open();
|
||||
}
|
||||
else flag_point_memorise_2 = true;
|
||||
}
|
||||
else flag_point_memorise_2 = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ligne de séparation :
|
||||
Shipheart_formulaire_ligne_separation {
|
||||
haut_bas_hautbas: shipheart_formulaire_ligne_separation_haute_basse
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Boutons de circuits :
|
||||
ListView {
|
||||
id: grille_principale
|
||||
x: parent.width * pourcentage_largeur_labels_formulaire
|
||||
y: (3 * hauteur_ligne_formulaire) + hauteur_bouton_droit
|
||||
width: parent.width * (1- pourcentage_largeur_labels_formulaire)
|
||||
height: parent.height - y
|
||||
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
|
||||
|
||||
|
||||
delegate: Rectangle {
|
||||
width: grille_principale.width
|
||||
height: grille_principale.height / nombre_circuits_affiches_sur_une_colonne
|
||||
color: "transparent"
|
||||
Rectangle { // c'est le bouton proprement dit...
|
||||
width:parent.width
|
||||
height: parent.height - 10
|
||||
color: shipheart_couleur_fond_bouton
|
||||
radius: shipheart_rayon_bouton
|
||||
anchors.bottom: parent.bottom
|
||||
Text { // Nom du circuit...
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Qt.AlignLeft
|
||||
verticalAlignment: Qt.AlignTop
|
||||
topPadding: 10
|
||||
leftPadding: 20
|
||||
text: model.nom
|
||||
color: commandable ? couleur_blanc_casse : couleur_gris_fonce
|
||||
font.pixelSize: 18
|
||||
}
|
||||
Text { // Intensité du circuit...
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Qt.AlignLeft
|
||||
verticalAlignment: Qt.AlignBottom
|
||||
bottomPadding: 10
|
||||
leftPadding: 20
|
||||
text: model.intensite.toFixed(1) + " A"
|
||||
color: commandable ? couleur_blanc_casse : couleur_gris_fonce
|
||||
font.pixelSize: 18
|
||||
}
|
||||
Rectangle { // Zone de consigne du circuit...
|
||||
anchors {
|
||||
top: parent.top
|
||||
bottom: parent.bottom
|
||||
right: parent.right
|
||||
}
|
||||
width: 100
|
||||
radius: shipheart_rayon_bouton
|
||||
color: (consigne === 0) ? couleur_rouge_transparent : couleur_vert_transparent
|
||||
visible: commandable
|
||||
Text { // Valeur de la consigne...
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Qt.AlignHCenter
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
text: (consigne === 0) ? qsTr("Off") : ((consigne === 100) ? qsTr("On") : qsTr("On (%1 %%)").arg(consigne))
|
||||
color: (consigne === 0) ? couleur_rouge : couleur_green_yellow
|
||||
font.pixelSize: 18
|
||||
}
|
||||
}
|
||||
MouseArea{
|
||||
anchors.fill : parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
toggle_circuit(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 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"
|
||||
}
|
||||
*/
|
||||
ListModel {
|
||||
id: modele_grille_principale
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// 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 :
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: hauteur_bouton_droit
|
||||
color: shipheart_couleur_fond_bouton
|
||||
radius: shipheart_rayon_bouton
|
||||
visible:
|
||||
// !clavier.active && // SDIR #255
|
||||
!flag_init &&
|
||||
flag_point_memorise_1 &&
|
||||
flag_point_memorise_2
|
||||
Text {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
font.pixelSize: 20
|
||||
text: qsTr("Enregistrer")
|
||||
color: couleur_blanc_casse
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
enregistrement();
|
||||
sortie();
|
||||
stackView.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Bouton Information :
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: hauteur_bouton_droit
|
||||
color: shipheart_couleur_fond_bouton
|
||||
radius: shipheart_rayon_bouton
|
||||
visible: (clavier.active || flag_init) ? false : true; // Si le clavier est déplié ou si l'init est eb cours, on ne propose pas le bouton
|
||||
Text {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
font.pixelSize: 20
|
||||
text: qsTr("Aide")
|
||||
color: couleur_blanc_casse
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
boite_information_shipbs.open();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Bandeau bas :
|
||||
//-------------------------------------------------------
|
||||
Row {
|
||||
x: 0
|
||||
y: shipheart_hauteur_page - shipheart_hauteur_bandeau_bas;
|
||||
width: shipheart_largeur_page;
|
||||
height: shipheart_hauteur_bandeau_bas;
|
||||
spacing: 5
|
||||
padding: 5
|
||||
|
||||
//.................................................
|
||||
// Bouton retour
|
||||
//.................................................
|
||||
Rectangle {
|
||||
id: bandeau_bas_zone_retour
|
||||
width: (parent.width * pourcentage_bandeau_bas_largeur_zone_retour) - (2 * parent.padding)
|
||||
height: shipheart_hauteur_bandeau_bas - parent.topPadding - parent.bottomPadding;
|
||||
radius: shipheart_rayon_bouton
|
||||
color: shipheart_couleur_fond_bouton
|
||||
|
||||
Image {
|
||||
source: "/images/icone_retour.png"
|
||||
sourceSize.height: 30
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
sortie();
|
||||
stackView.pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================
|
||||
// Boite d'alerte :
|
||||
//===========================================================
|
||||
Shipheart_boite_dialogue {
|
||||
id: boite_alerte
|
||||
niveau: 1
|
||||
imageTitreSource: "/images/attention.png";
|
||||
message: qsTr("L'étalonnage ne peut pas se faire avec deux points identiques.<br /><br />
|
||||
Essayer de modifier au moins l'un des deux points de référence en jouant sur la commande des circuits ci-dessous.<br />")
|
||||
}
|
||||
|
||||
//===========================================================
|
||||
// Boite d'information :
|
||||
//===========================================================
|
||||
Shipheart_boite_dialogue {
|
||||
id: boite_information_shipbs
|
||||
niveau: 0
|
||||
imageTitreSource: "/images/ampoule.png";
|
||||
alignementMessage: Text.AlignJustify
|
||||
message: qsTr("Le principe de l'étalonnage est de comparer en <u>2 points différents</u> la valeur de courant différentiel mesurée par le ShipBS d'une part et
|
||||
le courant de décharge mesuré par le système ShipHeart d'autre part.<br />
|
||||
Par exemple, en soumettant le ShipBS en cours d'étalonnage à une consommation faible ou nulle (premier point)
|
||||
puis en mettant en fonctionnement un ou plusieurs appareils pour obtenir une consommation de plusieurs ampères si possible (second point).<br />
|
||||
<br /><u><b>Très important</b> : pendant toute la phase d'étalonnage aucun courant de <b>charge</b> ne doit être appliqué sur ShipBS !</u>
|
||||
Il est donc essentiel de déconnecter tous les chargeurs, régulateurs solaires, etc... du système pendant l'étalonnage.
|
||||
Faute de cela, les valeurs d'étalonnage seront erronées...<br /><br />
|
||||
Remarques :<br />
|
||||
- toutes les consommations doivent passer par le système ShipHeart ! Il faut donc s'assurer qu'aucune charge n'est connectée directement
|
||||
au parc de batteries.<br />
|
||||
- les valeurs de courant n'ont pas d'importance.<br />
|
||||
- le courant du point 2 peut être inférieur ou supérieur à celui du point 1 (mais, aussi \"éloignés\" que possible l'un de l'autre).<br />
|
||||
- il est conseillé de choisir des charges dont la consommation est relativement stable ou, a minima, évolue peu sur une période de quelques secondes.")
|
||||
}
|
||||
|
||||
//===========================================================
|
||||
// Economiseur : Doit être placé en fin de page pour fonctionner
|
||||
//===========================================================
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
preventStealing: true // Permet que cela fonctionne même si un élément flickable (notamment) soit derrière et "vole" le click
|
||||
enabled: flag_economiseur_actif
|
||||
onClicked: {
|
||||
mise_en_veille(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=============================================================================================================
|
||||
// Initialistion de la page
|
||||
//=============================================================================================================
|
||||
function init_page()
|
||||
{
|
||||
var i;
|
||||
var req, res;
|
||||
var nb;
|
||||
var id_variable;
|
||||
var tmp;
|
||||
|
||||
if (adresse_module <= 0)
|
||||
{
|
||||
console.log("La page 'etalonnage_carte.qml' a été appelée sans 'adresse_module' valide. L'affichage de la page est impossible");
|
||||
return;
|
||||
}
|
||||
|
||||
// Recherche des informations sur la carte :
|
||||
req = 'SELECT Eeprom, Type FROM TB_Modules_physiques WHERE Adresse_k_bus=' + adresse_module + ' ';
|
||||
nb = bdd.requete(req);
|
||||
if (nb !== 0)
|
||||
{
|
||||
res = bdd.lecture_ligne();
|
||||
|
||||
i = 0;
|
||||
eeprom = res[i++]; // Sauvegarde car on va l'écraser sur la carte
|
||||
switch(Number(res[i++]))
|
||||
{
|
||||
//-----------------------------------------
|
||||
case shipheart_type_module_shipbase:
|
||||
nom_carte = "ShipBase";
|
||||
break;
|
||||
//-----------------------------------------
|
||||
case shipheart_type_module_shippower812:
|
||||
nom_carte = "ShipPower812";
|
||||
break;
|
||||
//-----------------------------------------
|
||||
case shipheart_type_module_shipBS:
|
||||
nom_carte = "ShipBS";
|
||||
break;
|
||||
//-----------------------------------------
|
||||
case shipheart_type_module_shippower4AC:
|
||||
nom_carte = "ShipPower4AC";
|
||||
break;
|
||||
//-----------------------------------------
|
||||
case shipheart_type_module_shippower8DC:
|
||||
nom_carte = "ShipPower8DC";
|
||||
break;
|
||||
//-----------------------------------------
|
||||
default:
|
||||
nom_carte = "Modèle inconnu";
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
console.log("Aucun module n'existe avec l'adresse K-bus indiquée. L'affichage de la page 'etalonnage_carte.qml' est impossible")
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Recherche des informations sur la batterie affectée à cette carte :
|
||||
req = 'SELECT Cle_primaire, Resistance_interne FROM TB_Batteries WHERE Type_entrees=' + shipheart_batteries_type_entrees_ibs + ' AND Adresse_module=' + adresse_module + ' ';
|
||||
nb = bdd.requete(req);
|
||||
if (nb !== 0)
|
||||
{
|
||||
res = bdd.lecture_ligne();
|
||||
|
||||
i = 0;
|
||||
id_batterie = Number(res[i++]);
|
||||
resistance = Number(res[i++]);
|
||||
}
|
||||
else
|
||||
{
|
||||
console.log("Aucune batterie n'est affectée à la carte à étalonner. L'affichage de la page 'etalonnage_carte.qml' est impossible")
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Remplissage du modèle de circuits :
|
||||
modele_grille_principale.clear();
|
||||
|
||||
// Récupération des informations sur les circuits rattachés à ce ShipBS :
|
||||
req = 'SELECT Cle_primaire, Nom, Consigne, Intensite, Adresse_module, No_circuit FROM TB_Circuits WHERE Adresse_module IN (SELECT Adresse_k_bus FROM TB_Modules_config WHERE ID_Batterie=' + id_batterie + ') ORDER BY Adresse_module, No_circuit';
|
||||
nb = bdd.requete(req);
|
||||
for (i = 0; i < nb; i ++)
|
||||
{
|
||||
res = bdd.lecture_ligne();
|
||||
if (!res.isEmpty)
|
||||
{
|
||||
if ((Number(res[4]) !== 0) || (Number(res[5]) !== 2)) // On exclus le port USB arrière car sa consommation est inclue dans ShipBase et sa commande semble peu pertinente...
|
||||
{
|
||||
modele_grille_principale.append({ "id": Number(res[0]),
|
||||
"nom": res[1],
|
||||
"consigne": Number(res[2]),
|
||||
"consigne_init": Number(res[2]),
|
||||
"intensite": Number(res[3]),
|
||||
"commandable": !((Number(res[4]) === 0) && (Number(res[5]) === 0)) });
|
||||
}
|
||||
}
|
||||
else break; // Ne devrait pas arriver....
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Demande de mis à 0 du gain et offset de la carte (uniquement les valeurs courantes, pas les valeurs usine) :
|
||||
req = 'UPDATE TB_Modules_physiques SET Eeprom="00000000", New_eeprom=1 WHERE Adresse_k_bus=' + adresse_module + ' ';
|
||||
bdd.requete_unique(req);
|
||||
|
||||
boite_information_shipbs.open();
|
||||
|
||||
flag_init = false;
|
||||
}
|
||||
|
||||
//=============================================================================================================
|
||||
// Mise à jour de la valeur instantannée
|
||||
//=============================================================================================================
|
||||
function mise_a_jour()
|
||||
{
|
||||
var req, res;
|
||||
var nb;
|
||||
var i;
|
||||
|
||||
i = 0;
|
||||
|
||||
// Récupération des informations sur les circuits rattachés à ce ShipBS :
|
||||
for (i=0; i < modele_grille_principale.count; i++) // L'init de 'i' dépend de la présence ou non de ShipBase dans la liste
|
||||
{
|
||||
req = 'SELECT Consigne, Intensite FROM TB_Circuits WHERE Cle_primaire=' + modele_grille_principale.get(i).id + ' ';
|
||||
res = bdd.requete_unique(req);
|
||||
modele_grille_principale.set(i, {"consigne": Number(res[0]), "intensite": Number(res[1])});
|
||||
}
|
||||
|
||||
// Récupération des courants différentiel et de décharge de la batterie en cours :
|
||||
req = 'SELECT Courant_decharge, courant_differentiel, Tension FROM TB_Batteries WHERE Cle_primaire=' + id_batterie + ' ';
|
||||
res = bdd.requete_unique(req);
|
||||
i = 0;
|
||||
courant_decharge = Number(res[i++]);
|
||||
courant_differentiel = Number(res[i++]);
|
||||
tension = Number(res[i++]);
|
||||
|
||||
if (!flag_point_memorise_1)
|
||||
{
|
||||
courant_decharge_1 = courant_decharge;
|
||||
courant_differentiel_1 = courant_differentiel;
|
||||
tension_1 = tension;
|
||||
}
|
||||
if (!flag_point_memorise_2)
|
||||
{
|
||||
courant_decharge_2 = courant_decharge;
|
||||
courant_differentiel_2 = courant_differentiel;
|
||||
tension_2 = tension;
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================================================
|
||||
// Commande d'un circuit
|
||||
//=============================================================================================================
|
||||
function toggle_circuit(index)
|
||||
{
|
||||
var consigne;
|
||||
|
||||
if (modele_grille_principale.get(index).consigne === 0) consigne = 100;
|
||||
else consigne = 0;
|
||||
|
||||
modele_grille_principale.set(index, {"consigne": consigne});
|
||||
|
||||
// Mise à jour de la nouvelle consigne du circuit:
|
||||
bdd.requete_unique('UPDATE TB_Circuits SET New_consigne=' + consigne + ' WHERE Cle_primaire="' + modele_grille_principale.get(index).id + '" ');
|
||||
synchro_bdd(shipheart_type_synchro_data);
|
||||
|
||||
}
|
||||
|
||||
//=============================================================================================================
|
||||
// Enregistrement des nouvelles valeur d'étalonnage
|
||||
//=============================================================================================================
|
||||
function enregistrement()
|
||||
{
|
||||
var req;
|
||||
var a, b;
|
||||
var gain, offset;
|
||||
var chaine_gain, chaine_offset;
|
||||
|
||||
|
||||
a = (courant_decharge_1 - courant_decharge_2) / (courant_differentiel_1 - courant_differentiel_2);
|
||||
b = courant_decharge_1 - (a * courant_differentiel_1);
|
||||
gain = Math.round(((a - 1) * 10000));
|
||||
offset = Math.round((b * 1000));
|
||||
|
||||
if ((gain > -9999) && (gain < 9999) && (offset > -32000) && (offset < 32000)) // Si l egain ou l'offset sont hors limite, on n'enregistre pas de valeur d'étalonnage...
|
||||
{
|
||||
chaine_gain = bdd.int16_to_chaine_hexa(gain);
|
||||
chaine_offset = bdd.int16_to_chaine_hexa(offset);
|
||||
//console.log("Gain = " + gain + " soit, en hexa = [" + chaine_gain + "] et Offset = " + offset + " soit, en hexa = [" + chaine_offset + "]");
|
||||
var new_eeprom;
|
||||
new_eeprom = chaine_offset.substring(2,3) + chaine_offset.substring(3,4) + chaine_offset.substring(0,1) + chaine_offset.substring(1,2);
|
||||
new_eeprom += chaine_gain.substring(2,3) + chaine_gain.substring(3,4) + chaine_gain.substring(0,1) + chaine_gain.substring(1,2);
|
||||
new_eeprom += eeprom.substring(8);
|
||||
eeprom = new_eeprom;
|
||||
}
|
||||
// Sinon, on conserve la valeur précédente de l'EEPROM qui va être rechargée dans le module.
|
||||
//console.log("Eeprom = " + eeprom);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=============================================================================================================
|
||||
// Opération avant sortie
|
||||
//=============================================================================================================
|
||||
function sortie()
|
||||
{
|
||||
var req;
|
||||
var i;
|
||||
var r;
|
||||
|
||||
// Estimation de la résistance interne :
|
||||
if ((tension_1 !== tension_2) && (courant_decharge_1 !== courant_decharge_2))
|
||||
{
|
||||
r = ((tension_1 - tension_2) * 1000) / (courant_decharge_1 - courant_decharge_2); // Le 'x 1000' permet d'avoir une valeur en mOhms. Le sens (I1 - I2) est inversé par rapport à la formule car les courants de décharge sont négatifs par convention.
|
||||
}
|
||||
|
||||
//console.log("tension_1 = " + tension_1 + "V, tension_2 = " + tension_2 + "V, courant_decharge_1 = " + courant_decharge_1 + "A, courant_decharge_2 = " + courant_decharge_2 + "A");
|
||||
|
||||
if ((r > 0) && (r < 10000)) resistance = r.toFixed(2); // On ne prend pas en compte les valeurs négatives ou > 10 Ohms
|
||||
else console.log("La valeur de résistance interne calculée est erronée : " + r + " mOhms");
|
||||
|
||||
// Mise à jour de la résistance dans TB_Batteries :
|
||||
req = 'UPDATE TB_Batteries SET Resistance_interne="' + resistance + '" WHERE Cle_primaire=' + id_batterie + ' ';
|
||||
//console.log("Requête = " + req)
|
||||
bdd.requete_unique(req);
|
||||
|
||||
|
||||
|
||||
// Mise à jour de la valeur d'EEPROM :
|
||||
req = 'UPDATE TB_Modules_physiques SET Eeprom="' + eeprom + '", New_eeprom=1 WHERE Adresse_k_bus=' + adresse_module + ' ';
|
||||
//console.log("Requête = " + req)
|
||||
bdd.requete_unique(req);
|
||||
|
||||
// Mise à leur valeur initiale des consignes des circuits rattachés à ce ShipBS :
|
||||
for (i=0; i < modele_grille_principale.count; i++) // L'init de 'i' dépend de la présence ou non de ShipBase dans la liste
|
||||
{
|
||||
bdd.requete_unique('UPDATE TB_Circuits SET New_consigne=' + modele_grille_principale.get(i).consigne_init + ' WHERE Cle_primaire="' + modele_grille_principale.get(i).id + '" ');
|
||||
}
|
||||
|
||||
// Demande de reconfiguration système via la BDD car on a modifié des valeurs de configuration :
|
||||
// synchro_bdd(shipheart_type_synchro_config);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Executable
+622
@@ -0,0 +1,622 @@
|
||||
.pragma library
|
||||
|
||||
|
||||
// Types unites :
|
||||
const UNITE_VOLUME = 1;
|
||||
const UNITE_TEMPERATURE = 2;
|
||||
const UNITE_LATITUDE = 3;
|
||||
const UNITE_LONGITUDE = 4;
|
||||
|
||||
// Unités de type Volume :
|
||||
const UNITE_VOLUME_LITRES = 0;
|
||||
const UNITE_VOLUME_US_GALLONS = 1;
|
||||
const UNITE_VOLUME_IMP_GALLONS = 2;
|
||||
|
||||
// Unités de type Température :
|
||||
const UNITE_TEMPERATURE_CELSIUS = 0;
|
||||
const UNITE_TEMPERATURE_FAHRENHEIT = 1;
|
||||
|
||||
// Langues :
|
||||
const LANGUE_FR = 0;
|
||||
const LANGUE_EN = 1;
|
||||
const LANGUE_DE = 2;
|
||||
const LANGUE_ES = 3;
|
||||
const LANGUE_PT = 4;
|
||||
const LANGUE_NL = 5;
|
||||
const LANGUE_IT = 6;
|
||||
const LANGUE_LV = 7; // Lettonie
|
||||
const LANGUE_CA = 8; // Catalan
|
||||
|
||||
|
||||
// Positionnement GNSS :
|
||||
const POSITION_VALEUR_ERRONNEE = 200000000; // Valeur hors limite de latitude (-90 000 000 à +90 000 000) et longitude (-180 000 000 à +180 000 000)
|
||||
|
||||
const SHIPHEART_TYPE_CARTE_INCONNU = -1;
|
||||
const SHIPHEART_TYPE_CARTE_SHIPBASE = 0;
|
||||
const SHIPHEART_TYPE_CARTE_SHIPPOWER812 = 1;
|
||||
const SHIPHEART_TYPE_CARTE_SHIPBS = 2;
|
||||
const SHIPHEART_TYPE_CARTE_SHIPPOWER4AC = 3;
|
||||
const SHIPHEART_TYPE_CARTE_SHIPPOWER8DC = 4;
|
||||
|
||||
const SHIPHEART_SOURCE_MESURE_CIRCUIT = 1;
|
||||
const SHIPHEART_SOURCE_MESURE_CAPTEUR = 2;
|
||||
const SHIPHEART_SOURCE_MESURE_RESERVOIR = 3;
|
||||
const SHIPHEART_SOURCE_MESURE_BATTERIE = 4;
|
||||
|
||||
|
||||
//=====================================================================================
|
||||
// Fonctions : Défini les paramètres d'affichage de la courbe en fonction du type de
|
||||
// période de temps choisie.
|
||||
// Reçoit : Le type de période
|
||||
// Retour : Les différents paramètres de la courbe
|
||||
//=====================================================================================
|
||||
function get_parametres_courbe(type_periode_graphique)
|
||||
{
|
||||
switch(type_periode_graphique)
|
||||
{
|
||||
default:
|
||||
case 1:
|
||||
return {
|
||||
duree: (1 * 1 * 60 * 60), // En secondes
|
||||
regroupement: 1, // En secondes
|
||||
graduations_x: 7, // Nombre de bandes verticales + 1
|
||||
format_x: "HH:mm", // exemple : "yyyy-MM-dd HH:mm:ss"
|
||||
format: 0 // 0=format court ("hh:mm") et 1=format long ("MM/dd hh:mm")
|
||||
}
|
||||
|
||||
case 2:
|
||||
return {
|
||||
duree: (1 * 24 * 60 * 60), // En secondes
|
||||
regroupement: 1, // En secondes
|
||||
graduations_x: 13, // Nombre de bandes verticales + 1
|
||||
format_x: "HH:mm", // exemple : "yyyy-MM-dd HH:mm:ss"
|
||||
format: 0 // 0=format court ("hh:mm") et 1=format long ("MM/dd hh:mm")
|
||||
}
|
||||
|
||||
case 3:
|
||||
return {
|
||||
duree: (7 * 24 * 60 * 60), // En secondes
|
||||
// regroupement: (2 * 60), // En secondes
|
||||
regroupement: 1, // En secondes
|
||||
graduations_x: 8, // Nombre de bandes verticales + 1
|
||||
format_x: "dd/MM HH:mm", // exemple : "yyyy-MM-dd HH:mm:ss"
|
||||
format: 1 // 0=format court ("hh:mm") et 1=format long ("MM/dd hh:mm")
|
||||
}
|
||||
|
||||
case 4:
|
||||
return {
|
||||
duree: (30 * 24 * 60 * 60), // En secondes
|
||||
// regroupement: (5 * 60), // En secondes
|
||||
regroupement: 1, // En secondes
|
||||
graduations_x: 31, // Nombre de bandes verticales + 1
|
||||
format_x: "dd", // exemple : "yyyy-MM-dd HH:mm:ss"
|
||||
format: 1 // 0=format court ("hh:mm") et 1=format long ("MM/dd hh:mm")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=====================================================================================
|
||||
// Fonctions : Calcule les valeurs mini et maxi optimales en fonction des valeurs
|
||||
// brutes de mini et de maxi de la série de données.
|
||||
// Reçoit : La valeur mini et maxi brutes
|
||||
// Retour : La valeur mini et maxi optimale
|
||||
//=====================================================================================
|
||||
function ajustement_mini_maxi(min, max, nb_graduations)
|
||||
{
|
||||
var ratio;
|
||||
|
||||
if ((max < min) || (nb_graduations <= 0)) return(min); // Si MIN > MAX ou si le nombre de graduations est nul, on ne peut rien faire...
|
||||
|
||||
if (min === max)
|
||||
{
|
||||
if (min !== 0)
|
||||
{
|
||||
min = max * 0.95; // On met le min à -5% en-dessous du maxi
|
||||
max = max * 1.05; // On met le maxi à 5% au-dessus du mini
|
||||
}
|
||||
else return {mini: 0, maxi: 0.5 }; // Si les deux valeurs sont égales à 0, on renvoit arbitrairement 0 et 1 en mini/maxi
|
||||
}
|
||||
|
||||
ratio = Math.log10((max - min) / nb_graduations);
|
||||
if (ratio < 0) ratio = Math.trunc(ratio) - 1; // Permet que -1.425 devienne -2
|
||||
else ratio = Math.trunc(ratio) + 1; // Permet que +1.425 devienne +2
|
||||
|
||||
return {
|
||||
mini: Math.floor(min * Math.pow(10, (-ratio)))*Math.pow(10, ratio),
|
||||
maxi: Math.ceil(max * Math.pow(10, (-ratio)))*Math.pow(10, ratio),
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
//=====================================================================================
|
||||
// Fonctions : Calcule la précision d'affichage optimale en fonction des valeurs brutes
|
||||
// de mini et de maxi de la série de données.
|
||||
// Reçoit : La valeur mini et maxi brutes
|
||||
// Retour : La précision optimale d'affichage
|
||||
//=====================================================================================
|
||||
function precision_affichage_mini_maxi(min, max, nb_graduations)
|
||||
{
|
||||
var ratio;
|
||||
|
||||
if ((max < min) || (nb_graduations <= 0)) return(0); // Dans ce cas, on ne peut rien faire...
|
||||
|
||||
if (min === max)
|
||||
{
|
||||
if (min !== 0)
|
||||
{
|
||||
min = max * 0.95; // On met le min à -5% en-dessous du maxi
|
||||
max = max * 1.05; // On met le maxi à 5% au-dessus du mini
|
||||
}
|
||||
else return 0; // Si les deux valeurs sont égales à 0, on renvoit arbitrairement 0 comme précision
|
||||
}
|
||||
|
||||
ratio = Math.log10((max - min) / (nb_graduations - 1)); // L'objectif est de définir le nombre de décades de l'intervalle entre 2 graduations.
|
||||
//console.log("Ratio = " + ratio);
|
||||
|
||||
if (ratio <= -2) return(3); // Si l'intervalle est <= 0.001
|
||||
else if (ratio <= -1) return(2); // Si l'intervalle est <= 0.01
|
||||
else if (ratio <= 0) return(1); // Si l'intervalle est <= 0.1
|
||||
else return(0); // Si l'intervalle est <= 1
|
||||
}
|
||||
|
||||
|
||||
//=====================================================================================
|
||||
// Fonctions : Génère une chaine de deux digits avec un caractère devant si la valeur
|
||||
// est inférieure à 9
|
||||
// Reçoit : La valeur et le caractère à ajouter si besoin (en général, '0' ou ' ')
|
||||
// Retour : La chaine sur 2 digits
|
||||
//=====================================================================================
|
||||
function format_deux_digits(val, lead)
|
||||
{
|
||||
if (val <= 9) return(lead + val);
|
||||
else return(val);
|
||||
}
|
||||
|
||||
|
||||
//=====================================================================================
|
||||
// Fonctions : Convertit une grandeur reçue dans son unité par défaut dans l'unité
|
||||
// passée en paramètre. La valeur obtenue est formattée avec la précision
|
||||
// demandée et le symbole de la nouvelle unité est ajoutée à la fin (si
|
||||
// elle n'est pas vide).
|
||||
// Reçoit : La valeur à convertir, l'unité cible, le symbole de cette unité (ou
|
||||
// une chaine vide si aucune) et la précision (sous forme d'entier >= 0)
|
||||
// Retour : La valeur dans la nouvelle unité avec l'unité à la fin si elle est demandée
|
||||
//=====================================================================================
|
||||
function conversion_temperature(val, unite, symbole, precision)
|
||||
{
|
||||
var retour;
|
||||
var tmp;
|
||||
|
||||
switch(unite)
|
||||
{
|
||||
//--------------------------------------------------------------------------------
|
||||
// Températures :
|
||||
case UNITE_TEMPERATURE_CELSIUS:
|
||||
retour = val.toFixed(precision); // Unité de base des températures
|
||||
break;
|
||||
|
||||
case UNITE_TEMPERATURE_FAHRENHEIT:
|
||||
retour = ((val * 1.8)+32).toFixed(precision); // T(°F) = (9/5).T(°C) + 32
|
||||
break;
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
// Autres :
|
||||
default:
|
||||
retour = val.toFixed(precision); // Pour les capteurs dont l'unité de température ne serait pas connue
|
||||
break;
|
||||
}
|
||||
|
||||
if (symbole !== "") retour = retour + " " + symbole;
|
||||
return(retour);
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
// Fonctions : Convertit une grandeur reçue dans son unité par défaut dans l'unité
|
||||
// passée en paramètre. La valeur obtenue est formattée avec la précision
|
||||
// demandée et le symbole de la nouvelle unité est ajoutée à la fin (si
|
||||
// elle n'est pas vide).
|
||||
// Reçoit : La valeur à convertir, l'unité cible, le symbole de cette unité (ou
|
||||
// une chaine vide si aucune) et la précision (sous forme d'entier >= 0)
|
||||
// Retour : La valeur dans la nouvelle unité avec l'unité à la fin si elle est demandée
|
||||
//=====================================================================================
|
||||
function conversion_volume(val, unite, symbole, precision)
|
||||
{
|
||||
var retour;
|
||||
var tmp;
|
||||
|
||||
switch(unite)
|
||||
{
|
||||
//--------------------------------------------------------------------------------
|
||||
// Volumes :
|
||||
case UNITE_VOLUME_LITRES:
|
||||
retour = val.toFixed(precision); // Unité de base des volumes
|
||||
break;
|
||||
|
||||
case UNITE_VOLUME_US_GALLONS:
|
||||
retour = (val / 3.785411784).toFixed(precision); // V(US Ga) = V(l) / 3.785411784
|
||||
break;
|
||||
|
||||
case UNITE_VOLUME_IMP_GALLONS:
|
||||
retour = (val / 4.546090).toFixed(precision); // V(Imp Ga) = V(l) / 4.546090
|
||||
break;
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
// Autres :
|
||||
default:
|
||||
retour = val.toFixed(precision); // Pour les capteurs dont l'unité de volume ne serait pas connue
|
||||
break;
|
||||
}
|
||||
|
||||
if (symbole !== "") retour = retour + " " + symbole;
|
||||
return(retour);
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
// Fonctions : Transfère vers la fonction correspondant à 'type_unite'
|
||||
//=====================================================================================
|
||||
function conversion_unites(val, unite, symbole, precision, type_unite)
|
||||
{
|
||||
var retour;
|
||||
|
||||
switch(type_unite)
|
||||
{
|
||||
case UNITE_VOLUME:
|
||||
retour = conversion_volume(val, unite, symbole, precision);
|
||||
break;
|
||||
case UNITE_TEMPERATURE:
|
||||
retour = conversion_temperature(val, unite, symbole, precision);
|
||||
break;
|
||||
case UNITE_LATITUDE:
|
||||
retour = chaine_latitude(val);
|
||||
break;
|
||||
case UNITE_LONGITUDE:
|
||||
retour = chaine_longitude(val);
|
||||
break;
|
||||
default:
|
||||
retour = val.toFixed(precision); // Pour les capteurs dont l'unité n'est ni un volume, ni une température
|
||||
}
|
||||
|
||||
return(retour);
|
||||
}
|
||||
|
||||
|
||||
//=====================================================================================
|
||||
// Fonction : Génère une chaine de latitude et/ou de longitude sous la forme 'xx.xxx°N'
|
||||
// ou 'xx.xxx°N - xx.xxx°E'
|
||||
// Reçoit : La valeur de latitude et/ou de longitude (-1 si pas utile)
|
||||
// Retour : La chaine générée
|
||||
//=====================================================================================
|
||||
function chaine_position(lat, lon)
|
||||
{
|
||||
var chaine_lat, chaine_lon;
|
||||
var retour;
|
||||
|
||||
// Calcul de la chaine de Latitude :
|
||||
if (lat !== -1) chaine_lat = chaine_latitude(lat);
|
||||
else chaine_lat = ""; // Si la valeur n'est pas demandée, cette partie de chaine sera vide
|
||||
|
||||
// Calcul de la chaine de Longitude :
|
||||
if (lon !== -1) chaine_lon = chaine_longitude(lon);
|
||||
else chaine_lon = ""; // Si la valeur n'est pas demandée, cette partie de chaine sera vide
|
||||
|
||||
if ((chaine_lat !== "") && (chaine_lon !== "")) retour = chaine_lat + " , " + chaine_lon;
|
||||
else retour = chaine_lat + chaine_lon; // Au moins une de vide, donc soit LAT, soit LON, soit ""
|
||||
|
||||
return(retour);
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
// Fonction : Génère une chaine de latitude sous la forme 'xx.xxx°N' ou 'xx.xxx°S'
|
||||
// Reçoit : La valeur de latitude
|
||||
// Retour : La chaine générée ou '---' si erreur
|
||||
//=====================================================================================
|
||||
function chaine_latitude(lat)
|
||||
{
|
||||
var chaine_lat
|
||||
var retour;
|
||||
var suffixe;
|
||||
|
||||
if (lat !== POSITION_VALEUR_ERRONNEE)
|
||||
{
|
||||
if (lat >= 0) suffixe = "N"; // Les valeurs positives sont considérées comme au Nord
|
||||
else suffixe = "S" // ... et les négatives au Sud
|
||||
|
||||
chaine_lat = Math.trunc(lat) + "°" + ((lat - Math.trunc(lat)) * 60).toFixed(3) + "' " + suffixe; // On fixe la précision à 3 digits après le point pour les secondes
|
||||
}
|
||||
else chaine_lat = "---°"; // Si la valeur reçue est hors limite, on affiche "---°"
|
||||
|
||||
return(chaine_lat);
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
// Fonction : Génère une chaine de longitude sous la forme 'xx.xxx°E' ou 'xx.xxx°W'
|
||||
// Reçoit : La valeur de longitude
|
||||
// Retour : La chaine générée ou '---' si erreur
|
||||
//=====================================================================================
|
||||
function chaine_longitude(lon)
|
||||
{
|
||||
var chaine_lon;
|
||||
var retour;
|
||||
var suffixe;
|
||||
|
||||
if (lon !== POSITION_VALEUR_ERRONNEE)
|
||||
{
|
||||
if (lon >= 0) suffixe = "E"; // Les valeurs positives sont considérées comme à l'Est
|
||||
else suffixe = "W" // ... et les négatives à l'Ouest
|
||||
|
||||
chaine_lon = Math.trunc(lon) + "°" + ((lon - Math.trunc(lon)) * 60).toFixed(3) + "' " + suffixe; // On fixe la précision à 3 digits après le point pour les secondes
|
||||
}
|
||||
else chaine_lon = "---°"; // Si la valeur reçue est hors limite, on affiche "---°"
|
||||
|
||||
return(chaine_lon);
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
// Fonction : Vérifie si la chaine reçue en paramètre correspond bien à une adresse IP V4
|
||||
// Reçoit : La chaine à vérifier
|
||||
// Retour : TRUE si l'adresse est correcte, FALSE sinon
|
||||
//=====================================================================================
|
||||
function test_format_adresse_ip_v4(ip) {
|
||||
|
||||
var Reg = new RegExp(/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/);
|
||||
|
||||
return Reg.test(ip);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=====================================================================================
|
||||
// Fonction : Renvoit le nom du type de carte à partir du code de type de carte
|
||||
// Reçoit : Le code du type
|
||||
// Retour : La chaine de caractère correspondant au type de carte reçu/
|
||||
//=====================================================================================
|
||||
function nom_type_module(code)
|
||||
{
|
||||
var nom;
|
||||
|
||||
switch(code)
|
||||
{
|
||||
//-----------------------------------------
|
||||
case SHIPHEART_TYPE_CARTE_INCONNU:
|
||||
nom = qsTr("Type non défini");
|
||||
break;
|
||||
|
||||
//-----------------------------------------
|
||||
case SHIPHEART_TYPE_CARTE_SHIPBASE:
|
||||
nom = "ShipBase";
|
||||
break;
|
||||
|
||||
//-----------------------------------------
|
||||
case SHIPHEART_TYPE_CARTE_SHIPPOWER812:
|
||||
nom = "ShipPower812";
|
||||
break;
|
||||
|
||||
//-----------------------------------------
|
||||
case SHIPHEART_TYPE_CARTE_SHIPBS:
|
||||
nom = "ShipBS";
|
||||
break;
|
||||
|
||||
//-----------------------------------------
|
||||
case SHIPHEART_TYPE_CARTE_SHIPPOWER4AC:
|
||||
nom = "ShipPower4AC";
|
||||
break;
|
||||
|
||||
//-----------------------------------------
|
||||
case SHIPHEART_TYPE_CARTE_SHIPPOWER8DC:
|
||||
nom = "ShipPower8DC";
|
||||
break;
|
||||
|
||||
|
||||
//-----------------------------------------
|
||||
default:
|
||||
nom = qsTr("Modèle inconnu");
|
||||
break;
|
||||
}
|
||||
|
||||
return(nom);
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
// Fonction : Renvoit le nom du type d'équipement à partir du code de type
|
||||
// Reçoit : Le code du type
|
||||
// Retour : La chaine de caractère correspondant au type d'équipement reçu
|
||||
//=====================================================================================
|
||||
function nom_type_equipement(code)
|
||||
{
|
||||
var nom;
|
||||
|
||||
switch(code)
|
||||
{
|
||||
//-----------------------------------------
|
||||
case SHIPHEART_SOURCE_MESURE_CIRCUIT:
|
||||
nom = qsTr("Circuit");
|
||||
break;
|
||||
|
||||
//-----------------------------------------
|
||||
case SHIPHEART_SOURCE_MESURE_CAPTEUR:
|
||||
nom = qsTr("Capteur");
|
||||
break;
|
||||
|
||||
//-----------------------------------------
|
||||
case SHIPHEART_SOURCE_MESURE_RESERVOIR:
|
||||
nom = qsTr("Réservoir");
|
||||
break;
|
||||
|
||||
//-----------------------------------------
|
||||
case SHIPHEART_SOURCE_MESURE_BATTERIE:
|
||||
nom = qsTr("Batterie");
|
||||
break;
|
||||
|
||||
//-----------------------------------------
|
||||
default:
|
||||
nom = qsTr("Type inconnu");
|
||||
break;
|
||||
}
|
||||
|
||||
return(nom);
|
||||
}
|
||||
|
||||
|
||||
//=====================================================================================
|
||||
// Fonction : Renvoit le nom d'une variabme à partir de son code
|
||||
// Reçoit : Le code de la variable
|
||||
// Retour : La chaine de caractère correspondant au code variable reçu
|
||||
//=====================================================================================
|
||||
function nom_variable(code)
|
||||
{
|
||||
var nom;
|
||||
|
||||
switch(code)
|
||||
{
|
||||
//---------------------
|
||||
case "Circ_consigne":
|
||||
nom = qsTr("Consigne");
|
||||
break;
|
||||
|
||||
//---------------------
|
||||
case "Circ_tension":
|
||||
nom = qsTr("Tension");
|
||||
break;
|
||||
|
||||
//---------------------
|
||||
case "Circ_courant":
|
||||
nom = qsTr("Courant");
|
||||
break;
|
||||
|
||||
//---------------------
|
||||
case "Circ_frequence":
|
||||
nom = qsTr("Fréquence");
|
||||
break;
|
||||
|
||||
//---------------------
|
||||
case "Circ_puissance":
|
||||
nom = qsTr("Puissance");
|
||||
break;
|
||||
|
||||
//---------------------
|
||||
case "Circ_energie":
|
||||
nom = qsTr("Energie");
|
||||
break;
|
||||
|
||||
//---------------------
|
||||
case "Circ_tension_secteur":
|
||||
nom = qsTr("Tension");
|
||||
break;
|
||||
|
||||
//---------------------
|
||||
case "Batt_temperature":
|
||||
nom = qsTr("Température");
|
||||
break;
|
||||
|
||||
//---------------------
|
||||
case "Batt_tension":
|
||||
nom = qsTr("Tension");
|
||||
break;
|
||||
|
||||
//---------------------
|
||||
case "Batt_courant_differentiel":
|
||||
nom = qsTr("Courant différentiel");
|
||||
break;
|
||||
|
||||
//---------------------
|
||||
case "Batt_courant_charge":
|
||||
nom = qsTr("Courant de charge");
|
||||
break;
|
||||
|
||||
//---------------------
|
||||
case "Batt_courant_decharge":
|
||||
nom = qsTr("Courant de décharge");
|
||||
break;
|
||||
|
||||
//---------------------
|
||||
case "Batt_soh":
|
||||
nom = qsTr("SOH (state Of Health)");
|
||||
break;
|
||||
|
||||
//---------------------
|
||||
case "Batt_soc":
|
||||
nom = qsTr("SOC (State Of Charge)");
|
||||
break;
|
||||
|
||||
//---------------------
|
||||
case "Batt_autonomie":
|
||||
nom = qsTr("Autonomie");
|
||||
break;
|
||||
|
||||
//---------------------
|
||||
case "Batt_puissance":
|
||||
nom = qsTr("Puissance");
|
||||
break;
|
||||
|
||||
//---------------------
|
||||
case "Batt_energie":
|
||||
nom = qsTr("Energie");
|
||||
break;
|
||||
}
|
||||
|
||||
return(nom);
|
||||
}
|
||||
|
||||
|
||||
//=====================================================================================
|
||||
// Fonctions : Génère une chaine de caractère correspondant à la taille du fichier
|
||||
// dont la valeur, en octet, est reçue en paramètres
|
||||
// Reçoit : La taille du fichier, en octets
|
||||
// Retour : La chaine
|
||||
//=====================================================================================
|
||||
function taille_fichier(taille, langue)
|
||||
{
|
||||
var unite_octet;
|
||||
|
||||
switch(langue)
|
||||
{
|
||||
//--------------------------------------------------------
|
||||
case LANGUE_EN:
|
||||
case LANGUE_ES:
|
||||
case LANGUE_PT:
|
||||
case LANGUE_NL:
|
||||
case LANGUE_IT:
|
||||
case LANGUE_LV: // Lettonie
|
||||
case LANGUE_CA:
|
||||
default:
|
||||
unite_octet = "b";
|
||||
break;
|
||||
//---------------------------------------------------------
|
||||
case LANGUE_FR:
|
||||
unite_octet = "o";
|
||||
break;
|
||||
//---------------------------------------------------------
|
||||
case LANGUE_DE:
|
||||
unite_octet = "B";
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// Inférieur à 1ko :
|
||||
|
||||
if (taille < 1000) return (taille + unite_octet);
|
||||
|
||||
// Entre 1ko et moins de 1Mo :
|
||||
taille /= 1000;
|
||||
if (taille < 10) return (taille.toFixed(1) + "k" + unite_octet);
|
||||
if (taille < 1000) return (taille.toFixed(0) + "k" + unite_octet);
|
||||
|
||||
// Entre 1Mo et moins de 1Go :
|
||||
taille /= 1000;
|
||||
if (taille < 10) return (taille.toFixed(1) + "M" + unite_octet);
|
||||
if (taille < 1000) return (taille.toFixed(0) + "M" + unite_octet);
|
||||
|
||||
// Entre 1Go et moins de 1To :
|
||||
taille /= 1000;
|
||||
if (taille < 10) return (taille.toFixed(1) + "G" + unite_octet);
|
||||
if (taille < 1000) return (taille.toFixed(0) + "G" + unite_octet);
|
||||
|
||||
taille /= 1000;
|
||||
return (taille.toFixed(1) + "T" + unite_octet);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Executable
+169
@@ -0,0 +1,169 @@
|
||||
.pragma library
|
||||
|
||||
//=====================================================================================
|
||||
// Fonctions : Fournit une chaine de caractères constituant une liste de valeurs§niveaux
|
||||
// de batterie. La liste est composée de couples de nombre séparés par des ';'
|
||||
// et les deux valeurs au sein d'un couple sont séparés par '/'.
|
||||
// Par exemple : "13800/10000;13400/9800;13150/9600;13000/9400;12900/9000;12800/8000;12443/4887;12100/2000;11800/1000;11500/500;11000/200;10500/0"
|
||||
// La chaine est établie en fonction du paramètre de 'Tension_nominale' recue en paramètre.
|
||||
// Reçoit : La tension nomniale (a priori, 12, 24 ou 48)
|
||||
// Retour : La chaine
|
||||
//=====================================================================================
|
||||
function chaine_tension_niveau_batterie_usine(tension)
|
||||
{
|
||||
var chaine;
|
||||
|
||||
switch(tension)
|
||||
{
|
||||
default:
|
||||
case 12:
|
||||
chaine = "13.800/100.00";
|
||||
chaine += ";13.200/98.00";
|
||||
chaine += ";13.000/96.00";
|
||||
chaine += ";12.800/94.00";
|
||||
chaine += ";12.600/90.00";
|
||||
chaine += ";12.480/80.00";
|
||||
chaine += ";12.100/30.00";
|
||||
chaine += ";12.020/20.00";
|
||||
chaine += ";11.800/10.00";
|
||||
chaine += ";11.500/5.00";
|
||||
chaine += ";11.000/2.00";
|
||||
chaine += ";10.500/0.00";
|
||||
break;
|
||||
case 24:
|
||||
chaine = "27.600/100.00";
|
||||
chaine += ";26.400/98.00";
|
||||
chaine += ";26.000/96.00";
|
||||
chaine += ";25.600/94.00";
|
||||
chaine += ";25.200/90.00";
|
||||
chaine += ";24.960/80.00";
|
||||
chaine += ";24.200/30.00";
|
||||
chaine += ";24.040/20.00";
|
||||
chaine += ";23.600/10.00";
|
||||
chaine += ";23.000/5.00";
|
||||
chaine += ";22.000/2.00";
|
||||
chaine += ";21.000/0.00";
|
||||
break;
|
||||
case 48:
|
||||
// Version issue des tables Suncy :
|
||||
chaine = "56.000/100.00";
|
||||
chaine += ";50.000/84.00";
|
||||
chaine += ";49.300/79.00";
|
||||
chaine += ";49.000/74.00";
|
||||
chaine += ";48.800/69.00";
|
||||
chaine += ";48.000/30.00";
|
||||
chaine += ";47.600/20.00";
|
||||
chaine += ";47.200/15.00";
|
||||
chaine += ";46.400/10.00";
|
||||
chaine += ";45.000/5.00";
|
||||
chaine += ";43.500/2.00";
|
||||
chaine += ";42.000/0.00";
|
||||
break;
|
||||
}
|
||||
|
||||
return(chaine);
|
||||
}
|
||||
|
||||
|
||||
//=====================================================================================
|
||||
// Fonctions : Fournit une chaine de caractères constituant une liste de temérature/résistance_interne
|
||||
// de batterie. La liste est composée de couples de nombre séparés par des ';'
|
||||
// et les deux valeurs au sein d'un couple sont séparés par '/'.
|
||||
// La chaine est établie en fonction du paramètre de 'Type' (de batterie) recue en paramètre.
|
||||
// Reçoit : Le type de batterie
|
||||
// Retour : La chaine
|
||||
//=====================================================================================
|
||||
function chaine_temperature_resistance_interne_usine(type)
|
||||
{
|
||||
var chaine;
|
||||
|
||||
switch(type)
|
||||
{
|
||||
default:
|
||||
case 0: // Non défini
|
||||
case 1: // Pb-Acide liquide
|
||||
case 2: // Pb-AGM/VRLA
|
||||
case 3: // Pb-Gel
|
||||
case 4: // Pb-Carbone
|
||||
chaine = "30/0.9";
|
||||
chaine += ";25/1.0";
|
||||
chaine += ";20/1.0";
|
||||
chaine += ";15/1.1";
|
||||
chaine += ";10/1.2";
|
||||
chaine += ";5/1.3";
|
||||
chaine += ";0/1.6";
|
||||
chaine += ";-5/1.8";
|
||||
chaine += ";-10/2.3";
|
||||
chaine += ";-15/2.9";
|
||||
chaine += ";-20/3.7";
|
||||
chaine += ";-25/4.7";
|
||||
chaine += ";-30/6.0"; // 30/0.9;25/1.0;20/1.0;15/1.1;10/1.2;5/1.3;0/1.6;-5/1.8;-10/2.3;-15/2.9;-20/3.7;-25/4.7;-30/6.0
|
||||
break;
|
||||
case 10: // Lithium
|
||||
chaine = "25/0.8";
|
||||
chaine += ";20/1.0";
|
||||
chaine += ";15/1.0";
|
||||
chaine += ";10/1.3";
|
||||
chaine += ";5/1.8";
|
||||
chaine += ";0/3.0";
|
||||
chaine += ";-5/4.5";
|
||||
chaine += ";-10/6.3";
|
||||
chaine += ";-15/8.3";
|
||||
chaine += ";-20/11.0";
|
||||
chaine += ";-25/16.0";
|
||||
chaine += ";-30/23.0"; // 25/0.8;20/1.0;15/1.0;10/1.3;5/1.8;0/3.0;-5/4.5;-10/6.3;-15/8.3;-20/11.0;-25/16.0;-30/23.0
|
||||
break;
|
||||
}
|
||||
|
||||
return(chaine);
|
||||
}
|
||||
|
||||
|
||||
//=====================================================================================
|
||||
// Fonctions : Calcule le coefficient de Peukert à partir de 2 couples de Capacité/Durée
|
||||
// de batterie. Si ces valeurs ne sont pas exploitables, la fonction renvoit la
|
||||
// valeur par défaut dépendant du type de batterie.
|
||||
// La formule pour calculer le coefficient est :
|
||||
// n = log (T0/T1) / [log(C1/C0) - log (T1/T0)]
|
||||
// Reçoit : Le type de batterie, la capacité 1 et la durée 1, la capacité 2 et la durée 2
|
||||
// Retour : Le coefficient de Peukert
|
||||
//=====================================================================================
|
||||
function coefficient_de_peukert(type, capacite_1, heures_capacite_1, capacite_2, heures_capacite_2)
|
||||
{
|
||||
var coeff_peukert = 0;
|
||||
|
||||
if ((capacite_1 > 0) && (heures_capacite_1 > 0) && (capacite_2 > 0) && (heures_capacite_2 > 0))
|
||||
{
|
||||
var denom = (Math.log(capacite_2/capacite_1) - Math.log(heures_capacite_2/heures_capacite_1));
|
||||
if (denom !== 0) coeff_peukert = Math.log(heures_capacite_1/heures_capacite_2) / denom;
|
||||
}
|
||||
if (coeff_peukert < 1) // On traite le cas où on n'a fait aucun calcul, où 'denom' est nul et si le résultat lui-même n'est pas conforme.
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
default:
|
||||
case 0: // Non défini
|
||||
coeff_peukert = 1.25
|
||||
break;
|
||||
case 1: // Plomb acide liquide
|
||||
coeff_peukert = 1.30
|
||||
break;
|
||||
case 2: // Plomb AGM
|
||||
coeff_peukert = 1.10
|
||||
break;
|
||||
case 3: // Plomb Gel
|
||||
coeff_peukert = 1.10
|
||||
break;
|
||||
case 4: // Plomb Carbone
|
||||
coeff_peukert = 1.15
|
||||
break;
|
||||
case 10: // Lithium
|
||||
coeff_peukert = 1.05
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return(coeff_peukert);
|
||||
}
|
||||
|
||||
|
||||
Executable
+20
@@ -0,0 +1,20 @@
|
||||
.pragma library
|
||||
|
||||
|
||||
|
||||
|
||||
//=====================================================================================
|
||||
// Fonctions : Vérifie si le circuit dispose de commandes AUTO
|
||||
// Reçoit : La liste à traiter
|
||||
// Retour : 0 si aucune commande auto n'existe, 1 si un ou plusieurs commandes auto existent
|
||||
//=====================================================================================
|
||||
function check_commandes_auto(liste)
|
||||
{
|
||||
|
||||
|
||||
if (liste === "") return (0);
|
||||
else return (1);
|
||||
|
||||
}
|
||||
|
||||
|
||||
Executable
+80
@@ -0,0 +1,80 @@
|
||||
.pragma library
|
||||
|
||||
const MAX_COULEURS_TEST_ECRAN = 8;
|
||||
|
||||
|
||||
|
||||
//=====================================================================================
|
||||
// Fonctions : Fournit une couleur en fonction d'un numéro reçu. Si le numéro est
|
||||
// supérieur au maxi, il y a bouclage pour toujours retourner une couleur.
|
||||
// Reçoit : Le numéro
|
||||
// Retour : La couleur
|
||||
//=====================================================================================
|
||||
function couleur(no)
|
||||
{
|
||||
var couleur;
|
||||
var max_couleurs = 12; // !! Vérifier que ce nombre est cohérent avec le nombre de cases ci-dessous... (ceci dit, il peut être inférieur sans soucis)
|
||||
|
||||
no %= max_couleurs;
|
||||
|
||||
switch (no) // Cf https://doc.qt.io/qt-5/qml-color.html#svg-color-reference
|
||||
{
|
||||
case 0: couleur = "aquamarine"; break;
|
||||
case 1: couleur = "darkcyan"; break;
|
||||
case 2: couleur = "coral"; break;
|
||||
case 3: couleur = "lightskyblue"; break;
|
||||
case 4: couleur = "cadetblue"; break;
|
||||
case 5: couleur = "darkturquoise"; break;
|
||||
case 6: couleur = "mediumpurple"; break;
|
||||
case 7: couleur = "darkseagreen"; break;
|
||||
case 8: couleur = "cornflowerblue"; break;
|
||||
case 9: couleur = "darkcyan"; break;
|
||||
case 10: couleur = "mediumaquamarine"; break;
|
||||
case 11: couleur = "mediumturquoise"; break;
|
||||
default: couleur = "orangered"; // Ne doit jamais arriver
|
||||
}
|
||||
|
||||
return(couleur);
|
||||
}
|
||||
|
||||
|
||||
//=================================================================================================
|
||||
// Fonction : Recherche la couleur suivante dans la liste (et reboucle dans le cas de fin de liste)
|
||||
//=================================================================================================
|
||||
function next_color_test_ecran(no)
|
||||
{
|
||||
if (++ no >= MAX_COULEURS_TEST_ECRAN) no = 0;
|
||||
return(no);
|
||||
}
|
||||
|
||||
|
||||
//=====================================================================================
|
||||
// Fonctions : Fournit une couleur en fonction d'un numéro reçu. Si le numéro est
|
||||
// supérieur au maxi, il y a bouclage pour toujours retourner une couleur.
|
||||
// Reçoit : Le numéro
|
||||
// Retour : La couleur
|
||||
//=====================================================================================
|
||||
function couleur_test_ecran(no)
|
||||
{
|
||||
var couleur;
|
||||
|
||||
no %= MAX_COULEURS_TEST_ECRAN;
|
||||
|
||||
switch (no) // Cf https://doc.qt.io/qt-5/qml-color.html#svg-color-reference
|
||||
{
|
||||
case 0: couleur = "white"; break;
|
||||
case 1: couleur = "red"; break;
|
||||
case 2: couleur = "blue"; break;
|
||||
case 3: couleur = "green"; break;
|
||||
case 4: couleur = "black"; break;
|
||||
case 5: couleur = "aqua"; break;
|
||||
case 6: couleur = "fuchsia"; break;
|
||||
case 7: couleur = "yellow"; break;
|
||||
default: couleur = "orangered"; // Ne doit jamais arriver
|
||||
}
|
||||
|
||||
return(couleur);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Executable
+541
@@ -0,0 +1,541 @@
|
||||
.pragma library
|
||||
|
||||
.import "fonctions.js" as Fonctions // Permet d'utiliser les fonctions classiques ci-dessous... (cf https://doc.qt.io/qt-5/qtqml-javascript-imports.html )
|
||||
|
||||
|
||||
|
||||
const LANGUE_FR = 0;
|
||||
const LANGUE_EN = 1;
|
||||
const LANGUE_DE = 2;
|
||||
const LANGUE_ES = 3;
|
||||
const LANGUE_PT = 4;
|
||||
const LANGUE_NL = 5;
|
||||
const LANGUE_IT = 6;
|
||||
const LANGUE_LV = 7; // Lettonie
|
||||
const LANGUE_CA = 8; // Catalan
|
||||
|
||||
|
||||
|
||||
|
||||
//=====================================================================================
|
||||
// Fonctions : Renvoit le durée, en secondes, de l'une des périodes d'analyse prédéfinies.
|
||||
// Reçoit : La période d'analyse (0: 1 heure, 1: 24 heures, 2: 7 jours et 3: 30 jours)
|
||||
// Retour : La durée, en secondes
|
||||
//=====================================================================================
|
||||
function duree_periode_analyse(periode_analyse)
|
||||
{
|
||||
var duree;
|
||||
|
||||
switch(periode_analyse)
|
||||
{
|
||||
default:
|
||||
case 0 : // 1 heure
|
||||
duree = (1 * 1 * 60 * 60);
|
||||
break;
|
||||
|
||||
case 1 : // 24 heures
|
||||
duree = (1 * 24 * 60 * 60);
|
||||
break;
|
||||
|
||||
case 2 : // 7 jours
|
||||
duree = (7 * 24 * 60 * 60);
|
||||
break;
|
||||
|
||||
case 3 : // 30 jours
|
||||
duree = (30 * 24 * 60 * 60);
|
||||
break;
|
||||
}
|
||||
return(duree)
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
// Fonctions : Renvoit le nom de l'une des périodes d'analyse prédéfinies.
|
||||
// Reçoit : La période d'analyse (0: 1 heure, 1: 24 heures, 2: 7 jours et 3: 30 jours)
|
||||
// Retour : Le texte du nom
|
||||
//=====================================================================================
|
||||
function nom_periode_analyse(periode_analyse)
|
||||
{
|
||||
var nom;
|
||||
|
||||
switch(periode_analyse)
|
||||
{
|
||||
default:
|
||||
case 0 : // 1 heure
|
||||
nom = qsTr("1 heure");
|
||||
break;
|
||||
|
||||
case 1 : // 24 heures
|
||||
nom = qsTr("24 heures");
|
||||
break;
|
||||
|
||||
case 2 : // 7 jours
|
||||
nom = qsTr("7 jours");
|
||||
break;
|
||||
|
||||
case 3 : // 30 jours
|
||||
nom = qsTr("30 jours");
|
||||
break;
|
||||
}
|
||||
return(nom);
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
// Fonctions : Renvoit da date de début et de fin de l'intervalle en cours d'analyse.
|
||||
// Reçoit : La période d'analyse (0: 1 heure, 1: 24 heures, 2: 7 jours et 3: 30 jours)
|
||||
// La date de début et la date de fin en UTC au format JS
|
||||
// Le fuseau horaire et l'heure d'été en cours
|
||||
// Retour : La date de début et la date de fin en UTC au format JS mais ajustées à
|
||||
// la période en cours d'analyse.
|
||||
//=====================================================================================
|
||||
function ajustement_periode_analyse(periode_analyse, debut, fin, fuseau, heure_ete)
|
||||
{
|
||||
var date_debut, date_fin;
|
||||
|
||||
// Passage en heure LOCALE pour effectuer les traitements :
|
||||
date_debut = date_courante(debut, fuseau, heure_ete); // En LOCALE
|
||||
date_fin = date_courante(fin, fuseau, heure_ete); // EN LOCALE
|
||||
|
||||
// Ajustements à l'intervalle fini d'analyse :
|
||||
switch(periode_analyse)
|
||||
{
|
||||
default:
|
||||
case 0: // 1 heure
|
||||
date_debut.setMinutes(Math.trunc(date_debut.getMinutes() / 5) * 5);
|
||||
date_debut.setSeconds(0);
|
||||
date_fin.setMinutes(Math.trunc(date_fin.getMinutes() / 5) * 5);
|
||||
date_fin.setSeconds(0);
|
||||
break;
|
||||
|
||||
case 1: // 24 heures
|
||||
date_debut.setMinutes(0);
|
||||
date_debut.setSeconds(0);
|
||||
date_fin.setMinutes(0);
|
||||
date_fin.setSeconds(0);
|
||||
break;
|
||||
|
||||
case 2: // 7 jours
|
||||
date_debut.setHours(Math.trunc(date_debut.getHours() / 6) * 6);
|
||||
date_debut.setMinutes(0);
|
||||
date_debut.setSeconds(0);
|
||||
date_fin.setHours(Math.trunc(date_fin.getHours() / 6) * 6);
|
||||
date_fin.setMinutes(0);
|
||||
date_fin.setSeconds(0);
|
||||
break;
|
||||
|
||||
case 3: // 30 jours
|
||||
date_debut.setHours(0);
|
||||
date_debut.setMinutes(0);
|
||||
date_debut.setSeconds(0);
|
||||
date_fin.setHours(0);
|
||||
date_fin.setMinutes(0);
|
||||
date_fin.setSeconds(0);
|
||||
break;
|
||||
}
|
||||
|
||||
return {
|
||||
debut: date_utc(date_debut, fuseau, heure_ete), // Retour en UTC
|
||||
fin: date_utc(date_fin, fuseau, heure_ete) // Retour en UTC
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//=====================================================================================
|
||||
// Fonctions : Génère une chaine de la forme "hh:mm" en heure locale à partir des
|
||||
// heures et minutes UTC reçues en paramètre
|
||||
// Reçoit : Valeur de heures et minutes, fuseau horaire
|
||||
// Retour : La chaine sur 5 caractères "hh:mm'
|
||||
//=====================================================================================
|
||||
function conversion_heure_minutes_locales(hr, mn, fuseau, heure_ete)
|
||||
{
|
||||
var retour;
|
||||
var today = new Date;
|
||||
var date = new Date(today.getFullYear(), today.getMonth(), today.getDate(), hr, mn, 0);
|
||||
|
||||
date = date_add_secondes(date, ((fuseau + heure_ete) * 60 * 60)); // Correction du fuseau horaire pour l'affichage
|
||||
|
||||
retour = Fonctions.format_deux_digits(date.getHours(), '0') + ":" + Fonctions.format_deux_digits(date.getMinutes(), '0');
|
||||
|
||||
//console.log("Valeur reçue Hr=" + hr + " et min=" + mn + " et chaine de retour =" + retour);
|
||||
return(retour)
|
||||
}
|
||||
|
||||
|
||||
//=====================================================================================
|
||||
// Fonctions : Génère la date du moment ou convertit une date existante en tenant
|
||||
// compte du fuseau horaire reçu
|
||||
// Reçoit : La date à convertir au format JS (ou NULL si on veut la date courante), le fuseau, et le décalage heure Eté/Hiver
|
||||
// Retour : La date dans le fuseau et avec décalage Eté/Hiver, au format JS
|
||||
//=====================================================================================
|
||||
function date_courante(dt, fuseau, heure_ete)
|
||||
{
|
||||
var date;
|
||||
|
||||
if (dt === null)
|
||||
{
|
||||
date = new Date;
|
||||
date = date_add_secondes(date, ((fuseau + heure_ete) * 60 * 60)); // Correction du fuseau horaire pour l'affichage
|
||||
return(date);
|
||||
}
|
||||
else
|
||||
{
|
||||
date = date_add_secondes(dt, ((fuseau + heure_ete) * 60 * 60)); // Correction du fuseau horaire pour l'affichage
|
||||
return(date);
|
||||
}
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
// Fonctions : Convertit une date existante en UTC
|
||||
// Reçoit : La date à convertir au format JS, le fuseau, et le décalage heure Eté/Hiver
|
||||
// Retour : La date UTC, au format JS
|
||||
//=====================================================================================
|
||||
function date_utc(dt, fuseau, heure_ete)
|
||||
{
|
||||
var date;
|
||||
|
||||
if (dt === null) return (null);
|
||||
|
||||
date = date_add_secondes(dt, -((fuseau + heure_ete) * 60 * 60)); // Correction du fuseau horaire et de l'heure Ete/Hiver
|
||||
|
||||
return(date);
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
// Fonctions : Convertit une valeur d'heure en une chaine dépendant de la langue
|
||||
// Reçoit : La valeur d'heure, entre 00 et 23, ou 24 (fin de nuit), 25 (aube nautique),
|
||||
// 26 (aube), 27 (lever du soleil), 28 (zénith), 29 (coucher du soleil),
|
||||
// 30 (crépuscule), 31 (crépuscule nautique) ou 32 (début de nuit).
|
||||
// Et la valeur de minutes, entre 00 et 59, ou 60 (aucune minute à retourner)
|
||||
// Retour : La chaine
|
||||
//=====================================================================================
|
||||
function nom_heure(heure, minute)
|
||||
{
|
||||
var chaine_h;
|
||||
var chaine_m;
|
||||
|
||||
var texte_heures_speciales = [qsTr("Fin de nuit"), qsTr("Aube nautique"), qsTr("Aube"), qsTr("Lever du soleil"), qsTr("Zénith"), qsTr("Coucher du soleil"), qsTr("Crépuscule"), qsTr("Crépuscule nautique"), qsTr("Début de nuit")];
|
||||
|
||||
if ((heure < 0) || (heure > 32)) return("---");
|
||||
|
||||
if (heure < 24)
|
||||
{
|
||||
chaine_h = qsTr("%1h").arg(((heure<10) ? "0" + heure : "" + heure));
|
||||
chaine_m = "" + ((minute<10) ? "0" + minute : "" + minute); // On ne renvoit les minutes que si l'on n'est pas sur une heure spéciale.
|
||||
}
|
||||
else
|
||||
{
|
||||
chaine_h = texte_heures_speciales[heure - 24];
|
||||
chaine_m = "";
|
||||
}
|
||||
|
||||
return (chaine_h + chaine_m);
|
||||
|
||||
}
|
||||
|
||||
|
||||
//=====================================================================================
|
||||
// Fonctions : Convertit une date au format JS en une chaine au format 'hh:mm:ss'
|
||||
// Reçoit : La date à convertir
|
||||
// Retour : La chaine
|
||||
//=====================================================================================
|
||||
function chaine_heure(date)
|
||||
{
|
||||
var retour;
|
||||
var heures = date.getHours();
|
||||
var minutes = date.getMinutes();
|
||||
var secondes = date.getSeconds();
|
||||
|
||||
retour = (heures <= 9) ? "0" + heures : heures;
|
||||
retour += ":";
|
||||
retour += (minutes <= 9) ? "0" + minutes : minutes;
|
||||
retour += ":";
|
||||
retour += (secondes <= 9) ? "0" + secondes : secondes;
|
||||
|
||||
return (retour);
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
// Fonctions : Convertit une date au format JS en une chaine au format 'hh:mm'
|
||||
// Reçoit : La date à convertir
|
||||
// Retour : La chaine
|
||||
//=====================================================================================
|
||||
function chaine_heure_courte(date)
|
||||
{
|
||||
var retour;
|
||||
var heures = date.getHours();
|
||||
var minutes = date.getMinutes();
|
||||
|
||||
retour = (heures <= 9) ? "0" + heures : heures;
|
||||
retour += ":";
|
||||
retour += (minutes <= 9) ? "0" + minutes : minutes;
|
||||
|
||||
return (retour);
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
// Fonctions : Convertit une date au format JS en une chaine au format 'dd/MM hh:mm'
|
||||
// Reçoit : La date à convertir
|
||||
// Retour : La chaine
|
||||
//=====================================================================================
|
||||
function chaine_date_heure_courte(date)
|
||||
{
|
||||
var retour;
|
||||
|
||||
var mois = date.getMonth() + 1; // Les mois commencent à 0
|
||||
var jour = date.getDate();
|
||||
var heures = date.getHours();
|
||||
var minutes = date.getMinutes();
|
||||
|
||||
retour = (jour <= 9) ? "0" + jour : jour;
|
||||
retour += "/";
|
||||
retour += (mois <= 9) ? "0" + mois : mois ;
|
||||
retour += " ";
|
||||
retour += (heures <= 9) ? "0" + heures : heures;
|
||||
retour += ":";
|
||||
retour += (minutes <= 9) ? "0" + minutes : minutes;
|
||||
|
||||
return (retour);
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
// Fonctions : Convertit une date au format JS en une chaine au format 'JJ/MM/AAAA'
|
||||
// Reçoit : La date à convertir
|
||||
// Retour : La chaine
|
||||
//=====================================================================================
|
||||
function chaine_date(date)
|
||||
{
|
||||
var retour;
|
||||
|
||||
var annee = date.getFullYear();
|
||||
var mois = date.getMonth() + 1; // Les mois commencent à 0
|
||||
var jour = date.getDate();
|
||||
|
||||
retour = (jour <= 9) ? "0" + jour : jour;
|
||||
retour += "/";
|
||||
retour += (mois <= 9) ? "0" + mois : mois ;
|
||||
retour += "/";
|
||||
retour += annee;
|
||||
|
||||
return (retour);
|
||||
}
|
||||
|
||||
|
||||
//=====================================================================================
|
||||
// Fonctions : Convertit un n° de jour (1=lundi, 7=dimanche, 8=tous les jours) en une
|
||||
// chaine de jour de la semaine dépendant de la langue
|
||||
// Reçoit : Le n° du jour
|
||||
// Retour : La chaine
|
||||
//=====================================================================================
|
||||
function nom_jour_semaine(no)
|
||||
{
|
||||
var textes_jour_semaine = [qsTr("Lundi"), qsTr("Mardi"), qsTr("Mercredi"), qsTr("Jeudi"), qsTr("Vendredi"), qsTr("Samedi"), qsTr("Dimanche"), qsTr("Tous les jours")];
|
||||
|
||||
if ((no < 1) || (no > 8)) return("---");
|
||||
|
||||
return (textes_jour_semaine[(no - 1)]);
|
||||
}
|
||||
|
||||
|
||||
//=====================================================================================
|
||||
// Fonctions : Convertit une date au format JS en une chaine de jour de la seamine dépendant de la langue
|
||||
// Reçoit : La date
|
||||
// Retour : La chaine
|
||||
//=====================================================================================
|
||||
function chaine_jour_semaine(date)
|
||||
{
|
||||
var jour_semaine = date.getDay();
|
||||
if (jour_semaine === 0) jour_semaine = 7;
|
||||
|
||||
return (nom_jour_semaine(jour_semaine));
|
||||
}
|
||||
|
||||
|
||||
//=====================================================================================
|
||||
// Fonctions : Convertit une date au format JS en une chaine au format 'JJ/MM/AAAA'
|
||||
// ou sa version correspondante au pays
|
||||
// Reçoit : La date à convertir, le code langue (de 1 à N - Cf 'fonctions_localisation.js')
|
||||
// Retour : La chaine
|
||||
//=====================================================================================
|
||||
function chaine_date_longue(date, langue)
|
||||
{
|
||||
var retour = "";
|
||||
var texte_jour = "";
|
||||
|
||||
var annee = date.getFullYear();
|
||||
var mois = date.getMonth() + 1; // Les mois commencent à 0
|
||||
var jour = date.getDate();
|
||||
var jour_semaine = date.getDay();
|
||||
|
||||
var textes_mois = [qsTr("janvier"), qsTr("février"), qsTr("mars"), qsTr("avril"), qsTr("mai"), qsTr("juin"), qsTr("juillet"), qsTr("août"), qsTr("septembre"), qsTr("octobre"), qsTr("novembre"), qsTr("décembre")];
|
||||
|
||||
switch(langue)
|
||||
{
|
||||
//--------------------------------------------------------
|
||||
default:
|
||||
// Mise en forme n° du jour :
|
||||
if (jour === 1) texte_jour = "1<sup>er</sup>";
|
||||
else if ((jour > 1) && (jour <= 9)) texte_jour = "0" + jour;
|
||||
else texte_jour = jour;
|
||||
|
||||
retour += texte_jour;
|
||||
retour += ' ';
|
||||
retour += textes_mois[mois - 1];
|
||||
retour += ' ';
|
||||
retour += annee;
|
||||
|
||||
break;
|
||||
|
||||
//---------------------------------------------------------
|
||||
case LANGUE_EN:
|
||||
// Mise en forme n° du jour :
|
||||
if ((jour === 1) || (jour === 21) || (jour === 31)) texte_jour = jour + "<sup>st</sup>";
|
||||
else if ((jour === 1) || (jour === 22)) texte_jour = jour + "<sup>nd</sup>";
|
||||
else if ((jour === 3) || (jour === 23)) texte_jour = jour + "<sup>rd</sup>";
|
||||
else texte_jour = jour + "th";
|
||||
|
||||
retour += texte_jour;
|
||||
retour += ' ';
|
||||
retour += textes_mois[mois - 1];
|
||||
retour += ' ';
|
||||
retour += annee;
|
||||
|
||||
break;
|
||||
//---------------------------------------------------------
|
||||
case LANGUE_DE:
|
||||
// Mise en forme n° du jour :
|
||||
texte_jour = jour + ".";
|
||||
|
||||
retour += texte_jour;
|
||||
retour += ' ';
|
||||
retour += textes_mois[mois - 1];
|
||||
retour += ' ';
|
||||
retour += annee;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return (retour);
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
// Fonctions : Convertit une date au format JS en une chaine au format 'YYY-MM-dd hh:mm:ss'
|
||||
// Reçoit : La date à convertir
|
||||
// Retour : La chaine
|
||||
//=====================================================================================
|
||||
function chaine_date_heure_bdd(date)
|
||||
{
|
||||
var retour;
|
||||
|
||||
var annee = date.getFullYear();
|
||||
var mois = date.getMonth() + 1; // Les mois commencent à 0
|
||||
var jour = date.getDate();
|
||||
var heures = date.getHours();
|
||||
var minutes = date.getMinutes();
|
||||
var secondes = date.getSeconds();
|
||||
|
||||
retour = annee;
|
||||
retour += "-";
|
||||
retour += (mois <= 9) ? "0" + mois : mois;
|
||||
retour += "-";
|
||||
retour += (jour <= 9) ? "0" + jour : jour;
|
||||
retour += " ";
|
||||
retour += (heures <= 9) ? "0" + heures : heures;
|
||||
retour += ":";
|
||||
retour += (minutes <= 9) ? "0" + minutes : minutes;
|
||||
retour += ":";
|
||||
retour += (secondes <= 9) ? "0" + secondes : secondes;
|
||||
return (retour);
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
// Fonctions : Convertit la date au format JS reçue en une chaine au format 'YYMMdd_hhmmss'
|
||||
// Reçoit : La date au format JS à convertir
|
||||
// Retour : La chaine
|
||||
//=====================================================================================
|
||||
function chaine_date_heure_fichier(date)
|
||||
{
|
||||
var retour;
|
||||
|
||||
var annee = date.getYear(); // Sur 2 digits
|
||||
var mois = date.getMonth() + 1; // Les mois commencent à 0
|
||||
var jour = date.getDate();
|
||||
var heures = date.getHours();
|
||||
var minutes = date.getMinutes();
|
||||
var secondes = date.getSeconds();
|
||||
|
||||
retour = annee;
|
||||
retour += (mois <= 9) ? "0" + mois : mois;
|
||||
retour += (jour <= 9) ? "0" + jour : jour;
|
||||
retour += "_";
|
||||
retour += (heures <= 9) ? "0" + heures : heures;
|
||||
retour += (minutes <= 9) ? "0" + minutes : minutes;
|
||||
retour += (secondes <= 9) ? "0" + secondes : secondes;
|
||||
return (retour);
|
||||
}
|
||||
|
||||
|
||||
//=====================================================================================
|
||||
// Fonctions : Convertit une chaine provenant de la BDD ('YYY-MM-ddThh:mm:ss.000') en
|
||||
// une date au format JS
|
||||
// Reçoit : La chaine à convertir
|
||||
// Retour : La date
|
||||
//=====================================================================================
|
||||
function chaine_bdd_date_heure(chaine_date)
|
||||
{
|
||||
var t, result = null;
|
||||
|
||||
if (typeof chaine_date === 'string')
|
||||
{
|
||||
t = chaine_date.split(/[-:.T ]/); // On coupe la chaine initiale en recherchant les '-', ':', '.', ' ' et 'T'
|
||||
// console.log(t[0] + "/" + t[1] + "/" + t[2] + "//" + t[3] + "/" + t[4] + "/" + t[5]);
|
||||
result = new Date(t[0], t[1] - 1, t[2], t[3] || 0, t[4] || 0, t[5] || 0); //when t[3], t[4] and t[5] are missing they defaults to zero
|
||||
}
|
||||
else console.log("Le type reçu dans la fonction 'chaine_bdd_date_heure' n'est pas correct");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//=====================================================================================
|
||||
// Fonctions : Ajoute une quantité de secondes à une date. Si le nombre de secondes est
|
||||
// négatif, il s'agit d'une soustraction...
|
||||
// Reçoit : La date à convertir et le nombre de secondes à ajouter
|
||||
// Retour : La nouvelle date
|
||||
//=====================================================================================
|
||||
function date_add_secondes(date, secondes)
|
||||
{
|
||||
var date_retour = new Date();
|
||||
|
||||
date_retour.setTime(date.getTime() + (secondes *1000));
|
||||
|
||||
return(date_retour);
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
// Fonctions : Convertir une valeur en ms en une chaine de durée (jour-heures-minutes-secondes)
|
||||
// Reçoit : Le nombre à convertir
|
||||
// Retour : La chaine de durée
|
||||
//=====================================================================================
|
||||
function chaine_duree(duree)
|
||||
{
|
||||
var x;
|
||||
|
||||
duree = Math.abs(duree); // Si la valeur est négative, on prend la valeur absolue (évite les erreurs...)
|
||||
var secondes = Math.trunc(duree / 1000); // Passage de ms en s
|
||||
var minutes = Math.trunc(secondes/60);
|
||||
var heures = Math.trunc(minutes/60);
|
||||
var jours = Math.trunc(heures/24);
|
||||
|
||||
secondes = secondes % 60;
|
||||
minutes = minutes % 60;
|
||||
heures = heures % 24;
|
||||
|
||||
if (jours !== 0) return(qsTr(jours + " jours," + heures + " heures"));
|
||||
else if (heures !== 0) return(qsTr(heures + " heures, " + minutes + " mins"));
|
||||
else if (minutes !== 0) return(qsTr(minutes + " mins, " + secondes + " secs"));
|
||||
else if (secondes !== 0) return(qsTr(secondes + " secondes"));
|
||||
else return("---")
|
||||
}
|
||||
|
||||
|
||||
Executable
+350
@@ -0,0 +1,350 @@
|
||||
.pragma library
|
||||
|
||||
|
||||
|
||||
// Type d'historique :
|
||||
const HISTORIQUE_TYPE_SYSTEME = 0;
|
||||
const HISTORIQUE_TYPE_CIRCUITS = 1;
|
||||
const HISTORIQUE_TYPE_CAPTEURS = 2;
|
||||
const HISTORIQUE_TYPE_RESERVOIRS = 3;
|
||||
const HISTORIQUE_TYPE_BATTERIES = 4;
|
||||
const HISTORIQUE_TYPE_USB = 5;
|
||||
|
||||
|
||||
// Sous-types d'historique :
|
||||
//-------------------------------------------------------------
|
||||
// Système :
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_REINIT = 1;
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_ERREUR_MYSQL = 2;
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_CONNEXION_USER = 3;
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_REBOOT = 4;
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_ARRET = 5;
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_TIME_OUT_CONNEXION = 6;
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_DECONNEXION_USER = 7;
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_CONFIGURATION_INVALIDE_DEMARRAGE_IMPOSSIBLE = 8;
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_SIGNAL_RECU = 9; // La valeur du signal reçu est stocké dans Valeur
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_DEMANDE_REINIT = 10;
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_CHANGEMENT_VEILLE = 11; // La nouvelle valeur de 'veille' est stockée dans Valeur
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_ERREUR_SAUVEGARDE_BDD = 12; // Le message d'info sur l'erreur est stocké dans le complément.
|
||||
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_MODEM_DEMANDE_ACTIVATION = 20; // La Valeur indique dans quel sens (On ou Off)
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_MODEM_CHANGEMENT_ETAT = 21; // La Valeur indique dans quel sens (On ou Off)
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_ERREUR_CHANGEMENT_ETAT = 22; // La Valeur indique dans quel sens (On ou Off) le changement était demandé et a échoué
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_MODEM_ERREUR_ETABLISSEMENT_LIAISON = 23;
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_CHANGEMENT_ETAT_NON_SOLLICITE = 24; // La Valeur indique dans quel sens (On ou Off) le modem se trouve alors qu'il ne devrait pas
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_CHANGEMENT_REVISION_FIRMWARE = 25; // La valeur de révision est stockée dans Complément
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_CHANGEMENT_IMEI = 26; // Le n° est stocké dans Complément
|
||||
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_MODEM_CHANGEMENT_IMSI = 27; // Le n° est stocké dans Complément
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_MODEM_CHANGEMENT_ICCID = 28; // Le n° est stocké dans Complément
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_MODEM_CHANGEMENT_NO_TELEPHONE = 29; // Le n° est stocké dans Complément
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_MODEM_CHANGEMENT_APN = 30; // Le n° est stocké dans Complément
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_MODEM_ERREUR_FTP = 31; // Le code d'erreur reçu du modem est stocké dans Valeur et la réponse complète du modem dans Complement
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_MODEM_ERREUR_GNSS = 32; // Le cycle d'acquisition n'a pas pu être réalisé complètement. Le nombre de cycles valides est indiqué dans Valeur.
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_MODEM_ERREUR_M_BUS_PLEIN = 33; // Le nombre de refus de nouvelle commande dans le buffer de commandes est trop important. Le nb de refus consécutifs est dans Valeur
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_MODEM_PERTE_LIAISON_4G_LTE = 34;
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_MODEM_ETABLISSEMENT_LIAISON_4G_LTE = 35;
|
||||
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_MODULES_NOUVEAU_MODULE = 40; // L'adresse K-Bus où est apparu le module est dans 'id'. Le Type de module est dans Valeur. L'adresse MAC est dans Complément
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_MODULES_SUPPRESSION_MODULE = 41; // L'adresse K-Bus où était le module est dans 'id'. Le Type de module est dans Valeur. L'adresse MAC est dans Complément
|
||||
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_FTP_UPLOAD_FICHIER_DEBUT_OK = 50; // Le nom du fichier source et du fichier destination sont stockés dans complément. La taille dans valeur
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_FTP_UPLOAD_FICHIER_DEBUT_NOK = 51; // Le nom du fichier source et du fichier destination sont stockés dans complément. La taille dans valeur
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_FTP_UPLOAD_FICHIER_FIN_OK = 52; // Le nom du fichier source et du fichier destination sont stockés dans complément. La taille dans valeur
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_FTP_UPLOAD_FICHIER_FIN_NOK = 53; // Le nom du fichier source et du fichier destination sont stockés dans complément
|
||||
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_FTP_DOWNLOAD_FICHIER_DEBUT_OK = 60; // Le nom du fichier source et du fichier destination sont stockés dans complément.
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_FTP_DOWNLOAD_FICHIER_DEBUT_NOK = 61; // Le nom du fichier source et du fichier destination sont stockés dans complément. La taille dans valeur
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_FTP_DOWNLOAD_FICHIER_FIN_OK = 62; // Le nom du fichier source et du fichier destination sont stockés dans complément.
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_FTP_DOWNLOAD_FICHIER_FIN_NOK = 63; // Le nom du fichier source et du fichier destination sont stockés dans complément. La taille dans valeur
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_FTP_DOWNLOAD_LIST_NOK = 64; // Le nom du fichier de LIST est stocké dans complément.
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_FTP_DOWNLOAD_NOMBRE_FICHIERS_LOCAUX_TROP_ELEVE = 65; // Le nombre maxi admissible est stocké dans Valeur
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_FTP_DOWNLOAD_NOMBRE_FICHIERS_SERVEUR_TROP_ELEVE = 66; // Le nombre maxi admissible est stocké dans Valeur
|
||||
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_EXECUTION_BASH_DEBUT_OK = 70; // Le nom du fichier utilisé pour l'upload est dans le complément.
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_EXECUTION_BASH_DEBUT_NOK = 71; // Le nom du fichier utilisé pour l'upload est dans le complément.
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_EXECUTION_BASH_FIN_OK = 72; // Le nom du fichier utilisé pour l'upload est dans le complément.
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_EXECUTION_BASH_FIN_NOK = 73; // Le nom du fichier utilisé pour l'upload est dans le complément.
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_COPIE_ARCHIVE_A_VALIDER_OK = 74; // Le nom du fichier est dans le complément.
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_COPIE_ARCHIVE_A_VALIDER_NOK = 75; // Le nom du fichier est dans le complément.
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_COPIE_ARCHIVE_A_CHARGER_OK = 76; // Le nom du fichier est dans le complément.
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_COPIE_ARCHIVE_A_CHARGER_NOK = 77; // Le nom du fichier est dans le complément.
|
||||
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_CHARGEMENT_CODE_DEBUT_OK = 80; // Le nom du fichier utilisé pour l'upload est dans le complément. L'ID de la carte dans ID
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_CHARGEMENT_CODE_DEBUT_NOK = 81; // Le nom du fichier utilisé pour l'upload est dans le complément. L'ID de la carte dans ID
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_CHARGEMENT_CODE_ERASE_FLASH_NOK = 82; // Le nom du fichier utilisé pour l'upload est dans le complément. L'ID de la carte dans ID
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_CHARGEMENT_CODE_ECRITURE_FLASH_NOK = 83; // Le nom du fichier utilisé pour l'upload est dans le complément. L'ID de la carte dans ID
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_CHARGEMENT_CODE_CRC_FLASH_NOK = 84; // Le nom du fichier utilisé pour l'upload est dans le complément. L'ID de la carte dans ID
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_CHARGEMENT_CODE_FIN_OK = 85; // Le nom du fichier utilisé pour l'upload est dans le complément. L'ID de la carte dans ID
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_CHARGEMENT_CODE_FIN_NOK = 86; // Le nom du fichier utilisé pour l'upload est dans le complément. L'ID de la carte dans ID
|
||||
|
||||
|
||||
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_UART_BUFFER_RX_PLEIN = 100; // L'ID précise quel UART
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_BUS_BUFFER_COMMANDES_PLEIN = 101; // L'ID précise quel bus ('M' ou 'C')
|
||||
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_BACKLIGHT_CHANGEMENT_CONSIGNE = 110; // La valeur indique la nouvelle consigne
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_VOLUME_CHANGEMENT_CONSIGNE = 111; // La valeur indique la nouvelle consigne
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_LEDS_CHANGEMENT_CONSIGNE = 112; // La valeur indique la nouvelle consigne
|
||||
|
||||
|
||||
|
||||
const HISTORIQUE_SOUS_TYPE_SYSTEME_WIFI_MISE_A_JOUR_CONFIG = 130; // Les informations sur la nouvelle config sont stockées dans Complément
|
||||
|
||||
//-------------------------------------------------------------
|
||||
// Circuits :
|
||||
const HISTORIQUE_SOUS_TYPE_CIRCUITS_CHANGEMENT_CONSIGNE = 1;
|
||||
|
||||
const HISTORIQUE_SOUS_TYPE_CIRCUITS_OK = 10; // La valeur de limitation (en mA) est stockée dans Valeur
|
||||
const HISTORIQUE_SOUS_TYPE_CIRCUITS_LIMITATION = 11; // La valeur de limitation (en mA) est stockée dans Valeur
|
||||
const HISTORIQUE_SOUS_TYPE_CIRCUITS_PROTECTION = 12; // La valeur de limitation (en mA) est stockée dans Valeur
|
||||
const HISTORIQUE_SOUS_TYPE_CIRCUITS_DISJONCTE = 13; // La valeur de limitation (en mA) est stockée dans Valeur
|
||||
const HISTORIQUE_SOUS_TYPE_CIRCUITS_CC_BATTERIE = 14; // La valeur de limitation (en mA) est stockée dans Valeur
|
||||
const HISTORIQUE_SOUS_TYPE_CIRCUITS_OPEN_LOAD = 15; // La valeur de limitation (en mA) est stockée dans Valeur
|
||||
|
||||
const HISTORIQUE_SOUS_TYPE_CIRCUITS_CREATION = 20;
|
||||
const HISTORIQUE_SOUS_TYPE_CIRCUITS_MODIFICATION = 21;
|
||||
const HISTORIQUE_SOUS_TYPE_CIRCUITS_SUPPRESSION = 22;
|
||||
|
||||
const HISTORIQUE_SOUS_TYPE_CIRCUITS_CONFIGURATION_INVALIDE = 30; // L'ID précise la clé primaire. Valeur contient l'ID_Carte actuellement configuré
|
||||
|
||||
const HISTORIQUE_SOUS_TYPE_CIRCUIT_EXPIRATION_TIME_OUT = 40; // La nouvelle valeur de consigne est stockée dans Valeur. De plus, Complément comprend 'origine_consigne/id_origine_consigne'.
|
||||
|
||||
//-------------------------------------------------------------
|
||||
// Capteurs :
|
||||
const HISTORIQUE_SOUS_TYPE_CAPTEURS_CAPTEUR_PASSAGE_OK = 1; // L'ID précise la clé primaire. VAleur contient la valeur du capteur au moment du changement
|
||||
const HISTORIQUE_SOUS_TYPE_CAPTEURS_CAPTEUR_PASSAGE_ALERTE = 2; // L'ID précise la clé primaire. VAleur contient la valeur du capteur au moment du changement
|
||||
const HISTORIQUE_SOUS_TYPE_CAPTEURS_CAPTEUR_PASSAGE_ALARME = 3; // L'ID précise la clé primaire. VAleur contient la valeur du capteur au moment du changement
|
||||
|
||||
//-------------------------------------------------------------
|
||||
// Batteries :
|
||||
const HISTORIQUE_SOUS_TYPE_BATTERIES_PASSAGE_NIVEAU_NORMAL = 1; // L'ID précise la batterie. La valeur indique l'ancien état
|
||||
const HISTORIQUE_SOUS_TYPE_BATTERIES_PASSAGE_NIVEAU_ALERTE = 2; // L'ID précise la batterie. La valeur indique l'ancien état
|
||||
const HISTORIQUE_SOUS_TYPE_BATTERIES_PASSAGE_NIVEAU_ALARME = 3; // L'ID précise la batterie. La valeur indique l'ancien état
|
||||
|
||||
//-------------------------------------------------------------
|
||||
// Réservoirs :
|
||||
const HISTORIQUE_SOUS_TYPE_RESERVOIRS_PASSAGE_NIVEAU_NORMAL = 1; // L'ID précise le Réservoir. La valeur indique l'ancien état
|
||||
const HISTORIQUE_SOUS_TYPE_RESERVOIRS_PASSAGE_NIVEAU_ALERTE = 2; // L'ID précise le Réservoir. La valeur indique l'ancien état
|
||||
const HISTORIQUE_SOUS_TYPE_RESERVOIRS_PASSAGE_NIVEAU_ALARME = 3; // L'ID précise le Réservoir. La valeur indique l'ancien état
|
||||
|
||||
//-------------------------------------------------------------
|
||||
// USB :
|
||||
const HISTORIQUE_SOUS_TYPE_USB_CHANGEMENT_CONSIGNE = 1; // La valeur indique le nouvel état
|
||||
|
||||
const HISTORIQUE_SOUS_TYPE_USB_PASSAGE_OK = 10; // L'ID contient le n° du port (1 à 3)
|
||||
const HISTORIQUE_SOUS_TYPE_USB_PASSAGE_DEFAUT = 11; // L'ID contient le n° du port (1 à 3)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//=====================================================================================
|
||||
// Fonctions : Génère une chaine avec le libellé de l'événement.
|
||||
// Reçoit : Le type, le SOUS_TYPE, le nom de l'ID concerné, la valeur et le
|
||||
// complément de l'événement.
|
||||
// NB : le nom de l'ID peut être une chaine vide. dans ce cas, le texte
|
||||
// généré suppose que l'on connait de façon non ambigüe l'objet concerné
|
||||
// (c'est utile quand on affiche l'historique d'un circuit particulier par
|
||||
// exemple).
|
||||
// Retour : La chaine générée
|
||||
//=====================================================================================
|
||||
function historique_libelle(type, event, nom_id, valeur, complement)
|
||||
{
|
||||
var libelle;
|
||||
var texte_nom;
|
||||
var texte_event_systeme;
|
||||
var texte_valeur_systeme;
|
||||
|
||||
if (nom_id === "") texte_nom = "";
|
||||
else texte_nom = "'" + nom_id + "' ";
|
||||
|
||||
texte_event_systeme = "";
|
||||
texte_valeur_systeme = "";
|
||||
|
||||
switch (type)
|
||||
{
|
||||
//----------------------------------------------------------------------------------------------------------------
|
||||
case HISTORIQUE_TYPE_SYSTEME:
|
||||
switch (event)
|
||||
{
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_REINIT: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_REINIT"; break;
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_ERREUR_MYSQL: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_ERREUR_MYSQL"; break;
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_CONNEXION_USER: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_CONNEXION_USER"; break;
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_REBOOT: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_REBOOT"; break;
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_ARRET: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_ARRET"; break;
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_TIME_OUT_CONNEXION: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_TIME_OUT_CONNEXION"; break;
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_DECONNEXION_USER: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_DECONNEXION_USER"; break;
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_CONFIGURATION_INVALIDE_DEMARRAGE_IMPOSSIBLE: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_CONFIGURATION_INVALIDE_DEMARRAGE_IMPOSSIBLE"; break;
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_SIGNAL_RECU: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_SIGNAL_RECU"; texte_valeur_systeme = valeur; break;
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_DEMANDE_REINIT: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_DEMANDE_REINIT"; break;
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_CHANGEMENT_VEILLE: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_CHANGEMENT_VEILLE"; break;
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_ERREUR_SAUVEGARDE_BDD : texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_ERREUR_SAUVEGARDE_BDD"; break;
|
||||
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_MODEM_DEMANDE_ACTIVATION: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_MODEM_DEMANDE_ACTIVATION"; break;
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_MODEM_CHANGEMENT_ETAT: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_MODEM_CHANGEMENT_ETAT"; texte_valeur_systeme = valeur; break;
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_ERREUR_CHANGEMENT_ETAT: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_ERREUR_CHANGEMENT_ETAT"; break;
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_MODEM_ERREUR_ETABLISSEMENT_LIAISON: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_MODEM_ERREUR_ETABLISSEMENT_LIAISON"; break;
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_CHANGEMENT_ETAT_NON_SOLLICITE: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_CHANGEMENT_ETAT_NON_SOLLICITE"; break;
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_CHANGEMENT_REVISION_FIRMWARE: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_CHANGEMENT_REVISION_FIRMWARE"; break;
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_CHANGEMENT_IMEI: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_CHANGEMENT_IMEI"; break;
|
||||
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_MODEM_CHANGEMENT_IMSI: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_MODEM_CHANGEMENT_IMSI"; break;
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_MODEM_CHANGEMENT_ICCID: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_MODEM_CHANGEMENT_ICCID"; break;
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_MODEM_CHANGEMENT_NO_TELEPHONE: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_MODEM_CHANGEMENT_NO_TELEPHONE"; break;
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_MODEM_CHANGEMENT_APN: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_MODEM_CHANGEMENT_APN"; break;
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_MODEM_ERREUR_FTP: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_MODEM_ERREUR_FTP"; break;
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_MODEM_ERREUR_GNSS: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_MODEM_ERREUR_GNSS"; break;
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_MODEM_ERREUR_M_BUS_PLEIN: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_MODEM_ERREUR_M_BUS_PLEIN"; break;
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_MODEM_PERTE_LIAISON_4G_LTE: texte_event_systeme = "SYSTEME_MODEM_PERTE_LIAISON_4G_LTE"; break;
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_MODEM_ETABLISSEMENT_LIAISON_4G_LTE: texte_event_systeme = "SYSTEME_MODEM_ETABLISSEMENT_LIAISON_4G_LTE"; break;
|
||||
|
||||
case SYSTEME_MODULES_NOUVEAU_MODULE: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_MODULES_NOUVEAU_MODULE"; break;
|
||||
case SYSTEME_MODULES_SUPPRESSION_MODULE: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_MODULES_SUPPRESSION_MODULE"; break;
|
||||
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_FTP_UPLOAD_FICHIER_DEBUT_OK: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_FTP_UPLOAD_FICHIER_DEBUT_OK"; break;
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_FTP_UPLOAD_FICHIER_DEBUT_NOK: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_FTP_UPLOAD_FICHIER_DEBUT_NOK"; break;
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_FTP_UPLOAD_FICHIER_FIN_OK: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_FTP_UPLOAD_FICHIER_FIN_OK"; break;
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_FTP_UPLOAD_FICHIER_FIN_NOK: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_FTP_UPLOAD_FICHIER_FIN_NOK"; break;
|
||||
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_FTP_DOWNLOAD_FICHIER_DEBUT_OK: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_FTP_DOWNLOAD_FICHIER_DEBUT_OK"; break;
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_FTP_DOWNLOAD_FICHIER_DEBUT_NOK: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_FTP_DOWNLOAD_FICHIER_DEBUT_NOK"; break;
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_FTP_DOWNLOAD_FICHIER_FIN_OK: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_FTP_DOWNLOAD_FICHIER_FIN_OK"; break;
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_FTP_DOWNLOAD_FICHIER_FIN_NOK: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_FTP_DOWNLOAD_FICHIER_FIN_NOK"; break;
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_FTP_DOWNLOAD_LIST_NOK: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_FTP_DOWNLOAD_LIST_NOK"; break;
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_FTP_DOWNLOAD_NOMBRE_FICHIERS_LOCAUX_TROP_ELEVE: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_FTP_DOWNLOAD_NOMBRE_FICHIERS_LOCAUX_TROP_ELEVE"; break;
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_FTP_DOWNLOAD_NOMBRE_FICHIERS_SERVEUR_TROP_ELEVE: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_FTP_DOWNLOAD_NOMBRE_FICHIERS_SERVEUR_TROP_ELEVE"; break;
|
||||
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_EXECUTION_BASH_DEBUT_OK: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_EXECUTION_BASH_DEBUT_OK"; break;
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_EXECUTION_BASH_DEBUT_NOK: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_EXECUTION_BASH_DEBUT_NOK"; break;
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_EXECUTION_BASH_FIN_OK: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_EXECUTION_BASH_FIN_OK"; break;
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_EXECUTION_BASH_FIN_NOK: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_EXECUTION_BASH_FIN_NOK"; break;
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_COPIE_ARCHIVE_A_VALIDER_OK: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_COPIE_ARCHIVE_A_VALIDER_OK"; break;
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_COPIE_ARCHIVE_A_VALIDER_NOK: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_COPIE_ARCHIVE_A_VALIDER_NOK"; break;
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_COPIE_ARCHIVE_A_CHARGER_OK: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_COPIE_ARCHIVE_A_CHARGER_OK"; break;
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_COPIE_ARCHIVE_A_CHARGER_NOK: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_COPIE_ARCHIVE_A_CHARGER_NOK"; break;
|
||||
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_CHARGEMENT_CODE_DEBUT_OK: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_CHARGEMENT_CODE_DEBUT_OK"; break;
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_CHARGEMENT_CODE_DEBUT_NOK: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_CHARGEMENT_CODE_DEBUT_NOK"; break;
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_CHARGEMENT_CODE_ERASE_FLASH_NOK: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_CHARGEMENT_CODE_ERASE_FLASH_NOK"; break;
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_CHARGEMENT_CODE_ECRITURE_FLASH_NOK: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_CHARGEMENT_CODE_ECRITURE_FLASH_NOK"; break;
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_CHARGEMENT_CODE_CRC_FLASH_NOK: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_CHARGEMENT_CODE_CRC_FLASH_NOK"; break;
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_CHARGEMENT_CODE_FIN_OK: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_CHARGEMENT_CODE_FIN_OK"; break;
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_CHARGEMENT_CODE_FIN_NOK: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_CHARGEMENT_CODE_FIN_NOK"; break;
|
||||
|
||||
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_UART_BUFFER_RX_PLEIN: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_UART_BUFFER_RX_PLEIN"; break;
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_BUS_BUFFER_COMMANDES_PLEIN: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_BUS_BUFFER_COMMANDES_PLEIN"; break;
|
||||
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_BACKLIGHT_CHANGEMENT_CONSIGNE: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_BACKLIGHT_CHANGEMENT_CONSIGNE"; break;
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_VOLUME_CHANGEMENT_CONSIGNE: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_VOLUME_CHANGEMENT_CONSIGNE"; break;
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_LEDS_CHANGEMENT_CONSIGNE: texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_LEDS_CHANGEMENT_CONSIGNE"; break;
|
||||
|
||||
|
||||
case HISTORIQUE_SOUS_TYPE_SYSTEME_WIFI_MISE_A_JOUR_CONFIG : texte_event_systeme = "HISTORIQUE_SOUS_TYPE_SYSTEME_WIFI_MISE_A_JOUR_CONFIG"; break;
|
||||
|
||||
default : libelle = "Evénement de type SYSTEME avec code de sous-type inconnu [" + event + "]";
|
||||
}
|
||||
|
||||
texte_event_systeme = texte_event_systeme.replace('HISTORIQUE_SOUS_TYPE_SYSTEME_', '');
|
||||
texte_event_systeme = texte_event_systeme.replace(/_/g, ' ');
|
||||
if (texte_event_systeme !== "") libelle = "Evénement système de type '" + texte_event_systeme.replace(/_/g, ' ') + "' [" + event + "]"; // le 'g' permet de remplacer toutes les occurences (sinon, seule la première sera remplacée)
|
||||
if (texte_valeur_systeme !== "") libelle = libelle + " avec valeur = [" + texte_valeur_systeme + "]";
|
||||
|
||||
break;
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------
|
||||
case HISTORIQUE_TYPE_CIRCUITS:
|
||||
|
||||
|
||||
switch (event)
|
||||
{
|
||||
case HISTORIQUE_SOUS_TYPE_CIRCUITS_CHANGEMENT_CONSIGNE:
|
||||
if (valeur === 0) libelle = qsTr("Commande 'OFF' du circuit %1").arg(texte_nom);
|
||||
else if (valeur === 100) libelle = qsTr("Commande 'ON' du circuit %1").arg(texte_nom);
|
||||
else libelle = qsTr("Commande à %1 % du circuit %2").arg(valeur).arg(texte_nom);
|
||||
break;
|
||||
|
||||
case HISTORIQUE_SOUS_TYPE_CIRCUITS_OK: libelle = qsTr("Le circuit %1 est revenu à son état de fonctionnement normal").arg(texte_nom); break;
|
||||
case HISTORIQUE_SOUS_TYPE_CIRCUITS_LIMITATION: libelle = qsTr("L'alimentation du circuit %1 a été coupée car sa limite de courant (%2 A) a été dépassée").arg(texte_nom).arg(valeur.toFixed(2)); break;
|
||||
case HISTORIQUE_SOUS_TYPE_CIRCUITS_PROTECTION: libelle = qsTr("L'alimentation du circuit %1 a été coupée car les circuits de protection interne ont détecté une anomalie").arg(texte_nom); break;
|
||||
case HISTORIQUE_SOUS_TYPE_CIRCUITS_DISJONCTE: libelle = qsTr("L'alimentation du circuit %1 a été coupée car le seuil de disjonction a été dépassé").arg(texte_nom); break;
|
||||
case HISTORIQUE_SOUS_TYPE_CIRCUITS_CC_BATTERIE: libelle = qsTr("Le circuit %1 est en court-circuit avec le + batterie").arg(texte_nom); break;
|
||||
case HISTORIQUE_SOUS_TYPE_CIRCUITS_OPEN_LOAD: libelle = qsTr("L'alimentation du circuit %1 a été coupée car la consommation totale du module a été dépassé").arg(texte_nom); break;
|
||||
|
||||
case HISTORIQUE_SOUS_TYPE_CIRCUITS_CREATION: libelle = qsTr("Le circuit %1 a été créé").arg(texte_nom); break;
|
||||
case HISTORIQUE_SOUS_TYPE_CIRCUITS_MODIFICATION: libelle = qsTr("La configuration du circuit %1 a été modifiée").arg(texte_nom); break;
|
||||
case HISTORIQUE_SOUS_TYPE_CIRCUITS_SUPPRESSION: libelle = qsTr("Le circuit %1 a été supprimé").arg(texte_nom); break;
|
||||
|
||||
case HISTORIQUE_SOUS_TYPE_CIRCUITS_CONFIGURATION_INVALIDE: libelle = qsTr("La configuration du circuit %1 est invalide car le module sur lequel le circuit est configuré n'est pas présent").arg(texte_nom); break;
|
||||
|
||||
case HISTORIQUE_SOUS_TYPE_CIRCUIT_EXPIRATION_TIME_OUT: libelle = qsTr("Le circuit %1 a fonctionné trop longtemps (> %2 secondes). Il a donc été désactivé automatiquement.").arg(texte_nom).arg(valeur); break;
|
||||
|
||||
default : libelle = qsTr("Evénement de type CIRCUITS avec code de sous-type inconnu [%1]").arg(event)
|
||||
}
|
||||
break;
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------
|
||||
case HISTORIQUE_TYPE_CAPTEURS:
|
||||
switch (event)
|
||||
{
|
||||
case HISTORIQUE_SOUS_TYPE_CAPTEURS_CAPTEUR_PASSAGE_OK: libelle = qsTr("Le capteur %1 est repassé à l'état normal").arg(texte_nom); break;
|
||||
|
||||
case HISTORIQUE_SOUS_TYPE_CAPTEURS_CAPTEUR_PASSAGE_ALERTE: libelle = qsTr("Le capteur %1 est passé à l'état ALERTE").arg(texte_nom); break;
|
||||
|
||||
case HISTORIQUE_SOUS_TYPE_CAPTEURS_CAPTEUR_PASSAGE_ALARME: libelle = qsTr("Le capteur %1 est passé à l'état ALARME").arg(texte_nom); break;
|
||||
|
||||
default : libelle = qsTr("Evénement de type CAPTEURS avec code de sous-type inconnu [%1]").arg(event)
|
||||
}
|
||||
break;
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------
|
||||
case HISTORIQUE_TYPE_BATTERIES:
|
||||
switch (event)
|
||||
{
|
||||
case HISTORIQUE_SOUS_TYPE_BATTERIES_PASSAGE_NIVEAU_NORMAL: libelle = qsTr("Le niveau de charge de la batterie %1 est repassé au niveau normal").arg(texte_nom); break;
|
||||
case HISTORIQUE_SOUS_TYPE_BATTERIES_PASSAGE_NIVEAU_ALERTE:
|
||||
if (valeur === HISTORIQUE_SOUS_TYPE_BATTERIES_PASSAGE_NIVEAU_NORMAL) libelle = qsTr("Le niveau de charge de la batterie %1 est passé en dessous du niveau d'alerte").arg(texte_nom);
|
||||
else libelle = qsTr("Le niveau de charge de la batterie %1 est passé au-dessus du niveau d'alarme (il est maintenant au niveau d'alerte uniquement)").arg(texte_nom);
|
||||
break;
|
||||
case HISTORIQUE_SOUS_TYPE_BATTERIES_PASSAGE_NIVEAU_ALARME: libelle = qsTr("Le niveau de charge de la batterie %1 est passé en-dessous du niveau d'alarme").arg(texte_nom); break;
|
||||
|
||||
default : libelle = qsTr("Evénement de type BATTERIES avec code de sous-type inconnu [%1]").arg(event)
|
||||
}
|
||||
break;
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------
|
||||
case HISTORIQUE_TYPE_RESERVOIRS:
|
||||
switch (event)
|
||||
{
|
||||
case HISTORIQUE_SOUS_TYPE_RESERVOIRS_PASSAGE_NIVEAU_NORMAL: libelle = qsTr("Le niveau du réservoir %1 est repassé au niveau normal").arg(texte_nom); break;
|
||||
case HISTORIQUE_SOUS_TYPE_RESERVOIRS_PASSAGE_NIVEAU_ALERTE:
|
||||
if (valeur === HISTORIQUE_SOUS_TYPE_RESERVOIRS_PASSAGE_NIVEAU_NORMAL) libelle = qsTr("Le niveau du réservoir %1 est passé en dessous du niveau d'alerte").arg(texte_nom);
|
||||
else libelle = qsTr("Le niveau du réservoir %1 est passé au-dessus du niveau d'alarme (il est maintenant au niveau d'alerte uniquement)").arg(texte_nom);
|
||||
break;
|
||||
case HISTORIQUE_SOUS_TYPE_RESERVOIRS_PASSAGE_NIVEAU_ALARME: libelle = qsTr("Le niveau du réservoir %1 est passé en-dessous du niveau d'alarme").arg(texte_nom); break;
|
||||
|
||||
default : libelle = qsTr("Evénement de type RESERVOIRS avec code de sous-type inconnu [%1]").arg(event)
|
||||
}
|
||||
break;
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------
|
||||
case HISTORIQUE_TYPE_USB:
|
||||
switch (event)
|
||||
{
|
||||
case HISTORIQUE_SOUS_TYPE_USB_CHANGEMENT_CONSIGNE: libelle = qsTr("La consigne des ports USB est passée à %1").arg(valeur); break;
|
||||
|
||||
case HISTORIQUE_SOUS_TYPE_USB_PASSAGE_OK: libelle = qsTr("L'état des ports USB est redevenu normal"); break;
|
||||
case HISTORIQUE_SOUS_TYPE_USB_PASSAGE_DEFAUT: libelle = qsTr("Défaut détecté sur les ports USB"); break;
|
||||
|
||||
default : libelle = qsTr("Evénement de type USB avec code de sous-type inconnu [%1]").arg(event)
|
||||
}
|
||||
break;
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------
|
||||
default : libelle = qsTr("Evénement de type INCONNU (avec code de sous-type [%1]").arg(event)
|
||||
}
|
||||
|
||||
|
||||
return(libelle);
|
||||
}
|
||||
Executable
+125
@@ -0,0 +1,125 @@
|
||||
.pragma library
|
||||
|
||||
|
||||
// Nb : l'ordre des array ci-dessous défini l'ordre d'affichage (sur la page Paramètres notamment)
|
||||
|
||||
let langues = [
|
||||
['FR', 'fr_FR', 'Français' ], // 0
|
||||
['EN', 'en_EN', 'English' ], // 1
|
||||
['IT', 'it_IT', 'Italiano' ], // 2
|
||||
['ES', 'es_ES', 'Español' ], // 3
|
||||
['DE', 'de_DE', 'Deutsch' ], // 4
|
||||
['PT', 'pt_PT', 'Português' ], // 5
|
||||
['NL', 'nl_NL', 'Nederlands' ], // 6
|
||||
['LV', 'lv_LV', 'Latviski' ], // 7
|
||||
['CA', 'ca_ES', 'català' ] // 8
|
||||
];
|
||||
|
||||
let volumes = [
|
||||
['Litres', 'lit.' ], // 0
|
||||
['US Gallons', 'US Ga' ], // 1
|
||||
['Imperial Gallons', 'Imp. Ga' ] // 2
|
||||
];
|
||||
|
||||
let temperatures = [
|
||||
['Celsius', '°C' ], // 0
|
||||
['Fahrenheit', '°F' ] // 1
|
||||
];
|
||||
|
||||
|
||||
|
||||
//=====================================================================================
|
||||
// Fonctions : Fournit le nombre de langues disponibles
|
||||
// Reçoit : Rien
|
||||
// Retour : Le nb de langues
|
||||
//=====================================================================================
|
||||
function nb_langues()
|
||||
{
|
||||
return(langues.length);
|
||||
}
|
||||
//=====================================================================================
|
||||
// Fonctions : Fournit le code pays de la langue dont le n° est passé en paramètre
|
||||
//=====================================================================================
|
||||
function code_pays(no)
|
||||
{
|
||||
if ((no < 0) || (no >= langues.length)) no = 0;
|
||||
return(langues[no][0]);
|
||||
}
|
||||
//=====================================================================================
|
||||
// Retour : Le code langue (par exemple : "fr_FR" ou "en_EN"
|
||||
//=====================================================================================
|
||||
function code_langue(no)
|
||||
{
|
||||
if ((no < 0) || (no >= langues.length)) no = 0;
|
||||
return(langues[no][1]);
|
||||
}
|
||||
//=====================================================================================
|
||||
// Retour : Le nom de la langue (par exemple : "Français" ou "English"
|
||||
//=====================================================================================
|
||||
function nom_langue(no)
|
||||
{
|
||||
if ((no < 0) || (no >= langues.length)) no = 0;
|
||||
return(langues[no][2]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=====================================================================================
|
||||
// Fonctions : Fournit le nombre d'unités de volume
|
||||
// Reçoit : Rien
|
||||
// Retour : Le nb d'unités de volume
|
||||
//=====================================================================================
|
||||
function nb_unites_volume()
|
||||
{
|
||||
return(volumes.length);
|
||||
}
|
||||
//=====================================================================================
|
||||
// Retour : Le nom (par exemple : "Litres" ou "US Gallons"
|
||||
//=====================================================================================
|
||||
function nom_unite_volume(no)
|
||||
{
|
||||
if ((no < 0) || (no >= volumes.length)) no = 0;
|
||||
return(volumes[no][0]);
|
||||
}
|
||||
//=====================================================================================
|
||||
// Retour : Le symbole (par exemple : "lit." ou "US Ga")
|
||||
//=====================================================================================
|
||||
function symbole_unite_volume(no)
|
||||
{
|
||||
if ((no < 0) || (no >= volumes.length)) no = 0;
|
||||
return(volumes[no][1]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//=====================================================================================
|
||||
// Fonctions : Fournit le nombre d'unités de température
|
||||
// Reçoit : Rien
|
||||
// Retour : Le nb d'unités de temperature
|
||||
//=====================================================================================
|
||||
function nb_unites_temperature()
|
||||
{
|
||||
return(temperatures.length);
|
||||
}
|
||||
//=====================================================================================
|
||||
// Retour : Le nom (par exemple : "Celsius" ou "Farenheit"
|
||||
//=====================================================================================
|
||||
function nom_unite_temperature(no)
|
||||
{
|
||||
if ((no < 0) || (no >= temperatures.length)) no = 0;
|
||||
return(temperatures[no][0]);
|
||||
}
|
||||
//=====================================================================================
|
||||
// Retour : Le symbole (par exemple : "°C" ou "°F")
|
||||
//=====================================================================================
|
||||
function symbole_unite_temperature(no)
|
||||
{
|
||||
if ((no < 0) || (no >= temperatures.length)) no = 0;
|
||||
return(temperatures[no][1]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Executable
+86
@@ -0,0 +1,86 @@
|
||||
.pragma library
|
||||
|
||||
//=====================================================================================
|
||||
// Fonctions : Fournit une chaine de caractères constituant une liste de valeurs§niveaux
|
||||
// du réservoir. La liste est composée de couples de nombre séparés par des ';'
|
||||
// et les deux valeurs au sein d'un couple sont séparés par '/'.
|
||||
// Par exemple : "0/0.00;190/100.00"
|
||||
// La chaine est établie en fonction du paramètre de 'mode' et de 'sous_mode' du réservoir.
|
||||
// Reçoit : Le type d'entrée, le mode et sous_mode utilisés pour ce réservoir
|
||||
// Retour : La chaine
|
||||
//=====================================================================================
|
||||
function chaine_valeur_niveau_reservoir_usine(type, mode, sous_mode)
|
||||
{
|
||||
var i;
|
||||
var masque;
|
||||
var chaine = "";
|
||||
|
||||
switch (type)
|
||||
{
|
||||
//===============================================
|
||||
case 1 : // Entrée Auxiliaire :
|
||||
if ((mode < 1) || (mode > 12)) break; // Cf 'shipheart_reservoir_max_nombre_entrees_aux' dans main.qml
|
||||
|
||||
masque = 1;
|
||||
chaine = "0/0";
|
||||
for (i=1; i<=mode; i++)
|
||||
{
|
||||
chaine += ';' + masque + '/' + ((100*i) / mode).toFixed(2);
|
||||
masque = (masque << 1) | 1;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
//===============================================
|
||||
case 2 : // Entrée Level Sensor :
|
||||
switch(mode)
|
||||
{
|
||||
//------------------------------------------------------------
|
||||
case 0:
|
||||
break;
|
||||
|
||||
//------------------------------------------------------------
|
||||
case 1: // 0-10V
|
||||
chaine = "0.000/0.00";
|
||||
chaine += ";10.000/100.00";
|
||||
break;
|
||||
|
||||
//------------------------------------------------------------
|
||||
case 2: // 500R
|
||||
switch(sous_mode)
|
||||
{
|
||||
case 1: // 0-190R
|
||||
chaine = "2/0.00";
|
||||
chaine += ";185/100.00";
|
||||
break;
|
||||
case 2: // 240-30R
|
||||
chaine = "235/0.00";
|
||||
chaine += ";45/100.00";
|
||||
break;
|
||||
case 0: // 0-500R
|
||||
default:
|
||||
chaine = "0/0.00";
|
||||
chaine += ";700/100.00";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
//------------------------------------------------------------
|
||||
case 3: // 4-20mA
|
||||
chaine = "4.000/0.00";
|
||||
chaine += ";20.000/100.00";
|
||||
break;
|
||||
|
||||
|
||||
//------------------------------------------------------------
|
||||
default: // Non défini (on part donc sur une entrée en tension de 0 à 10V)
|
||||
chaine = "0.000/0.00";
|
||||
chaine += ";10.000/100.00";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
console.log("Chaine de valeurs/niveaux pour le réservoir = [" + chaine + "]")
|
||||
return(chaine);
|
||||
}
|
||||
Executable
+20
@@ -0,0 +1,20 @@
|
||||
# Exécuté à CHAQUE build (pas seulement à chaque reconfiguration CMake) via
|
||||
# la cible "generate_version" dans CMakeLists.txt, qui n'a aucun suivi de
|
||||
# fichier et est donc toujours considérée périmée par Ninja/Make.
|
||||
#
|
||||
# Reproduit le comportement du .pro d'origine : deux exécutables différents
|
||||
# (même par une modification infime du code) obtiennent systématiquement un
|
||||
# horodatage différent, garantissant l'unicité recherchée.
|
||||
|
||||
string(TIMESTAMP APP_VERSION "%y%m%d_%H%M%S")
|
||||
|
||||
file(WRITE "${OUTPUT_FILE}"
|
||||
"#ifndef _VERSION_H
|
||||
#define _VERSION_H
|
||||
|
||||
#define VERSION \"${APP_VERSION}\"
|
||||
|
||||
#endif // _VERSION_H
|
||||
")
|
||||
|
||||
message(STATUS "Version ShipHeart Qt régénérée : ${APP_VERSION}")
|
||||
@@ -0,0 +1,222 @@
|
||||
//========================================================================================================================================================================
|
||||
// HOME_ACCUEIL.QML
|
||||
// Ce fichier est la page d'accueil par défaut. Il propose l'affichage du logo ShipHeart et le nom du bateau.
|
||||
// La page est appelée depuis la page main.qml lorsque le paramètre 'shipheart_specifique_client[0]' est égal à 0
|
||||
//========================================================================================================================================================================
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
import qt.koriolan.shipheart 1.0
|
||||
|
||||
|
||||
|
||||
Shipheart_page {
|
||||
id: page_home_o_yachts
|
||||
|
||||
|
||||
// Mis en forme :
|
||||
readonly property double pourcentage_hauteur_ligne_haut: 0.7
|
||||
readonly property double espace_lignes_principales: 0 // L'espace ne sert à rien et est même contre-productif pour avoir le logo centré entre haut de l'écran et le texte "Bienvenue à bord...."
|
||||
readonly property double affichage_hauteur_utile: shipheart_hauteur_page - shipheart_hauteur_bandeau_bas
|
||||
|
||||
readonly property int periode_raffraichissement_parametres: 1000 // En ms
|
||||
readonly property int duree_affichage: 15 // En s
|
||||
|
||||
// Affichage :
|
||||
|
||||
// Données :
|
||||
property string nom_du_bateau: ""
|
||||
property int compteur_affichage: 0
|
||||
|
||||
// Modèles :
|
||||
// Note : les modèles chargés dans 'main.qml' n'ont pas à être rechargés dans les pages suivantes
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// Ouverture :
|
||||
//-------------------------------------------------
|
||||
StackView.onActivating: { // Le 'onActivating' permet de ne pas voir la mise à jour puisqu'elle est lancée dès que la page va être chargée
|
||||
init_page();
|
||||
timer_raffraichissement_parametres.start();
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// Fermeture :
|
||||
//-------------------------------------------------
|
||||
StackView.onDeactivating: {
|
||||
timer_raffraichissement_parametres.stop();
|
||||
}
|
||||
|
||||
//===========================================================
|
||||
// Timer periode raffraichissement parametres :
|
||||
//===========================================================
|
||||
Timer {
|
||||
id: timer_raffraichissement_parametres
|
||||
interval: periode_raffraichissement_parametres
|
||||
triggeredOnStart: false
|
||||
running: true
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
if (++ compteur_affichage > duree_affichage) sortie_page();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Ecran Haut :
|
||||
//-------------------------------------------------------
|
||||
Rectangle {
|
||||
id: zone_affichage_haut_gauche
|
||||
x: 0
|
||||
y: 0
|
||||
width: shipheart_largeur_page
|
||||
height: (affichage_hauteur_utile * pourcentage_hauteur_ligne_haut) - (espace_lignes_principales);
|
||||
color: "transparent"
|
||||
|
||||
Image {
|
||||
source: (shipheart_fichier_image_accueil !== "")
|
||||
? "file://" + shipheart_repertoire_config + shipheart_sous_repertoire_images_accueil + "/" + shipheart_fichier_image_accueil
|
||||
: "/images/" + shipheart_nom_fichier_image_accueil_par_defaut
|
||||
sourceSize.height: parent.height * 0.7
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Ecran Bas :
|
||||
//-------------------------------------------------------
|
||||
Rectangle {
|
||||
id: zone_affichage_bas_gauche
|
||||
x: 0
|
||||
y: zone_affichage_haut_gauche.height + espace_lignes_principales;
|
||||
width: shipheart_largeur_page
|
||||
height: (affichage_hauteur_utile * (1 - pourcentage_hauteur_ligne_haut)) - (espace_lignes_principales);
|
||||
color: "transparent"
|
||||
|
||||
Text {
|
||||
anchors {
|
||||
top: parent.top // Permet que ce texte soit juste en-dessous de la zone haute (sur laquelle le logo est centré => donc le logo est centré entre haut de l'écran et ce texte)
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
font.pixelSize: 24
|
||||
text: qsTr("Bienvenue à bord de");
|
||||
color: couleur_blanc_casse
|
||||
}
|
||||
|
||||
Text {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
verticalCenterOffset: -20 // Remonté légèrement le nom du bateau...
|
||||
}
|
||||
font.pixelSize: 50
|
||||
text: '" ' + nom_du_bateau + ' "';
|
||||
color: couleur_blanc_casse
|
||||
font.weight: Font.Black
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// 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
|
||||
|
||||
Rectangle {
|
||||
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
color: shipheart_couleur_fond_bouton //"transparent"
|
||||
|
||||
Rectangle { // Barre augmentant selon l'évolution du compteur_affichage
|
||||
width: (compteur_affichage / duree_affichage) * parent.width
|
||||
height: parent.height
|
||||
color: shipheart_couleur_fond_bouton_actif
|
||||
opacity: 0.5
|
||||
radius: shipheart_rayon_bouton
|
||||
Behavior on width { NumberAnimation { duration: periode_raffraichissement_parametres } }
|
||||
}
|
||||
|
||||
Image {
|
||||
source: "/images/right_sombre.png"
|
||||
sourceSize.height: parent.height * 0.5
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
horizontalCenterOffset: -10
|
||||
}
|
||||
}
|
||||
Image {
|
||||
source: "/images/right_sombre.png"
|
||||
sourceSize.height: parent.height * 0.5
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
horizontalCenterOffset: +10
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
sortie_page();
|
||||
//stackView.push("parametres_avances.qml");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================
|
||||
// Economiseur : Doit être placé en fin de page pour fonctionner
|
||||
//===========================================================
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
preventStealing: true // Permet que cela fonctionne même si un élément flickable (notamment) soit derrière et "vole" le click
|
||||
enabled: flag_economiseur_actif
|
||||
onClicked: {
|
||||
mise_en_veille(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================================================
|
||||
// Init de la page
|
||||
//=============================================================================================================
|
||||
function init_page()
|
||||
{
|
||||
var req, res
|
||||
|
||||
mise_en_veille(0);
|
||||
console.log("Init de Home_accueil...");
|
||||
|
||||
// Mise à jour du nom du bateau :
|
||||
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Nom_du_bateau" ';
|
||||
res = bdd.requete_unique(req);
|
||||
nom_du_bateau = res[0];
|
||||
|
||||
compteur_affichage = 0;
|
||||
}
|
||||
|
||||
//=============================================================================================================
|
||||
// Sortie de la page
|
||||
//=============================================================================================================
|
||||
function sortie_page()
|
||||
{
|
||||
|
||||
compteur_affichage = 0; // Pour le cas où on réouvrirait la page (via le bouton paramètres / appui long) ; dans ce cas, la remise à 0 du compteur prend quelques secondes (ce sera donc fait avant si on le remet de suite à 0)
|
||||
stackView.push("home.qml");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,282 @@
|
||||
//========================================================================================================================================================================
|
||||
// HOME_ATTENTE.QML
|
||||
// Ce fichier affiche un fond d'écran standard mais avec rien dedans. Il est utilisé au démarrage, pour attendre que l'ApplicationWindow soit prête
|
||||
// et que l'accès à la BDD permette de décider quelle page d'accueil lancer.
|
||||
// Sans cette page, la StackView affiche une page toute blanche pendant 1-2s avant que la première Home page soit chargée...
|
||||
//========================================================================================================================================================================
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
import qt.koriolan.shipheart 1.0
|
||||
|
||||
|
||||
|
||||
Shipheart_page {
|
||||
id: page_home_attente
|
||||
|
||||
|
||||
//==============================================================
|
||||
// Recherche de la Home Page à utiliser :
|
||||
//==============================================================
|
||||
Timer {
|
||||
id: timer_recherche_home_page
|
||||
interval: 300
|
||||
running: true
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
|
||||
console.log("Adresse de ShipBase = " + AppInfo.adresse_shipbase)
|
||||
console.log("Etat de la connexion à la BDD = " + AppInfo.etat_connexion_bdd)
|
||||
console.log("Type d'installation = " + AppInfo.type_installation)
|
||||
console.log("Taille de l'écran = " + AppInfo.taille_ecran)
|
||||
|
||||
//----------------------------------------------------
|
||||
// Valeurs correspondant au type d'installation :
|
||||
//----------------------------------------------------
|
||||
switch (Number(AppInfo.type_installation))
|
||||
{
|
||||
default:
|
||||
case shipheart_type_installation_shipbase:
|
||||
shipheart_type_installation = shipheart_type_installation_shipbase;
|
||||
break;
|
||||
|
||||
case shipheart_type_installation_ecran_deporte:
|
||||
switch (Number(AppInfo.taille_ecran))
|
||||
{
|
||||
default:
|
||||
case 7:
|
||||
shipheart_type_installation = shipheart_type_installation_ecran_deporte_7_pouces;
|
||||
break;
|
||||
case 10:
|
||||
shipheart_type_installation = shipheart_type_installation_ecran_deporte_10_pouces;
|
||||
break;
|
||||
case 22:
|
||||
shipheart_type_installation = shipheart_type_installation_ecran_deporte_22_pouces;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
console.log("Type d'installation = " + shipheart_type_installation)
|
||||
//shipheart_type_installation = shipheart_type_installation_shipbase
|
||||
//shipheart_type_installation = shipheart_type_installation_ecran_deporte_22_pouces
|
||||
|
||||
// Valeurs par défaut :
|
||||
shipheart_largeur_page = 1280
|
||||
shipheart_hauteur_page = 800
|
||||
shipheart_hauteur_bandeau_haut = 60
|
||||
shipheart_hauteur_titre_2 = 50
|
||||
shipheart_hauteur_bandeau_bas = 80
|
||||
shipheart_hauteur_clavier = 305
|
||||
|
||||
|
||||
//----------------------------------------------------
|
||||
// Cas où la connexion à la BDD n'a pas été possible :
|
||||
//----------------------------------------------------
|
||||
if ((AppInfo.etat_connexion_bdd === 0) && (Number(AppInfo.type_installation) === shipheart_type_installation_ecran_deporte))
|
||||
{
|
||||
stackView.push("config_shiprs.qml", {"connexion_impossible": true})
|
||||
timer_recherche_home_page.stop(); // Arret du timer car il n'est plus utile maintenant
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
//----------------------------------------------------
|
||||
// Paramètres spécifiques dans le cas des ShipRS :
|
||||
// NB il est important de ne PAS faire ce traitement avant l'appel
|
||||
// à 'connexion_impossible.qml' car, sinon, on peut se trouver dans une
|
||||
// config de 22" (par exemple) et ne plus avoir accès aux boutons de
|
||||
// configuration !!
|
||||
//----------------------------------------------------
|
||||
switch (shipheart_type_installation)
|
||||
{
|
||||
//---------------------------------------------------------------------------
|
||||
case shipheart_type_installation_ecran_deporte_7_pouces:
|
||||
shipheart_largeur_page = 1280;
|
||||
shipheart_hauteur_page = 800;
|
||||
synchro_repertoires_shiprs();
|
||||
break;
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
case shipheart_type_installation_ecran_deporte_10_pouces:
|
||||
shipheart_largeur_page = 1280; // Spec de l'écran DENSITRON de ShipBase
|
||||
shipheart_hauteur_page = 800; // Spec de l'écran DENSITRON de ShipBase
|
||||
synchro_repertoires_shiprs();
|
||||
break;
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
case shipheart_type_installation_ecran_deporte_22_pouces:
|
||||
shipheart_largeur_page = 1920;
|
||||
shipheart_hauteur_page = 1080;
|
||||
synchro_repertoires_shiprs();
|
||||
break;
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
default: // Dans ce cas, ce sont les valeurs par défaut qui sont conservées.
|
||||
case shipheart_type_installation_shipbase:
|
||||
break;
|
||||
}
|
||||
|
||||
//----------------------------------------------------
|
||||
// Recherche de la version de ShipBase :
|
||||
//----------------------------------------------------
|
||||
init_shipheart_version_cm();
|
||||
|
||||
//----------------------------------------------------
|
||||
// Recherche du thème d'affichage :
|
||||
//----------------------------------------------------
|
||||
init_shipheart_theme();
|
||||
|
||||
|
||||
//----------------------------------------------------
|
||||
// Première page à afficher selon le client :
|
||||
//----------------------------------------------------
|
||||
var shipheart_nom_initial_page = "";
|
||||
switch (Number(init_shipheart_specifique_client()))
|
||||
{
|
||||
//---------------------------------
|
||||
default:
|
||||
case shipheart_specifique_client_tous:
|
||||
shipheart_nom_initial_page = "qrc:/home_accueil.qml"
|
||||
break;
|
||||
|
||||
//---------------------------------
|
||||
case shipheart_specifique_client_suncy:
|
||||
shipheart_nom_initial_page = "qrc:/home_suncy.qml";
|
||||
break;
|
||||
}
|
||||
|
||||
if ((shipheart_generation_shipbase != shipheart_generation_shipbase_inconnue) && // A priori, ne devrait pas arriver mais si on n'a pas trouvé, on va reommencer la recherche après une période de timer.
|
||||
(shipheart_nom_initial_page !== ""))
|
||||
{
|
||||
timer_recherche_home_page.stop(); // Arret du timer car il n'est plus utile maintenant
|
||||
stackView.push(shipheart_nom_initial_page)
|
||||
//console.log("La Home Page sélectionnée est '" + shipheart_nom_initial_page + "'")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================
|
||||
// Réactivation de la recherche lors d'un retour sur cette page :
|
||||
//==============================================================
|
||||
StackView.onActivated: {
|
||||
//console.log("!!! Page Home_attente activée")
|
||||
timer_recherche_home_page.start(); // Relance le timer pour faire une nouvelle recherche
|
||||
}
|
||||
|
||||
//==============================================================
|
||||
// Zone d'affichage :
|
||||
//==============================================================
|
||||
Rectangle {
|
||||
x: 0
|
||||
y: 0
|
||||
width: 5000 // Permet d'être qûr qu'on couvre tout l'écran, quel qu'il soit
|
||||
height: 5000 // Permet d'être qûr qu'on couvre tout l'écran
|
||||
color: "transparent" // C'est la ligne importante qui permet de ne pas avoir un "flash' blanc au démarrage
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
// Fonction : Récpère dans la BDD la valeur de 'Specifique_client' dans
|
||||
// TB_Configuration. sépare chaque champs (séparés par des ';').
|
||||
// Met à jour la propriété globale 'shipheart_specifique_client'
|
||||
// avec toutes les valeurs. Renvoi la première.
|
||||
// Reçoit : Rien
|
||||
// Retour : La valeur de 'shipheart_specifique_client[0]'
|
||||
//============================================================================
|
||||
function init_shipheart_specifique_client()
|
||||
{
|
||||
var req, res
|
||||
|
||||
// Récupération du paramètre 'TB_Configuration.Specifique_client'
|
||||
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Specifique_client" ';
|
||||
res = bdd.requete_unique(req);
|
||||
|
||||
shipheart_specifique_client = res[0].split(';') // Mémorisation de l'ensemble du tableau
|
||||
|
||||
return(shipheart_specifique_client[0]); // Renvoi de la première valeur
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
// Fonction : Récupère dans la BDD la valeur de 'Theme' dans
|
||||
// TB_Configuration et met à jour la propriété globale 'shipheart_theme'.
|
||||
// Reçoit : Rien
|
||||
// Retour : Rien
|
||||
//============================================================================
|
||||
function init_shipheart_theme()
|
||||
{
|
||||
var req, res;
|
||||
var nb;
|
||||
|
||||
// Chargement du thème demandé en config :
|
||||
chargement_theme();
|
||||
|
||||
// Récupération du paramètre 'TB_Configuration.Fichier_image_accueil'
|
||||
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Fichier_image_accueil" ';
|
||||
//console.log("Requête = [ " + req + "; ]");
|
||||
nb = bdd.requete(req);
|
||||
//console.log("NB = "+nb);
|
||||
if (nb >0)
|
||||
{
|
||||
res = bdd.lecture_ligne();
|
||||
if (!res.isEmpty)
|
||||
{
|
||||
shipheart_fichier_image_accueil = res[0];
|
||||
console.log("Le fichier d'image d'accueil est : [" + shipheart_fichier_image_accueil + "]");
|
||||
}
|
||||
else
|
||||
{
|
||||
shipheart_fichier_image_accueil = "";
|
||||
console.log("/!\ Erreur dans le traitementr de la requête de recherche de fichier d'image d'accueil a échouée. Le nom de fichier est mis à sa valeur par défaut...");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
shipheart_fichier_image_accueil = "";
|
||||
console.log("/!\ La requête de recherche de fichier d'image d'accueil a échouée. Le nom de fichier est mis à sa valeur par défaut...");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
// Fonction : Récupère dans la BDD la valeur de 'Version_cm' dans
|
||||
// TB_Systeme et met à jour la propriété globale 'shipheart_generation_shipbase'.
|
||||
// Reçoit : Rien
|
||||
// Retour : Rien
|
||||
//============================================================================
|
||||
function init_shipheart_version_cm()
|
||||
{
|
||||
var req, res
|
||||
|
||||
// Récupération du paramètre 'TB_Systeme.Version_cm'
|
||||
req = 'SELECT Valeur FROM TB_Systeme WHERE Nom="Version_cm" ';
|
||||
res = bdd.requete_unique(req);
|
||||
|
||||
if (res[0].indexOf("CM3+") !== -1) shipheart_generation_shipbase = shipheart_generation_shipbase_v1;
|
||||
else if (res[0].indexOf("CM4") !== -1) shipheart_generation_shipbase = shipheart_generation_shipbase_v2;
|
||||
else if (res[0].indexOf("CM5") !== -1) shipheart_generation_shipbase = shipheart_generation_shipbase_v3;
|
||||
else shipheart_generation_shipbase = shipheart_generation_shipbase_inconnue;
|
||||
console.log("Génération de ShipBase = " + shipheart_generation_shipbase);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================================================
|
||||
// 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, "");
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
+372
@@ -0,0 +1,372 @@
|
||||
//========================================================================================================================================================================
|
||||
// HOME_SUNCY.QML
|
||||
// Ce fichier est la page d'accueil pour le client Suncy. Il propose un clavier et un petit message d'accueil.
|
||||
// La page est appelée depuis la page main.qml lorsque le paramètre 'shipheart_specifique_client[0]' est égal à 1
|
||||
//========================================================================================================================================================================
|
||||
import QtQuick 2.12
|
||||
|
||||
import qt.koriolan.shipheart 1.0
|
||||
|
||||
|
||||
|
||||
Shipheart_page {
|
||||
id: page_home_suncy
|
||||
|
||||
|
||||
// Mis en forme :
|
||||
readonly property double pourcentage_largeur_colonne_gauche: 0.5
|
||||
readonly property double espace_colonnes_principales: 20
|
||||
readonly property double pourcentage_hauteur_ligne_haut: 0.15
|
||||
readonly property double espace_lignes_principales: 20
|
||||
readonly property double affichage_hauteur_utile: shipheart_hauteur_page - shipheart_hauteur_bandeau_haut - shipheart_hauteur_bandeau_bas
|
||||
|
||||
readonly property double pourcentage_bandeau_bas_largeur_zone_retour: 1
|
||||
|
||||
|
||||
readonly property int periode_init_raffraichissement_parametres: 1 // En ms
|
||||
readonly property int periode_raffraichissement_parametres: 1000 // En ms
|
||||
|
||||
|
||||
|
||||
// Affichage :
|
||||
property bool bouton_bandeau_bas_zone_retour_actif: false
|
||||
property int protection_mode: 0
|
||||
|
||||
|
||||
// Données :
|
||||
property string code_saisi: ""
|
||||
property string code_saisi_pattern: "" // Contient une suite de '*' dont le nombre correspond à la taille du code entré (avec un maxi)
|
||||
property int max_taille_code_pattern: 10
|
||||
|
||||
// Modèles :
|
||||
// Note : les modèles chargés dans 'main.qml' n'ont pas à être rechargés dans les pages suivantes
|
||||
|
||||
|
||||
|
||||
//===========================================================
|
||||
// Timer periode raffraichissement parametres :
|
||||
//===========================================================
|
||||
Timer {
|
||||
id: timer_raffraichissement_parametres
|
||||
interval: periode_init_raffraichissement_parametres
|
||||
triggeredOnStart: false
|
||||
running: true
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
if (interval == periode_init_raffraichissement_parametres) { // Premier passage, 1ms après le premier chargement
|
||||
interval = periode_raffraichissement_parametres;
|
||||
|
||||
init_page();
|
||||
timer_raffraichissement_parametres.stop(); // Arret du timer une fois l'init faite car il n'y a rien à faire.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Titre de la page :
|
||||
Shipheart_titre_1 {titre:""; hauteur: shipheart_hauteur_bandeau_haut}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Ecran Haut - Gauche :
|
||||
//-------------------------------------------------------
|
||||
Rectangle {
|
||||
id: zone_affichage_haut_gauche
|
||||
x: 0
|
||||
y: shipheart_hauteur_bandeau_haut;
|
||||
width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2)
|
||||
height: (affichage_hauteur_utile * pourcentage_hauteur_ligne_haut) - (espace_lignes_principales / 2);
|
||||
color: "transparent"
|
||||
border.width: 1
|
||||
border.color: couleur_gris_moyen
|
||||
radius: shipheart_rayon_bouton
|
||||
|
||||
Text {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
verticalCenterOffset: 12 // Les '*' sont naturellement décalées vers le haut de la ligne...
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
font.pixelSize: 80
|
||||
font.letterSpacing: 10
|
||||
text: code_saisi_pattern;
|
||||
color: couleur_blanc_casse
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Ecran Bas - Gauche :
|
||||
//-------------------------------------------------------
|
||||
Rectangle {
|
||||
id: zone_affichage_bas_gauche
|
||||
x: 0
|
||||
y: shipheart_hauteur_bandeau_haut + zone_affichage_haut_gauche.height + espace_lignes_principales;
|
||||
width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2)
|
||||
height: (affichage_hauteur_utile * (1 - pourcentage_hauteur_ligne_haut)) - (espace_lignes_principales / 2);
|
||||
color: "transparent"
|
||||
|
||||
Grid {
|
||||
id: grille_clavier
|
||||
|
||||
width: parent.width * 0.6
|
||||
height: parent.height * 0.8
|
||||
columns: 3
|
||||
rows: 4
|
||||
spacing: 10
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
Repeater {
|
||||
model: modele_clavier
|
||||
Rectangle {
|
||||
width: (grille_clavier.width - ((grille_clavier.columns - 1) * grille_clavier.spacing)) / grille_clavier.columns
|
||||
height: (grille_clavier.height - ((grille_clavier.rows - 1) * grille_clavier.spacing)) / grille_clavier.rows
|
||||
color: shipheart_couleur_fond_bouton
|
||||
radius: shipheart_rayon_bouton
|
||||
Text {
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
font.pixelSize: 50
|
||||
text: libelle;
|
||||
color: couleur_blanc_casse
|
||||
visible: (libelle === "") ? false : true
|
||||
}
|
||||
Image {
|
||||
source: icone
|
||||
sourceSize.height: 30
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
visible: (libelle === "") ? true : false
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
shipheart_clic();
|
||||
switch(action)
|
||||
{
|
||||
case "backspace": code_saisi = code_saisi.slice(0, code_saisi.length - 1); break;
|
||||
case "clear": code_saisi = ""; break;
|
||||
default: code_saisi += libelle; break;
|
||||
}
|
||||
if (check_code() === 0) deverrouillage();
|
||||
mise_a_jour_pattern();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ListModel {
|
||||
id: modele_clavier
|
||||
|
||||
ListElement { libelle: "7"; action: ""; icone: "" }
|
||||
ListElement { libelle: "8"; action: ""; icone: "" }
|
||||
ListElement { libelle: "9"; action: ""; icone: "" }
|
||||
ListElement { libelle: "4"; action: ""; icone: "" }
|
||||
ListElement { libelle: "5"; action: ""; icone: "" }
|
||||
ListElement { libelle: "6"; action: ""; icone: "" }
|
||||
ListElement { libelle: "1"; action: ""; icone: "" }
|
||||
ListElement { libelle: "2"; action: ""; icone: "" }
|
||||
ListElement { libelle: "3"; action: ""; icone: "" }
|
||||
ListElement { libelle: ""; action: "backspace"; icone: "/images/backspace.png" }
|
||||
ListElement { libelle: "0"; action: ""; icone: "" }
|
||||
ListElement { libelle: ""; action: "clear"; icone: "/images/double_fleche_gauche.png" }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// Ecran Droite :
|
||||
//-------------------------------------------------------
|
||||
Rectangle {
|
||||
id: zone_affichage_droite
|
||||
x: zone_affichage_haut_gauche.width + espace_colonnes_principales
|
||||
y: shipheart_hauteur_bandeau_haut;
|
||||
width: (shipheart_largeur_page * (1 - pourcentage_largeur_colonne_gauche)) - (espace_colonnes_principales / 2)
|
||||
height: affichage_hauteur_utile;
|
||||
color: "transparent"
|
||||
|
||||
Image {
|
||||
source: "/images/logo_suncy_concept.png"
|
||||
sourceSize.height: parent.height * 0.2;
|
||||
// sourceSize.width: bandeau_bas_largeur_zone_status_connexions
|
||||
anchors.top: parent.top
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
|
||||
Text {
|
||||
id: texte_home_suncy_fr
|
||||
width: parent.width
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
wrapMode: Text.Wrap
|
||||
padding: 20
|
||||
font.pixelSize: 20
|
||||
|
||||
text: qsTr("L'accès au bateau est protégé.\nMerci d'entrer votre code de déverrouillage pour y accéder...")
|
||||
color: couleur_blanc_casse
|
||||
visible: true
|
||||
}
|
||||
|
||||
Text {
|
||||
id: texte_home_suncy_en
|
||||
width: parent.width
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
verticalCenterOffset: 100
|
||||
}
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
wrapMode: Text.Wrap
|
||||
padding: 20
|
||||
font.pixelSize: 20
|
||||
font.italic: true
|
||||
|
||||
text: "Ship access is restricted.\nPlease enter your unlocking code to proceed...";
|
||||
color: couleur_blanc_casse
|
||||
visible: true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------
|
||||
// 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
|
||||
}
|
||||
|
||||
|
||||
//===========================================================
|
||||
// Economiseur : Doit être placé en fin de page pour fonctionner
|
||||
//===========================================================
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
preventStealing: true // Permet que cela fonctionne même si un élément flickable (notamment) soit derrière et "vole" le click
|
||||
enabled: flag_economiseur_actif
|
||||
onClicked: {
|
||||
mise_en_veille(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================================================
|
||||
// Init de la page
|
||||
//=============================================================================================================
|
||||
function init_page()
|
||||
{
|
||||
var req, res
|
||||
|
||||
mise_en_veille(0);
|
||||
|
||||
activation_moteur(0); // Dans le doute, on coupe l'activation du moteur dès le démarrage
|
||||
|
||||
//console.log("Mode actuel : " + protection_mode);
|
||||
|
||||
// Coupure de tous les circuits par défaut :
|
||||
req = 'UPDATE TB_Circuits SET New_consigne="0" '
|
||||
bdd.requete_unique(req);
|
||||
|
||||
|
||||
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Code_client" ';
|
||||
res = bdd.requete_unique(req);
|
||||
shipheart_code_client = res[0];
|
||||
|
||||
req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Max_taille_code" ';
|
||||
res = bdd.requete_unique(req);
|
||||
if (Number(res[0]) >= max_taille_code_pattern) max_taille_code_pattern = Number(res[0]) + 2;
|
||||
|
||||
}
|
||||
|
||||
//=============================================================================================================
|
||||
// Déverrouillage
|
||||
//=============================================================================================================
|
||||
function deverrouillage()
|
||||
{
|
||||
var i;
|
||||
|
||||
//console.log("Le code est valide. La page est déverrouillée....")
|
||||
|
||||
if ((activation_moteur(100)) === -1) console.log("/!\ Aucune sortie valide d'activation du moteur a été trouvée")
|
||||
|
||||
code_saisi = "";
|
||||
stackView.push("home.qml");
|
||||
}
|
||||
|
||||
//=============================================================================================================
|
||||
// Vérification du code_saisi vs le code
|
||||
//=============================================================================================================
|
||||
function check_code()
|
||||
{
|
||||
var code_saisi_encrypte;
|
||||
|
||||
code_saisi_encrypte = bdd.sha256(code_saisi);
|
||||
//console.debug("Le code saisi est [" + code_saisi + "] et le code saisi encrypté est [" + code_saisi_encrypte + "]");
|
||||
|
||||
//console.debug("Le hash du code Client est [" + shipheart_code_client + "]");
|
||||
|
||||
if (shipheart_code_client.localeCompare(code_saisi_encrypte) === 0) return(0);
|
||||
else return(-1);
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================================================
|
||||
// Mise à jour du pattern
|
||||
//=============================================================================================================
|
||||
function mise_a_jour_pattern()
|
||||
{
|
||||
var longueur;
|
||||
var i;
|
||||
|
||||
longueur = code_saisi.length;
|
||||
if (longueur > max_taille_code_pattern) longueur = max_taille_code_pattern;
|
||||
|
||||
code_saisi_pattern = "";
|
||||
for (i=0; i<longueur; i++) code_saisi_pattern += '*';
|
||||
}
|
||||
|
||||
|
||||
//=====================================================================================
|
||||
// Fonctions : Recherche dans le tableau 'shipheart_specifique_client' le paramètre contenant
|
||||
// le n° de circuit à utiliser pour activer le moteur. Si le circuit existe,
|
||||
// envoi la consigne reçue comme nouvelle consigne du circuit.
|
||||
// Reçoit : La consigne (entre 0 et 100%)
|
||||
// Retour : 0 si Ok (un circuit a été trouvé) ou -1 si pas de circuit trouvé.
|
||||
//=====================================================================================
|
||||
function activation_moteur(consigne)
|
||||
{
|
||||
var i;
|
||||
var res;
|
||||
|
||||
if (consigne < 0) consigne = 0;
|
||||
if (consigne > 100) consigne = 100;
|
||||
|
||||
// Acivation du moteur si un numéro de circuit valide pour le faire existe :
|
||||
for (i = 1; i < shipheart_specifique_client.length; i ++) // Parcourt de tous les paramètres spécifiques au client (sauf le 1er qui est le n° de client et qui est déjà connu et testé)
|
||||
{
|
||||
var parametre = shipheart_specifique_client[i].split('='); // Séparation du nom du champ et de sa valeur
|
||||
if (parametre[0] === 'id_circuit_activation_moteur') // Si le paramètre en cours est bien celui concernant l'ID du circuit d'activation du moteur
|
||||
{
|
||||
bdd.requete_unique("UPDATE TB_Circuits SET New_consigne=" + consigne + " WHERE Cle_primaire='" + Number(parametre[1]) + "'")
|
||||
}
|
||||
}
|
||||
return (-1); // Cas où on n'a trouvé aucune sortie valide.
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
Executable
BIN
Binary file not shown.
|
After Width: | Height: | Size: 2.5 KiB |
Executable
BIN
Binary file not shown.
|
After Width: | Height: | Size: 2.6 KiB |
Executable
BIN
Binary file not shown.
|
After Width: | Height: | Size: 2.6 KiB |
Executable
BIN
Binary file not shown.
|
After Width: | Height: | Size: 2.5 KiB |
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user