commit 53e47729fb4bc5e7a65cd835b47786bbe9bb405f Author: Pierre Date: Thu Aug 13 09:19:38 2026 +0200 Import initial du projet shipheart_cm5 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..77ca5ac --- /dev/null +++ b/.gitignore @@ -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 +*~ diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..8ae7502 --- /dev/null +++ b/CMakeLists.txt @@ -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. diff --git a/Shipheart_boite_dialogue.qml b/Shipheart_boite_dialogue.qml new file mode 100755 index 0000000..712ed93 --- /dev/null +++ b/Shipheart_boite_dialogue.qml @@ -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 + } + } + } +} diff --git a/Shipheart_boite_dialogue_action_circuit.qml b/Shipheart_boite_dialogue_action_circuit.qml new file mode 100755 index 0000000..ff63cbc --- /dev/null +++ b/Shipheart_boite_dialogue_action_circuit.qml @@ -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 bascule") + 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 à ON s'il est OFF
ou à OFF s'il est ON]") + 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) ? "
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 + } + } + } +} diff --git a/Shipheart_boite_dialogue_affichage_duree.qml b/Shipheart_boite_dialogue_affichage_duree.qml new file mode 100644 index 0000000..f3a08bc --- /dev/null +++ b/Shipheart_boite_dialogue_affichage_duree.qml @@ -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. + } + + + +} diff --git a/Shipheart_boite_dialogue_condition_horaire.qml b/Shipheart_boite_dialogue_condition_horaire.qml new file mode 100755 index 0000000..d6d43a6 --- /dev/null +++ b/Shipheart_boite_dialogue_condition_horaire.qml @@ -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; + } + } + } + + + +} diff --git a/Shipheart_boite_dialogue_entrees_aux.qml b/Shipheart_boite_dialogue_entrees_aux.qml new file mode 100755 index 0000000..3c128bc --- /dev/null +++ b/Shipheart_boite_dialogue_entrees_aux.qml @@ -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 + } + } + } +} diff --git a/Shipheart_boite_dialogue_entrees_level_sensor.qml b/Shipheart_boite_dialogue_entrees_level_sensor.qml new file mode 100755 index 0000000..2668987 --- /dev/null +++ b/Shipheart_boite_dialogue_entrees_level_sensor.qml @@ -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 + } + } + } +} diff --git a/Shipheart_boite_dialogue_liste_alarmes.qml b/Shipheart_boite_dialogue_liste_alarmes.qml new file mode 100644 index 0000000..2c011f4 --- /dev/null +++ b/Shipheart_boite_dialogue_liste_alarmes.qml @@ -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: "" + model.nom_event + " [" + 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; + } + } + } + } + } + +} diff --git a/Shipheart_boite_dialogue_minuteur.qml b/Shipheart_boite_dialogue_minuteur.qml new file mode 100644 index 0000000..3d9d5d1 --- /dev/null +++ b/Shipheart_boite_dialogue_minuteur.qml @@ -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; + } + } + } + + + +} diff --git a/Shipheart_boite_dialogue_nettoyage_ecran.qml b/Shipheart_boite_dialogue_nettoyage_ecran.qml new file mode 100755 index 0000000..1522590 --- /dev/null +++ b/Shipheart_boite_dialogue_nettoyage_ecran.qml @@ -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.

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 + } + } + } +} + diff --git a/Shipheart_boite_dialogue_reveils.qml b/Shipheart_boite_dialogue_reveils.qml new file mode 100755 index 0000000..6ebf322 --- /dev/null +++ b/Shipheart_boite_dialogue_reveils.qml @@ -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); + } + +} diff --git a/Shipheart_boite_dialogue_validation_securisee.qml b/Shipheart_boite_dialogue_validation_securisee.qml new file mode 100755 index 0000000..7b18698 --- /dev/null +++ b/Shipheart_boite_dialogue_validation_securisee.qml @@ -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 + } + } + } +} diff --git a/Shipheart_bouton_batterie.qml b/Shipheart_bouton_batterie.qml new file mode 100644 index 0000000..5f3e475 --- /dev/null +++ b/Shipheart_bouton_batterie.qml @@ -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)) + } + } + +} diff --git a/Shipheart_bouton_capteur.qml b/Shipheart_bouton_capteur.qml new file mode 100644 index 0000000..931ebec --- /dev/null +++ b/Shipheart_bouton_capteur.qml @@ -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}) + } + } +} diff --git a/Shipheart_bouton_circuit.qml b/Shipheart_bouton_circuit.qml new file mode 100644 index 0000000..25d87be --- /dev/null +++ b/Shipheart_bouton_circuit.qml @@ -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... + } +} diff --git a/Shipheart_bouton_reservoir.qml b/Shipheart_bouton_reservoir.qml new file mode 100644 index 0000000..4d83860 --- /dev/null +++ b/Shipheart_bouton_reservoir.qml @@ -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)) + } + } +} diff --git a/Shipheart_busy_indicator.qml b/Shipheart_busy_indicator.qml new file mode 100755 index 0000000..51a015d --- /dev/null +++ b/Shipheart_busy_indicator.qml @@ -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 + } + ] + } + } + } + } +} diff --git a/Shipheart_formulaire_bouton.qml b/Shipheart_formulaire_bouton.qml new file mode 100644 index 0000000..8bdbb7a --- /dev/null +++ b/Shipheart_formulaire_bouton.qml @@ -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 + } + + +} diff --git a/Shipheart_formulaire_checkbox.qml b/Shipheart_formulaire_checkbox.qml new file mode 100644 index 0000000..56b6d65 --- /dev/null +++ b/Shipheart_formulaire_checkbox.qml @@ -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 + } + } + } +} diff --git a/Shipheart_formulaire_combobox.qml b/Shipheart_formulaire_combobox.qml new file mode 100755 index 0000000..e37dae4 --- /dev/null +++ b/Shipheart_formulaire_combobox.qml @@ -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 + } +} diff --git a/Shipheart_formulaire_combobox_icones.qml b/Shipheart_formulaire_combobox_icones.qml new file mode 100755 index 0000000..a0fd20c --- /dev/null +++ b/Shipheart_formulaire_combobox_icones.qml @@ -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 + } +} diff --git a/Shipheart_formulaire_label.qml b/Shipheart_formulaire_label.qml new file mode 100755 index 0000000..ecdcfa1 --- /dev/null +++ b/Shipheart_formulaire_label.qml @@ -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: "--" +} diff --git a/Shipheart_formulaire_ligne_separation.qml b/Shipheart_formulaire_ligne_separation.qml new file mode 100644 index 0000000..775e5c1 --- /dev/null +++ b/Shipheart_formulaire_ligne_separation.qml @@ -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 + } +} diff --git a/Shipheart_formulaire_textarea.qml b/Shipheart_formulaire_textarea.qml new file mode 100755 index 0000000..33762fc --- /dev/null +++ b/Shipheart_formulaire_textarea.qml @@ -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 + } + +} diff --git a/Shipheart_formulaire_textfield.qml b/Shipheart_formulaire_textfield.qml new file mode 100755 index 0000000..a4c5a60 --- /dev/null +++ b/Shipheart_formulaire_textfield.qml @@ -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 + "]"); + } + +} diff --git a/Shipheart_formulaire_unite.qml b/Shipheart_formulaire_unite.qml new file mode 100755 index 0000000..545aac1 --- /dev/null +++ b/Shipheart_formulaire_unite.qml @@ -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: "--" +} diff --git a/Shipheart_formulaire_valeur_fixe.qml b/Shipheart_formulaire_valeur_fixe.qml new file mode 100644 index 0000000..e5af5e2 --- /dev/null +++ b/Shipheart_formulaire_valeur_fixe.qml @@ -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: "--" +} diff --git a/Shipheart_page.qml b/Shipheart_page.qml new file mode 100755 index 0000000..d302a17 --- /dev/null +++ b/Shipheart_page.qml @@ -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 + "']"); + } +} diff --git a/Shipheart_titre_1.qml b/Shipheart_titre_1.qml new file mode 100644 index 0000000..4c12a09 --- /dev/null +++ b/Shipheart_titre_1.qml @@ -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 + } +} diff --git a/Shipheart_titre_2.qml b/Shipheart_titre_2.qml new file mode 100644 index 0000000..13ebdfa --- /dev/null +++ b/Shipheart_titre_2.qml @@ -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 !== "" + } + + +} + diff --git a/Shipheart_titre_3.qml b/Shipheart_titre_3.qml new file mode 100644 index 0000000..61758c4 --- /dev/null +++ b/Shipheart_titre_3.qml @@ -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 !== "" + } + + +} + diff --git a/backend.cpp b/backend.cpp new file mode 100644 index 0000000..3231b93 --- /dev/null +++ b/backend.cpp @@ -0,0 +1,38 @@ +#include "backend.h" + +#include +#include +#include +#include + +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("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("currentEngine"); + engine->retranslate(); + + qDebug() << "L'activation de la langue [" << lang << "] a été effectuée avec succès."; +} + diff --git a/backend.h b/backend.h new file mode 100755 index 0000000..ad2705f --- /dev/null +++ b/backend.h @@ -0,0 +1,20 @@ +#ifndef BACKEND_H +#define BACKEND_H + +#include +#include + +class Backend : public QObject +{ + Q_OBJECT +public: + Backend(); +// explicit Backend(QObject *parent = 0); + + + +public slots: + void change_langue(QString lang); +}; + +#endif // BACKEND_H diff --git a/batterie.qml b/batterie.qml new file mode 100644 index 0000000..9970441 --- /dev/null +++ b/batterie.qml @@ -0,0 +1,2000 @@ +import QtQuick 2.12 +import QtQuick.Controls 2.12 +import QtQuick.Layouts 1.12 +import QtCharts 2.3 + +import qt.koriolan.shipheart 1.0 +import"fonctions.js" as Fonctions +import"fonctions_date_heure.js" as Fonctions_date_heure + + +Shipheart_page { + id: page_conso_globale + + + // Mis en forme : + readonly property int espace_colonnes_secondaires: 10 + readonly property double pourcentage_hauteur_ligne_haut: 0.6 + readonly property int espace_lignes_principales: 20 + readonly property int espace_lignes_secondaires: 10 + readonly property int nombre_widgets_par_ligne: 4 + readonly property double pourcentage_largeur_graphique: 0.85 + readonly property int nb_boutons_periode: 4 + readonly property int largeur_bouton_suite: 15 + + readonly property int periode_init_raffraichissement_parametres: 1 // En ms ATtention : The Timer type is synchronized with the animation timer. Since the animation timer is usually set to 60fps, the resolution of Timer will be at best 16ms. + readonly property int periode_raffraichissement_parametres: 1000 // En ms + readonly property int periode_init_raffraichissement_graphiques: 1 // En ms + readonly property int periode_raffraichissement_graphiques: 15 * 1000 // en ms + + + // Affichage : + property int periode_analyse: 0 + + property bool courbe_flag_vide: false // Flag indiquant s'il y a des données à afficher ou pas + property int courbe_nombre_principal_graduations_axe_x: 13 + property int courbe_nombre_zoom_1_graduations_axe_x: 8 + property int courbe_nombre_graduations_axe_y: 5 + property string courbe_format_principal_axe_x: "HH:mm" // exemple : "yyyy-MM-dd HH:mm:ss" + property string courbe_format_zoom_1_axe_x: "HH:mm" // exemple : "yyyy-MM-dd HH:mm:ss" + + property bool flag_zoom_en_cours: false + property real zoomx_en_cours: 1 + + property date xMin_date + property date xMax_date + property real yMin_valeur: 0 + property real yMax_valeur: 1 + property int precision_affichage_axe_y_courbe: 1 + property string symbole_unite: "W" + + property int etat_systeme: 0 // Le '0' permet simplement d'aviter l'affichage du message d'erreur pendant un très court instant au démarrage + + + // Données : + property bool flag_init: true // Permet de bloquer certains affichage tant que l'init n'est pas terminée + + property int id_batterie: 0 + property int id_variable: 0 + property string nom: "" + property int nombre_cycles: 0 + property int nombre_decharges_completes: 0 + property int type_entrees: 0 + property string temperature: "" + property int temperature_id_variable: 0 + property string temperature_unite_variable: "" + property string tension: "" + property int tension_id_variable: 0 + property string tension_unite_variable: "" + property string courant_differentiel: "" + property int courant_differentiel_id_variable: 0 + property string courant_differentiel_unite_variable: "" + property string courant_charge: "" + property int courant_charge_id_variable: 0 + property string courant_charge_unite_variable: "" + property string courant_decharge:"" + property int courant_decharge_id_variable: 0 + property string courant_decharge_unite_variable: "" + property string puissance: "" + property int puissance_id_variable: 0 + property string puissance_unite_variable: "" + property string soh: "" + property int soh_id_variable: 0 + property string soh_unite_variable: "" + property string soc: "" + property int soc_id_variable: 0 + property string soc_unite_variable: "" + property string autonomie: "" + property int autonomie_id_variable: 0 + property string autonomie_unite_variable: "" + property string energie: "" + property int energie_id_variable: 0 + property string energie_unite_variable: "" + + property int id_variable_energie_circuit: 0 + property int id_variable_puissance_circuit: 0 + + property double pourcentage_maxi: 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 { + mise_a_jour_valeurs_instantanées(); + } + } + } + + //=========================================================== + // Timer periode raffraichissement graphiques : + //=========================================================== + Timer { + id: timer_raffraichissement_graphiques + interval: periode_raffraichissement_graphiques + triggeredOnStart: false + running: true + repeat: true + onTriggered: { + if (interval === periode_init_raffraichissement_graphiques) interval = periode_raffraichissement_graphiques; + + if (!flag_init) // La gestion du premier calcul des courbes est géré directement par 'init()' car le séquençage des 2 timers au démarrage n'est pas garanti !! + { + if (id_variable === 0) // Affichage du bilan d'énergie : + { + comparatif_conso_energie(); + } + else // Affichage d'une courbe spécifique : + { + if (!flag_zoom_en_cours) + { + mise_a_jour_courbes(); // On ne met pas à jour les courbes si on est en train de zoomer + mise_a_jour_valeur_energie(); // On utilise ce timer "lent" pour mettre à jour cette valeur qui évolue peu + } + } + } + } + } + + + // Titre de la page : + Shipheart_titre_1 {titre: nom; hauteur: shipheart_hauteur_bandeau_haut} + + + + //------------------------------------------------------- + // Ecran haut : + //------------------------------------------------------- + Rectangle { + id: zone_affichage_haut + x: 0 + y: shipheart_hauteur_bandeau_haut; + width: shipheart_largeur_page + height: (shipheart_hauteur_page - shipheart_hauteur_bandeau_haut - shipheart_hauteur_bandeau_bas - (2 * espace_lignes_principales)) * pourcentage_hauteur_ligne_haut; + color: "transparent" + visible: (etat_systeme === 0) + + //-------------------- + // Grille principale: + GridView { + id : grille_donnees_principale + + property int index_base_en_cours: 0 // Utilsé pour stocker l'index du premier widget affiché à gauche + + highlightRangeMode: GridView.StrictlyEnforceRange // Nécessaire pour que 'index_base_en_cours' soit mis à jour. Au passage, autorise de faire défiler les widgets jusqu'à ne garder que le dernier visible (pas génant et même plutôt sympa...) + width: parent.width - (2 * largeur_bouton_suite) + height: (type_entrees === shipheart_batteries_type_entrees_ibs) ? parent.height : (parent.height / 2) + cellWidth: width / nombre_widgets_par_ligne + cellHeight: (type_entrees === shipheart_batteries_type_entrees_ibs) ? (height / 2) : height + flow: GridView.FlowTopToBottom // Items are laid out from top to bottom, and the view scrolls horizontally + snapMode: GridView.SnapToRow // L'arret de l'affichage se fera sur une rangée entière + anchors.verticalCenter: parent.verticalCenter // Utile pour les batteries sans IBS (une seule ligne de widgets) + anchors.horizontalCenter: parent.horizontalCenter + clip: true // Nécessaire pour que les Delegates s'arretent à l'intérieur de la GridView + model: ListModel { } + + onMovementEnded: { + index_base_en_cours = currentIndex; // Capte la valeur de currentIndex aà la fin du mouvement (la valeur vaut alors l'index du widget le plus à gauche). Si on ne le capte pas, la valeur de CurrentIndex repasse à 0 après l'arrêt du flicker (pourquoi...???) +//console.log("index_base_en_cours = "+ index_base_en_cours) + } + + delegate: Rectangle { // Permet d'occuper toute la cellule de la grille + width: grille_donnees_principale.cellWidth + height: grille_donnees_principale.cellHeight + color: "transparent" + + Rectangle { // Permet d'avoir un bouton plus petit que la cellule de la grille et de le centrer sur la cellule (=> espace entre boutons) + width: parent.width - espace_colonnes_secondaires; + height: parent.height - espace_lignes_secondaires; + color: (id_variable === model.id_var) ? shipheart_couleur_fond_bouton_actif : shipheart_couleur_fond_bouton + radius: shipheart_rayon_bouton + anchors { + verticalCenter: parent.verticalCenter + horizontalCenter: parent.horizontalCenter + } + + //----------------------------------- + // Titre : + Text { + id: titre + text: model.titre + padding: 10 + font.pixelSize: 18 + color: couleur_blanc_casse + } + + //----------------------------------- + // Valeur courante : + Text { + id: valeur + text: model.valeur + anchors { + verticalCenter: parent.verticalCenter + horizontalCenter: parent.horizontalCenter + horizontalCenterOffset: soh_icone.visible ? 0 : -20 // Permet de garder l'ensemble 'valeur + unité) centré sans utiliser un conteneur spécial + } + font.family: "Montserrat" + font.pixelSize: 60 + font.weight: Font.Black + color: (model.etat <= 0) ? + ( ((model.type_couleur !== 0) && (model.valeur < 0)) ? + couleur_orange : + couleur_blanc_casse ) : + couleur_rouge + } + Text { + id: unite + text: model.unite + anchors { + baseline: valeur.baseline + left: valeur.right + } + leftPadding: 10 + font.pixelSize: 20 +// color: (model.etat === 0) ? couleur_blanc_casse : couleur_rouge + color: couleur_blanc_casse + } + + //----------------------------------- + // SOH : + Image { + id: soh_icone + source: (id_variable === model.id_var) ? "/images/soh.png" : "/images/soh_sombre.png" + sourceSize.width: 20 + anchors { + top: parent.top + topMargin: 50 + left: parent.left + leftMargin: 20 + } + visible: (type_entrees === shipheart_batteries_type_entrees_ibs) && flag_affichage_complementaire + } + Text { + id: soh_valeur + text: soh + "%" + anchors { + verticalCenter: soh_icone.verticalCenter + left: soh_icone.right + leftMargin: 5 + } + font.pixelSize: 10 + color: (id_variable === model.id_var) ? couleur_blanc_casse : couleur_gris_moyen + visible: soh_icone.visible + } + + //----------------------------------- + // Cycles : + Image { + id: cycles_icone + source: (id_variable === model.id_var) ? "/images/cycle_clair.png" : "/images/cycle_sombre.png" + sourceSize.width: soh_icone.sourceSize.width + anchors { + top: parent.top + topMargin: soh_icone.anchors.topMargin + 30 + left: parent.left + leftMargin: soh_icone.anchors.leftMargin + } + visible: (type_entrees === shipheart_batteries_type_entrees_ibs) && flag_affichage_complementaire + } + Text { + id: cycles_valeur + text: nombre_cycles + anchors { + verticalCenter: cycles_icone.verticalCenter + left: cycles_icone.right + leftMargin: soh_valeur.anchors.leftMargin + } + font.pixelSize: soh_valeur.font.pixelSize + color: (id_variable === model.id_var) ? couleur_blanc_casse : couleur_gris_moyen + visible: cycles_icone.visible + } + + //----------------------------------- + // Cycles : + Image { + id: decharges_completes_icone + source: (id_variable === model.id_var) ? "/images/cycle_100pc.png" : "/images/cycle_100pc_sombre.png" + sourceSize.width: soh_icone.sourceSize.width + anchors { + top: parent.top + topMargin: soh_icone.anchors.topMargin + 60 + left: parent.left + leftMargin: soh_icone.anchors.leftMargin + } + visible: (type_entrees === shipheart_batteries_type_entrees_ibs) && flag_affichage_complementaire + } + Text { + id: decharges_completes_valeur + text: nombre_decharges_completes + anchors { + verticalCenter: decharges_completes_icone.verticalCenter + left: decharges_completes_icone.right + leftMargin: soh_valeur.anchors.leftMargin + } + font.pixelSize: soh_valeur.font.pixelSize + color: (id_variable === model.id_var) ? couleur_blanc_casse : couleur_gris_moyen + visible: decharges_completes_icone.visible + } + + //----------------------------------- + // Zone de clic principale : + MouseArea{ + width: parent.width + height: parent.height - zone_alarmes.height + anchors { + left: parent.left + top: parent.top + } + + onClicked: { + shipheart_clic(); + raz_zoom(); // Au-delà de la fonctionnalité, c'est obligatoire sinon, le raffraichissement des la courbe est bloqué au niveau du timer + if (id_variable === model.id_var) id_variable = 0; + else + { + id_variable = model.id_var; + symbole_unite = model.unite; + } +console.log("ID Variable = " + id_variable) + busy_indicator.running = true; + timer_raffraichissement_graphiques.interval = periode_init_raffraichissement_graphiques; // Cela permet de lancer le "busy_indicator' avant de faire la mise à jour de la courbe + } + } + + //----------------------------------- + // Alarmes : + Rectangle { + id: zone_alarmes + width: parent.width + height: 50 + color: shipheart_couleur_fond_bouton + radius: shipheart_rayon_bouton + anchors { + left: parent.left + bottom: parent.bottom + } + visible: model.etat >= 0 + + Image { + source: (model.etat === 0) ? "/images/cloche_sombre.png" : "/images/cloche_rouge.png" + sourceSize.height: 20 + anchors { + verticalCenter: zone_alarmes.verticalCenter + horizontalCenter: zone_alarmes.horizontalCenter + } + } + + //----------------------------------- + // Zone de clics dédiée aux alarmes : + MouseArea{ + anchors.fill: zone_alarmes + + onClicked: { + shipheart_clic(); + boite_dialogue_liste_alarmes.id_variable = model.id_var; + boite_dialogue_liste_alarmes.titre_widget = model.titre; + boite_dialogue_liste_alarmes.unite = model.unite; + boite_dialogue_liste_alarmes.open(); + } + } + } + + + } + } + } // Fin de Gridview + + // Flèche de suite gauche : + Image { + anchors.verticalCenter: grille_donnees_principale.verticalCenter + anchors.right: grille_donnees_principale.left + source: "/images/fleche_suite_gauche_sombre.png" + width: largeur_bouton_suite + height: grille_donnees_principale.height - espace_lignes_secondaires + opacity: 0.5 + visible: (!grille_donnees_principale.moving) && // Permet de ne pas afficher la flèche pendant le mouvement (surtout génant à cause du lag généré par la fin du mouvement qui est assez lent). + (grille_donnees_principale.index_base_en_cours > 0) + } + + // Flèche de suite droite : + Image { + anchors.verticalCenter: grille_donnees_principale.verticalCenter + anchors.left: grille_donnees_principale.right + source: "/images/fleche_suite_droite_sombre.png" + width: largeur_bouton_suite + height: grille_donnees_principale.height - espace_lignes_secondaires + opacity: 0.5 + visible: (!grille_donnees_principale.moving) && // Permet de ne pas afficher la flèche pendant le mouvement (surtout génant à cause du lag généré par la fin du mouvement qui est assez lent). + ((grille_donnees_principale.count - grille_donnees_principale.index_base_en_cours) > (nombre_widgets_par_ligne * (grille_donnees_principale.height / grille_donnees_principale.cellHeight))) // le calcul 'height/cellheight' donne le nombre de lignes de widget (généralement, 1 ou 2) + } + + } + + + //------------------------------------------------------- + // Ecran bas : + //------------------------------------------------------- + Rectangle { + id: zone_affichage_bas + x: 0 + y: zone_affichage_haut.y + zone_affichage_haut.height + espace_lignes_principales; + width: shipheart_largeur_page; + height: (shipheart_hauteur_page - shipheart_hauteur_bandeau_haut - shipheart_hauteur_bandeau_bas - (2 * espace_lignes_principales)) * (1 - pourcentage_hauteur_ligne_haut) + 5; // +5 pour compenser margin-top du bandeau bas + color: "transparent" + visible: (etat_systeme === 0) + + //=================================== + // Comparatif consommation d'énergie + Rectangle { + id: zone_affichage_consommateurs + x: 0 + y: 0 + width: (parent.width * pourcentage_largeur_graphique) - espace_colonnes_secondaires; + height: parent.height + color: "transparent" + visible: (id_variable === 0) + + GridView { + id : grille_consommateurs + width: parent.width + height: parent.height + cellWidth: parent.width / 8 + cellHeight: parent.height + flow: GridView.FlowTopToBottom // Items are laid out from top to bottom, and the view scrolls horizontally + 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 { // Permet d'occuper toute la cellule de la grille + width: grille_consommateurs.cellWidth + height: grille_consommateurs.cellHeight + color: "transparent" + visible: !busy_indicator.running + + Rectangle { // Permet d'avoir un bouton plus petit que la cellule de la grille et de le centrer sur la cellule (=> espace entre boutons) + id: bouton_consommateur + width: parent.width - espace_colonnes_secondaires; + height: parent.height; + color: "transparent" + anchors { + verticalCenter: parent.verticalCenter + horizontalCenter: parent.horizontalCenter + } + + // Nom du circuit : + Text { + id: nom_consommateur + text: model.nom + width: parent.height - 75 // le '-75' permet de limiter le texte en partie haute. ATTENTION : la valeur influe sur le '60' ci-dessous ! Pourquoi ???? + height: parent.width + anchors { + bottom: parent.bottom // calage du texte en bas + bottomMargin: 60 // Permet de remonter le texte qui, sinon, part d'en-dessous du rectangle (provient de la rotation mais pas clair du pourquoi...!!!) + horizontalCenter: parent.horizontalCenter + horizontalCenterOffset: 20 // Petit espace à gauche + } + wrapMode: Text.Wrap + font.pixelSize: 15 + color: couleur_blanc_casse + rotation: 270 // Affichage vertical + } + + // Icone de circuit On : + Image { + source: (model.consigne !== 0) ? "/images/circuit_on.png" : "/images/icone_consommation_electrique.png" + sourceSize.width: 15 + opacity: (model.consigne !== 0) ? 1.0 : 0.2 + anchors { + bottom: parent.bottom + bottomMargin: 5 + horizontalCenter: parent.horizontalCenter + horizontalCenterOffset: -35 + } + rotation: 270 + } + + // Valeur d'énergie (yc unité) : + Text { + id: energie_consommateur + text: model.energie.toFixed(0) + " Wh" + anchors { + top: parent.top + topMargin: 5 + horizontalCenter: parent.horizontalCenter +// horizontalCenterOffset: 20 + } + font.weight: Font.Bold + font.pixelSize: 15 + color: couleur_blanc_casse + } + + // Pourcentage : + Text { + id: pourcentage + text: model.pourcentage.toFixed(2) + " %" + anchors { + top: energie_consommateur.bottom + topMargin: 5 + horizontalCenter: parent.horizontalCenter +// horizontalCenterOffset: 20 + } + font.weight: Font.Thin + font.pixelSize: 12 + color: couleur_blanc_casse + } + + // Bargraph : + Rectangle { + id: bargraph_consommateur + width: 40 +// height: (parent.height - 60) * model.pourcentage / (100 * pourcentage_maxi); + color: couleur_orange + radius: shipheart_rayon_bouton + anchors { + bottom: parent.bottom + horizontalCenter: parent.horizontalCenter + horizontalCenterOffset: 20 + } + PropertyAnimation on height { + to: (bouton_consommateur.height - 60) * model.pourcentage / (100 * pourcentage_maxi); // Le '-60' permet de laisser la place à l'énergie et au pourcentage + duration: 500; + } + } + + // Fond du bouton : + Rectangle { // Permet d'avoir un fond et de pouvoir régler son opacité sans changer celle des textes au-dessus +// width: parent.width +// height: parent.height + anchors.fill : parent + color: shipheart_couleur_fond_bouton + opacity: 0.5 + radius: shipheart_rayon_bouton + } + + //----------------------------------- + MouseArea{ + anchors.fill : parent + onClicked: { + shipheart_clic(); + stackView.push("circuit.qml", {"id_circuit": model.id }) + + } + } + } + } + } + + Label { + anchors.fill: parent + horizontalAlignment: Qt.AlignHCenter + verticalAlignment: Qt.AlignVCenter + visible: grille_consommateurs.model.count === 0 + text: qsTr("Aucune consommation d'énergie sur cette période...") + color: couleur_gris_moyen + font.pixelSize: 15 + font.bold: true + wrapMode: Label.Wrap + } + } + + + + //=================================== + // Consommation d'énergie + Rectangle { + id: zone_affichage_energie + x: 0 + y: 0 + width: (parent.width * pourcentage_largeur_graphique) - espace_colonnes_secondaires; + height: parent.height + color: "transparent" + visible: (id_variable === energie_id_variable) + + + GridView { + id : grille_energie + width: parent.width + height: parent.height + cellWidth: parent.width / grille_energie.model.count + cellHeight: parent.height + flow: GridView.FlowTopToBottom // Items are laid out from top to bottom, and the view scrolls horizontally + 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 { // Permet d'occuper toute la cellule de la grille + id: barre_energie + width: grille_energie.cellWidth + height: grille_energie.cellHeight + color: "transparent" + visible: !busy_indicator.running + + // Valeur d'énergie (yc unité) : + Text { + id: valeur_energie + text: (model.valeur !== 0) ? model.valeur.toFixed(model.precision) : "--" + anchors { + top: parent.top + horizontalCenter: parent.horizontalCenter + } + font.weight: (model.hauteur === 1) ? Font.Bold : Font.Normal + font.pixelSize: 13 + color: (model.hauteur === 1) ? + (!flag_periode_en_cours ? couleur_orange : couleur_jaune_post_it) : + ((model.valeur !== 0) ? couleur_blanc_casse : couleur_gris_moyen) + } + Text { + id: unite_energie + text: model.unite + anchors { + top: valeur_energie.bottom + horizontalCenter: parent.horizontalCenter + } + font.pixelSize: 10 + color: (model.valeur !== 0) ? couleur_blanc_casse : couleur_gris_moyen + } + // Bargraph : + Rectangle { + width: model.largeur + color: !flag_periode_en_cours ? couleur_orange : couleur_jaune_post_it + radius: shipheart_rayon_bouton + anchors { + bottom: parent.bottom + bottomMargin: 20 + horizontalCenter: parent.horizontalCenter + } + PropertyAnimation on height { + to: (barre_energie.height - 70) * model.hauteur; // Le '-60' permet de laisser la place à l'énergie et au pourcentage + duration: 500; + } + } + // Date de début principale : + Text { + text: model.debut_principal + anchors { + bottom: parent.bottom + horizontalCenter: parent.horizontalCenter + } + font.pixelSize: 12 + font.weight: Font.Bold + color: couleur_blanc_casse + } + // Date de début secondaire : + Text { + text: model.debut_secondaire + anchors { + bottom: parent.bottom + horizontalCenter: parent.horizontalCenter + } + font.pixelSize: 10 + color: couleur_blanc_casse + } + } + } + + Label { + anchors.fill: parent + horizontalAlignment: Qt.AlignHCenter + verticalAlignment: Qt.AlignVCenter + visible: grille_energie.model.count === 0 + text: qsTr("Aucune consommation d'énergie sur cette période...") + color: couleur_gris_moyen + font.pixelSize: 15 + font.bold: true + wrapMode: Label.Wrap + } + } + + + + //======================== + // Graphique : + ChartView { + id: graphique + antialiasing: true + anchors { + top: parent.top; + left:parent.left; + bottom:parent.bottom; + margins: -15 // Un peu compliqué mais permet, avec la ligne suivante, ... + } + margins { right: 0; bottom: 0; left: 5; top: 0 } // ... d'annuler les marges. + width: parent.width * pourcentage_largeur_graphique; + backgroundColor: "transparent" + // animationDuration: 10000 + // animationOptions: ChartView.SeriesAnimations + legend {visible: false } + visible: (id_variable !== energie_id_variable) && (id_variable !== 0) + + DateTimeAxis { + id: axisX + format: (zoomx_en_cours > 0.5) ? courbe_format_principal_axe_x : courbe_format_zoom_1_axe_x + min: xMin_date + max: xMax_date + tickCount: (zoomx_en_cours > 0.5) ? courbe_nombre_principal_graduations_axe_x : courbe_nombre_zoom_1_graduations_axe_x + //labelsColor: (!flag_zoom_en_cours) ? couleur_blanc_casse : couleur_green_yellow + labelsColor: couleur_blanc_casse + labelsFont: Qt.font({pointSize: 10}) + color: couleur_gris_moyen + shadesColor: courbes_couleur_shades_fond + shadesVisible: true + gridVisible: false + // gridLineColor: "green" + } + ValueAxis { + id: axisY1 + min: yMin_valeur + max: yMax_valeur + tickCount: courbe_nombre_graduations_axe_y + labelFormat: "%." + precision_affichage_axe_y_courbe + "f" +// labelsColor: (!flag_zoom_en_cours) ? couleur_blanc_casse : couleur_green_yellow + labelsColor: couleur_blanc_casse + labelsFont:Qt.font({pointSize: 10}) + color: couleur_gris_moyen + // shadesColor: courbes_couleur_shades_fond + shadesVisible: false + gridVisible: true + gridLineColor: couleur_gris_tres_fonce + titleText: "" + symbole_unite + "" + titleFont { + pointSize: 20 + bold: true + } + } + LineSeries { // Utilisé si on veut renforcer la courbe mais sans avoir tout le tour de l'area renfocée (qui se fait dans AreaSeries pour le coup) + id: courbe_principale + name: "Courbe principale" + axisX: axisX + axisY: axisY1 + capStyle: Qt.RoundCap + style: Qt.SolidLine + width: courbes_epaisseur_bordure + color: shipheart_couleur_bordure_courbes + + } + Text { + id: texte_courbe_vide + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + text: qsTr("Aucune donnée n'est disponible pour cette période") + font.pixelSize: 20 + font.weight: Font.Bold + color: "red" + visible: courbe_flag_vide ? true : false; + } + + //--------------------------------- + // Rectangle de sélection de zoom : + Rectangle { + id: rectangle_zoom + x: pinch_area.zoom_x + y: pinch_area.zoom_y + width: pinch_area.zoom_w + height: pinch_area.zoom_h + radius: shipheart_rayon_zoom + + color: couleur_bleu_koriolan_tres_transparent + } + + //--------------------------------- + // Zone de pinch : + PinchArea{ + id: pinch_area + + // Propriété de la eone de zoom pendant toute la phase de sélection : + property real zoom_x: 0 + property real zoom_y: 0 + property real zoom_w: 0 + property real zoom_h: 0 + + anchors.fill: parent // Calé sur 'graphique'. + // Attention : la zone de traçage à l'intérieur de 'graphique' est 'graphique.plotArea'. + // Toutes les coordonnées sont données dans 'graphique' mais on limite à l'usage les coordonnées intérieures à 'graphique.plotArea'. + + //----------------------------------------------- + // Mis à jour en cours de déplacement du pinch : + onPinchUpdated: { + + if ((pinch.point1.x !== pinch.point2.x) || // Il arrive, en fin de pinch, que les 2 points renvoyés soient les mêmes... + (pinch.point1.y !== pinch.point2.y)) // ... Il faut éviter de les traiter sous peine de ramener W et H à 0. + { + // Récupération des données en s'affranchissant de la position des 2 points : + zoom_x = Math.min(pinch.point1.x, pinch.point2.x) + zoom_y = Math.min(pinch.point1.y, pinch.point2.y) + zoom_w = Math.abs(pinch.point1.x - pinch.point2.x) + zoom_h = Math.abs(pinch.point1.y - pinch.point2.y) + + // Limitation de 'x' et 'w' à la largeur de la zone de traçage : + if (zoom_x < graphique.plotArea.x) zoom_x = graphique.plotArea.x; + if (zoom_x > (graphique.plotArea.x + graphique.plotArea.width)) zoom_x = graphique.plotArea.x + graphique.plotArea.width + if ((zoom_x + zoom_w) > (graphique.plotArea.x + graphique.plotArea.width)) zoom_w = (graphique.plotArea.x + graphique.plotArea.width) - zoom_x; + + // Limitation de 'y' et 'h' à la hauteur de la zone de traçage : + if (zoom_y < graphique.plotArea.y) zoom_y = graphique.plotArea.y; + if (zoom_y > (graphique.plotArea.y + graphique.plotArea.height)) zoom_y = graphique.plotArea.y + graphique.plotArea.height + if ((zoom_y + zoom_h) > (graphique.plotArea.y + graphique.plotArea.height)) zoom_h = (graphique.plotArea.y + graphique.plotArea.height) - zoom_y; + } + } + + //------------------------- + // Valeur de fin du pinch : + onPinchFinished: { + // Préparation du zoom sur le rectangle sélectionné : + var r = Qt.rect(zoom_x, zoom_y, zoom_w, zoom_h); + graphique.zoomIn(r); + flag_zoom_en_cours = true; + + zoomx_en_cours *= (zoom_w / graphique.plotArea.width); + + // Effacement du rectangle : + zoom_x = 0 + zoom_y = 0 + zoom_w = 0 + zoom_h = 0 + } + + // Déplacement de la courbe : + MouseArea{ + anchors.fill: parent + drag.target: dragTarget + drag.axis: Drag.XAndYAxis + onClicked: { + shipheart_clic(); + if (!flag_zoom_en_cours) // Si le zoom est en cours, il ne faut PAS lancer le raffraichissement...! + { + busy_indicator.running = true; + timer_raffraichissement_graphiques.interval = periode_init_raffraichissement_graphiques; // Cela permet de lancer le "busy_indicator' avant de faire la mise à jour de la courbe + } + } + onPressAndHold: { + raz_zoom(); + } + } + Item { + id: dragTarget + property real oldX : x // Permet de mémoriser la dernière position d'arrivée + property real oldY : y + + property real cumulX : 0 // Permet de revenir à un déclage nul lorsque nécessaire + property real cumulY : 0 + + onXChanged: { + graphique.scrollLeft( x - oldX ); + cumulX -= (x - oldX); // Le signe '-' permettra ensuite de revenir à le position de départ + oldX = x; + } + + onYChanged: { + graphique.scrollUp( y - oldY ); + cumulY -= (y - oldY); // Le signe '-' permettra ensuite de revenir à le position de départ + oldY = y; + } + } + } + } + + //======================== + // Busy Indicator : + Shipheart_busy_indicator { + id: busy_indicator + } + + //======================== + // Boutons de pếriode : + ColumnLayout { + spacing: 10 + anchors { + top: parent.top; + right:parent.right; + rightMargin: 5; + bottom:parent.bottom; + } + width: (parent.width * (1 - pourcentage_largeur_graphique)) - anchors.rightMargin; + + ListModel { + id: modele_periodes_graphique + } + + Repeater { + model: modele_periodes_graphique + + Rectangle { + color: "transparent" + Layout.preferredWidth: parent.width; + Layout.preferredHeight: (parent.height / nb_boutons_periode) - parent.spacing; + + Text { + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + text: model.libelle + font.pixelSize: 18 + font.weight: (model.index === periode_analyse) ? Font.Bold : Font.Normal + color: couleur_blanc_casse + } + 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 + onClicked: { + shipheart_clic(); + raz_zoom(); // Au-delà de la fonctionnalité, c'est obligatoire sinon, le raffraichissement des la courbe est bloqué au niveau du timer + periode_analyse = model.index; + busy_indicator.running = true; + mise_a_jour_valeur_energie(); // Permet que la mise à jour du widget soit quasi instantanée après l'appui. + timer_raffraichissement_graphiques.interval = periode_init_raffraichissement_graphiques; // Cela permet de lancer le "busy_indicator' avant de faire la mise à jour de la courbe + } + } + // Fond du bouton : + Rectangle { // Permet d'avoir un fond et de pouvoir régler son opacité sans changer celle des textes au-dessus + width: parent.width + height: parent.height + color: (model.index === periode_analyse) ? (flag_zoom_en_cours ? couleur_green_yellow_transparent : shipheart_couleur_fond_bouton_actif) : shipheart_couleur_fond_bouton; + opacity: 0.5 + radius: shipheart_rayon_bouton + } + } + } + } + } + + //------------------------------------------------------- + // Message d'erreur si batterie Absente + // (le module sur lequel la batterie est configurée n'est pas physiquement présent) + //------------------------------------------------------- + Rectangle { + id: zone_message_absence + x: 0 + y: shipheart_hauteur_bandeau_haut + espace_lignes_principales + width: shipheart_largeur_page + height: shipheart_hauteur_page - shipheart_hauteur_bandeau_haut - shipheart_hauteur_bandeau_bas - espace_lignes_principales + color: "transparent" + visible: (etat_systeme !== 0) + + Rectangle { // Rectangle entouré de rouge + anchors.verticalCenter: parent.verticalCenter + anchors.verticalCenterOffset: -50 + anchors.horizontalCenter: parent.horizontalCenter + width: parent.width + height: parent.height / 2 + radius: shipheart_rayon_bouton + border.width: 3 + border.color: couleur_rouge + color: couleur_rouge_transparent//"transparent" + + Image { // Pictogramme DANGER + anchors.verticalCenter: parent.verticalCenter + anchors.verticalCenterOffset: -100 + anchors.horizontalCenter: parent.horizontalCenter + source: "/images/ak14.png" + sourceSize.height: 70; + } + + Text { // Texte d'info + anchors.verticalCenter: parent.verticalCenter + anchors.verticalCenterOffset: 50 + anchors.horizontalCenter: parent.horizontalCenter + width: parent.width + height : parent.height / 2 + horizontalAlignment: Qt.AlignCenter + verticalAlignment: Qt.AlignVCenter + padding: 50 + text: qsTr("Le module assurant la supervision de cette batterie n'est pas accessible !

Si des ajouts/suppression/déplacements de modules ont eu lieu récemment, mettez à jour la configuration correspondant dans le menu MODULES de PARAMETRES AVANCES.

Dans le cas où aucune modification n'a été effectuée récemment, vérifier les connexions de tous les modules.") + color: couleur_blanc_casse + font.pixelSize: 18 + wrapMode: Label.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: 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() + } + } + } + } + + + //------------------------------------------------------- + // Boite d'affichage de la liste des alarmes : + //------------------------------------------------------- + Shipheart_boite_dialogue_liste_alarmes { + id: boite_dialogue_liste_alarmes + + titre: nom + type_source: shipheart_source_mesure_batterie + id_source: id_batterie + } + + //=========================================================== + // 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; + + id_variable = 0; // Par défaut, on affiche le comparatif d'énergie + + //==================================================================== + // Init du nom des périodes du graphique : + modele_periodes_graphique.append({ "libelle": Fonctions_date_heure.nom_periode_analyse(0), "actif": true }); + modele_periodes_graphique.append({ "libelle": Fonctions_date_heure.nom_periode_analyse(1), "actif": true }); + modele_periodes_graphique.append({ "libelle": Fonctions_date_heure.nom_periode_analyse(2), "actif": true }); + modele_periodes_graphique.append({ "libelle": Fonctions_date_heure.nom_periode_analyse(3), "actif": true }); + + //==================================================================== + // Lecture des infos générales concernant la batterie : + req = 'SELECT Nom, Type_entrees FROM TB_Batteries WHERE Cle_primaire="' + id_batterie + '" '; + res = bdd.requete_unique(req); + nom = res[0]; + type_entrees = Number(res[1]); + + //==================================================================== + // Recherche de ID_Variable_puissance_circuit : + req = ' SELECT Cle_primaire FROM TB_Variables WHERE Code="' + shipheart_circuit_puissance + '" '; + res = bdd.requete_unique(req); + id_variable_puissance_circuit = Number(res[0]); +//console.log("ID_Variable_puissance_circuit = " + id_variable_puissance_circuit + " "); + + //==================================================================== + // Recherche de ID_Variable_energie_circuit : + req = ' SELECT Cle_primaire FROM TB_Variables WHERE Code="' + shipheart_circuit_energie + '" '; + res = bdd.requete_unique(req); + id_variable_energie_circuit = Number(res[0]); +//console.log("ID_Variable_energie_circuit = " + id_variable_energie_circuit + " "); + + //==================================================================== + // Recherche des ID_Variable batterie : + req = ' SELECT Code, Cle_primaire, Unite FROM TB_Variables WHERE Code LIKE "%Batt_%" '; + nb = bdd.requete(req); + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + switch(res[0]) + { + case shipheart_batterie_temperature: + temperature_id_variable = Number(res[1]); + temperature_unite_variable = res[2]; + break; + case shipheart_batterie_tension: + tension_id_variable = Number(res[1]); + tension_unite_variable = res[2]; + break; + case shipheart_batterie_courant_differentiel: + courant_differentiel_id_variable = Number(res[1]); + courant_differentiel_unite_variable = res[2]; + break; + case shipheart_batterie_courant_charge: + courant_charge_id_variable = Number(res[1]); + courant_charge_unite_variable = res[2]; + break; + case shipheart_batterie_courant_decharge: + courant_decharge_id_variable = Number(res[1]); + courant_decharge_unite_variable = res[2]; + break; + case shipheart_batterie_soh: + soh_id_variable = Number(res[1]); + soh_unite_variable = res[2]; + break; + case shipheart_batterie_soc: + soc_id_variable = Number(res[1]); + soc_unite_variable = res[2]; + break; + case shipheart_batterie_autonomie: + autonomie_id_variable = Number(res[1]); + autonomie_unite_variable = res[2]; + break; + case shipheart_batterie_puissance: + puissance_id_variable = Number(res[1]); + puissance_unite_variable = res[2]; + break; + case shipheart_batterie_energie: + energie_id_variable = Number(res[1]); + energie_unite_variable = res[2]; + break; + default: + break; + } + } + else break; // Ne devrait pas arriver.... + } + + //==================================================================== + // Mise à jour intiale : + mise_a_jour_valeurs_instantanées(); + mise_a_jour_valeur_energie(); + + if (id_variable === 0) comparatif_conso_energie(); + else mise_a_jour_courbes(); + + + + flag_init = false; // Libération du flag + } + + + //============================================================================================================= + // Mise à jour de la valeur instantanée + //============================================================================================================= + function mise_a_jour_valeurs_instantanées() + { + var req, res; + var nb; + var i; + var valeur; + + // Requete : + req = 'SELECT '; + req += ' Etat_systeme, '; + req += ' Nombre_cycles, '; + req += ' Nombre_decharges_completes, '; + req += ' Temperature, '; + req += ' Tension, '; + req += ' Courant_differentiel, '; + req += ' Courant_charge, '; + req += ' Courant_decharge, '; + req += ' Tension * Courant_decharge, '; // Puissance consommée + req += ' Soh, '; + req += ' Soc, '; + req += ' Autonomie '; + req += ' FROM TB_Batteries WHERE Cle_primaire="' + id_batterie + '" '; +//console.log("Requête = [ " + req + "; ]"); + res = bdd.requete_unique(req); + + // Récupération des données : + i = 0; + etat_systeme = Number(res[i++]); + nombre_cycles = Number(res[i++]).toFixed(0); + nombre_decharges_completes = Number(res[i++]).toFixed(0); + temperature = Number(res[i++]).toFixed(1); + tension = Number(res[i++]).toFixed(2); + courant_differentiel = Number(res[i++]).toFixed(1); + courant_charge = Number(res[i++]).toFixed(1); + courant_decharge = Number(res[i++]).toFixed(1); + + valeur = Number(res[i++]); + if (Math.abs(valeur) > 99.90) puissance = valeur.toFixed(0); // Le seuil de 99.90 permet que 99.91 qui est affiché 100 soit affiché '100%' et non '100.0%' (valable pour 99.92 et jusqu'à 99.99....) + else puissance = valeur.toFixed(1); + + valeur = Number(res[i++]); + if (valeur > 99.90) soh = valeur.toFixed(0); // Le seuil de 99.90 permet que 99.91 qui est affiché 100 soit affiché '100%' et non '100.0%' (valable pour 99.92 et jusqu'à 99.99....) + else soh = valeur.toFixed(1); + + valeur = Number(res[i++]); + if (valeur > 99.90) soc = valeur.toFixed(0); // Le seuil de 99.90 permet que 99.91 qui est affiché 100 soit affiché '100%' et non '100.0%' (valable pour 99.92 et jusqu'à 99.99....) + else soc = valeur.toFixed(1); + + autonomie = Number(res[i++]).toFixed(1); + + + + // Recherche des éventuelles alarmes provenant des évènements : + var temperature_etat = -1; + var tension_etat = -1; + var courant_differentiel_etat = -1; + var courant_charge_etat = -1; + var courant_decharge_etat = -1; + var soh_etat = -1; + var soc_etat = -1; + var autonomie_etat = -1; + var puissance_etat = -1; + var energie_etat = -1; + + req = 'SELECT ID_Variable, Etat_test '; + req += ' FROM TB_Events '; + req += ' WHERE Validite=1 '; + req += ' AND Alarme_source>0 '; + req += ' AND Type_source=' + shipheart_source_mesure_batterie + ' '; + req += ' AND ID_Source=' + id_batterie + ' '; +//console.log("Requête = [ " + req + "; ]"); + nb = bdd.requete(req); + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + switch(Number(res[0])) + { + case temperature_id_variable: + if (temperature_etat < Number(res[1])) temperature_etat = Number(res[1]); + break; + case tension_id_variable: + if (tension_etat < Number(res[1])) tension_etat = Number(res[1]); + break; + case courant_differentiel_id_variable: + if (courant_differentiel_etat < Number(res[1])) courant_differentiel_etat = Number(res[1]); + break; + case courant_charge_id_variable: + if (courant_charge_etat < Number(res[1])) courant_charge_etat = Number(res[1]); + break; + case courant_decharge_id_variable: + if (courant_decharge_etat < Number(res[1])) courant_decharge_etat = Number(res[1]); + break; + case soh_id_variable: + if (soh_etat < Number(res[1])) soh_etat = Number(res[1]); + break; + case soc_id_variable: + if (soc_etat < Number(res[1])) soc_etat = Number(res[1]); + break; + case autonomie_id_variable: + if (autonomie_etat < Number(res[1])) autonomie_etat = Number(res[1]); + break; + case puissance_id_variable: + if (puissance_etat < Number(res[1])) puissance_etat = Number(res[1]); + break; + case energie_id_variable: + if (energie_etat < Number(res[1])) energie_etat = Number(res[1]); + break; + default: + break; + } + } + } + + + // Mise à jour du modèle de la grille principale : + grille_donnees_principale.model.clear(); + + grille_donnees_principale.model.append({ + "titre": Fonctions.nom_variable("Batt_soc"), + "id_var":soc_id_variable, + "valeur": soc, + "unite": soc_unite_variable, + "etat": soc_etat, + "type_couleur": 0, + "flag_affichage_complementaire": true }) + grille_donnees_principale.model.append({ + "titre": Fonctions.nom_variable("Batt_tension"), + "id_var":tension_id_variable, + "valeur": tension, + "unite": tension_unite_variable, + "etat": tension_etat, + "type_couleur": 0, + "flag_affichage_complementaire": false }) + + if (type_entrees === shipheart_batteries_type_entrees_ibs) + { + grille_donnees_principale.model.append({ + "titre": Fonctions.nom_variable("Batt_courant_differentiel"), + "id_var":courant_differentiel_id_variable, + "valeur": courant_differentiel, + "unite": courant_differentiel_unite_variable, + "etat": courant_differentiel_etat, + "type_couleur": 1, + "flag_affichage_complementaire": false }) + grille_donnees_principale.model.append({ + "titre": Fonctions.nom_variable("Batt_puissance"), + "id_var":puissance_id_variable, + "valeur": puissance, + "unite": puissance_unite_variable, + "etat": puissance_etat, + "type_couleur": 0, + "flag_affichage_complementaire": false }) + + grille_donnees_principale.model.append({ + "titre": Fonctions.nom_variable("Batt_courant_charge"), + "id_var":courant_charge_id_variable, + "valeur": courant_charge, + "unite": courant_charge_unite_variable, + "etat": courant_charge_etat, + "type_couleur": 0, + "flag_affichage_complementaire": false }) + grille_donnees_principale.model.append({ + "titre": Fonctions.nom_variable("Batt_courant_decharge"), + "id_var":courant_decharge_id_variable, + "valeur": courant_decharge, + "unite": courant_decharge_unite_variable, + "etat": courant_decharge_etat, + "type_couleur": 0, + "flag_affichage_complementaire": false }) + + grille_donnees_principale.model.append({ + "titre": Fonctions.nom_variable("Batt_temperature"), + "id_var":temperature_id_variable, + "valeur": temperature, + "unite": temperature_unite_variable, + "etat": temperature_etat, + "type_couleur": 0, + "flag_affichage_complementaire": false }) + grille_donnees_principale.model.append({ + "titre": Fonctions.nom_variable("Batt_energie"), + "id_var":energie_id_variable, + "valeur": energie, + "unite": energie_unite_variable, + "etat": energie_etat, + "type_couleur": 0, + "flag_affichage_complementaire": false }) + } + } + + + //============================================================================================================= + // Mise à jour de la valeur globale de l'énergie consommée sur la période en cours + //============================================================================================================= + function mise_a_jour_valeur_energie() + { + var req, res; + var i; + var date_debut, date_fin; + var type_mesure; + var total; + + +console.time('calcul_valeur_energie') + + // Dates et durée : + date_fin = new Date(); // En UTC + date_debut = Fonctions_date_heure.date_add_secondes(date_fin, -(Fonctions_date_heure.duree_periode_analyse(periode_analyse))); // En UTC +//console.log("Date de début initiale UTC = " + date_debut + " et date de fin UTC = " + date_fin) + + // Ajustements à l'intervalle fini d'analyse : + var debut_fin = Fonctions_date_heure.ajustement_periode_analyse(periode_analyse, date_debut, date_fin, shipheart_fuseau_horaire, shipheart_heure_ete); + switch(periode_analyse) + { + default: + case 0: // 1 heure + type_mesure=3; + break; + case 1: // 24 heures + case 2: // 7 jours + case 3: // 30 jours + type_mesure=2; + break; + } + + // Requete : + req = ' SELECT'; + req += ' SUM(Valeur)'; + req += ' FROM TB_Mesures_circuits as tb_mes '; + req += ' WHERE tb_mes.Type=' + type_mesure + ' '; + req += ' AND tb_mes.ID_Variable=' + id_variable_energie_circuit + ' '; + req += ' AND tb_mes.ID IN '; + req += ' (SELECT Cle_primaire FROM TB_Circuits WHERE '; + req += ' Adresse_module IN '; + req += ' (SELECT Adresse_k_bus FROM TB_Modules_config WHERE '; + req += ' ID_Batterie=' + id_batterie + ' '; + req += ' AND (Type=' + shipheart_type_module_shipbase + ' OR Type=' + shipheart_type_module_shippower812 + ' OR Type=' + shipheart_type_module_shippower8DC + ') '; + req += ' ) '; + req += ' ) '; + req += ' AND tb_mes.Date>="' + Fonctions_date_heure.chaine_date_heure_bdd(debut_fin.debut) + '" '; + req += ' AND tb_mes.Date<="' + Fonctions_date_heure.chaine_date_heure_bdd(debut_fin.fin) + '" '; + req += ' ORDER BY tb_mes.Date '; +//console.log("Requête = [" + req + "]"); + res = bdd.requete_unique(req); + total = Number(res[0]); + + // Mise en forme du résultat : + energie_unite_variable = "Wh"; // Par défaut + if (total < 100) energie = total.toFixed(1); + else if (total < 1000) energie = total.toFixed(0); + else + { + total /= 1000; + energie_unite_variable = "kWh" + if (total < 10) energie = total.toFixed(1); + else energie = total.toFixed(0); + } + + // Mise à jour immédiate du modele (sinon, il faudra attendre mise_a_jour_valeurs_instantanées()) : + for (i = 0; i < grille_donnees_principale.model.count; i ++) + { + if (grille_donnees_principale.model.get(i).id_var === energie_id_variable) + { + grille_donnees_principale.model.setProperty(i, "valeur", energie); + grille_donnees_principale.model.setProperty(i, "unite", energie_unite_variable); + } + } + +console.timeEnd('calcul_valeur_energie') + } + + //============================================================================================================= + // Consommation d'énergie de la batterie entre dates + //============================================================================================================= + function conso_energie_intervalle(date_debut, date_fin) + { + var req, res; + var nb; + var i; + var id_circuits = []; + var chaine_date_debut = Fonctions_date_heure.chaine_date_heure_bdd(date_debut); + var chaine_date_fin = Fonctions_date_heure.chaine_date_heure_bdd(date_fin); + var energie; + + +//console.time('maj_energie'); + + energie = 0; + +// Ancienne requête très longue à cause de la sous-requete [SELECT ID, max(Date) AS date_prev FROM TB_Mesures_circuits WHERE ID_Variable=24 AND Date<="2024-02-05 05:00:00" GROUP BY ID ; ] +// qui prend près de 5 secondes sur une V2 chargée normalement. La solution créée en 02/2024 utilise le fait que la table des mesures est indexée sur Date et qu'une mesure d'energie +// sur un circuit est quasi instantanée. On est donc passé à lister les circuits concerné (1 requête) puis l'énegrie de chaque circuit sur l'intervalle (N requete) avec la somme de tous les résultats. +// La fonction qui prenait 5s donne un résultat strictement identique en 92ms... +// ATTENTION : cette ancienne requête n'a PAS été mise à jour lors de la suppression du champ 'TB_Circuits.Type_circuit'. + +/* req = 'SELECT (SUM(Duree * Puissance) / 3600) AS Energie '; // 3600 secondes. NB : la division a intérêt à être faite sur la somme (et non la somme des divisions...) + req += ' FROM ( '; + req += ' SELECT '; + req += ' IFNULL'; // Return the specified value IF the expression is NULL, otherwise return the expression ie on convertit les valeurs NULL en 0. + req += ' (mesures.Valeur, 0) as Puissance, '; // Contrairement aux calculs usuels d'intégrale, la forme de stockage des mesures ne nécessite de connaitre que la valeur du point de début d'intervalle. + req += ' ( UNIX_TIMESTAMP('; + req += ' COALESCE('; // Returns the first non-null value in a list + req += ' LEAST(LEAD(mesures.Date) OVER (PARTITION BY mesures.ID ORDER BY mesures.Date), "' + chaine_date_fin + '"),'; // "Plus petit" entre [date de la prochaine mesure] et [date de fin] ou NULL si l'un au moins est NULL (cas du dernier point de l'intervalle avec aucun point au-delà). + req += ' LEAD(mesures.Date) OVER (PARTITION BY mesures.ID ORDER BY mesures.Date),'; // Date de la prochaine mesure (qui peut être NULL si on est sur le dernier point et qu'aucun point ultérieur n'existe) + req += ' "' + chaine_date_fin + '")) '; // Date de fin qui est forcément non NULL... + req += ' - '; + req += ' UNIX_TIMESTAMP('; + req += ' GREATEST(mesures.Date, "' + chaine_date_debut + '"))'; // "Plus grand" entre [date de mesure] et [date de début]. NB : contrairement à la fin de la période, aucune de ces deux valeurs ne peut être nulle... + req += ' ) as Duree'; // en secondes, entre le point en cours (ou la date de début si on est sur le point "ajouté") et le point suivant (ou la date de fin si on est sur le dernier point de l'intervalle) + req += ' FROM ('; + req += ' (SELECT ID, Date, Valeur FROM TB_Mesures_circuits WHERE ID_Variable=' + id_variable_puissance_circuit + ' AND Date>="' + chaine_date_debut + '" AND Date<="' + chaine_date_fin + '") '; // Tous les points dans l'intervalle (y compris ceux avec la valeur NULL) + req += ' UNION '; + req += ' (SELECT tb_mes.ID, tb_mes.Date, tb_mes.Valeur'; // On ne peut malheureusement pas récupérer directement ces valeurs dans le SELECT suivant car le MAX l'en empêche... + req += ' FROM '; + req += ' TB_Mesures_circuits AS tb_mes, '; + req += ' (SELECT ID, max(Date) AS date_prev FROM TB_Mesures_circuits WHERE ID_Variable=' + id_variable_puissance_circuit + ' AND Date<="' + chaine_date_debut + '" GROUP BY ID) AS tb_prev '; // Renvoit pour chaque ID (via GROUP BY) la date la plus récente < date de début et l'ID correspondant. NB : la récup d'ID est possible à l'issue du GROUP BY mais pas les autres champs (qui varient) + req += ' WHERE tb_mes.ID=tb_prev.ID AND tb_mes.ID_Variable=' + id_variable_puissance_circuit + ' AND tb_mes.Date=tb_prev.date_prev)'; // Filtre pour récupérer un seul enregistrement par ID qui corresponde à la date la plus récente trouvée pour cet ID. Pour chaque ID, on a donc un point "ajouté" qui est le dernier point juste avant la période en cours (ou aucun point "ajouté" s'il n'y en pas avant pour cet ID !) + req += ' ) AS mesures '; + req += ' WHERE '; // On filtre les enregistrements concernant un circuit : + req += ' mesures.ID IN (SELECT Cle_primaire FROM TB_Circuits WHERE (Type_circuit=0 OR Type_circuit=1 OR Type_circuit=4) '; // ... affectés à un ShipBase, à un SP812 ou un SP8DC + req += ' AND '; + req += ' Adresse_module IN (SELECT Adresse_k_bus FROM TB_Modules_config WHERE ID_Batterie="' + id_batterie + '"))'; // ... lui-même (le module) affecté à la batterie en cours. NB : on ne filtre pas sur les modules "présents" car on considère que si le module a été retiré, on afffiche quand même l'historique + req += ' ) AS valeurs '; +//console.log("Requête = [" + req + "]"); + res = bdd.requete_unique(req); + energie = Number(res[0]); */ + + req = 'SELECT Cle_primaire FROM TB_Circuits WHERE '; + req += ' Adresse_module IN '; + req += ' (SELECT Adresse_k_bus FROM TB_Modules_config WHERE '; + req += ' ID_Batterie=' + id_batterie + ' '; + req += ' AND (Type=' + shipheart_type_module_shipbase + ' OR Type=' + shipheart_type_module_shippower812 + ' OR Type=' + shipheart_type_module_shippower8DC + ') )'; +//console.log("Requête = [" + req + "]"); + nb = bdd.requete(req); + + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + id_circuits.push(Number(res[0])); + } + else break; // Ne devrait pas arriver.... + } + + for (let i = 0; i < id_circuits.length; i++) + { +//console.log(" ID # " + i + " = " + id_circuits[i]); + + // NB : cette requete est la copie exacte de celle utilisée dans 'conso_energie_intervalle()' de 'circuit.qml'. Seul le nom des variables 'id_variable_puissance_circuit' et 'id_circuit' sont adaptées à cet environnement. + req = 'SELECT (SUM(Duree * Puissance) / 3600) AS Energie '; // 3600 secondes. NB : la division a intérêt à être faite sur la somme (et non la somme des divisions...) + req += ' FROM ( '; + req += ' SELECT '; + req += ' IFNULL'; // Return the specified value IF the expression is NULL, otherwise return the expression ie on convertit les valeurs NULL en 0. + req += ' (mesures.Valeur, 0) as Puissance, '; // Contrairement aux calculs usuels d'intégrale, la forme de stockage des mesures ne nécessite de connaitre que la valeur du point de début d'intervalle. + req += ' ( UNIX_TIMESTAMP('; + req += ' COALESCE('; // Returns the first non-null value in a list + req += ' LEAST(LEAD(mesures.Date) OVER (ORDER BY mesures.Date), "' + chaine_date_fin + '"),'; // "Plus petit" entre [date de la prochaine mesure] et [date de fin] ou NULL si l'un au moins est NULL (cas du dernier point de l'intervalle avec aucun point au-delà). + req += ' LEAD(mesures.Date) OVER (ORDER BY mesures.Date),'; // Date de la prochaine mesure (qui peut être NULL si on est sur le dernier point et qu'aucun point ultérieur n'existe) + req += ' "' + chaine_date_fin + '")) '; // Date de fin qui est forcément non NULL... + req += ' - '; + req += ' UNIX_TIMESTAMP('; + req += ' GREATEST(mesures.Date, "' + chaine_date_debut + '"))'; // "Plus grand" entre [date de mesure] et [date de début]. NB : contrairement à la fin de la période, aucune de ces deux valeurs ne peut être nulle... + req += ' ) as Duree'; // en secondes, entre le point en cours (ou la date de début si on est sur le point "ajouté") et le point suivant (ou la date de fin si on est sur le dernier point de l'intervalle) + req += ' FROM ('; + req += ' (SELECT Date, Valeur FROM TB_Mesures_circuits WHERE ID_Variable=' + id_variable_puissance_circuit + ' AND Date>="' + chaine_date_debut + '" AND Date<="' + chaine_date_fin + '" AND ID=' + id_circuits[i] + ') '; // Tous les points dans l'intervalle (y compris ceux avec la valeur NULL) + req += ' UNION '; + req += ' (SELECT Date, Valeur FROM TB_Mesures_circuits WHERE ID_Variable=' + id_variable_puissance_circuit + ' AND Date<="' + chaine_date_debut + '" AND ID=' + id_circuits[i] + ' ORDER BY Date DESC LIMIT 1) '; + req += ' ) AS mesures '; + req += ' ) AS valeurs '; +//console.log("Requête = [" + req + "]"); + res = bdd.requete_unique(req); + + energie += Number(res[0]); + } + +//console.log(" Energie = " + energie); + + +//console.timeEnd('maj_energie') + + return(energie); + } + + + //============================================================================================================= + // Mise à jour du comparatif de consommation d'énergie par circuits + //============================================================================================================= + function comparatif_conso_energie() + { + var req, res; + var nb; + var i; + var date_debut, date_fin; + var type_mesure; + var total; + + +//console.time('maj_energie') + + // Dates et durée : + date_fin = new Date(); // En UTC + date_debut = Fonctions_date_heure.date_add_secondes(date_fin, -(Fonctions_date_heure.duree_periode_analyse(periode_analyse))); // En UTC +//console.log("Date de début initiale UTC = " + date_debut + " et date de fin UTC = " + date_fin) + + // Ajustements à l'intervalle fini d'analyse : + var debut_fin = Fonctions_date_heure.ajustement_periode_analyse(periode_analyse, date_debut, date_fin, shipheart_fuseau_horaire, shipheart_heure_ete); + switch(periode_analyse) + { + default: + case 0: // 1 heure + type_mesure=3; + break; + case 1: // 24 heures + case 2: // 7 jours + case 3: // 30 jours + type_mesure=2; + break; + } + + // Requete : + req = 'SELECT ID, SUM(Valeur) AS Energie '; + req += ' FROM TB_Mesures_circuits AS tb_mes '; + req += ' WHERE tb_mes.Type=' + type_mesure + ' '; + req += ' AND tb_mes.ID_Variable=' + id_variable_energie_circuit + ' '; + req += ' AND tb_mes.ID IN '; + req += ' ( SELECT Cle_primaire FROM TB_Circuits WHERE '; + req += ' Adresse_module IN '; + req += ' (SELECT Adresse_k_bus FROM TB_Modules_config WHERE '; + req += ' ID_Batterie=' + id_batterie + ' '; + req += ' AND (Type=' + shipheart_type_module_shipbase + ' OR Type=' + shipheart_type_module_shippower812 + ' OR Type=' + shipheart_type_module_shippower8DC + ') )'; + req += ' ) '; + req += ' AND tb_mes.Date>="' + Fonctions_date_heure.chaine_date_heure_bdd(debut_fin.debut) + '" '; + req += ' AND tb_mes.Date<="' + Fonctions_date_heure.chaine_date_heure_bdd(debut_fin.fin) + '" '; + req += ' GROUP BY tb_mes.ID '; + req += ' ORDER BY Energie DESC; '; +//console.log("Requête = [" + req + "]"); + nb = bdd.requete(req); + + // Mise à jour du modèle, trié par ordre décroissant d'énergie consommée par la reqête : + total = 0; + var nb_consommateurs = 0; + + grille_consommateurs.model.clear(); + + //--------------------------------------------------- + // renseignerment de l'ID et de l'énergie consommée : + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + total += Number(res[1]); + nb_consommateurs ++; + grille_consommateurs.model.append({"id": Number(res[0]), "nom": "", "consigne": 0, "energie": Number(res[1]), "pourcentage": 0 }); + } + else break; // Ne devrait pas arriver.... + } + + //--------------------------------------------------- + // Mise à jour des autres informations du circuit : + // NB : on est obligé de faire cette mise à jour en deuxième passe car on doit dabord avoir le TOTAL calculé lors de la précédente... + if (total !== 0) + { + for(i = 0; i < nb_consommateurs; i++) + { + // Mise à jour du pourcentage maxi (afin de normaliser ensuite toutes les barres sur la plus grande) : + if (i === 0) pourcentage_maxi = grille_consommateurs.model.get(i).energie / total; + + // Sous-requête de recherche des infos sur le circuit : + req = 'SELECT Nom, Consigne from TB_Circuits WHERE Cle_primaire=' + grille_consommateurs.model.get(i).id + ' '; + res = bdd.requete_unique(req); + + // Mise à jour des informations dans le modèle : + grille_consommateurs.model.setProperty(i, "pourcentage", (grille_consommateurs.model.get(i).energie * 100 / total)); + grille_consommateurs.model.setProperty(i, "nom", res[0]); + grille_consommateurs.model.setProperty(i, "consigne", Number(res[1])); + } + } + else grille_consommateurs.model.clear(); // Si le total vaut 0Wh, on peut supprimer toutes les entrées car elles sont toutes nulles... + + + // Arrêt du sablier: + busy_indicator.running = false; + + +//console.timeEnd('maj_energie') + } + + + //============================================================================================================= + // Mise à jour des données des courbes + //============================================================================================================= + function mise_a_jour_courbes() + { + var req, res; + var nb; + var i; + var courbe_principale_duree; + var date_debut, date_fin; + var date_debut_intervalle, date_fin_intervalle; + var date_debut_intervalle_locale; + var mini_maxi; + var type_mesure; + var valeur; + var precision; + var unite; + var max; + var largeur_bargraph; + var texte_debut_principal; + var texte_debut_secondaire; + var regroupement; + + +console.time('mise_a_jour_courbes') + + + // Préparation des paramètres du graphique : + + courbe_principale_duree = Fonctions_date_heure.duree_periode_analyse(periode_analyse); // En secondes + date_fin = new Date(); // En UTC + date_debut = Fonctions_date_heure.date_add_secondes(date_fin, -(courbe_principale_duree)); // En UTC + + //======================================================= + // Barres d'énergie : + if (id_variable === energie_id_variable) + { + max = 0; + + grille_energie.model.clear(); + + // Ajustements à l'intervalle fini d'analyse : + var debut_fin = Fonctions_date_heure.ajustement_periode_analyse(periode_analyse, date_debut, date_fin, shipheart_fuseau_horaire, shipheart_heure_ete); + + switch(periode_analyse) + { + default: + case 0: // 1 heure + type_mesure=3; + courbe_nombre_principal_graduations_axe_x = 13; + largeur_bargraph = 40; + regroupement = "(1)"; + break; + + case 1: // 24 heures + type_mesure=2; + courbe_nombre_principal_graduations_axe_x = 25; + largeur_bargraph = 35; + regroupement = "(1)"; + break; + + case 2: // 7 jours + type_mesure=2; + courbe_nombre_principal_graduations_axe_x = 29; + largeur_bargraph = 30; + regroupement = "(6*60*60)"; + break; + + case 3: // 30 jours + type_mesure=2; + courbe_nombre_principal_graduations_axe_x = 31; + largeur_bargraph = 28; + regroupement = "(24*60*60)"; + break; + } + + // Recherche des data dans la BDD : + req = ' SELECT'; + req += ' SUM(Valeur),'; + req += ' MAX(Date)'; + req += ' FROM TB_Mesures_circuits as tb_mes '; + req += ' WHERE tb_mes.Type=' + type_mesure + ' '; + req += ' AND tb_mes.ID_Variable=' + id_variable_energie_circuit + ' '; + req += ' AND tb_mes.ID IN '; + req += ' ('; + req += ' SELECT Cle_primaire FROM TB_Circuits WHERE '; + req += ' Adresse_module IN '; + req += ' ('; + req += ' SELECT Adresse_k_bus FROM TB_Modules_config WHERE '; + req += ' ID_Batterie=' + id_batterie + ' '; + req += ' AND (Type=' + shipheart_type_module_shipbase + ' OR Type=' + shipheart_type_module_shippower812 + ' OR Type=' + shipheart_type_module_shippower8DC + ') '; + req += ' )'; + req += ' ) '; + req += ' AND tb_mes.Date>="' + Fonctions_date_heure.chaine_date_heure_bdd(debut_fin.debut) + '" '; + req += ' AND tb_mes.Date<="' + Fonctions_date_heure.chaine_date_heure_bdd(debut_fin.fin) + '" '; + req += ' GROUP BY (UNIX_TIMESTAMP(Date) - UNIX_TIMESTAMP("' + Fonctions_date_heure.chaine_date_heure_bdd(debut_fin.debut) + '")) DIV ' + regroupement + ' '; + req += ' ORDER BY tb_mes.Date '; +//console.log("Requête = [" + req + "]"); + nb = bdd.requete(req); + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + // Récupération des données de l'intervalle : + valeur = Number(res[0]); + date_fin_intervalle = Fonctions_date_heure.chaine_bdd_date_heure(res[1]); + date_debut_intervalle = Fonctions_date_heure.date_add_secondes(date_fin_intervalle, -((courbe_principale_duree / (courbe_nombre_principal_graduations_axe_x - 1)) - 1) ); + + // Calcul du 'max' (en Wh) : + if (max < valeur) max = valeur; + + // Ajout de l'intervale au modèle : + grille_energie.model.append({"debut_intervalle": date_debut_intervalle, "debut_principal": "", "debut_secondaire": "", "valeur": valeur, "precision": 0, "unite": "", "hauteur": 0.0, "largeur": largeur_bargraph, "flag_periode_en_cours": false }); + } + else break; // Ne devrait pas arriver.... + } + + //------------------------------------------------------------------------- + // Calcul de l'échantillon "période en cours" (qui se termine MAINTENANT) : + // NOTA : la ligne suivnte représente environ 200-250ms, soit 90% du temps total de traitement...! + valeur = conso_energie_intervalle(debut_fin.fin, date_fin); +//console.log("DERNIER INTERVALLE : Début intervalle UTC = " + debut_fin.fin + " et fin d'intervalle UTC = " + date_fin); + + // Calcul du 'max' (en Wh) avec le dernier intervalle : + if (max < valeur) max = valeur; + + // Ajout du dernier intervalle au modèle : + grille_energie.model.append({"debut_intervalle": debut_fin.fin, "debut_principal": "", "debut_secondaire": "", "valeur": valeur, "precision": 0, "unite": "", "hauteur": 0.0, "largeur": largeur_bargraph, "flag_periode_en_cours": true }); + + + //--------------------------------------------------- + // Mise à jour des autres informations du circuit : + // NB : on est obligé de faire cette mise à jour en deuxième passe car on doit d'abord avoir le MAX calculé lors de la précédente... + if (max > 0) + { + for(i = 0; i < grille_energie.model.count; i++) + { + // Récupéartion de la valeur brute de l'échantillon : + valeur = grille_energie.model.get(i).valeur; + + // Calcul de la hauteur de la barre : + // NB : à faire avant ajustement de la valeur en kWh !! + grille_energie.model.setProperty(i, "hauteur", (valeur / max)); + + // Calcul de l'unité et de la précision d'affichage en fonction de la valeur : + unite = "Wh"; // Par défaut + if (valeur < 100) precision = 1; + else if (valeur < 1000) precision = 0; + else + { + valeur /= 1000; + grille_energie.model.setProperty(i, "valeur", valeur); // Dans ce cas, il faut mettre à jour la valeur dans le modèle... + unite = "kWh" + if (valeur < 10) precision = 1; + else precision = 0; + } + grille_energie.model.setProperty(i, "precision", precision); + grille_energie.model.setProperty(i, "unite", unite); + + // Calcul des dates de début principales et secondaires de l'échantillon avec le format associé : + date_debut_intervalle = grille_energie.model.get(i).debut_intervalle; + date_debut_intervalle_locale = Fonctions_date_heure.date_courante(date_debut_intervalle, shipheart_fuseau_horaire, shipheart_heure_ete); + + // Détermination des légendes de temps : + switch(periode_analyse) + { + default: + case 0: // 1 heure + texte_debut_principal = Qt.formatDateTime(date_debut_intervalle_locale, "HH:mm"); + texte_debut_secondaire = ""; + break; + + case 1: // 24 heures + if (Math.trunc(date_debut_intervalle_locale.getHours() % 6) === 0) + { + texte_debut_principal = Qt.formatDateTime(date_debut_intervalle_locale, "HH:mm"); + texte_debut_secondaire = ""; + } + else + { + texte_debut_principal = ""; + texte_debut_secondaire = Qt.formatDateTime(date_debut_intervalle_locale, "HH:mm"); + } + break; + + case 2: // 7 jours + if (date_debut_intervalle_locale.getHours() === 0) + { + texte_debut_principal = Qt.formatDateTime(date_debut_intervalle_locale, "dd/MM"); + texte_debut_secondaire = ""; + } + else + { + texte_debut_principal = ""; + texte_debut_secondaire = Qt.formatDateTime(date_debut_intervalle_locale, "HH:mm"); + } + break; + + case 3: // 30 jours + texte_debut_principal = Qt.formatDateTime(date_debut_intervalle_locale, "dd"); + texte_debut_secondaire = ""; + break; + } + grille_energie.model.setProperty(i, "debut_principal", texte_debut_principal); + grille_energie.model.setProperty(i, "debut_secondaire", texte_debut_secondaire); + } + } + else grille_energie.model.clear(); // Si le MAX vaut 0Wh, on peut supprimer toutes les entrées car elles sont toutes nulles... + + } + + //======================================================= + // Courbes des variables (autre qu'énergie) : + else + { + + switch(periode_analyse) + { + default: + case 0: // 1 heure + courbe_nombre_principal_graduations_axe_x = 7 // Nombre de bandes verticales + 1 + courbe_nombre_zoom_1_graduations_axe_x = 7 // Utilisé lorsque le taux de zoom passe en-dessous de 0.5 + courbe_format_principal_axe_x = "HH:mm" // exemple : "yyyy-MM-dd HH:mm:ss" + courbe_format_zoom_1_axe_x = "HH:mm" // Utilisé lorsque le taux de zoom passe en-dessous de 0.5 + break; + + case 1: // 24 heures + courbe_nombre_principal_graduations_axe_x = 13 // Nombre de bandes verticales + 1 + courbe_nombre_zoom_1_graduations_axe_x = 13 // Utilisé lorsque le taux de zoom passe en-dessous de 0.5 + courbe_format_principal_axe_x = "HH:mm" // exemple : "yyyy-MM-dd HH:mm:ss" + courbe_format_zoom_1_axe_x = "HH:mm" // Utilisé lorsque le taux de zoom passe en-dessous de 0.5 + break; + + case 2: // 7 jours + courbe_nombre_principal_graduations_axe_x = 8 // Nombre de bandes verticales + 1 + courbe_nombre_zoom_1_graduations_axe_x = 8 // Utilisé lorsque le taux de zoom passe en-dessous de 0.5 + courbe_format_principal_axe_x = "dd/MM HH:mm" // exemple : "yyyy-MM-dd HH:mm:ss" + courbe_format_zoom_1_axe_x = "HH:mm" // Utilisé lorsque le taux de zoom passe en-dessous de 0.5 + break; + + case 3: // 30 jours + courbe_nombre_principal_graduations_axe_x = 31 // Nombre de bandes verticales + 1 + courbe_nombre_zoom_1_graduations_axe_x = 13 // Utilisé lorsque le taux de zoom passe en-dessous de 0.5 + courbe_format_principal_axe_x = "dd" // exemple : "yyyy-MM-dd HH:mm:ss" + courbe_format_zoom_1_axe_x = "HH:mm" // Utilisé lorsque le taux de zoom passe en-dessous de 0.5 + break; + } + + // Mise à jour des données de la courbe principale : + res = tbmesuresModel.maj_data(graphique.series("Courbe principale"), "TB_Mesures_batteries", id_batterie, id_variable, date_debut, date_fin, 1, 1, (shipheart_fuseau_horaire + shipheart_heure_ete), 0, 0); + + //----------------------------------------------------------------------------------------------------- + // Cas où aucune donnée n'est disponible sur la période : + if (Number(res[0]) === 0) + { + id_circuit = true; // Permet d'afficher le texte "Aucune donnée disponible..." sur la zone graphique + } + //----------------------------------------------------------------------------------------------------- + // Cas où des données sont disponibles sur la période (cas normal donc...) : + else + { + courbe_flag_vide = false; + + xMin_date = new Date(Number(res[1])); // Nécessaire pour la Min de l'axe X (NB : les dates retournées par 'maj_data' sont en heure locale) + xMax_date = new Date(Number(res[3])); // Nécessaire pour la Max de l'axe X (NB : les dates retournées par 'maj_data' sont en heure locale) + mini_maxi = Fonctions.ajustement_mini_maxi(Number(res[6]), Number(res[8]), courbe_nombre_graduations_axe_y); + yMin_valeur = mini_maxi.mini // Nécessaire pour le Min de l'axe Y + yMax_valeur = mini_maxi.maxi // Nécessaire pour le Max de l'axe Y + precision_affichage_axe_y_courbe = Fonctions.precision_affichage_mini_maxi(Number(res[6]), Number(res[8]), courbe_nombre_graduations_axe_y); + //console.log("Min val=" + Number(res[6]) + " et mini=" + yMin_valeur + " - Max val=" + Number(res[8]) + " et maxi=" + yMax_valeur); + } + + } + +console.timeEnd('mise_a_jour_courbes') + + // Arrêt du sablier : + busy_indicator.running = false; // Arrêt du tourniquet s'il est en marche + } + + + + //============================================================================================================= + // RAZ du zoom + //============================================================================================================= + function raz_zoom() + { + + graphique.zoomReset(); // RAZ du zoom proprement dit + graphique.scrollLeft(dragTarget.cumulX); // RAZ du déplacement horizontal par annulation du cumul + graphique.scrollUp(dragTarget.cumulY); // RAZ du déplacement vertical par annulation du cumul + + dragTarget.cumulX = 0; // RAZ du cumul après retour à la position d'origine + dragTarget.cumulY = 0; + + flag_zoom_en_cours = false; + zoomx_en_cours = 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 +#include +#include +//#include +#include + + +//============================================================================ +// 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); +} + + + diff --git a/bdd.h b/bdd.h new file mode 100755 index 0000000..0122378 --- /dev/null +++ b/bdd.h @@ -0,0 +1,71 @@ +#ifndef BDD_H +#define BDD_H + +#include +#include +#include + + + +//============================================================== +class Bdd : public QObject +{ + Q_OBJECT + + + QList 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 diff --git a/capteur.qml b/capteur.qml new file mode 100644 index 0000000..3492bfa --- /dev/null +++ b/capteur.qml @@ -0,0 +1,1168 @@ +//======================================================================================================================================================================== +// CAPTEUR.QML +// Ce fichier traite l'affichage des détails d'un capteur. La page affiche notamment : +// - La valeur actuelle +// - les valeurs mini et maxi sur la période avec leur date, la moyenne sur la période et le delta @1h +// - la courbe historique de niveau +// La page est appelée depuis la page HOME, en cliquant sur l'une des zones de bas de page ou depuis la page CAPTEURS. +//======================================================================================================================================================================== + +import QtQuick 2.12 +import QtQuick.Controls 2.12 +import QtQuick.Layouts 1.12 +//import QtCharts 2.3 +import QtCharts + +import qt.koriolan.shipheart 1.0 +import"fonctions.js" as Fonctions +import"fonctions_date_heure.js" as Fonctions_date_heure + + + +Shipheart_page { + id: page_capteur + + + // Mis en forme : + readonly property double pourcentage_largeur_colonne_gauche: 0.5 + readonly property double pourcentage_largeur_graphique: 0.85 + readonly property double espace_colonnes_principales: 20 + + readonly property double affichage_hauteur_utile: shipheart_hauteur_page - shipheart_hauteur_bandeau_haut - shipheart_hauteur_bandeau_bas - (2 * espace_lignes_principales) + readonly property double pourcentage_hauteur_ligne_haut: 0.6 + readonly property double pourcentage_hauteur_ligne_erreur: 0.3 // Part de 'pourcentage_hauteur_ligne_haut' + readonly property double espace_lignes_principales: 20 + + readonly property double donnees_capteur_pourcentage_largeur_donnee: 0.33 + readonly property double donnees_capteur_pourcentage_largeur_valeur: 0.33 + readonly property double donnees_capteur_pourcentage_largeur_heure: 1 - (donnees_capteur_pourcentage_largeur_donnee + donnees_capteur_pourcentage_largeur_valeur) + + readonly property double nb_boutons_periode: 4 + + readonly property int periode_init_raffraichissement_parametres: 1 // En ms + readonly property int periode_raffraichissement_parametres: 1000 // En ms + readonly property int periode_init_raffraichissement_graphiques: 20 // En ms + readonly property int periode_raffraichissement_graphiques: (15 * 1000) // en ms + + + // Affichage : + property bool courbe_flag_vide: false // Flag indiquant s'il y a des données à afficher ou pas + property int courbe_nombre_principal_graduations_axe_x: 13 + property int courbe_nombre_zoom_1_graduations_axe_x: 8 + property int courbe_nombre_graduations_axe_y: 5 + property string courbe_format_principal_axe_x: "HH:mm" // exemple : "yyyy-MM-dd HH:mm:ss" + property string courbe_format_zoom_1_axe_x: "HH:mm" // exemple : "yyyy-MM-dd HH:mm:ss" + property bool flag_zoom_en_cours: false + property real zoomx_en_cours: 1 + + + // Données : + property bool flag_init: true // Permet de bloquer certains affichage tant que l'init n'est pas terminée + + property int code_capteur: shipheart_capteur_predefini_aucun + property int id_capteur: 0 + property int etat_systeme: 0 + property string nom_capteur: "---" + property int type_entrees: -1 + property string entrees: "" + property int id_variable: -1 + property int etat: 0 + property string chaine_valeur: "---" + property string symbole_unite: "" + property int type_unite: 0 + property int precision_affichage: 1 + property int conversion_unite: 0 + property int nouvelle_unite: 0 + property int periode_analyse: 0 + property string texte_alerte: "" + property int nb_events: -1 // -1: aucun event n'est lié à ce capteur, 0: au moins 1 event est lié à ce capteur mais aucun n'a Etat_test>0, 1: au moins un event lié et au moins un Etat_test=1 + + property date xMin_date + property date xMax_date + property real yMin_valeur: 0 + property real yMax_valeur: 1 + property int precision_affichage_axe_y_courbe: 1 + + + + + // 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; + busy_indicator.running = true; + init_page(); + } + else + { + mise_a_jour_valeurs_instantanees(); + } + } + } + + //=========================================================== + // Timer periode raffraichissement graphiques : + //=========================================================== + Timer { + id: timer_raffraichissement_graphiques + interval: periode_raffraichissement_graphiques + triggeredOnStart: false + running: true + repeat: true + onTriggered: { + if (interval === periode_init_raffraichissement_graphiques) interval = periode_raffraichissement_graphiques; + + if (!flag_init) // La gestion du premier calcul des courbes est géré directement par 'init()' car le séquençage des 2 timers au démarrage n'est pas garanti !! + { + if (!flag_zoom_en_cours) // On ne met pas à jour les courbes si on est en train de zoomer + { + mise_a_jour_courbes(); + } + } + } + } + + + // Titre de la page : + Shipheart_titre_1 {titre: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; + color: "transparent" + visible: (etat_systeme === 0) + + //------------------------------------------------------- + // Valeur si aucune unité : + Rectangle { + id: valeur_capteur_sans_unite + anchors.fill: parent + color: "transparent" + visible: (symbole_unite === "") + + Text { + anchors.fill: parent + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + padding: 10 + text: chaine_valeur + font.family: "Montserrat" + fontSizeMode: Text.HorizontalFit; + minimumPixelSize: 30; + font.pixelSize: 80 + elide: Text.ElideRight + wrapMode: Text.Wrap + font.weight: Font.Bold + color: couleur_blanc_casse + } + } + + //------------------------------------------------------- + // Valeur si unité : + Rectangle { + id: valeur_capteur_avec_unite + anchors.fill: parent + color: "transparent" + visible: (symbole_unite !== "") + + Text { + id: valeur_actuelle + anchors { + verticalCenter: parent.verticalCenter + horizontalCenter: parent.horizontalCenter + horizontalCenterOffset: -20 + } + text: chaine_valeur + font.family: "Montserrat" + font.pixelSize: 120 + font.weight: Font.Bold + color: (nb_events > 0) ? couleur_rouge : couleur_blanc_casse + } + + //------------------------------------------------------- + // Unite : + Text { + anchors { + baseline: valeur_actuelle.baseline + left: valeur_actuelle.right + leftMargin: 10 + } + text: symbole_unite + font.pixelSize: 20 + color: couleur_blanc_casse + } + } + + //----------------------------------- + // Alarmes : + Rectangle { + id: zone_alarmes + width: parent.width + height: 50 + color: shipheart_couleur_fond_bouton + radius: shipheart_rayon_bouton + anchors { + left: parent.left + bottom: parent.bottom + } + visible: nb_events >= 0 + + Image { + source: (nb_events === 0) ? "/images/cloche_sombre.png" : "/images/cloche_rouge.png" + sourceSize.height: 20 + anchors { + verticalCenter: zone_alarmes.verticalCenter + horizontalCenter: zone_alarmes.horizontalCenter + } + } + + //----------------------------------- + // Zone de clics dédiée aux alarmes : + MouseArea{ + anchors.fill: zone_alarmes + + onClicked: { + shipheart_clic(); + boite_dialogue_liste_alarmes.open(); + } + } + } + + Component.onCompleted: { + mise_a_jour_valeurs_instantanees(); + } + } + + + //------------------------------------------------------- + // Ecran haut - droite : + //------------------------------------------------------- + Rectangle { + id: zone_affichage_haut_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 * pourcentage_hauteur_ligne_haut * pourcentage_hauteur_ligne_erreur) - (espace_lignes_principales / 2) + color: "transparent" + border.width: 3 + border.color: couleur_rouge + radius: shipheart_rayon_bouton + visible: (etat_systeme === 0) && (texte_alerte !== "") + + Image { + id: picto_alerte + source: "/images/ak14.png" + sourceSize.height: 30; + 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. + 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: texte_alerte; + anchors { + left: picto_alerte.right + verticalCenter: parent.verticalCenter + } + font.pixelSize: 16 + color: couleur_blanc_casse + } + } + + + //------------------------------------------------------- + // Ecran milieu - droite : + //------------------------------------------------------- + Rectangle { + id: zone_affichage_milieu_droite + x: zone_affichage_haut_droite.x + y: zone_affichage_haut_droite.y + zone_affichage_haut_droite.height + espace_lignes_principales + width: zone_affichage_haut_droite.width + height: (affichage_hauteur_utile * pourcentage_hauteur_ligne_haut * (1 - pourcentage_hauteur_ligne_erreur)) - (espace_lignes_principales / 2) + color: "transparent" + visible: (etat_systeme === 0) + + ColumnLayout { + width: parent.width + anchors.verticalCenter: parent.verticalCenter + spacing: 10 + + ListModel { + id: modele_donnees_capteur + ListElement { donnee: qsTr("Max"); valeur: "---"; heure: "--:--" ; ligne_sup: 1; ligne_inf: 1; hauteur:50; } + ListElement { donnee: qsTr("Moyen"); valeur: "---"; heure: "" ; ligne_sup: 0; ligne_inf: 1; hauteur:50; } + ListElement { donnee: qsTr("Min"); valeur: "---"; heure: "--:--" ; ligne_sup: 0; ligne_inf: 1; hauteur:50; } + ListElement { donnee: qsTr("Delta (Max - Min)"); valeur: "---"; heure: "-----" ; ligne_sup: 0; ligne_inf: 1; hauteur:80; } + // ListElement { donnee: qsTr("Delta (24h)"); valeur: "---"; heure: "-----" ; ligne_sup: 0; ligne_inf: 1; hauteur:40; } + } + + Repeater { + model: modele_donnees_capteur + + 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 * donnees_capteur_pourcentage_largeur_donnee; + anchors.verticalCenter: parent.verticalCenter + horizontalAlignment: Text.AlignLeft + leftPadding: 10 + text: model.donnee + font.pixelSize: 18 + color: couleur_blanc_casse + } + Text { + id: valeur_ligne + anchors.left: titre_ligne.right + width: parent.width * donnees_capteur_pourcentage_largeur_valeur; + anchors.verticalCenter: parent.verticalCenter + horizontalAlignment: Text.AlignHCenter + text: model.valeur + font.pixelSize: 18 + color: couleur_blanc_casse + } + Text { + id: heure_ligne + anchors.left: valeur_ligne.right + width: parent.width * donnees_capteur_pourcentage_largeur_heure; + anchors.verticalCenter: parent.verticalCenter + horizontalAlignment: Text.AlignRight + rightPadding: 10 + text: model.heure + font.pixelSize: 18 + color: couleur_blanc_casse + } + 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; + } + } + } + } + + } + + //------------------------------------------------------- + // Ecran bas : + //------------------------------------------------------- + Rectangle { + id: zone_affichage_bas + x: 0 + y: zone_affichage_haut_gauche.y + zone_affichage_haut_gauche.height + espace_lignes_principales; + width: shipheart_largeur_page; + height: affichage_hauteur_utile * (1 - pourcentage_hauteur_ligne_haut) + color: "transparent" + visible: (etat_systeme === 0) + + //======================== + // Graphique : + ChartView { + id: graphique + antialiasing: true + anchors { + top: parent.top; + left:parent.left; + bottom:parent.bottom; + margins: -15 // Un peu compliqué mais permet, avec la ligne suivante, ... + } + margins { right: 0; bottom: 0; left: 5; top: 0 } // ... d'annuler les marges. + width: parent.width * pourcentage_largeur_graphique; + backgroundColor: "transparent" + // animationDuration: 10000 + // animationOptions: ChartView.SeriesAnimations + legend {visible: false } + visible: (id_variable !== 0) + + DateTimeAxis { + id: axisX + format: (zoomx_en_cours > 0.5) ? courbe_format_principal_axe_x : courbe_format_zoom_1_axe_x + min: xMin_date + max: xMax_date + tickCount: (zoomx_en_cours > 0.5) ? courbe_nombre_principal_graduations_axe_x : courbe_nombre_zoom_1_graduations_axe_x + //labelsColor: (!flag_zoom_en_cours) ? couleur_blanc_casse : couleur_green_yellow + labelsColor: couleur_blanc_casse + labelsFont: Qt.font({pointSize: 10}) + color: couleur_gris_moyen + shadesColor: courbes_couleur_shades_fond + shadesVisible: true + gridVisible: false + // gridLineColor: "green" + } + ValueAxis { + id: axisY1 + min: yMin_valeur + max: yMax_valeur + tickCount: courbe_nombre_graduations_axe_y + labelFormat: "%." + precision_affichage_axe_y_courbe + "f" +// labelsColor: (!flag_zoom_en_cours) ? couleur_blanc_casse : couleur_green_yellow + labelsColor: couleur_blanc_casse + labelsFont:Qt.font({pointSize: 10}) + color: couleur_gris_moyen + // shadesColor: courbes_couleur_shades_fond + shadesVisible: false + gridVisible: true + gridLineColor: couleur_gris_tres_fonce + titleText: "" + symbole_unite + "" + titleFont { + pointSize: 20 + bold: true + } + } + LineSeries { // Utilisé si on veut renforcer la courbe mais sans avoir tout le tour de l'area renfocée (qui se fait dans AreaSeries pour le coup) + id: courbe_principale + name: "Courbe principale" + axisX: axisX + axisY: axisY1 + capStyle: Qt.RoundCap + style: Qt.SolidLine + width: courbes_epaisseur_bordure + color: shipheart_couleur_bordure_courbes + } + + // Affichage des 2 points Min et Maxi : + ScatterSeries { + id: courbe_principale_mini_maxi + axisX: axisX + axisY: axisY1 + + markerSize: 10 + borderColor: "transparent" + borderWidth: 0 + color: couleur_green_yellow + } + + Text { + id: texte_courbe_vide + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + text: qsTr("Aucune donnée n'est disponible pour cette période") + font.pixelSize: 20 + font.weight: Font.Bold + color: "red" + visible: courbe_flag_vide ? true : false; + } + + + //--------------------------------- + // Rectangle de sélection de zoom : + Rectangle { + id: rectangle_zoom + x: pinch_area.zoom_x + y: pinch_area.zoom_y + width: pinch_area.zoom_w + height: pinch_area.zoom_h + radius: shipheart_rayon_zoom + + color: couleur_bleu_koriolan_tres_transparent + } + + //--------------------------------- + // Zone de pinch : + PinchArea{ + id: pinch_area + + // Propriété de la eone de zoom pendant toute la phase de sélection : + property real zoom_x: 0 + property real zoom_y: 0 + property real zoom_w: 0 + property real zoom_h: 0 + + anchors.fill: parent // Calé sur 'graphique'. + // Attention : la zone de traçage à l'intérieur de 'graphique' est 'graphique.plotArea'. + // Toutes les coordonnées sont données dans 'graphique' mais on limite à l'usage les coordonnées intérieures à 'graphique.plotArea'. + + //----------------------------------------------- + // Mis à jour en cours de déplacement du pinch : + onPinchUpdated: { + + if ((pinch.point1.x !== pinch.point2.x) || // Il arrive, en fin de pinch, que les 2 points renvoyés soient les mêmes... + (pinch.point1.y !== pinch.point2.y)) // ... Il faut éviter de les traiter sous peine de ramener W et H à 0. + { + // Récupération des données en s'affranchissant de la position des 2 points : + zoom_x = Math.min(pinch.point1.x, pinch.point2.x) + zoom_y = Math.min(pinch.point1.y, pinch.point2.y) + zoom_w = Math.abs(pinch.point1.x - pinch.point2.x) + zoom_h = Math.abs(pinch.point1.y - pinch.point2.y) + + // Limitation de 'x' et 'w' à la largeur de la zone de traçage : + if (zoom_x < graphique.plotArea.x) zoom_x = graphique.plotArea.x; + if (zoom_x > (graphique.plotArea.x + graphique.plotArea.width)) zoom_x = graphique.plotArea.x + graphique.plotArea.width + if ((zoom_x + zoom_w) > (graphique.plotArea.x + graphique.plotArea.width)) zoom_w = (graphique.plotArea.x + graphique.plotArea.width) - zoom_x; + + // Limitation de 'y' et 'h' à la hauteur de la zone de traçage : + if (zoom_y < graphique.plotArea.y) zoom_y = graphique.plotArea.y; + if (zoom_y > (graphique.plotArea.y + graphique.plotArea.height)) zoom_y = graphique.plotArea.y + graphique.plotArea.height + if ((zoom_y + zoom_h) > (graphique.plotArea.y + graphique.plotArea.height)) zoom_h = (graphique.plotArea.y + graphique.plotArea.height) - zoom_y; + } + } + + //------------------------- + // Valeur de fin du pinch : + onPinchFinished: { + // Préparation du zoom sur le rectangle sélectionné : + var r = Qt.rect(zoom_x, zoom_y, zoom_w, zoom_h); + graphique.zoomIn(r); + flag_zoom_en_cours = true; + + zoomx_en_cours *= (zoom_w / graphique.plotArea.width); + + // Effacement du rectangle : + zoom_x = 0 + zoom_y = 0 + zoom_w = 0 + zoom_h = 0 + } + + // Déplacement de la courbe : + MouseArea{ + anchors.fill: parent + drag.target: dragTarget + drag.axis: Drag.XAndYAxis + onClicked: { + shipheart_clic(); + if (!flag_zoom_en_cours) // Si le zoom est en cours, il ne faut PAS lancer le raffraichissement...! + { + busy_indicator.running = true; + timer_raffraichissement_graphiques.interval = periode_init_raffraichissement_graphiques; // Cela permet de lancer le "busy_indicator' avant de faire la mise à jour de la courbe + } + } + onPressAndHold: { + raz_zoom(); + } + } + Item { + id: dragTarget + property real oldX : x // Permet de mémoriser la dernière position d'arrivée + property real oldY : y + + property real cumulX : 0 // Permet de revenir à un déclage nul lorsque nécessaire + property real cumulY : 0 + + onXChanged: { + graphique.scrollLeft( x - oldX ); + cumulX -= (x - oldX); // Le signe '-' permettra ensuite de revenir à le position de départ + oldX = x; + } + + onYChanged: { + graphique.scrollUp( y - oldY ); + cumulY -= (y - oldY); // Le signe '-' permettra ensuite de revenir à le position de départ + oldY = y; + } + } + } + } + + + //======================== + // Busy Indicator : + Shipheart_busy_indicator { + id: busy_indicator + } + + //======================== + // Boutons de pếriode : + ColumnLayout { + spacing: 10 + anchors { + top: parent.top; + right:parent.right; + rightMargin: 5; + bottom:parent.bottom; + } + width: (parent.width * (1 - pourcentage_largeur_graphique)) - anchors.rightMargin; + + ListModel { + id: modele_periodes_graphique + } + + Repeater { + model: modele_periodes_graphique + + Rectangle { + color: "transparent" + Layout.preferredWidth: parent.width; + Layout.preferredHeight: (parent.height / nb_boutons_periode) - parent.spacing; + + Text { + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + text: model.libelle + font.pixelSize: 18 + font.weight: (model.index === periode_analyse) ? Font.Bold : Font.Normal + color: couleur_blanc_casse + } + 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 + onClicked: { + shipheart_clic(); + raz_zoom(); // Au-delà de la fonctionnalité, c'est obligatoire sinon, le raffraichissement des la courbe est bloqué au niveau du timer + periode_analyse = model.index; + busy_indicator.running = true; + timer_raffraichissement_graphiques.interval = periode_init_raffraichissement_graphiques; // Cela permet de lancer le "busy_indicator' avant de faire la mise à jour de la courbe + } + } + // Fond du bouton : + Rectangle { // Permet d'avoir un fond et de pouvoir régler son opacité sans changer celle des textes au-dessus + width: parent.width + height: parent.height + color: (model.index === periode_analyse) ? (flag_zoom_en_cours ? couleur_green_yellow_transparent : shipheart_couleur_fond_bouton_actif) : shipheart_couleur_fond_bouton; + opacity: 0.5 + radius: shipheart_rayon_bouton + } + } + } + } + + + + Component.onCompleted: { +// mise_a_jour_courbes(); // Si on met la MAJ là, on va attendre la dispo des valeurs avant d'afficher le Rectangle. En la mettant dans un timer séparé, la page est affichée et on charge ensuite les valeurs. + + } + } + + + //------------------------------------------------------- + // Message d'erreur si capteur Absent + // (le module sur lequel le capteur est configuré n'est pas physiquement présent) + //------------------------------------------------------- + Rectangle { + id: zone_message_absence + x: 0 + y: shipheart_hauteur_bandeau_haut + espace_lignes_principales + width: shipheart_largeur_page + height: shipheart_hauteur_page - shipheart_hauteur_bandeau_haut - shipheart_hauteur_bandeau_bas - espace_lignes_principales + color: "transparent" + visible: (etat_systeme !== 0) + + Rectangle { // Rectangle entouré de rouge + anchors.verticalCenter: parent.verticalCenter + anchors.verticalCenterOffset: -50 + anchors.horizontalCenter: parent.horizontalCenter + width: parent.width + height: parent.height / 2 + radius: shipheart_rayon_bouton + border.width: 3 + border.color: couleur_rouge + color: couleur_rouge_transparent//"transparent" + + Image { // Pictogramme DANGER + anchors.verticalCenter: parent.verticalCenter + anchors.verticalCenterOffset: -100 + anchors.horizontalCenter: parent.horizontalCenter + source: "/images/ak14.png" + sourceSize.height: 70; + } + + Text { // Texte d'info + anchors.verticalCenter: parent.verticalCenter + anchors.verticalCenterOffset: 50 + anchors.horizontalCenter: parent.horizontalCenter + width: parent.width + height : parent.height / 2 + horizontalAlignment: Qt.AlignCenter + verticalAlignment: Qt.AlignVCenter + padding: 50 + text: (type_entrees === shipheart_capteur_type_entrees_ow) + ? qsTr("La sonde One Wire correspondant à ce capteur n'est pas accessible.
Vérifier son câblage entre le port One Wire à l'arrière de ShipBase et la sonde.") + : qsTr("Le module assurant la supervision de ce capteur n'est pas accessible !

Si des ajouts/suppression/déplacements de modules ont eu lieu récemment, mettez à jour la configuration correspondant dans le menu MODULES de PARAMETRES AVANCES.

Dans le cas où aucune modification n'a été effectuée récemment, vérifier les connexions de tous les modules.") + color: couleur_blanc_casse + font.pixelSize: 18 + wrapMode: Label.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: 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() + } + } + } + } + + //------------------------------------------------------- + // Boite d'affichage de la liste des alarmes : + //------------------------------------------------------- + Shipheart_boite_dialogue_liste_alarmes { + id: boite_dialogue_liste_alarmes + + titre: nom_capteur + type_source: shipheart_source_mesure_capteur + id_source: id_capteur + id_variable: page_capteur.id_variable + titre_widget: nom_capteur + unite: symbole_unite + } + + //=========================================================== + // 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() + { + + if (id_capteur === 0) + { + console.log("La page 'capteur.qml' a été appelée sans 'id_capteur'. L'affichage de la page est impossible"); + return; + } + + //==================================================================== + // Init du nom des périodes du graphique : + modele_periodes_graphique.append({ "libelle": Fonctions_date_heure.nom_periode_analyse(0), "actif": true }); + modele_periodes_graphique.append({ "libelle": Fonctions_date_heure.nom_periode_analyse(1), "actif": true }); + modele_periodes_graphique.append({ "libelle": Fonctions_date_heure.nom_periode_analyse(2), "actif": true }); + modele_periodes_graphique.append({ "libelle": Fonctions_date_heure.nom_periode_analyse(3), "actif": true }); + + // Première mise à jour : + mise_a_jour_valeurs_instantanees(); + mise_a_jour_courbes(); + + // Libération du flag : + flag_init = false; + } + + + //============================================================================================================= + // Mise à jour de la valeur instantannée + //============================================================================================================= + function mise_a_jour_valeurs_instantanees() + { + var req, res; + var nb; + var i; + var liste_valeurs_textes; + var age; + var valeur; + + + req = 'SELECT Cle_primaire, '; + req += ' Etat_systeme, '; + req += ' Nom, '; + req += ' Type_entrees, '; + req += ' Entrees, '; + req += ' ID_Variable, '; + req += ' Etat, '; + req += ' Valeur, '; + req += ' Precision_affichage_mesures, '; + req += ' Liste_valeurs_textes, '; + + req += ' IF ( (Type_entrees=' + shipheart_capteur_type_entrees_nmea + '), '; + req += ' ( SELECT ( UNIX_TIMESTAMP() - UNIX_TIMESTAMP(Date_maj) ) '; + req += ' FROM TB_Nmea2000 WHERE '; + req += ' Pgn=SUBSTRING_INDEX(Entrees, \':\', 1) AND Field=SUBSTRING_INDEX(Entrees, \':\', -1) ), '; + req += ' (UNIX_TIMESTAMP() - UNIX_TIMESTAMP(Date_maj)) )'; + req += ' AS Age '; + + + req += ' FROM TB_Capteurs WHERE Cle_primaire="' + id_capteur + '" '; +//console.log("Requête = [" + req + "]"); + res = bdd.requete_unique(req); + + i = 0; + id_capteur = Number(res[i++]); + etat_systeme = Number(res[i++]); + nom_capteur = res[i++]; + type_entrees = Number(res[i++]); + entrees = res[i++]; + id_variable = Number(res[i++]); + etat = Number(res[i++]); + valeur = Number(res[i++]); + precision_affichage = Number(res[i++]); + liste_valeurs_textes = res[i++]; + age = Number(res[i++]); + + texte_alerte = ""; + + // Recherche infos sur variable : + req = ' SELECT Unite, Conversion_unite FROM TB_Variables WHERE Cle_primaire="' + id_variable + '" '; + res = bdd.requete_unique(req); + i = 0; + symbole_unite = res[i++]; + conversion_unite = Number(res[i++]); + + // 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; + break; + } + + // Cas spécifiques en fonction du type de capteur : + 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: + + if (etat !== shipheart_capteur_etat_normal) + { + texte_alerte = qsTr("La sonde One Wire du capteur est détectée en défaut.
Vérifier son câblage depuis l'arrière de ShipBase.") + } + + break; + + //----------------------------------------------------------------- + case shipheart_capteur_type_entrees_predefinie: + break; + + //----------------------------------------------------------------- + case shipheart_capteur_type_entrees_nmea: + if (age > shipheart_periode_obsolescence_capteur_nmea) + { + texte_alerte = qsTr("Le capteur n'a pas reçu de mise à jour sur le réseau NMEA depuis
%1
Les données affichées sont donc probablement obsolètes.").arg(Fonctions_date_heure.chaine_duree(age * 1000)); + } + break; + + //----------------------------------------------------------------- + default : + break; + } + + + // Recherche des events liés à ce capteur et leur valeur : + nb_events = -1; + + req = 'SELECT Etat_test '; + req += ' FROM TB_Events '; + req += ' WHERE Validite=1 '; + req += ' AND Alarme_source>0 '; + req += ' AND Type_source=' + shipheart_source_mesure_capteur + ' '; + req += ' AND ID_Source=' + id_capteur + ' '; +//console.log("Requête = [ " + req + "; ]"); + nb = bdd.requete(req); + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + if (nb_events < Number(res[0])) nb_events = Number(res[0]); + } + } + // En sorttant, on a donc nb_events=-1 si aucun event lié, 0 si au moins un event lié mais tous leurs Etat_test=0, et 1 si au moins un event et au moins un a Etat_test=1. + + } + + + //============================================================================================================= + // Mise à jour des données des courbes + //============================================================================================================= + function mise_a_jour_courbes() + { + var req, res; + var nb; + var date_debut, date_fin; + var courbe_principale_duree; + var mini_maxi; + var ymin_x, ymin_y, ymax_x, ymax_y; + var delta_x, delta_y; + var gradient; + var chaine_valeur_min, chaine_valeur_moyenne, chaine_valeur_max; + var format_chaine_heure; // 0=format court ("hh:mm") et 1=format long ("MM/dd hh:mm") + +console.time('mise_a_jour_courbes') + + // Paramètres de la courbe dépendant de la période d'analyse : + switch(periode_analyse) + { + default: + case 0: // 1 heure + courbe_nombre_principal_graduations_axe_x = 7 // Nombre de bandes verticales + 1 + courbe_nombre_zoom_1_graduations_axe_x = 7 // Utilisé lorsque le taux de zoom passe en-dessous de 0.5 + courbe_format_principal_axe_x = "HH:mm" // exemple : "yyyy-MM-dd HH:mm:ss" + courbe_format_zoom_1_axe_x = "HH:mm" // Utilisé lorsque le taux de zoom passe en-dessous de 0.5 + break; + + case 1: // 24 heures + courbe_nombre_principal_graduations_axe_x = 13 // Nombre de bandes verticales + 1 + courbe_nombre_zoom_1_graduations_axe_x = 13 // Utilisé lorsque le taux de zoom passe en-dessous de 0.5 + courbe_format_principal_axe_x = "HH:mm" // exemple : "yyyy-MM-dd HH:mm:ss" + courbe_format_zoom_1_axe_x = "HH:mm" // Utilisé lorsque le taux de zoom passe en-dessous de 0.5 + break; + + case 2: // 7 jours + courbe_nombre_principal_graduations_axe_x = 8 // Nombre de bandes verticales + 1 + courbe_nombre_zoom_1_graduations_axe_x = 8 // Utilisé lorsque le taux de zoom passe en-dessous de 0.5 + courbe_format_principal_axe_x = "dd/MM HH:mm" // exemple : "yyyy-MM-dd HH:mm:ss" + courbe_format_zoom_1_axe_x = "HH:mm" // Utilisé lorsque le taux de zoom passe en-dessous de 0.5 + break; + + case 3: // 30 jours + courbe_nombre_principal_graduations_axe_x = 31 // Nombre de bandes verticales + 1 + courbe_nombre_zoom_1_graduations_axe_x = 13 // Utilisé lorsque le taux de zoom passe en-dessous de 0.5 + courbe_format_principal_axe_x = "dd" // exemple : "yyyy-MM-dd HH:mm:ss" + courbe_format_zoom_1_axe_x = "HH:mm" // Utilisé lorsque le taux de zoom passe en-dessous de 0.5 + break; + } + + + // Dates et durée : + courbe_principale_duree = Fonctions_date_heure.duree_periode_analyse(periode_analyse); // En secondes + date_fin = new Date(); // En UTC + date_debut = Fonctions_date_heure.date_add_secondes(date_fin, -(courbe_principale_duree)); // En UTC +//console.log("Date de début initiale UTC = " + date_debut + " et date de fin UTC = " + date_fin) + + // Mise à jour des données de la courbe principale : +console.log("Type_unite="+type_unite+", et nouvelle_unite="+nouvelle_unite); + res = tbmesuresModel.maj_data(graphique.series("Courbe principale"), "TB_Mesures_capteurs", id_capteur, id_variable, date_debut, date_fin, 1, 1, (shipheart_fuseau_horaire + shipheart_heure_ete), type_unite, nouvelle_unite); + + + // Traitements spécifiques en focntion du type de capteur : + chaine_valeur_min = Number(res[6]).toFixed(precision_affichage) + " " + symbole_unite; + chaine_valeur_moyenne = Number(res[9]).toFixed(precision_affichage) + " " + symbole_unite; + chaine_valeur_max = Number(res[8]).toFixed(precision_affichage) + " " + symbole_unite; + + switch(type_entrees) + { + //----------------------------------------------------------------- + case shipheart_capteur_type_entrees_aux: + break; + + //----------------------------------------------------------------- + case shipheart_capteur_type_entrees_level_sensor: + break; + + //----------------------------------------------------------------- + case shipheart_capteur_type_entrees_ow: + break; + + //----------------------------------------------------------------- + case shipheart_capteur_type_entrees_predefinie: + + if (Number(entrees) === shipheart_capteur_predefini_lat) + { + chaine_valeur_min = Fonctions.chaine_latitude(Number(res[6])); + chaine_valeur_moyenne = Fonctions.chaine_latitude(Number(res[9])); + chaine_valeur_max = Fonctions.chaine_latitude(Number(res[8])); + } + if (Number(entrees) === shipheart_capteur_predefini_lon) + { + chaine_valeur_min = Fonctions.chaine_longitude(Number(res[6])); + chaine_valeur_moyenne = Fonctions.chaine_longitude(Number(res[9])); + chaine_valeur_max = Fonctions.chaine_longitude(Number(res[8])); + } + + break; + + //----------------------------------------------------------------- + default : + break; + } + + //----------------------------------------------------------------------------------------------------- + // Cas où aucune donnée n'est disponible sur la période : + if (Number(res[0]) === 0) + { + courbe_principale_flag_vide = true; // Permet d'afficher le texte "Aucune donnée disponible..." sur la zone graphique + + modele_donnees_capteur.set(0, {"valeur": "---", heure : "--:--"}) // valeurs par défaut pour supprimer les anciennes valeurs + modele_donnees_capteur.set(1, {"valeur": "---", heure : "--"}) + modele_donnees_capteur.set(2, {"valeur": "---", heure : "--:--"}) + modele_donnees_capteur.set(3, {"valeur": "---", heure : "--:--"}) +// modele_donnees_capteur.set(4, {"valeur": "---", heure : "--:--"}) + } + //----------------------------------------------------------------------------------------------------- + // Cas où des données sont disponibles sur la période (cas normal donc...) : + else + { + courbe_flag_vide = false; + + xMin_date = new Date(Number(res[1])); // Nécessaire pour la Min de l'axe X (NB : les dates retournées par 'maj_data' sont en heure locale) + xMax_date = new Date(Number(res[3])); // Nécessaire pour la Max de l'axe X (NB : les dates retournées par 'maj_data' sont en heure locale) + mini_maxi = Fonctions.ajustement_mini_maxi(Number(res[6]), Number(res[8]), courbe_nombre_graduations_axe_y); + yMin_valeur = mini_maxi.mini // Nécessaire pour le Min de l'axe Y + yMax_valeur = mini_maxi.maxi // Nécessaire pour le Max de l'axe Y + precision_affichage_axe_y_courbe = Fonctions.precision_affichage_mini_maxi(Number(res[6]), Number(res[8]), courbe_nombre_graduations_axe_y); +//console.log("Min val=" + Number(res[6]) + " et mini=" + yMin_valeur + " - Max val=" + Number(res[8]) + " et maxi=" + yMax_valeur); + + // Mise à jour des données numériques : + var chaine_heure; + + if (format_chaine_heure === 0) chaine_heure = Fonctions_date_heure.chaine_heure_courte(new Date(Number(res[7]))); // Date MAX format court... + else chaine_heure = Fonctions_date_heure.chaine_date_heure_courte(new Date(Number(res[7]))); // ... ou format long + modele_donnees_capteur.set(0, {"valeur": chaine_valeur_max, "heure": "[" + chaine_heure + "]"}) // Valeur MAX + modele_donnees_capteur.set(1, {"valeur": chaine_valeur_moyenne}) // Valeur MOYENNE + if (format_chaine_heure === 0) chaine_heure = Fonctions_date_heure.chaine_heure_courte(new Date(Number(res[5]))); // Date MIN format court... + else chaine_heure = Fonctions_date_heure.chaine_date_heure_courte(new Date(Number(res[5]))); // ... ou format long + modele_donnees_capteur.set(2, {"valeur": chaine_valeur_min, "heure": "[" + chaine_heure + "]"}) // Valeur MIN + + // Calcul du delta X : + ymin_x = Number(res[5]); + ymax_x = Number(res[7]); + delta_x = ymax_x - ymin_x; + + // Calcul du delta Y : + ymin_y = Number(res[6]); + ymax_y = Number(res[8]); + delta_y = ymax_y - ymin_y; + + // Ajout du delta : + modele_donnees_capteur.set(3, {"valeur": ((ymax_x > ymin_x) ? "+" : "-") + delta_y.toFixed(precision_affichage + 1) + " " + symbole_unite, "heure": Fonctions_date_heure.chaine_duree(delta_x)}) + + // Ajout des points de Min/Max sur la courbe : + courbe_principale_mini_maxi.clear(); + courbe_principale_mini_maxi.append(ymin_x, ymin_y); + courbe_principale_mini_maxi.append(ymax_x, ymax_y); + + } + busy_indicator.running = false; // Arrêt du tourniquet s'il est en marche + +console.timeEnd('mise_a_jour_courbes') + } + + //============================================================================================================= + // RAZ du zoom + //============================================================================================================= + function raz_zoom() + { + + graphique.zoomReset(); // RAZ du zoom proprement dit + graphique.scrollLeft(dragTarget.cumulX); // RAZ du déplacement horizontal par annulation du cumul + graphique.scrollUp(dragTarget.cumulY); // RAZ du déplacement vertical par annulation du cumul + + dragTarget.cumulX = 0; // RAZ du cumul après retour à la position d'origine + dragTarget.cumulY = 0; + + flag_zoom_en_cours = false; + zoomx_en_cours = 1; + } +} + diff --git a/circuit.qml b/circuit.qml new file mode 100644 index 0000000..6b05144 --- /dev/null +++ b/circuit.qml @@ -0,0 +1,2156 @@ +//======================================================================================================================================================================== +// CIRCUIT.QML +// Ce fichier traite l'affichage des détails d'un circuit. La page affiche notamment : +// - la commande actuelle du circuit (et permet la commande, y compris en variateur s'il est configuré pour), +// - la consommation actuelle du circuit, +// - la liste des derniers événements, +// - les éventuelles infos d'état ou d'alarme (commande manuelle, défaut, etc...). +// - la courbe de consommation +// La page est appelée depuis la page HOME, en cliquant sur la zone d'information du circuit. +//======================================================================================================================================================================== + +import QtQuick 2.12 +import QtQuick.Controls 2.12 +import QtQuick.Layouts 1.12 +import QtCharts 2.3 + +import qt.koriolan.shipheart 1.0 +import"fonctions.js" as Fonctions +import"fonctions_date_heure.js" as Fonctions_date_heure + + +Shipheart_page { + id: page_circuit + + + // Mis en forme : + readonly property double pourcentage_largeur_colonne_gauche_haut: 0.5 + readonly property double pourcentage_largeur_colonne_centre_haut: 0.07 // 80/1280 pour se rapprocher du bouton de slider (80) + readonly property double pourcentage_largeur_graphique: 0.85 + readonly property int espace_colonnes_principales: 10 + readonly property int espace_colonnes_secondaires: 10 + readonly property int largeur_bouton_slider: 80 + + readonly property double pourcentage_hauteur_ligne_haut: 0.15 + readonly property double pourcentage_hauteur_ligne_milieu: (1 - pourcentage_hauteur_ligne_haut - pourcentage_hauteur_ligne_graphique) + readonly property double pourcentage_hauteur_ligne_graphique: 0.45 + readonly property double hauteur_utile: (shipheart_hauteur_page - shipheart_hauteur_bandeau_haut - shipheart_hauteur_bandeau_bas - (4 * espace_lignes_principales)) + readonly property int espace_lignes_principales: 20 + readonly property int espace_lignes_secondaires: 10 + + readonly property int nombre_widgets_par_ligne: 4 + readonly property int largeur_bouton_suite: 15 + + readonly property int nombre_lignes_historique_visibles: 8 + readonly property int nombre_lignes_historique_par_page: 30 + + readonly property int nb_boutons_periode: 4 + + readonly property int periode_init_raffraichissement_parametres: 20 // En ms ATtention : The Timer type is synchronized with the animation timer. Since the animation timer is usually set to 60fps, the resolution of Timer will be at best 16ms. + readonly property int periode_raffraichissement_parametres: 1000 // En ms + readonly property int periode_init_raffraichissement_graphiques: 20 // En ms + readonly property int periode_raffraichissement_graphiques: (15 * 1000) // en ms + + // Affichage : + property int periode_analyse: 0 + + property string source_picto_alerte: "" + property string texte_alerte : "---" + + property string date_premiere_entree_historique: "" // Contient une chaine (format BDD) représentant la date/heure de l'entrée historique la plus ancienne. Permet de recharger de plus anciennes lors d'un MORE... + property string date_derniere_entree_historique: "" // Contient une chaine (format BDD) représentant la date/heure de l'entrée historique la plus récente. Permet de ne recharger que les nouvelles... + property bool flag_journal_full: false // est positionné à vrai quand il n'y a plus d'enregistrements supplémentaires disponibles pour ce filtre + + property bool courbe_flag_vide: false // Flag indiquant s'il y a des données à afficher ou pas + property int courbe_nombre_principal_graduations_axe_x: 13 + property int courbe_nombre_zoom_1_graduations_axe_x: 8 + property int courbe_nombre_graduations_axe_y: 5 + property string courbe_format_principal_axe_x: "HH:mm" // exemple : "yyyy-MM-dd HH:mm:ss" + property string courbe_format_zoom_1_axe_x: "HH:mm" // exemple : "yyyy-MM-dd HH:mm:ss" + + property bool flag_zoom_en_cours: false + property real zoomx_en_cours: 1 + + property date xMin_date + property date xMax_date + property real yMin_valeur: 0 + property real yMax_valeur: 1 + property int precision_affichage_axe_y_courbe: 1 + property string symbole_unite: "--" + + property int etat_systeme: 0 // Le '0' permet d'éviter l'affichage du message d'erreur pendant un très court instant au démarrage + + // Données : + property bool flag_init: true // Permet de bloquer certains affichage tant que l'init n'est pas terminée + + property int id_circuit: 0 + property int id_variable: -1 + property string nom: "---" + property string nom_batterie: "---" + property int type_module: shipheart_type_module_inconnu + property int no_circuit: 0 + property double plancher_intensite; + property int precision_tension: 0 + property int precision_intensite: 0 + property int mode_commande: 0 // 0=On-Off, 1=On-Off soft, 2=Variable soft et 3=Cadencé + property int etat_commande_carte: 0 // 0=Ok, 1=Undervoltage, 2=Test + property int mode_test: 0 + property int etat: 0 + property int mode_cdes_auto: -1 + + property int consigne: 0 + property int consigne_id_variable: 0 + property string consigne_unite_variable: "" + property string tension: "" + property int tension_etat: 0 + property int tension_id_variable: 0 + property string tension_unite_variable: "" + property string intensite: "" + property string intensite_seuil_haut: "" + property int intensite_etat: 0 + property int intensite_id_variable: 0 + property string intensite_unite_variable: "" + property string frequence: "" + property int frequence_etat: 0 + property int frequence_id_variable: 0 + property string frequence_unite_variable: "" + property string puissance: "" + property int puissance_etat: 0 + property int puissance_id_variable: 0 + property string puissance_unite_variable: "" + property string energie: "--" + property int energie_etat: 0 + property int energie_id_variable: 0 + property string energie_unite_variable: "" + + + // 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 du circuit : + //=========================================================== + 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; + busy_indicator.running = true; + init_page(); + } + else + { + mise_a_jour_valeurs_instantanees(); + } + } + } + //=========================================================== + // Timer periode raffraichissement graphiques : + //=========================================================== + Timer { + id: timer_raffraichissement_graphiques + interval: periode_raffraichissement_graphiques + triggeredOnStart: false + running: true + repeat: true + onTriggered: { + if (interval === periode_init_raffraichissement_graphiques) interval = periode_raffraichissement_graphiques; + + if (!flag_init) // La gestion du premier calcul des courbes est géré directement par 'init()' car le séquençage des 2 timers au démarrage n'est pas garanti !! + { + if (!flag_zoom_en_cours) // On ne met pas à jour les courbes si on est en train de zoomer + { + if (id_variable !== -1) // Cas du port USB arrière par exemple + { + mise_a_jour_courbes(); + mise_a_jour_valeur_energie(); // On utilise ce timer "lent" pour mettre à jour cette valeur qui évolue peu + } + } + } + } + } + + + // Titre de la page : + Shipheart_titre_1 {titre:nom; hauteur: shipheart_hauteur_bandeau_haut} + + + //=========================================================== + // Ecran haut - gauche : Commande du circuit + //=========================================================== + Rectangle { + id: zone_affichage_haut_gauche + x: largeur_bouton_suite + (espace_colonnes_secondaires / 2) // Alignement avec les widgets + y: shipheart_hauteur_bandeau_haut + espace_lignes_principales + width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche_haut) // Part de la zone de gauche + - largeur_bouton_suite - (espace_colonnes_secondaires / 2) // Espace à gauche pour s'aligner avec les widgets + - (espace_colonnes_principales / 2) // 1/2 de l'espace entre cette zone et la zone centrale (à droite donc) + height: hauteur_utile * pourcentage_hauteur_ligne_haut + color: "transparent" + visible: (etat_systeme === 0) && ((type_module !== shipheart_type_module_shipbase) || (no_circuit !== 0)) + + //----------------------------------------- + // Cas d'un circuit en commande TOR : + //----------------------------------------- + // Bouton OFF : + Rectangle { + id: zone_consigne_off + x: 0 + width: (parent.width / 2) - (espace_colonnes_secondaires / 2); + height: parent.height +// color: (consigne === 0) ? couleur_rouge_transparent : shipheart_couleur_fond_bouton + color: (consigne === 0) ? shipheart_couleur_fond_bouton_actif : shipheart_couleur_fond_bouton // SDIR #207 + radius: shipheart_rayon_bouton + visible: (etat_commande_carte === shipheart_etat_commande_module_ok) && + (mode_commande !== shipheart_mode_commande_circuit_soft_variable) + + Text { + id: consigne_off + text: qsTr("Off") + anchors.verticalCenter: parent.verticalCenter + anchors.verticalCenterOffset: 0 + anchors.horizontalCenter: parent.horizontalCenter + font.pixelSize: 24 + font.weight: (consigne === 0) ? Font.Bold : Font.Normal // SDIR #207 + color: (consigne === 0) ? couleur_blanc_casse : couleur_gris_pale // 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_off + anchors.fill: parent + onClicked: { + shipheart_clic(); + changement_consigne(0, -1); // La Old_consigne n'est pas affecté par une commande OFF + } + } + } + + //------------------- + // Bouton ON : + Rectangle { + id: zone_consigne_on + x: (parent.width / 2) + (espace_colonnes_secondaires / 2); + width: (parent.width / 2) - (espace_colonnes_secondaires / 2); + height: parent.height + color: (consigne !== 0) ? couleur_vert_transparent : shipheart_couleur_fond_bouton + radius: shipheart_rayon_bouton + visible: (etat_commande_carte === shipheart_etat_commande_module_ok) && + (mode_commande !== shipheart_mode_commande_circuit_soft_variable) + + Text { + id: consigne_on + text: qsTr("On") + anchors.verticalCenter: parent.verticalCenter + anchors.verticalCenterOffset: 0 + anchors.horizontalCenter: parent.horizontalCenter + font.pixelSize: 24 + font.weight: (consigne !== 0) ? Font.Bold : Font.Normal // SDIR #207 + color: (consigne !== 0) ? couleur_green_yellow : couleur_gris_pale + } + + 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_on + anchors.fill: parent + onClicked: { + shipheart_clic(); + changement_consigne(100, -1); // La Old_consigne n'est pas affecté par une commande ON + } + } + } + + //----------------------------------------- + // Cas d'un circuit en commande variable : + //----------------------------------------- + Slider { + id: slider_consigne + + width: parent.width + height: parent.height + padding: 0 + anchors { + horizontalCenter: parent.horizontalCenter + } + visible: (etat_commande_carte === shipheart_etat_commande_module_ok) && + (mode_commande === shipheart_mode_commande_circuit_soft_variable) + from: 0 + value: consigne + to: 100 + stepSize:1 // Permet de n'avoir que des valeurs en %, sans décimales (il est probable que cela accélère le traitement mais pas vérifié...) + + background: Rectangle { + x: parent.leftPadding + y: 0 + width: parent.width + height: parent.height + radius: shipheart_rayon_bouton + color: shipheart_couleur_fond_bouton + + Rectangle { + id: slider_consigne_bande_active + width: slider_consigne.visualPosition * parent.width + height: parent.height + color: couleur_vert_transparent + radius: shipheart_rayon_bouton + Behavior on width { + NumberAnimation { + properties:"width" + duration: 350 + easing.type: Easing.OutQuad + } + } + + + Text { // Affichage de la valeur dans la barre lorsque le circuit est ON : + text: qsTr("On\n%1%").arg(slider_consigne.value.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: 18 + font.weight: Font.Bold + color: couleur_green_yellow + visible: (slider_consigne.value === 0) ? false : true + } + } + } + + handle: Rectangle { + x: parent.leftPadding + (parent.visualPosition * (parent.availableWidth - width)) + y: (parent.availableHeight / 2) - (height / 2) + implicitWidth: largeur_bouton_slider // Le bouton n'étant pas visible la plupart du temps, cette taille n'est pas critique + implicitHeight: parent.height + radius: shipheart_rayon_bouton + color: (slider_consigne_bande_active.width === 0) ? +// couleur_rouge_transparent : + shipheart_couleur_fond_bouton_actif : // SDIR #207 + "transparent" + border.color: "transparent" + + Text { // Affichage de la valeur dans le bouton lorsque le circuit est OFF : + text: qsTr("Off") + 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: 18 + font.weight: Font.Bold + color: couleur_blanc_casse // SDIR #207 + visible: (slider_consigne_bande_active.width === 0) + } + + } + onMoved: { + shipheart_clic(); + if (!timer_time_out_consigne.running) + { + timer_time_out_consigne.running = true + changement_consigne(slider_consigne.value, slider_consigne.value); + } + } + Timer { // Timer qui permet de brider les envoi de mise à jour dans la BDD + id: timer_time_out_consigne + interval: 250 + triggeredOnStart: false + running: false + repeat: false + onTriggered: { // Permet d'être sûr que la dernière position est bien enregistrée dans la BDD, même si l'arrêt s'est produit pendant que le timer tournait + changement_consigne(slider_consigne.value, slider_consigne.value); + } + } + } + + + //------------------------------------------------------------- + // Cas d'un circuit sur une carte en Undervoltage + //------------------------------------------------------------- + Rectangle { + id: zone_info_etat_circuit_undervoltage + anchors.fill: parent + color: "transparent" + radius: shipheart_rayon_bouton + border.color: couleur_rouge + border.width: 3 + visible: (etat_commande_carte === shipheart_etat_commande_module_undervoltage) ? true : false + + Text { + text: qsTr("Off") + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + font.pixelSize: 24 + color: couleur_rouge + } + } + + //------------------------------------------------------------- + // Cas d'un circuit sur une carte en mode Test + //------------------------------------------------------------- + Rectangle { + id: zone_info_etat_circuit_test + anchors.fill: parent + color: "transparent" + radius: shipheart_rayon_bouton + border.color: (mode_test === 0) ? couleur_rouge : couleur_vert + border.width: 3 + visible: (etat_commande_carte === shipheart_etat_commande_module_test) ? true : false + + Text { + text: (mode_test === 0) ? qsTr("Off") : qsTr("On") + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + font.pixelSize: 24 + color: (mode_test === 0) ? couleur_rouge : couleur_green_yellow + } + } + } + + + //------------------------------------------------------- + // Ecran haut - centre : Commandes Auto + //------------------------------------------------------- + Rectangle { + id: zone_affichage_haut_centre + x: zone_affichage_haut_gauche.x + zone_affichage_haut_gauche.width + espace_colonnes_principales // Alignement avec les widgets + y: shipheart_hauteur_bandeau_haut + espace_lignes_principales + width: (shipheart_largeur_page * pourcentage_largeur_colonne_centre_haut) - (espace_colonnes_principales) + height: hauteur_utile * pourcentage_hauteur_ligne_haut; + color: shipheart_couleur_fond_bouton +// border.width: (etat !== 0) ? 3 : 0 +// border.color: (etat !== 0) ? couleur_rouge : "transparent" + radius: shipheart_rayon_bouton + visible: (etat_systeme === 0) && (mode_cdes_auto !== -1) + + 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: 18 + font.weight: Font.Bold + color : (mode_cdes_auto === 0) ? couleur_gris_moyen : couleur_green_yellow + opacity: 1//0.8 + } + MouseArea { + id: mouse_area_cdes_auto + anchors.fill: parent + pressAndHoldInterval: shipheart_mouse_press_and_hold_interval_long + onPressed: { + shipheart_clic(); + } + onPressAndHold: { + shipheart_clic(); + toggle_cdes_auto(); + timer_raffraichissement_parametres.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... + } + onClicked: { + maj_liste_events(); + boite_information.open(); + } + } + + // 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: (mode_cdes_auto === 0) ? couleur_gris_moyen : couleur_green_yellow + opacity: 0.2 + visible: mouse_area_cdes_auto.pressed + } + } + + + + //------------------------------------------------------- + // Ecran haut - droite : Messages d'alerte + //------------------------------------------------------- + Rectangle { + id: zone_affichage_haut_droite + x: zone_affichage_haut_centre.x + zone_affichage_haut_centre.width + espace_colonnes_principales + y: shipheart_hauteur_bandeau_haut + espace_lignes_principales + width: (shipheart_largeur_page * (1 - pourcentage_largeur_colonne_gauche_haut - pourcentage_largeur_colonne_centre_haut)) + - (espace_colonnes_principales / 2) // 1/2 de l'espace entre cette zone et la zone centrale (à gauche donc) + - largeur_bouton_suite - (espace_colonnes_secondaires / 2) // Espace à gauche pour s'aligner avec les widgets + height: hauteur_utile * pourcentage_hauteur_ligne_haut; + color: "transparent" + border.width: 3 + border.color: couleur_rouge + radius: shipheart_rayon_bouton + visible: (etat_systeme === 0) && (texte_alerte !== "") + + Image { + id: picto_alerte + source: source_picto_alerte + sourceSize.height: 30; + anchors { + left: parent.left + leftMargin: 20 + verticalCenter: parent.verticalCenter + } +// visible: (texte_alerte !== "") + } + 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 - 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: texte_alerte; + anchors { + left: picto_alerte.right + verticalCenter: parent.verticalCenter + } + font.pixelSize: 16 + color: couleur_blanc_casse +// visible: (texte_alerte !== "") + } + } + + + + + + //------------------------------------------------------- + // Ecran milieu : Widgets + //------------------------------------------------------- + Rectangle { + id: zone_affichage_milieu + x: 0 + y: shipheart_hauteur_bandeau_haut + zone_affichage_haut_gauche.height + (2 * espace_lignes_principales); + width: shipheart_largeur_page + height: hauteur_utile * pourcentage_hauteur_ligne_milieu; + color: "transparent" + visible: (etat_systeme === 0) + + + + //-------------------- + // Grille principale: + GridView { + id : grille_donnees_principale + + property int index_base_en_cours: 0 // Utilsé pour stocker l'index du premier widget affiché à gauche + + highlightRangeMode: GridView.StrictlyEnforceRange // Nécessaire pour que 'index_base_en_cours' soit mis à jour. Au passage, autorise de faire défiler les widgets jusqu'à ne garder que le dernier visible (pas génant et même plutôt sympa...) + width: parent.width - (2 * largeur_bouton_suite) + height: parent.height + cellWidth: width / nombre_widgets_par_ligne + cellHeight: height + flow: GridView.FlowTopToBottom // Items are laid out from top to bottom, and the view scrolls horizontally + snapMode: GridView.SnapToRow // L'arret de l'affichage se fera sur une rangée entière + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + clip: true // Nécessaire pour que les Delegates s'arretent à l'intérieur de la GridView + model: ListModel { } + + onMovementEnded: { + index_base_en_cours = currentIndex; // Capte la valeur de currentIndex aà la fin du mouvement (la valeur vaut alors l'index du widget le plus à gauche). Si on ne le capte pas, la valeur de CurrentIndex repasse à 0 après l'arrêt du flicker (pourquoi...???) + } + + delegate: Rectangle { // Permet d'occuper toute la cellule de la grille + width: grille_donnees_principale.cellWidth + height: grille_donnees_principale.cellHeight + color: "transparent" + + Rectangle { // Permet d'avoir un bouton plus petit que la cellule de la grille et de le centrer sur la cellule (=> espace entre boutons) + width: parent.width - espace_colonnes_secondaires; + height: parent.height - espace_lignes_secondaires; + color: (id_variable === model.id_var) ? shipheart_couleur_fond_bouton_actif : shipheart_couleur_fond_bouton + radius: shipheart_rayon_bouton + anchors { + verticalCenter: parent.verticalCenter + horizontalCenter: parent.horizontalCenter + } + + //----------------------------------- + // Titre : + Text { + id: titre + text: model.titre + padding: 10 + font.pixelSize: 18 + color: couleur_blanc_casse + } + + //----------------------------------- + // Valeur courante : + Text { + id: valeur + text: model.valeur + anchors { + verticalCenter: parent.verticalCenter + verticalCenterOffset: 10 // Permet de 'rencentre' du fait de l'affichage du nom de la batterie et que le titre du widget est plus gros que l'alerte basse ou haute + horizontalCenter: parent.horizontalCenter + horizontalCenterOffset: -20 // Permet de garder l'ensemble 'valeur + unité) centré sans utiliser un conteneur spécial + } + font.family: "Montserrat" + font.pixelSize: 60 + font.weight: Font.Black + color: (model.etat <= 0) ? + ( ((model.type_couleur !== 0) && (model.valeur < 0)) ? + couleur_orange : + couleur_blanc_casse ) : + couleur_rouge + } + Text { + id: unite + text: model.unite + anchors { + baseline: valeur.baseline + left: valeur.right + } + leftPadding: 20 + font.pixelSize: 20 +// color: (model.etat === 0) ? couleur_blanc_casse : couleur_rouge + color: couleur_blanc_casse + } + + //----------------------------------- + // Nom de batterie : + Image { + id: batterie_icone + source: (id_variable === model.id_var) ? "/images/batterie.png" : "/images/batterie_sombre.png" + sourceSize.width: 20 + anchors { + top: parent.top + topMargin: 50 + left: parent.left + leftMargin: 10 + } + visible: (id_var === tension_id_variable) && (nom_batterie !== "") + } + Text { + id: batterie_nom + text: nom_batterie + anchors { + verticalCenter: batterie_icone.verticalCenter + left: batterie_icone.right + leftMargin: 5 + } + font.pixelSize: 10 + color: (id_variable === model.id_var) ? couleur_blanc_casse : couleur_gris_moyen + visible: batterie_icone.visible + } + + //----------------------------------- + // Zone de clic principale : + MouseArea{ + anchors.fill : parent + onClicked: { + shipheart_clic(); + raz_zoom(); // Au-delà de la fonctionnalité, c'est obligatoire sinon, le raffraichissement des la courbe est bloqué au niveau du timer + if (id_variable === model.id_var) // Toggle pour revenir à la consigne si aucun widget n'est sélectionné + { + if ((type_module !== shipheart_type_module_shipbase) || (no_circuit !== 0)) // Le circuit ShipHeart est le seul à ne pas avoir de consigne... + { + id_variable = consigne_id_variable; + symbole_unite = consigne_unite_variable; + } + } + else + { + id_variable = model.id_var; + symbole_unite = model.unite; + } + busy_indicator.running = true; + timer_raffraichissement_graphiques.interval = periode_init_raffraichissement_graphiques; // Cela permet de lancer le "busy_indicator' avant de faire la mise à jour de la courbe + } + } + + //----------------------------------- + // Alarmes : + Rectangle { + id: zone_alarmes + width: parent.width + height: 50 + color: shipheart_couleur_fond_bouton + radius: shipheart_rayon_bouton + anchors { + left: parent.left + bottom: parent.bottom + } + visible: model.etat >= 0 + + Image { + source: (model.etat === 0) ? "/images/cloche_sombre.png" : "/images/cloche_rouge.png" + sourceSize.height: 20 + anchors { + verticalCenter: zone_alarmes.verticalCenter + horizontalCenter: zone_alarmes.horizontalCenter + } + } + + //----------------------------------- + // Zone de clics dédiée aux alarmes : + MouseArea{ + anchors.fill: zone_alarmes + + onClicked: { + shipheart_clic(); + boite_dialogue_liste_alarmes.id_variable = model.id_var; + boite_dialogue_liste_alarmes.titre_widget = model.titre; + boite_dialogue_liste_alarmes.unite = model.unite; + boite_dialogue_liste_alarmes.open(); + } + } + } + } + } + } // Fin de Gridview + + // Flèche de suite gauche : + Image { + anchors.verticalCenter: grille_donnees_principale.verticalCenter + anchors.right: grille_donnees_principale.left + source: "/images/fleche_suite_gauche_sombre.png" + width: largeur_bouton_suite + height: grille_donnees_principale.height - espace_lignes_secondaires + opacity: 0.5 + visible: (!grille_donnees_principale.moving) && // Permet de ne pas afficher la flèche pendant le mouvement (surtout génant à cause du lag généré par la fin du mouvement qui est assez lent). + (grille_donnees_principale.index_base_en_cours > 0) + } + + // Flèche de suite droite : + Image { + anchors.verticalCenter: grille_donnees_principale.verticalCenter + anchors.left: grille_donnees_principale.right + source: "/images/fleche_suite_droite_sombre.png" + width: largeur_bouton_suite + height: grille_donnees_principale.height - espace_lignes_secondaires + opacity: 0.5 + visible: (!grille_donnees_principale.moving) && // Permet de ne pas afficher la flèche pendant le mouvement (surtout génant à cause du lag généré par la fin du mouvement qui est assez lent). + ((grille_donnees_principale.count - grille_donnees_principale.index_base_en_cours) > (nombre_widgets_par_ligne * (grille_donnees_principale.height / grille_donnees_principale.cellHeight))) // le calcul 'height/cellheight' donne le nombre de lignes de widget (généralement, 1 ou 2) + } + + } // Fin des Widgets + + + + //------------------------------------------------------- + // Ecran bas : + //------------------------------------------------------- + Rectangle { + id: zone_affichage_bas + x: 0 + y: shipheart_hauteur_bandeau_haut + zone_affichage_haut_gauche.height + zone_affichage_milieu.height + (3 * espace_lignes_principales); + width: shipheart_largeur_page; + height: hauteur_utile * pourcentage_hauteur_ligne_graphique; + color: "transparent" + visible: (etat_systeme === 0) && (id_variable !== -1) + + + + //=================================== + // Consommation d'énergie + Rectangle { + id: zone_affichage_energie + x: 0 + y: 0 + width: (parent.width * pourcentage_largeur_graphique) - espace_colonnes_secondaires; + height: parent.height + color: "transparent" + visible: (id_variable === 0) + + + GridView { + id : grille_energie + width: parent.width + height: parent.height + cellWidth: parent.width / grille_energie.model.count + cellHeight: parent.height + flow: GridView.FlowTopToBottom // Items are laid out from top to bottom, and the view scrolls horizontally + 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 { // Permet d'occuper toute la cellule de la grille + id: bouton_consommateur + width: grille_energie.cellWidth + height: grille_energie.cellHeight + color: "transparent" + visible: !busy_indicator.running + + // Valeur d'énergie (yc unité) : + Text { + id: valeur_energie + text: (model.valeur !== 0) ? model.valeur.toFixed(model.precision) : "--" + anchors { + top: parent.top + horizontalCenter: parent.horizontalCenter + } + font.weight: (model.hauteur === 1) ? Font.Bold : Font.Normal + font.pixelSize: 13 + color: (model.hauteur === 1) ? + (!flag_periode_en_cours ? couleur_orange : couleur_jaune_post_it) : + ((model.valeur !== 0) ? couleur_blanc_casse : couleur_gris_moyen) + } + Text { + id: unite_energie + text: model.unite + anchors { + top: valeur_energie.bottom + horizontalCenter: parent.horizontalCenter + } + font.pixelSize: 10 + color: (model.valeur !== 0) ? couleur_blanc_casse : couleur_gris_moyen + } + // Bargraph : + Rectangle { + width: model.largeur + color: !flag_periode_en_cours ? couleur_orange : couleur_jaune_post_it + radius: shipheart_rayon_bouton + anchors { + bottom: parent.bottom + bottomMargin: 20 + horizontalCenter: parent.horizontalCenter + } + PropertyAnimation on height { + to: (bouton_consommateur.height - 70) * model.hauteur; // Le '-60' permet de laisser la place à l'énergie et au pourcentage + duration: 500; + } + } + // Date de début principale : + Text { + text: model.debut_principal + anchors { + bottom: parent.bottom + horizontalCenter: parent.horizontalCenter + } + font.pixelSize: 12 + font.weight: Font.Bold + color: couleur_blanc_casse + } + // Date de début secondaire : + Text { + text: model.debut_secondaire + anchors { + bottom: parent.bottom + horizontalCenter: parent.horizontalCenter + } + font.pixelSize: 10 + color: couleur_blanc_casse + } + } + } + + Label { + anchors.fill: parent + horizontalAlignment: Qt.AlignHCenter + verticalAlignment: Qt.AlignVCenter + visible: (grille_energie.model.count === 0) && + (!busy_indicator.running) // Tant que le sablier tourne, on n'affiche pas le texte (car il risque d'y avoir des données ensuite...) + text: qsTr("Aucune consommation d'énergie sur cette période...") + color: couleur_gris_moyen + font.pixelSize: 15 + font.bold: true + wrapMode: Label.Wrap + } + } + + //======================== + // Graphique : + ChartView { + id: graphique + antialiasing: true + anchors { + top: parent.top; + left:parent.left; + bottom:parent.bottom; + margins: -15 // Un peu compliqué mais permet, avec la ligne suivante, ... + } + margins { right: 0; bottom: 0; left: 5; top: 0 } // ... d'annuler les marges. + width: parent.width * pourcentage_largeur_graphique; + backgroundColor: "transparent" + // animationDuration: 10000 + // animationOptions: ChartView.SeriesAnimations + legend {visible: false } + visible: (id_variable !== 0) + + DateTimeAxis { + id: axisX + format: (zoomx_en_cours > 0.5) ? courbe_format_principal_axe_x : courbe_format_zoom_1_axe_x + min: xMin_date + max: xMax_date + tickCount: (zoomx_en_cours > 0.5) ? courbe_nombre_principal_graduations_axe_x : courbe_nombre_zoom_1_graduations_axe_x + //labelsColor: (!flag_zoom_en_cours) ? couleur_blanc_casse : couleur_green_yellow + labelsColor: couleur_blanc_casse + labelsFont: Qt.font({pointSize: 10}) + color: couleur_gris_moyen + shadesColor: courbes_couleur_shades_fond + shadesVisible: true + gridVisible: false + // gridLineColor: "green" + } + ValueAxis { + id: axisY1 + min: yMin_valeur + max: yMax_valeur + tickCount: courbe_nombre_graduations_axe_y + labelFormat: "%." + precision_affichage_axe_y_courbe + "f" +// labelsColor: (!flag_zoom_en_cours) ? couleur_blanc_casse : couleur_green_yellow + labelsColor: couleur_blanc_casse + labelsFont:Qt.font({pointSize: 10}) + color: couleur_gris_moyen + // shadesColor: courbes_couleur_shades_fond + shadesVisible: false + gridVisible: true + gridLineColor: couleur_gris_tres_fonce + titleText: "" + symbole_unite + "" + titleFont { + pointSize: 20 + bold: true + } + } + LineSeries { // Utilisé si on veut renforcer la courbe mais sans avoir tout le tour de l'area renfocée (qui se fait dans AreaSeries pour le coup) + id: courbe_principale + name: "Courbe principale" + axisX: axisX + axisY: axisY1 + capStyle: Qt.RoundCap + style: Qt.SolidLine + width: courbes_epaisseur_bordure + color: shipheart_couleur_bordure_courbes + } + Text { + id: texte_courbe_vide + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + text: qsTr("Aucune donnée n'est disponible pour cette période") + font.pixelSize: 20 + font.weight: Font.Bold + color: "red" + visible: courbe_flag_vide ? true : false; + } + + //--------------------------------- + // Rectangle de sélection de zoom : + Rectangle { + id: rectangle_zoom + x: pinch_area.zoom_x + y: pinch_area.zoom_y + width: pinch_area.zoom_w + height: pinch_area.zoom_h + radius: shipheart_rayon_zoom + + color: couleur_bleu_koriolan_tres_transparent + } + + //--------------------------------- + // Zone de pinch : + PinchArea{ + id: pinch_area + + // Propriété de la eone de zoom pendant toute la phase de sélection : + property real zoom_x: 0 + property real zoom_y: 0 + property real zoom_w: 0 + property real zoom_h: 0 + + anchors.fill: parent // Calé sur 'graphique'. + // Attention : la zone de traçage à l'intérieur de 'graphique' est 'graphique.plotArea'. + // Toutes les coordonnées sont données dans 'graphique' mais on limite à l'usage les coordonnées intérieures à 'graphique.plotArea'. + + //----------------------------------------------- + // Mis à jour en cours de déplacement du pinch : + onPinchUpdated: { + + if ((pinch.point1.x !== pinch.point2.x) || // Il arrive, en fin de pinch, que les 2 points renvoyés soient les mêmes... + (pinch.point1.y !== pinch.point2.y)) // ... Il faut éviter de les traiter sous peine de ramener W et H à 0. + { + // Récupération des données en s'affranchissant de la position des 2 points : + zoom_x = Math.min(pinch.point1.x, pinch.point2.x) + zoom_y = Math.min(pinch.point1.y, pinch.point2.y) + zoom_w = Math.abs(pinch.point1.x - pinch.point2.x) + zoom_h = Math.abs(pinch.point1.y - pinch.point2.y) + + // Limitation de 'x' et 'w' à la largeur de la zone de traçage : + if (zoom_x < graphique.plotArea.x) zoom_x = graphique.plotArea.x; + if (zoom_x > (graphique.plotArea.x + graphique.plotArea.width)) zoom_x = graphique.plotArea.x + graphique.plotArea.width + if ((zoom_x + zoom_w) > (graphique.plotArea.x + graphique.plotArea.width)) zoom_w = (graphique.plotArea.x + graphique.plotArea.width) - zoom_x; + + // Limitation de 'y' et 'h' à la hauteur de la zone de traçage : + if (zoom_y < graphique.plotArea.y) zoom_y = graphique.plotArea.y; + if (zoom_y > (graphique.plotArea.y + graphique.plotArea.height)) zoom_y = graphique.plotArea.y + graphique.plotArea.height + if ((zoom_y + zoom_h) > (graphique.plotArea.y + graphique.plotArea.height)) zoom_h = (graphique.plotArea.y + graphique.plotArea.height) - zoom_y; + } + } + + //------------------------- + // Valeur de fin du pinch : + onPinchFinished: { + // Préparation du zoom sur le rectangle sélectionné : + var r = Qt.rect(zoom_x, zoom_y, zoom_w, zoom_h); + graphique.zoomIn(r); + flag_zoom_en_cours = true; + + zoomx_en_cours *= (zoom_w / graphique.plotArea.width); + + // Effacement du rectangle : + zoom_x = 0 + zoom_y = 0 + zoom_w = 0 + zoom_h = 0 + } + + // Déplacement de la courbe : + MouseArea{ + anchors.fill: parent + drag.target: dragTarget + drag.axis: Drag.XAndYAxis + onClicked: { + shipheart_clic(); + if (!flag_zoom_en_cours) // Si le zoom est en cours, il ne faut PAS lancer le raffraichissement...! + { + busy_indicator.running = true; + timer_raffraichissement_graphiques.interval = periode_init_raffraichissement_graphiques; // Cela permet de lancer le "busy_indicator' avant de faire la mise à jour de la courbe + } + } + onPressAndHold: { + raz_zoom(); + } + } + Item { + id: dragTarget + property real oldX : x // Permet de mémoriser la dernière position d'arrivée + property real oldY : y + + property real cumulX : 0 // Permet de revenir à un déclage nul lorsque nécessaire + property real cumulY : 0 + + onXChanged: { + graphique.scrollLeft( x - oldX ); + cumulX -= (x - oldX); // Le signe '-' permettra ensuite de revenir à le position de départ + oldX = x; + } + + onYChanged: { + graphique.scrollUp( y - oldY ); + cumulY -= (y - oldY); // Le signe '-' permettra ensuite de revenir à le position de départ + oldY = y; + } + } + } + } + + //======================== + // Busy Indicator : + Shipheart_busy_indicator { + id: busy_indicator + } + + //======================== + // Boutons de pếriode : + ColumnLayout { + spacing: 10 + anchors { + top: parent.top; + right:parent.right; + rightMargin: 5; + bottom:parent.bottom; + } + width: (parent.width * (1 - pourcentage_largeur_graphique)) - anchors.rightMargin; + + ListModel { + id: modele_periodes_graphique + } + + Repeater { + model: modele_periodes_graphique + + Rectangle { + color: "transparent" + Layout.preferredWidth: parent.width; + Layout.preferredHeight: (parent.height / nb_boutons_periode) - parent.spacing; + + Text { + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + text: model.libelle + font.pixelSize: 18 + font.weight: (model.index === periode_analyse) ? Font.Bold : Font.Normal + color: couleur_blanc_casse + } + 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 + onClicked: { + shipheart_clic(); + raz_zoom(); // Au-delà de la fonctionnalité, c'est obligatoire sinon, le raffraichissement des la courbe est bloqué au niveau du timer + periode_analyse = model.index; + busy_indicator.running = true; + mise_a_jour_valeur_energie(); // Permet que la mise à jour du widget soit quasi instantanée après l'appui. + timer_raffraichissement_graphiques.interval = periode_init_raffraichissement_graphiques; // Cela permet de lancer le "busy_indicator' avant de faire la mise à jour de la courbe + } + } + // Fond du bouton : + Rectangle { // Permet d'avoir un fond et de pouvoir régler son opacité sans changer celle des textes au-dessus + width: parent.width + height: parent.height + color: (model.index === periode_analyse) ? (flag_zoom_en_cours ? couleur_green_yellow_transparent : shipheart_couleur_fond_bouton_actif) : shipheart_couleur_fond_bouton; + opacity: 0.5 + radius: shipheart_rayon_bouton + } + } + } + } + } + + + //------------------------------------------------------- + // Message d'erreur si circuit Absent + // (le module sur lequel le circuit est configuré n'est pas physiquement présent) + //------------------------------------------------------- + Rectangle { + id: zone_message_absence + x: 0 + y: shipheart_hauteur_bandeau_haut + espace_lignes_principales + width: shipheart_largeur_page + height: shipheart_hauteur_page - shipheart_hauteur_bandeau_haut - shipheart_hauteur_bandeau_bas - espace_lignes_principales + color: "transparent" + visible: (etat_systeme !== 0) + + Rectangle { // Rectangle entouré de rouge + anchors.verticalCenter: parent.verticalCenter + anchors.verticalCenterOffset: -50 + anchors.horizontalCenter: parent.horizontalCenter + width: parent.width + height: parent.height / 2 + radius: shipheart_rayon_bouton + border.width: 3 + border.color: couleur_rouge + color: couleur_rouge_transparent//"transparent" + + Image { // Pictogramme DANGER + anchors.verticalCenter: parent.verticalCenter + anchors.verticalCenterOffset: -100 + anchors.horizontalCenter: parent.horizontalCenter + source: "/images/ak14.png" + sourceSize.height: 70; + } + + Text { // Texte d'info + anchors.verticalCenter: parent.verticalCenter + anchors.verticalCenterOffset: 50 + anchors.horizontalCenter: parent.horizontalCenter + width: parent.width + height : parent.height / 2 + horizontalAlignment: Qt.AlignCenter + verticalAlignment: Qt.AlignVCenter + padding: 50 + text: shipheart_defaut_config_k_bus ? + qsTr("Le module assurant le pilotage de ce circuit n'est pas accessible !

Si des ajouts/suppression/déplacements de modules ont eu lieu récemment, mettez à jour la configuration correspondant dans le menu [Réseau ShipHeart] de [Paramètres Avancés].

Dans le cas où aucune modification n'a été effectuée récemment, vérifier les connexions de tous les modules.") : + qsTr("Ce circuit est configuré comme Non Affecté et n'est donc pas accessible !

Pour accéder à nouveau à ce circuit, merci de l'affecter à un circuit disponible dans le menu [Circuits] de [Paramètres Avancés].") + color: couleur_blanc_casse + font.pixelSize: 18 + wrapMode: Label.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: 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() + } + } + } + } + + //------------------------------------------------------- + // Boite d'information sur les events déclenchannt la commande du circuit : + //------------------------------------------------------- + Shipheart_boite_dialogue { + id: boite_information + imageTitreSource: "/images/event.png" + alignementMessage: Text.AlignLeft + } + + //------------------------------------------------------- + // Boite d'affichage de la liste des alarmes : + //------------------------------------------------------- + Shipheart_boite_dialogue_liste_alarmes { + id: boite_dialogue_liste_alarmes + + titre: nom + type_source: shipheart_source_mesure_circuit + id_source: id_circuit + } + + //=========================================================== + // 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 res, req; + var nb; + var i; + + + //==================================================================== + // Init du nom des périodes du graphique : + modele_periodes_graphique.append({ "libelle": Fonctions_date_heure.nom_periode_analyse(0), "actif": true }); + modele_periodes_graphique.append({ "libelle": Fonctions_date_heure.nom_periode_analyse(1), "actif": true }); + modele_periodes_graphique.append({ "libelle": Fonctions_date_heure.nom_periode_analyse(2), "actif": true }); + modele_periodes_graphique.append({ "libelle": Fonctions_date_heure.nom_periode_analyse(3), "actif": true }); + + //==================================================================== + // Lecture des infos générales concernant le circuit : + req = 'SELECT Nom, Adresse_module, intensite_seuil_haut, No_circuit FROM TB_Circuits WHERE Cle_primaire=' + id_circuit + ' '; +//console.log("Requête = [" + req + "]"); + res = bdd.requete_unique(req); + nom = res[0]; + var adresse_module = Number(res[1]); + intensite_seuil_haut = Number(res[2]); + no_circuit = Number(res[3]); + + if (adresse_module >= 0) // Permet de ne pas effectuer les traitements (qui ne pourront de toutes façons pas se faire !) si le circuit est dévalidé... + { + req = 'SELECT Type FROM TB_Modules_config WHERE Adresse_k_bus=' + adresse_module + ' '; +//console.log("Requête = [" + req + "]"); + res = bdd.requete_unique(req); + type_module = res[0]; + + //==================================================================== + // Recherche de la batterie alimentant le circuit : + if (type_module !== shipheart_type_module_shippower4AC) + { + req = 'SELECT batt.Nom AS Nom_batterie from TB_Circuits AS circ, TB_Modules_config AS module, TB_Batteries as batt WHERE circ.Cle_primaire=' + id_circuit + ' AND circ.Adresse_module=module.Adresse_k_bus AND module.ID_Batterie=batt.Cle_primaire'; +//console.log("Requête = [ " + req + "; ]"); +// res = bdd.requete_unique(req); // SDIR #262 : Début + nb = bdd.requete(req); + if (nb > 0) + { + res = bdd.lecture_ligne(); + nom_batterie = res[0]; + } + else nom_batterie = qsTr("Non défini"); // SDIR #262 : Fin + } + else nom_batterie = ""; + + + //==================================================================== + // Recherche des ID_Variable circuit : + req = ' SELECT Code, Cle_primaire, Unite FROM TB_Variables WHERE Code LIKE "%Circ_%" '; + nb = bdd.requete(req); + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + switch(res[0]) + { + case shipheart_circuit_consigne: + consigne_id_variable = Number(res[1]); + consigne_unite_variable = res[2]; + break; + case shipheart_circuit_tension: + if (type_module !== shipheart_type_module_shippower4AC) + { + tension_id_variable = Number(res[1]); + tension_unite_variable = res[2]; + } + break; + case shipheart_circuit_courant: + intensite_id_variable = Number(res[1]); + intensite_unite_variable = res[2]; + break; + case shipheart_circuit_frequence: + frequence_id_variable = Number(res[1]); + frequence_unite_variable = res[2]; + break; + case shipheart_circuit_puissance: + puissance_id_variable = Number(res[1]); + puissance_unite_variable = res[2]; + break; + case shipheart_circuit_energie: + energie_id_variable = Number(res[1]); + energie_unite_variable = res[2]; + break; + case shipheart_circuit_tension_secteur: + if (type_module === shipheart_type_module_shippower4AC) + { + tension_id_variable = Number(res[1]); + tension_unite_variable = res[2]; + } + break; + default: + break; + } + } + else break; // Ne devrait pas arriver.... + } + + + switch(type_module) + { + case shipheart_type_module_shipbase: + plancher_intensite = shipheart_plancher_intensite_circuit_shipbase; + precision_tension = 2; + precision_intensite = 2; + break; + case shipheart_type_module_shippower812: + case shipheart_type_module_shippower8DC: + plancher_intensite = shipheart_plancher_intensite_circuit_sp8xx; + precision_tension = 2; + precision_intensite = 2; + break; + case shipheart_type_module_shippower4AC: + plancher_intensite = shipheart_plancher_intensite_circuit_sp4ac; + precision_tension = 0; + precision_intensite = 1; + break; + default: + plancher_intensite = 0; + precision_tension = 0; + precision_intensite = 0; + } + + // Choix de la variable par défaut : + if ((type_module === shipheart_type_module_shipbase) && (no_circuit === 0)) // Circuit ShipHeart (le seul à ne pas avoir de consigne...) + { + id_variable = intensite_id_variable; + symbole_unite = intensite_unite_variable; + } + else // Tous les autres circuits + { + id_variable = consigne_id_variable; + symbole_unite = consigne_unite_variable; + } + + // Première mise à jour : + if (id_variable !== -1) // Cas du port USB arrière par exemple qui n'a aucuns mesures (mais qui doit apparaitre pour sa consigne...) + { + mise_a_jour_valeur_energie(); + mise_a_jour_valeurs_instantanees(); + mise_a_jour_courbes(); + } + } + + // Libération du flag : + flag_init = false; + } + + + + //============================================================================================================= + // Mise à jour de la valeur instantanée + //============================================================================================================= + function mise_a_jour_valeurs_instantanees() + { + var req, res; + var nb; + var i; + var adresse_module; + var tens, intens, puiss; + var nb_events; + +//console.time('mise_a_jour_valeurs_instantanées') + + // Requete : + req = 'SELECT '; + req += 'Adresse_module, '; + req += 'Etat_systeme, '; + req += 'Tension, '; + req += 'Intensite, '; + req += 'Frequence, '; + req += 'Intensite_seuil_haut, '; + req += 'Consigne, '; + req += 'Etat, '; + req += 'Etat_commande_carte, '; + req += 'Mode_commande, ' + req += 'Mode_test, '; + req += ' (SELECT COUNT(*) FROM TB_Events WHERE Validite=1 AND (Action_circuits LIKE CONCAT(TB_Circuits.Cle_primaire,"/%") OR Action_circuits LIKE CONCAT("%;", TB_Circuits.Cle_primaire,"/%") ) ) AS nb_events, '; + req += ' Validation_cdes_events '; + req += 'FROM TB_Circuits WHERE Cle_primaire="' + id_circuit + '" '; +//console.log("Requête = [ " + req + "; ]"); + res = bdd.requete_unique(req); + + // Récupération des données : + i = 0; + adresse_module = Number(res[i++]); + etat_systeme = Number(res[i++]); + tens = Number(res[i++]); + tension = tens.toFixed(precision_tension); + intens = Number(res[i++]); + intensite = intens.toFixed(precision_intensite); + frequence = Number(res[i++]).toFixed(2); + intensite_seuil_haut = Number(res[i++]).toFixed(0); + consigne = Number(res[i++]); + etat = Number(res[i++]); + etat_commande_carte = Number(res[i++]); + mode_commande = Number(res[i++]); + mode_test = Number(res[i++]); + nb_events = Number(res[i++]); // Nb d'event Valides (mais pas forcément Visibilite) ayant une Action sur ce circuit. + mode_cdes_auto = Number(res[i++]); // Flag de validation de commande depuis les évènements. + if (nb_events === 0) mode_cdes_auto = -1; // Si aucun event Valide ne pointe sur ce circuit, on n'afffiche même pas le bouton + puiss = tens * intens; + puissance_unite_variable = "W"; // Par défaut + if (puiss < 100) puissance = puiss.toFixed(1); + else if (puiss < 1000) puissance = puiss.toFixed(0); + else + { + puiss /= 1000; + puissance_unite_variable = "kW" + if (puiss < 10) puissance = puiss.toFixed(1); + else puissance = puiss.toFixed(0); + } + + + + // Recherche des éventuelles alarmes provenant des évènements : + var consigne_etat = -1; + var tension_etat = -1; + var intensite_etat = -1; + var frequence_etat = -1; + var puissance_etat = -1; + var energie_etat = -1; + + req = 'SELECT ID_Variable, Etat_test '; + req += ' FROM TB_Events '; + req += ' WHERE Validite=1 '; + req += ' AND Alarme_source>0 '; + req += ' AND Type_source=' + shipheart_source_mesure_circuit + ' '; + req += ' AND ID_Source=' + id_circuit + ' '; +//console.log("Requête = [ " + req + "; ]"); + nb = bdd.requete(req); + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + switch(Number(res[0])) + { + case consigne_id_variable: + if (consigne_etat < Number(res[1])) consigne_etat = Number(res[1]); + break; + case tension_id_variable: + if (tension_etat < Number(res[1])) tension_etat = Number(res[1]); + break; + case intensite_id_variable: + if (intensite_etat < Number(res[1])) intensite_etat = Number(res[1]); + break; + case frequence_id_variable: + if (frequence_etat < Number(res[1])) frequence_etat = Number(res[1]); + break; + case puissance_id_variable: + if (puissance_etat < Number(res[1])) puissance_etat = Number(res[1]); + break; + case energie_id_variable: + if (energie_etat < Number(res[1])) energie_etat = Number(res[1]); + break; + default: + break; + } + } + } + + + // Mise à jour du modèle de la grille principale : + grille_donnees_principale.model.clear(); + + + if ((type_module !== shipheart_type_module_shipbase) || // Pour tous les modules autres que ShipBase... + (no_circuit === 0) || // ou, sur ShipBase, uniquement les circuit 'ShipHeart' ... + (no_circuit === 1) ) // ... ou "ShipHeart-USB" + { + grille_donnees_principale.model.append({ + "titre": Fonctions.nom_variable("Circ_courant"), + "id_var":intensite_id_variable, + "valeur": intensite, + "unite": intensite_unite_variable, + "etat": intensite_etat, + "type_couleur": 0 }) + grille_donnees_principale.model.append({ + "titre": Fonctions.nom_variable("Circ_tension"), + "id_var":tension_id_variable, + "valeur": tension, + "unite": tension_unite_variable, + "etat": tension_etat, + "type_couleur": 0 }) + } + + if (type_module === shipheart_type_module_shippower4AC) + { + grille_donnees_principale.model.append({ + "titre": Fonctions.nom_variable("Circ_frequence"), + "id_var":frequence_id_variable, + "valeur": frequence, + "unite": frequence_unite_variable, + "etat": frequence_etat, + "type_couleur": 0 }) + } + + if ((type_module !== shipheart_type_module_shipbase) || // Pour tous les modules autres que ShipBase... + (no_circuit === 0) || // ou, sur ShipBase, uniquement les circuit 'ShipHeart' ... + (no_circuit === 1) ) // ... ou "ShipHeart-USB" + { + grille_donnees_principale.model.append({ + "titre": Fonctions.nom_variable("Circ_puissance"), + "id_var":puissance_id_variable, + "valeur": puissance, + "unite": puissance_unite_variable, + "etat": puissance_etat, + "type_couleur": 0 }) + grille_donnees_principale.model.append({ + "titre": Fonctions.nom_variable("Circ_energie"), + "id_var":0, + "valeur": energie, + "unite": energie_unite_variable, + "etat": energie_etat, + "type_couleur": 0 }) + } + + + + + // Définition du message d'alerte et du picto associé en fonction de l'état de la carte et du circuit : + if (etat_commande_carte === shipheart_etat_commande_module_undervoltage) + { + texte_alerte = qsTr("Le module pilotant ce circuit n'est pas alimentée correctement.\n Vérifier l'alimentation correspondante.") + source_picto_alerte = "/images/ak14.png" + } + else if (etat_commande_carte === shipheart_etat_commande_module_test) + { + texte_alerte = qsTr("Le module pilotant ce circuit est en mode MANUEL.\n Repositionnez le module en mode AUTO pour commander à nouveau ce circuit normalement.") +// Définir un message spécifique à chaque carte ? Ajout d'une photo ? + + source_picto_alerte = "/images/ak5.png" + } + else + { + if (type_module === shipheart_type_module_shipbase) // Cas particulier de ShipBase : + { + if (no_circuit === 1) + { + switch(etat) + { + case 0 : texte_alerte = ""; break; + case 1: texte_alerte = qsTr("Le port USB du bas est en défaut."); break; + case 2: texte_alerte = qsTr("Le port USB du milieu est en défaut."); break; + case 3: texte_alerte = qsTr("Les 2 ports USB du milieu et du bas sont en défaut."); break; + case 4: texte_alerte = qsTr("Le port USB du haut est en défaut."); break; + case 5: texte_alerte = qsTr("Les 2 ports USB du haut et du bas sont en défaut."); break; + case 6: texte_alerte = qsTr("Les 2 ports USB du haut et du milieu sont en défaut."); break; + case 6: texte_alerte = qsTr("Les 3 ports USB du haut, du milieu et du bas sont en défaut."); break; + default : texte_alerte = qsTr("Etat inconnu...") + } + } + else if (no_circuit === 2) + { + switch(etat) + { + case 0 : texte_alerte = ""; break; + case 1: texte_alerte = qsTr("Le port USB est en défaut."); break; + default : texte_alerte = qsTr("Etat inconnu...") + } + } + else texte_alerte = ""; + } + else // Cas général : + { + switch(etat) + { + case shipheart_etat_circuit_ok: texte_alerte = ""; break; + case shipheart_etat_circuit_limitation: texte_alerte = qsTr("L'alimentation du circuit a été coupée \n car sa limite de courant (%1 A)\n a été dépassée.").arg(intensite_seuil_haut); break; + case shipheart_etat_circuit_protection: texte_alerte = qsTr("L'alimentation du circuit a été coupée \n car les circuits de protection interne ont détecté une anomalie."); break; + case shipheart_etat_circuit_disjonte: texte_alerte = qsTr("L'alimentation du circuit a été coupée \n car le seuil de disjonction du circuit a été dépassé."); break; + case shipheart_etat_circuit_cc_batterie: texte_alerte = qsTr("Le circuit est en court-circuit avec le + batterie."); break; + case shipheart_etat_circuit_deleste: + req = 'SELECT Courant_maxi, Courant_maxi_tempo FROM TB_Modules_config WHERE Adresse_k_bus=' + adresse_module + ' '; + res = bdd.requete_unique(req); + + texte_alerte = qsTr("L'alimentation du circuit a été coupée
car la consommation totale du module a dépassé %1 A pendant plus de %2 secondes (limite du module)").arg(Number(res[0])).arg(Number(res[1])); + break; + case shipheart_etat_circuit_undervoltage: texte_alerte = qsTr("La tension du circuit est anormalement basse."); break; + case shipheart_etat_circuit_inversion_phase_neutre: texte_alerte = qsTr("La phase et le neutre sont inversés sur ce circuit."); break; + case shipheart_etat_circuit_absence_terre: texte_alerte = qsTr("DANGER : Le neutre n'est pas référencé à la terre sur ce circuit (\"absence de terre\")."); break; // SDIR #283 + case shipheart_etat_circuit_absence_masse: texte_alerte = qsTr("La masse est absente du connecteur d'alimentation du module"); break; + default : texte_alerte = qsTr("Etat inconnu...") + } + } + + source_picto_alerte = "/images/ak14.png" + } + +//console.timeEnd('mise_a_jour_valeurs_instantanées') + } + + //============================================================================================================= + // Mise à jour de la valuer de consigne + //============================================================================================================= + function maj_liste_events() + { + var req, res; + var nb; + var i; + + req = " SELECT Type_source, '' AS nom_source, TB_Events.Nom AS nom_event"; + req += " FROM TB_Events"; + req += " WHERE Validite=1 "; + req += " AND Type_source=0 "; + req += " AND (Action_circuits LIKE '" + id_circuit + "/%' OR Action_circuits LIKE '%;" + id_circuit + "/%') "; + req += " UNION"; + req += " SELECT Type_source, tb_source.Nom AS nom_source, TB_Events.Nom AS nom_event"; + req += " FROM TB_Events"; + req += " INNER JOIN TB_Circuits AS tb_source ON TB_Events.ID_Source=tb_source.Cle_primaire"; + req += " WHERE TB_Events.Validite=1 "; + req += " AND Type_source=1 "; + req += " AND (Action_circuits LIKE '" + id_circuit + "/%' OR Action_circuits LIKE '%;" + id_circuit + "/%') "; + req += " UNION"; + req += " SELECT Type_source, tb_source.Nom AS nom_source, TB_Events.Nom AS nom_event"; + req += " FROM TB_Events"; + req += " INNER JOIN TB_Capteurs AS tb_source ON TB_Events.ID_Source=tb_source.Cle_primaire"; + req += " WHERE TB_Events.Validite=1 "; + req += " AND Type_source=2 "; + req += " AND (Action_circuits LIKE '" + id_circuit + "/%' OR Action_circuits LIKE '%;" + id_circuit + "/%') "; + req += " UNION"; + req += " SELECT Type_source, tb_source.Nom AS nom_source, TB_Events.Nom AS nom_event"; + req += " FROM TB_Events"; + req += " INNER JOIN TB_Reservoirs AS tb_source ON TB_Events.ID_Source=tb_source.Cle_primaire"; + req += " WHERE TB_Events.Validite=1 "; + req += " AND Type_source=3 "; + req += " AND (Action_circuits LIKE '" + id_circuit + "/%' OR Action_circuits LIKE '%;" + id_circuit + "/%') "; + req += " UNION"; + req += " SELECT Type_source, tb_source.Nom AS nom_source, TB_Events.Nom AS nom_event"; + req += " FROM TB_Events"; + req += " INNER JOIN TB_Batteries AS tb_source ON TB_Events.ID_Source=tb_source.Cle_primaire"; + req += " WHERE TB_Events.Validite=1 "; + req += " AND Type_source=4 "; + req += " AND (Action_circuits LIKE '" + id_circuit + "/%' OR Action_circuits LIKE '%;" + id_circuit + "/%') "; + req += " ORDER BY Type_source, nom_source, nom_event "; +//console.log("Requête = [ " + req + "; ]"); + nb = bdd.requete(req); + + // Renseignement de la partie fixe du message : + if (nb !== 0) boite_information.message = qsTr("Evènements actuellement actifs qui sont susceptibles de commander ce circuit :"); +// else boite_information.message = qsTr("Aucun évènement actuellement actif n'est sont susceptibles de commander ce circuit."); +// Ne devrait pas arriver... + + // Ajout de chaque évènement trouvé : + boite_information.message += "
    "; + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + boite_information.message += "
  • " + res[2] + "" + (Number(res[0]) !==0 ? (" [" + res[1] + "]") : "") + "
  • "; + } + else break; // Ne devrait pas arriver.... + } + boite_information.message += "
"; + } + + + //============================================================================================================= + // Mise à jour de la valuer de consigne + //============================================================================================================= + function changement_consigne(new_consigne, old_consigne) + { + var req; + + if (new_consigne !== consigne) // Ce cas apparait souvent en fin de mouvement de slider ; il est alors inutile de recharger la même demande vers la BDD puis l'appli... + { + req = "UPDATE TB_Circuits SET New_consigne=" + new_consigne + " "; + if (old_consigne !== -1) req += ", Old_consigne=" + old_consigne + " "; + req += " WHERE Cle_primaire='" + id_circuit + "'"; +//console.log("Requête = [" + req + "]"); + + bdd.requete_unique(req); + synchro_bdd(shipheart_type_synchro_data); + + consigne = new_consigne; // Permet la prise en compte immédiate par toute la page + timer_raffraichissement_parametres.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... + } + } + + + //============================================================================================================= + // Mise à jour de la valeur instantanée + //============================================================================================================= + function toggle_cdes_auto() + { + var req; + + if (mode_cdes_auto > -1) // Si la valeur est -1, c'est qu'aucun Event valide ne pointe sur ce circuit et on ne devrait pas arriver là... + { + if (mode_cdes_auto === 0) mode_cdes_auto = 1; + else mode_cdes_auto = 0; + + bdd.requete_unique("UPDATE TB_Circuits SET Validation_cdes_events=" + mode_cdes_auto + " WHERE Cle_primaire='" + id_circuit + "'") + } + } + + //============================================================================================================= + // Mise à jour de la valeur globale de l'énergie consommée sur la période en cours + //============================================================================================================= + function mise_a_jour_valeur_energie() + { + var req, res; + var i; + var date_debut, date_fin; + var type_mesure; + var total; + + +//console.time('calcul_valeur_energie') + + // Dates et durée : + date_fin = new Date(); // En UTC + date_debut = Fonctions_date_heure.date_add_secondes(date_fin, -(Fonctions_date_heure.duree_periode_analyse(periode_analyse))); // En UTC +//console.log("Date de début initiale UTC = " + date_debut + " et date de fin UTC = " + date_fin) + + // Ajustements à l'intervalle fini d'analyse : + var debut_fin = Fonctions_date_heure.ajustement_periode_analyse(periode_analyse, date_debut, date_fin, shipheart_fuseau_horaire, shipheart_heure_ete); + switch(periode_analyse) + { + default: + case 0: // 1 heure + type_mesure=3; + break; + case 1: // 24 heures + case 2: // 7 jours + case 3: // 30 jours + type_mesure=2; + break; + } + + // Requete : + req = ' SELECT'; + req += ' SUM(Valeur)'; + req += ' FROM TB_Mesures_circuits'; + req += ' WHERE ID=' + id_circuit + ' AND'; + req += ' ID_Variable=' + energie_id_variable + ' AND'; + req += ' Type=' + type_mesure + ' AND'; + req += ' Date>="' + Fonctions_date_heure.chaine_date_heure_bdd(debut_fin.debut) + '" AND'; + req += ' Date<="' + Fonctions_date_heure.chaine_date_heure_bdd(debut_fin.fin) + '"'; +// req += ' ORDER BY Date '; // Pas utile pour faire la somme au final... +//console.log("Requête = [" + req + "]"); + res = bdd.requete_unique(req); + total = Number(res[0]); + + // Mise en forme du résultat : + energie_unite_variable = "Wh"; // Par défaut + if (total < 100) energie = total.toFixed(1); + else if (total < 1000) energie = total.toFixed(0); + else + { + total /= 1000; + energie_unite_variable = "kWh" + if (total < 10) energie = total.toFixed(1); + else energie = total.toFixed(0); + } + + // Mise à jour immédiate du modele (sinon, il faudra attendre mise_a_jour_valeurs_instantanées()) : + for (i = 0; i < grille_donnees_principale.model.count; i ++) + { + if (grille_donnees_principale.model.get(i).id_var === 0) + { + grille_donnees_principale.model.setProperty(i, "valeur", energie); + grille_donnees_principale.model.setProperty(i, "unite", energie_unite_variable); + } + } + +//console.timeEnd('calcul_valeur_energie') + } + + + //============================================================================================================= + // Consommation d'énergie du circuit entre dates + // Attention : cette fonction marche à tous les coups puisqu'elle va chercher les mesures de puissance du circuit et + // recalcule complètement l'énergie correspondante. Mais elle a un coût d'environ 200-250ms par appel !! + // Par comparaison, calculer TOUTES les barres d'énergie sur 30 jours en se basant sur les mresures de type 2 + // coûte 30ms environ... Le calcul de la dernière barre "en cours" côute donc 10 fois plus que toutes les autres + // réunies...! + //============================================================================================================= + function conso_energie_intervalle(date_debut, date_fin) + { + var req, res; + var nb; + var chaine_date_debut = Fonctions_date_heure.chaine_date_heure_bdd(date_debut); + var chaine_date_fin = Fonctions_date_heure.chaine_date_heure_bdd(date_fin); + + +//console.time('maj_energie') + + req = 'SELECT (SUM(Duree * Puissance) / 3600) AS Energie '; // 3600 secondes. NB : la division a intérêt à être faite sur la somme (et non la somme des divisions...) + req += ' FROM ( '; + req += ' SELECT '; + req += ' IFNULL'; // Return the specified value IF the expression is NULL, otherwise return the expression ie on convertit les valeurs NULL en 0. + req += ' (mesures.Valeur, 0) as Puissance, '; // Contrairement aux calculs usuels d'intégrale, la forme de stockage des mesures ne nécessite de connaitre que la valeur du point de début d'intervalle. + req += ' ( UNIX_TIMESTAMP('; + req += ' COALESCE('; // Returns the first non-null value in a list + req += ' LEAST(LEAD(mesures.Date) OVER (ORDER BY mesures.Date), "' + chaine_date_fin + '"),'; // "Plus petit" entre [date de la prochaine mesure] et [date de fin] ou NULL si l'un au moins est NULL (cas du dernier point de l'intervalle avec aucun point au-delà). + req += ' LEAD(mesures.Date) OVER (ORDER BY mesures.Date),'; // Date de la prochaine mesure (qui peut être NULL si on est sur le dernier point et qu'aucun point ultérieur n'existe) + req += ' "' + chaine_date_fin + '")) '; // Date de fin qui est forcément non NULL... + req += ' - '; + req += ' UNIX_TIMESTAMP('; + req += ' GREATEST(mesures.Date, "' + chaine_date_debut + '"))'; // "Plus grand" entre [date de mesure] et [date de début]. NB : contrairement à la fin de la période, aucune de ces deux valeurs ne peut être nulle... + req += ' ) as Duree'; // en secondes, entre le point en cours (ou la date de début si on est sur le point "ajouté") et le point suivant (ou la date de fin si on est sur le dernier point de l'intervalle) + req += ' FROM ('; + req += ' (SELECT Date, Valeur FROM TB_Mesures_circuits WHERE ID_Variable=' + puissance_id_variable + ' AND Date>="' + chaine_date_debut + '" AND Date<="' + chaine_date_fin + '" AND ID=' + id_circuit + ') '; // Tous les points dans l'intervalle (y compris ceux avec la valeur NULL) + req += ' UNION '; + req += ' (SELECT Date, Valeur FROM TB_Mesures_circuits WHERE ID_Variable=' + puissance_id_variable + ' AND Date<="' + chaine_date_debut + '" AND ID=' + id_circuit + ' ORDER BY Date DESC LIMIT 1) '; + req += ' ) AS mesures '; + req += ' ) AS valeurs '; +//console.log("Requête = [" + req + "]"); + res = bdd.requete_unique(req); + +//console.timeEnd('maj_energie') + + return(Number(res[0])); + } + + + + //============================================================================================================= + // Mise à jour des données des courbes + //============================================================================================================= + function mise_a_jour_courbes() + { + var req, res; + var nb; + var i; + var courbe_principale_duree; + var date_debut, date_fin; + var date_debut_intervalle, date_fin_intervalle; + var date_debut_intervalle_locale; + var mini_maxi; + var type_mesure; + var valeur; + var precision; + var unite; + var max; + var largeur_bargraph; + var texte_debut_principal; + var texte_debut_secondaire; + var regroupement; + + +console.time('mise_a_jour_courbes') + + //======================================================= + // Elements communs à tous les type de graphique : + + // Dates et durée : + courbe_principale_duree = Fonctions_date_heure.duree_periode_analyse(periode_analyse); // En secondes + date_fin = new Date(); // En UTC + date_debut = Fonctions_date_heure.date_add_secondes(date_fin, -(courbe_principale_duree)); // En UTC +//console.log("Date de début initiale UTC = " + date_debut + " et date de fin UTC = " + date_fin) + + + //======================================================= + // Barres d'énergie : + if (id_variable === 0) + { + max = 0; + + grille_energie.model.clear(); + + // Ajustements à l'intervalle fini d'analyse : + var debut_fin = Fonctions_date_heure.ajustement_periode_analyse(periode_analyse, date_debut, date_fin, shipheart_fuseau_horaire, shipheart_heure_ete); + + switch(periode_analyse) + { + default: + case 0: // 1 heure + type_mesure=3; + courbe_nombre_principal_graduations_axe_x = 13; + largeur_bargraph = 40; + regroupement = ""; + break; + + case 1: // 24 heures + type_mesure=2; + courbe_nombre_principal_graduations_axe_x = 25; + largeur_bargraph = 35; + regroupement = ""; + break; + + case 2: // 7 jours + type_mesure=2; + courbe_nombre_principal_graduations_axe_x = 29; + largeur_bargraph = 30; + regroupement = "(6*60*60)"; + break; + + case 3: // 30 jours + type_mesure=2; + courbe_nombre_principal_graduations_axe_x = 31; + largeur_bargraph = 28; + regroupement = "(24*60*60)"; + break; + } + + // Recherche des data dans la BDD : + req = ' SELECT'; + if (regroupement === "") req += ' Valeur,'; + else req += ' SUM(Valeur),'; // Somme des valeurs uniquement si un regroupement est nécessaire (sinon, on obtient une seule valeur !) + if (regroupement === "") req += ' Date'; + else req += ' MAX(Date)'; // Max des dates du groupe est obligatoire en cas de regoupement, sous peine de résultats aléatoires ! + req += ' FROM TB_Mesures_circuits'; + req += ' WHERE ID=' + id_circuit + ' AND'; + req += ' ID_Variable=' + energie_id_variable + ' AND'; + req += ' Type=' + type_mesure + ' AND'; + req += ' Date>="' + Fonctions_date_heure.chaine_date_heure_bdd(debut_fin.debut) + '" AND'; + req += ' Date<="' + Fonctions_date_heure.chaine_date_heure_bdd(debut_fin.fin) + '"'; + if (regroupement !== "") req += ' GROUP BY (UNIX_TIMESTAMP(Date) - UNIX_TIMESTAMP("' + Fonctions_date_heure.chaine_date_heure_bdd(debut_fin.debut) + '")) DIV ' + regroupement + ' '; + req += ' ORDER BY Date '; +//console.log("Requête = [" + req + "]"); + nb = bdd.requete(req); + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + // Récupération des données de l'intervalle : + valeur = Number(res[0]); + date_fin_intervalle = Fonctions_date_heure.chaine_bdd_date_heure(res[1]); + date_debut_intervalle = Fonctions_date_heure.date_add_secondes(date_fin_intervalle, -((courbe_principale_duree / (courbe_nombre_principal_graduations_axe_x - 1)) - 1) ); + + // Calcul du 'max' (en Wh) : + if (max < valeur) max = valeur; + + // Ajout de l'intervale au modèle : + grille_energie.model.append({"debut_intervalle": date_debut_intervalle, "debut_principal": "", "debut_secondaire": "", "valeur": valeur, "precision": 0, "unite": "", "hauteur": 0.0, "largeur": largeur_bargraph, "flag_periode_en_cours": false }); + } + else break; // Ne devrait pas arriver.... + } + + //------------------------------------------------------------------------- + // Calcul de l'échantillon "période en cours" (qui se termine MAINTENANT) : + // NOTA : la ligne suivnte représente environ 200-250ms, soit 90% du temps total de traitement...! + valeur = conso_energie_intervalle(debut_fin.fin, date_fin); +//console.log("DERNIER INTERVALLE : Début intervalle UTC = " + debut_fin.fin + " et fin d'intervalle UTC = " + date_fin); + + // Calcul du 'max' (en Wh) avec le dernier intervalle : + if (max < valeur) max = valeur; + + // Ajout du dernier intervalle au modèle : + grille_energie.model.append({"debut_intervalle": debut_fin.fin, "debut_principal": "", "debut_secondaire": "", "valeur": valeur, "precision": 0, "unite": "", "hauteur": 0.0, "largeur": largeur_bargraph, "flag_periode_en_cours": true }); + + + //--------------------------------------------------- + // Mise à jour des autres informations du circuit : + // NB : on est obligé de faire cette mise à jour en deuxième passe car on doit d'abord avoir le MAX calculé lors de la précédente... + if (max > 0) + { + for(i = 0; i < grille_energie.model.count; i++) + { + // Récupéartion de la valeur brute de l'échantillon : + valeur = grille_energie.model.get(i).valeur; + + // Calcul de la hauteur de la barre : + // NB : à faire avant ajustement de la valeur en kWh !! + grille_energie.model.setProperty(i, "hauteur", (valeur / max)); + + // Calcul de l'unité et de la précision d'affichage en fonction de la valeur : + unite = "Wh"; // Par défaut + if (valeur < 100) precision = 1; + else if (valeur < 1000) precision = 0; + else + { + valeur /= 1000; + grille_energie.model.setProperty(i, "valeur", valeur); // Dans ce cas, il faut mettre à jour la valeur dans le modèle... + unite = "kWh" + if (valeur < 10) precision = 1; + else precision = 0; + } + grille_energie.model.setProperty(i, "precision", precision); + grille_energie.model.setProperty(i, "unite", unite); + + // Calcul des dates de début principales et secondaires de l'échantillon avec le format associé : + date_debut_intervalle = grille_energie.model.get(i).debut_intervalle; + date_debut_intervalle_locale = Fonctions_date_heure.date_courante(date_debut_intervalle, shipheart_fuseau_horaire, shipheart_heure_ete); + + // Détermination des légendes de temps : + switch(periode_analyse) + { + default: + case 0: // 1 heure + texte_debut_principal = Qt.formatDateTime(date_debut_intervalle_locale, "HH:mm"); + texte_debut_secondaire = ""; + break; + + case 1: // 24 heures + if (Math.trunc(date_debut_intervalle_locale.getHours() % 6) === 0) + { + texte_debut_principal = Qt.formatDateTime(date_debut_intervalle_locale, "HH:mm"); + texte_debut_secondaire = ""; + } + else + { + texte_debut_principal = ""; + texte_debut_secondaire = Qt.formatDateTime(date_debut_intervalle_locale, "HH:mm"); + } + break; + + case 2: // 7 jours + if (date_debut_intervalle_locale.getHours() === 0) + { + texte_debut_principal = Qt.formatDateTime(date_debut_intervalle_locale, "dd/MM"); + texte_debut_secondaire = ""; + } + else + { + texte_debut_principal = ""; + texte_debut_secondaire = Qt.formatDateTime(date_debut_intervalle_locale, "HH:mm"); + } + break; + + case 3: // 30 jours + texte_debut_principal = Qt.formatDateTime(date_debut_intervalle_locale, "dd"); + texte_debut_secondaire = ""; + break; + } + grille_energie.model.setProperty(i, "debut_principal", texte_debut_principal); + grille_energie.model.setProperty(i, "debut_secondaire", texte_debut_secondaire); + } + } + else grille_energie.model.clear(); // Si le MAX vaut 0Wh, on peut supprimer toutes les entrées car elles sont toutes nulles... + + } + + //======================================================= + // Courbes des variables (autre qu'énergie) : + else + { + // Paramètres de la courbe dépendant de la période d'analyse : + switch(periode_analyse) + { + default: + case 0: // 1 heure + courbe_nombre_principal_graduations_axe_x = 7 // Nombre de bandes verticales + 1 + courbe_nombre_zoom_1_graduations_axe_x = 7 // Utilisé lorsque le taux de zoom passe en-dessous de 0.5 + courbe_format_principal_axe_x = "HH:mm" // exemple : "yyyy-MM-dd HH:mm:ss" + courbe_format_zoom_1_axe_x = "HH:mm" // Utilisé lorsque le taux de zoom passe en-dessous de 0.5 + break; + + case 1: // 24 heures + courbe_nombre_principal_graduations_axe_x = 13 // Nombre de bandes verticales + 1 + courbe_nombre_zoom_1_graduations_axe_x = 13 // Utilisé lorsque le taux de zoom passe en-dessous de 0.5 + courbe_format_principal_axe_x = "HH:mm" // exemple : "yyyy-MM-dd HH:mm:ss" + courbe_format_zoom_1_axe_x = "HH:mm" // Utilisé lorsque le taux de zoom passe en-dessous de 0.5 + break; + + case 2: // 7 jours + courbe_nombre_principal_graduations_axe_x = 8 // Nombre de bandes verticales + 1 + courbe_nombre_zoom_1_graduations_axe_x = 8 // Utilisé lorsque le taux de zoom passe en-dessous de 0.5 + courbe_format_principal_axe_x = "dd/MM HH:mm" // exemple : "yyyy-MM-dd HH:mm:ss" + courbe_format_zoom_1_axe_x = "HH:mm" // Utilisé lorsque le taux de zoom passe en-dessous de 0.5 + break; + + case 3: // 30 jours + courbe_nombre_principal_graduations_axe_x = 31 // Nombre de bandes verticales + 1 + courbe_nombre_zoom_1_graduations_axe_x = 13 // Utilisé lorsque le taux de zoom passe en-dessous de 0.5 + courbe_format_principal_axe_x = "dd" // exemple : "yyyy-MM-dd HH:mm:ss" + courbe_format_zoom_1_axe_x = "HH:mm" // Utilisé lorsque le taux de zoom passe en-dessous de 0.5 + break; + } + + // Mise à jour des données de la courbe principale : + res = tbmesuresModel.maj_data(graphique.series("Courbe principale"), "TB_Mesures_circuits", id_circuit, id_variable, date_debut, date_fin, 1, 1, (shipheart_fuseau_horaire + shipheart_heure_ete), 0, 0); + + //----------------------------------------------------------------------------------------------------- + // Cas où aucune donnée n'est disponible sur la période : + if (Number(res[0]) === 0) + { + courbe_flag_vide = true; // Permet d'afficher le texte "Aucune donnée disponible..." sur la zone graphique + } + //----------------------------------------------------------------------------------------------------- + // Cas où des données sont disponibles sur la période (cas normal donc...) : + else + { + courbe_flag_vide = false; + +//console.log("Min val=" + Number(res[6]) + " et mini=" + yMin_valeur + " - Max val=" + Number(res[8]) + " et maxi=" + yMax_valeur); + xMin_date = new Date(Number(res[1])); // Nécessaire pour la Min de l'axe X (NB : les dates retournées par 'maj_data' sont en heure locale) + xMax_date = new Date(Number(res[3])); // Nécessaire pour la Max de l'axe X (NB : les dates retournées par 'maj_data' sont en heure locale) + mini_maxi = Fonctions.ajustement_mini_maxi(Number(res[6]), Number(res[8]), courbe_nombre_graduations_axe_y); + yMin_valeur = mini_maxi.mini // Nécessaire pour le Min de l'axe Y + yMax_valeur = mini_maxi.maxi // Nécessaire pour le Max de l'axe Y + precision_affichage_axe_y_courbe = Fonctions.precision_affichage_mini_maxi(Number(res[6]), Number(res[8]), courbe_nombre_graduations_axe_y); + + + } + } + +console.timeEnd('mise_a_jour_courbes') + + // Arrêt du sablier : + busy_indicator.running = false; // Arrêt du tourniquet s'il est en marche + } + + + + //============================================================================================================= + // RAZ du zoom + //============================================================================================================= + function raz_zoom() + { + + graphique.zoomReset(); // RAZ du zoom proprement dit + graphique.scrollLeft(dragTarget.cumulX); // RAZ du déplacement horizontal par annulation du cumul + graphique.scrollUp(dragTarget.cumulY); // RAZ du déplacement vertical par annulation du cumul + + dragTarget.cumulX = 0; // RAZ du cumul après retour à la position d'origine + dragTarget.cumulY = 0; + + flag_zoom_en_cours = false; + zoomx_en_cours = 1; + } + + +} + diff --git a/config_acces_parametres.qml b/config_acces_parametres.qml new file mode 100644 index 0000000..ac95b2a --- /dev/null +++ b/config_acces_parametres.qml @@ -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 "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; itype de batterie(s) va nécessiter la remise en configuration usine de certains paramètres.

Si vous ne souhaitez pas que cette reconfiguration soit effectuée, notamment si vous avez effectué des réglages spécifiques, cliquez sur ANNULER.

Sinon, cliquez sur CONFIRMER pour valider le changement."); + boite_information.boutonOkTexte = qsTr("Confirmer") + boite_information.boutonAnnuler = true + boite_information.type = type_boite_information_alerte_changement_type; + boite_information.open(); + } + else // Sinon, on prend immédiatement en compte le changement : + { + if (model.get(currentIndex).valeur !== 0) // Dans le cas où on passe à "Non défini", on ne traite rien et on garde la valeur précédente (aisni, si on revient ensuite sur la version initiale, on n'affichera pas le message d'alerte...) + { + type_batterie = model.get(currentIndex).valeur; + maj_valeurs_par_defaut_type_batterie(); + } + } + } + } + + Shipheart_formulaire_ligne_separation { + haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse + } + } + + //------------------------------------------------------------------------------- + // Ligne de formulaire : Tension_nominale + Rectangle { + width: parent.width + height: visible ? hauteur_ligne_formulaire : 0 + color: "transparent" + visible: (champ_formulaire_Type_entrees.currentIndex !== 0) && (champ_formulaire_Type.currentIndex !== 0) + + Shipheart_formulaire_label { + text: qsTr("Tension nominale") + width: parent.width * pourcentage_largeur_labels_formulaire + couleur: (champ_formulaire_Tension_nominale.currentIndex !== 0) + ? shipheart_formulaire_couleur_texte_par_defaut + : shipheart_formulaire_couleur_texte_en_erreur + } + + Shipheart_formulaire_combobox { + id: champ_formulaire_Tension_nominale + model: ListModel { } + width: parent.width * (1 - pourcentage_largeur_labels_formulaire) + onActivated: { + shipheart_clic(); + + if (model.get(currentIndex).valeur === 0) affichage_avance = false; // Dévalide le mode avancé si on revient à un état inconnu... + + if ((id_batterie !== 0) && // Si on n'est pas en phase de création... + (model.get(currentIndex).valeur !== tension_nominale) && // ... et qu'on change la tension nominale... + (model.get(currentIndex).valeur !== 0)) // ... et que la nouvelle valeur n'est pas "non définie" + { + shipheart_clic(); + boite_information.niveau = 1 + boite_information.imageTitreSource = "/images/attention.png" + boite_information.message = qsTr("La modification de la tension nominale du parc de batteries va nécessiter la remise en configuration usine de certains paramètres.

Si vous ne souhaitez pas que cette reconfiguration soit effectuée, notamment si vous avez effectué des réglages spécifiques, cliquez sur ANNULER.

Sinon, cliquez sur CONFIRMER pour valider le changement."); + boite_information.boutonOkTexte = qsTr("Confirmer") + boite_information.boutonAnnuler = true + boite_information.type = type_boite_information_alerte_changement_tension; + boite_information.open(); + } + else // Sinon, on prend immédiatement en compte le changement : + { + if (model.get(currentIndex).valeur !== 0) // Dans le cas où on passe à "Non défini", on ne traite rien et on garde la valeur précédente (aisni, si on revient ensuite sur la version initiale, on n'affichera pas le message d'alerte...) + { + tension_nominale = champ_formulaire_Tension_nominale.model.get(champ_formulaire_Tension_nominale.currentIndex).valeur; + } + } + } + } + + Shipheart_formulaire_ligne_separation { + haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse + } + } + + //------------------------------------------------------------------------------- + // Ligne de formulaire : Capacite_1 + Rectangle { + width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2) + height: visible ? hauteur_ligne_formulaire : 0 + color: "transparent" + visible: (champ_formulaire_Type_entrees.currentIndex !== 0) && + (champ_formulaire_Type.currentIndex !== 0) && + (champ_formulaire_Tension_nominale.currentIndex !== 0) +// && (type_entrees === shipheart_batteries_type_entrees_ibs) + + Shipheart_formulaire_label { // Label : + text: qsTr("Capacité") + width: parent.width * pourcentage_largeur_labels_formulaire + } + + Shipheart_formulaire_textfield { // Champ de saisie : + id: champ_formulaire_Capacite_1 + 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: qsTr("Ah") + width: parent.width * pourcentage_largeur_unites_formulaire + } + + Shipheart_formulaire_ligne_separation { + haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse + } + } + + + //============================================================================== + // Bouton "Affichage avancé" : + //==============================================================================- + Rectangle { + id: bouton_affichage_avance + width: parent.width + height: visible ? hauteur_ligne_formulaire : 0 + color: "transparent" + visible: (champ_formulaire_Type_entrees.currentIndex !== 0) && + (champ_formulaire_Type.currentIndex !== 0) && + (champ_formulaire_Tension_nominale.currentIndex !== 0) + + Shipheart_formulaire_bouton { + titre: (affichage_avance) ? qsTr("Masquer les paramètres avancés") : qsTr("Afficher les paramètres avancés") + actif: false + affichage_fleche : true + fleche_haut: affichage_avance + couleur_titre: couleur_gris_moyen + gras_titre: true + width: parent.width + + MouseArea{ + anchors.fill : parent + onClicked: { + if (affichage_avance) affichage_avance = false; + else affichage_avance = true; + } + } + } + + Shipheart_formulaire_ligne_separation { + haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse + } + } + //============================================================================== + + + + //------------------------------------------------------------------------------- + // Ligne de formulaire : Tension_gain + Rectangle { + width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2) + height: visible ? hauteur_ligne_formulaire : 0 + color: "transparent" + visible: (affichage_avance) && (type_entrees !== shipheart_batteries_type_entrees_ibs) + + Shipheart_formulaire_label { // Label : + text: qsTr("Coefficient correcteur d'entrée de tension") + width: parent.width * pourcentage_largeur_labels_formulaire + } + + Shipheart_formulaire_textfield { // Champ de saisie : + id: champ_formulaire_Tension_gain + 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: qsTr("") + width: parent.width * pourcentage_largeur_unites_formulaire + } + + Shipheart_formulaire_ligne_separation { + haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse + } + } + + + Shipheart_titre_2 {titre: qsTr("Caractéristiques du parc de batteries"); visible: affichage_avance && (type_entrees === shipheart_batteries_type_entrees_ibs)} + + + //------------------------------------------------------------------------------- + // Ligne de formulaire : Heures_capacite_1 + Rectangle { + width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2) + height: visible ? hauteur_ligne_formulaire : 0 + color: "transparent" + visible: (affichage_avance) && (type_entrees === shipheart_batteries_type_entrees_ibs) + + Shipheart_formulaire_label { // Label : + text: qsTr("Durée correspondant à la capacité") + width: parent.width * pourcentage_largeur_labels_formulaire + } + + Shipheart_formulaire_textfield { // Champ de saisie : + id: champ_formulaire_Heures_capacite_1 + 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: qsTr("h") + width: parent.width * pourcentage_largeur_unites_formulaire + } + + Shipheart_formulaire_ligne_separation { + haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse + } + } + + //------------------------------------------------------------------------------- + // Ligne de formulaire : Capacite_2 + Rectangle { + width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2) + height: visible ? hauteur_ligne_formulaire : 0 + color: "transparent" +// visible: (affichage_avance) && (type_entrees === shipheart_batteries_type_entrees_ibs) +visible: false + + Shipheart_formulaire_label { // Label : + text: qsTr("Capacité 2") + width: parent.width * pourcentage_largeur_labels_formulaire + } + + Shipheart_formulaire_textfield { // Champ de saisie : + id: champ_formulaire_Capacite_2 + 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: qsTr("Ah") + width: parent.width * pourcentage_largeur_unites_formulaire + } + + Shipheart_formulaire_ligne_separation { + haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse + } + } + + //------------------------------------------------------------------------------- + // Ligne de formulaire : Heures_capacite_2 + Rectangle { + width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2) + height: visible ? hauteur_ligne_formulaire : 0 + color: "transparent" +// visible: (affichage_avance) && (type_entrees === shipheart_batteries_type_entrees_ibs) +visible: false + + Shipheart_formulaire_label { // Label : + text: qsTr("Durée de capacité 2") + width: parent.width * pourcentage_largeur_labels_formulaire + } + + Shipheart_formulaire_textfield { // Champ de saisie : + id: champ_formulaire_Heures_capacite_2 + 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: qsTr("h") + width: parent.width * pourcentage_largeur_unites_formulaire + } + + Shipheart_formulaire_ligne_separation { + haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse + } + } + + //------------------------------------------------------------------------------- + // Ligne de formulaire : Coeff_peukert + Rectangle { + width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2) + height: visible ? hauteur_ligne_formulaire : 0 + color: "transparent" + visible: (affichage_avance) && (type_entrees === shipheart_batteries_type_entrees_ibs) + + Shipheart_formulaire_label { // Label : + text: qsTr("Coefficient de Peukert") + width: parent.width * pourcentage_largeur_labels_formulaire + } + + Shipheart_formulaire_textfield { // Champ de saisie : + id: champ_formulaire_Coeff_peukert + 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: qsTr("") + width: parent.width * pourcentage_largeur_unites_formulaire + } + + Shipheart_formulaire_ligne_separation { + haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse + } + } + + //------------------------------------------------------------------------------- + // Ligne de formulaire : Résistance_interne + Rectangle { + width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2) + height: visible ? hauteur_ligne_formulaire : 0 + color: "transparent" + visible: (affichage_avance) && (type_entrees === shipheart_batteries_type_entrees_ibs) + + Shipheart_formulaire_label { // Label : + text: qsTr("Résistance interne") + width: parent.width * pourcentage_largeur_labels_formulaire + } + + Shipheart_formulaire_textfield { // Champ de saisie : + id: champ_formulaire_Resistance_interne + 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: qsTr("mΩ") + width: parent.width * pourcentage_largeur_unites_formulaire + } + + Shipheart_formulaire_ligne_separation { + haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse + } + } + + + //------------------------------------------------------------------------------- + // Ligne de formulaire : Soh + Rectangle { + width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2) + height: visible ? hauteur_ligne_formulaire : 0 + color: "transparent" + visible: (affichage_avance) && (type_entrees === shipheart_batteries_type_entrees_ibs) + + Shipheart_formulaire_label { + text: qsTr("Soh actuel") + width: parent.width * pourcentage_largeur_labels_formulaire + } + + Shipheart_formulaire_valeur_fixe { + id: champ_formulaire_Soh + width: parent.width * (1 - pourcentage_largeur_labels_formulaire - pourcentage_largeur_unites_formulaire) + x: parent.width * pourcentage_largeur_labels_formulaire + } + + Shipheart_formulaire_unite { // Unités : + text: qsTr("%") + width: parent.width * pourcentage_largeur_unites_formulaire + } + + Shipheart_formulaire_ligne_separation { + haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse + } + } + + + Shipheart_titre_2 {titre: qsTr("Paramètres de pleine charge"); visible: affichage_avance && (type_entrees === shipheart_batteries_type_entrees_ibs)} + + //------------------------------------------------------------------------------- + // Ligne de formulaire : Tension_pleine_charge + Rectangle { + width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2) + height: visible ? hauteur_ligne_formulaire : 0 + color: "transparent" + visible: (affichage_avance) && (type_entrees === shipheart_batteries_type_entrees_ibs) + + Shipheart_formulaire_label { // Label : + text: qsTr("Tension mini pleine charge") + width: parent.width * pourcentage_largeur_labels_formulaire + } + + Shipheart_formulaire_textfield { // Champ de saisie : + id: champ_formulaire_Tension_pleine_charge + 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: qsTr("V") + width: parent.width * pourcentage_largeur_unites_formulaire + } + + Shipheart_formulaire_ligne_separation { + haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse + } + } + + //------------------------------------------------------------------------------- + // Ligne de formulaire : Courant_pleine_charge + Rectangle { + width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2) + height: visible ? hauteur_ligne_formulaire : 0 + color: "transparent" + visible: (affichage_avance) && (type_entrees === shipheart_batteries_type_entrees_ibs) + + Shipheart_formulaire_label { // Label : + text: qsTr("Courant maxi pleine charge") + width: parent.width * pourcentage_largeur_labels_formulaire + } + + Shipheart_formulaire_textfield { // Champ de saisie : + id: champ_formulaire_Courant_pleine_charge + 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: qsTr("A") + width: parent.width * pourcentage_largeur_unites_formulaire + } + + Shipheart_formulaire_ligne_separation { + haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse + } + } + + + //------------------------------------------------------------------------------- + // Ligne de formulaire : Temporisation_pleine_charge + Rectangle { + width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2) + height: visible ? hauteur_ligne_formulaire : 0 + color: "transparent" + visible: (affichage_avance) && (type_entrees === shipheart_batteries_type_entrees_ibs) + + Shipheart_formulaire_label { // Label : + text: qsTr("Temporisation pleine charge") + width: parent.width * pourcentage_largeur_labels_formulaire + } + + Shipheart_formulaire_textfield { // Champ de saisie : + id: champ_formulaire_Temporisation_pleine_charge + 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: qsTr("s") + width: parent.width * pourcentage_largeur_unites_formulaire + } + + Shipheart_formulaire_ligne_separation { + haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse + } + } + + + //------------------------------------------------------------------------------- + // Ligne de formulaire : Efficacite_charge + Rectangle { + width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2) + height: visible ? hauteur_ligne_formulaire : 0 + color: "transparent" + visible: (affichage_avance) && (type_entrees === shipheart_batteries_type_entrees_ibs) + + Shipheart_formulaire_label { // Label : + text: qsTr("Efficacité de charge") + width: parent.width * pourcentage_largeur_labels_formulaire + } + + Shipheart_formulaire_textfield { // Champ de saisie : + id: champ_formulaire_Efficacite_charge + 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: qsTr("") + width: parent.width * pourcentage_largeur_unites_formulaire + } + + Shipheart_formulaire_ligne_separation { + haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse + } + } + + + Shipheart_titre_2 {titre: qsTr("Caractéristiques de charge nulle"); visible: affichage_avance && (type_entrees === shipheart_batteries_type_entrees_ibs)} + + + //------------------------------------------------------------------------------- + // Ligne de formulaire : Tension_charge_nulle + Rectangle { + width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2) + height: visible ? hauteur_ligne_formulaire : 0 + color: "transparent" + visible: (affichage_avance) && (type_entrees === shipheart_batteries_type_entrees_ibs) + + Shipheart_formulaire_label { // Label : + text: qsTr("Tension de détection charge nulle") + width: parent.width * pourcentage_largeur_labels_formulaire + } + + Shipheart_formulaire_textfield { // Champ de saisie : + id: champ_formulaire_Tension_charge_nulle + 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: qsTr("V") + width: parent.width * pourcentage_largeur_unites_formulaire + } + + Shipheart_formulaire_ligne_separation { + haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse + } + } + + + //------------------------------------------------------------------------------- + // Ligne de formulaire : Temporisation_charge_nulle + Rectangle { + width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2) + height: visible ? hauteur_ligne_formulaire : 0 + color: "transparent" + visible: (affichage_avance) && (type_entrees === shipheart_batteries_type_entrees_ibs) + + Shipheart_formulaire_label { // Label : + text: qsTr("Temporisation charge nulle") + width: parent.width * pourcentage_largeur_labels_formulaire + } + + Shipheart_formulaire_textfield { // Champ de saisie : + id: champ_formulaire_Temporisation_charge_nulle + 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: qsTr("s") + width: parent.width * pourcentage_largeur_unites_formulaire + } + + Shipheart_formulaire_ligne_separation { + haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse + } + } + + + Shipheart_titre_2 {titre: qsTr("Historique"); visible: affichage_avance && (type_entrees === shipheart_batteries_type_entrees_ibs)} + + //------------------------------------------------------------------------------- + // Ligne de formulaire : Nombre_cycles + Rectangle { + width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2) + height: visible ? hauteur_ligne_formulaire : 0 + color: "transparent" + visible: (affichage_avance) && (type_entrees === shipheart_batteries_type_entrees_ibs) + + Shipheart_formulaire_label { + text: qsTr("Nombre de cycles de charge") + width: parent.width * pourcentage_largeur_labels_formulaire + } + + Shipheart_formulaire_valeur_fixe { + id: champ_formulaire_Nombre_cycles + 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 : Nombre_decharges_completes + Rectangle { + width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2) + height: visible ? hauteur_ligne_formulaire : 0 + color: "transparent" + visible: (affichage_avance) && (type_entrees === shipheart_batteries_type_entrees_ibs) + + Shipheart_formulaire_label { + text: qsTr("Nombre de décharges complètes") + width: parent.width * pourcentage_largeur_labels_formulaire + } + + Shipheart_formulaire_valeur_fixe { + id: champ_formulaire_Nombre_decharges_completes + 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/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 n'est PAS déplié... // SDIR #255 + (champ_formulaire_Nom.text !== "") && // Si le nom n'est PAS vide... + (id_famille !== 0) && // Si la famille est définie... + (type_entrees !== 0) && // Si le type d'entrées EST défini... + (type_batterie != 0) && // Si le type de batterie (plomb, Li,...) est défini... + (tension_nominale !== 0) // et si la tension (12/24V) est définie. + Text { + anchors.centerIn: parent + font.pixelSize: 20 + text: (id_batterie === 0) ? qsTr("Créer la batterie") : qsTr("Enregistrer") + color: couleur_blanc_casse + } + MouseArea { + anchors.fill: parent + onClicked: { + shipheart_clic(); + if (id_batterie !== 0) mise_a_jour_batterie(); // Mise à jour des données saisies dans la BDD et reconfiguration par l'application pour prise en compte. + else creation_batterie(); + timer_tempo_reconfiguration.restart(); + } + } + } + + + //....................................................... + // Bouton de suppression + //....................................................... + Rectangle { + width: parent.width + height: hauteur_bouton_droit + color: shipheart_couleur_fond_bouton + radius: shipheart_rayon_bouton + visible: (! clavier.active) && (id_batterie !== 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; + } + } + } + + + //....................................................... + // Bouton Forcer Pleine Charge + //....................................................... + Rectangle { + width: parent.width + height: hauteur_bouton_droit + color: shipheart_couleur_fond_bouton + radius: shipheart_rayon_bouton + visible: (! clavier.active) && (id_batterie !== 0) && (affichage_avance) + + 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_forcer_pleine_charge.pressed + } + + Text { + anchors.centerIn: parent + font.pixelSize: 20 + text: qsTr("Forcer Pleine Charge") + color: couleur_blanc_casse + } + + MouseArea { + id: mousearea_forcer_pleine_charge + 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; + } + } + } + + + //....................................................... + // Bouton Reset SOH + //....................................................... + Rectangle { + width: parent.width + height: hauteur_bouton_droit + color: shipheart_couleur_fond_bouton + radius: shipheart_rayon_bouton + visible: (! clavier.active) && (id_batterie !== 0) && (affichage_avance) + + 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_reset_soh.pressed + } + + Text { + anchors.centerIn: parent + font.pixelSize: 20 + text: qsTr("Réinitialiser SOH") + color: couleur_blanc_casse + } + + MouseArea { + id: mousearea_reset_soh + 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; + } + } + } + + //....................................................... + // Bouton Reset compteurs + //....................................................... + Rectangle { + width: parent.width + height: hauteur_bouton_droit + color: shipheart_couleur_fond_bouton + radius: shipheart_rayon_bouton + visible: (! clavier.active) && (id_batterie !== 0) && (affichage_avance) + + 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_reset_compteur.pressed + } + + Text { + anchors.centerIn: parent + font.pixelSize: 20 + text: qsTr("Réinitialiser Compteurs") + color: couleur_blanc_casse + } + + MouseArea { + id: mousearea_reset_compteur + 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; + } + } + } + + + //....................................................... + // Bouton d'accès à l'étalonnage + //....................................................... + Rectangle { + width: parent.width + height: hauteur_bouton_droit + color: shipheart_couleur_fond_bouton + radius: shipheart_rayon_bouton + visible: (! clavier.active) && + (id_batterie !== 0) && // Si l'on est en création, inutile de proposer le bouton + (affichage_avance) && // Lors de la création, on ne propose pas d'étalonner (éviter de devoir s'adapter en permanence au remplissage en cours... + (tension_nominale === tension_nominale_init) // Si on a chnagé de tension nominale, on ne propose pas d'étalonner (avant d'enregitrer les changements) + Text { + anchors.centerIn: parent + font.pixelSize: 20 + text: qsTr("Etalonner") + color: couleur_blanc_casse + } + MouseArea { + anchors.fill: parent + onClicked: { + shipheart_clic(); + if (type_entrees !== shipheart_batteries_type_entrees_ibs) + { + stackView.push("config_valeurs_niveaux.qml", {"table": "TB_Batteries", "id": id_batterie}) + } + else + { + stackView.push("etalonnage_carte.qml", {"adresse_module": champ_formulaire_Type_entrees.model.get(champ_formulaire_Type_entrees.currentIndex).module}) + } + } + } + } + + 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 circuits + } + 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; + padding: 5 + spacing: 10 + + //................................................. + // 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 + onClicked: { +//console.log("Le Bouton [" + bouton + "] est appuyé"); + switch (type) + { + //----------------------------------------------------- + case type_boite_information_alerte_changement_type: + if (bouton === shipheart_boite_dialogue_bouton_1) + { + type_batterie = champ_formulaire_Type.model.get(champ_formulaire_Type.currentIndex).valeur; + maj_valeurs_par_defaut_type_batterie(); + } + if (bouton === shipheart_boite_dialogue_bouton_2) + { + // Repositionnement à la valeur d'origine : + champ_formulaire_Type.currentIndex = recherche_index_valeur_modele(type, champ_formulaire_Type.model, "Type"); + } + + break; + + //----------------------------------------------------- + case type_boite_information_alerte_changement_tension: + if (bouton === shipheart_boite_dialogue_bouton_1) + { + tension_nominale = champ_formulaire_Tension_nominale.model.get(champ_formulaire_Tension_nominale.currentIndex).valeur; + } + if (bouton === shipheart_boite_dialogue_bouton_2) + { + // Repositionnement à la valeur d'origine : + champ_formulaire_Tension_nominale.currentIndex = recherche_index_valeur_modele(tension_nominale, champ_formulaire_Tension_nominale.model, "Tension_nominale"); + } + + break; + + //----------------------------------------------------- + case type_boite_information_supprimer : + default: ; + } + } + } + + //=========================================================== + // 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 nb; + var i; + var chaine_capacite_1, chaine_capacite_2; + +//console.log("Id de la batterie = " + id_batterie); + + if (id_batterie > 0) // Cas d'une modification de batterie existante : + { + req = 'SELECT Nom, '; + req += ' Adresse_module, '; + req += ' Type_entrees, '; + req += ' Entrees, '; + req += ' Type, '; + req += ' Tension_nominale, '; + req += ' Capacite_1, '; + req += ' Capacite_2, '; + req += ' Tension_gain, '; + req += ' Coeff_peukert, '; + req += ' Resistance_interne, '; + req += ' Tension_pleine_charge, '; + req += ' Courant_pleine_charge, '; + req += ' Temporisation_pleine_charge, '; + req += ' Efficacite_charge, '; + req += ' Tension_charge_nulle, '; + req += ' Temporisation_charge_nulle, '; + req += ' Soh, '; + req += ' Nombre_cycles, '; + req += ' Nombre_decharges_completes, '; + req += ' ID_Famille '; + req += ' FROM TB_Batteries '; + req += ' WHERE Cle_primaire=' + id_batterie + ' '; +//console.log("req = [ " + req + "; ]"); + + + res = bdd.requete_unique(req); + + //--------------------------------------------------------------- + // Mise à jour du champs de saisie de chaque zone de formulaire : + i = 0; + champ_formulaire_Nom.text = res[i ++]; + adresse_module = Number(res[i ++]); + type_entrees = Number(res[i ++]); + no_entree = Number(res[i ++]); + type_batterie = Number(res[i ++]); + tension_nominale = Number(res[i ++]); + chaine_capacite_1 = res[i ++]; + chaine_capacite_2 = res[i ++]; + champ_formulaire_Tension_gain.text = Number(res[i ++]).toFixed(3); + champ_formulaire_Coeff_peukert.text = Number(res[i ++]).toFixed(2); + champ_formulaire_Resistance_interne.text = Number(res[i ++]).toFixed(1); + champ_formulaire_Tension_pleine_charge.text = Number(res[i ++]).toFixed(2); + champ_formulaire_Courant_pleine_charge.text = Number(res[i ++]).toFixed(2); + champ_formulaire_Temporisation_pleine_charge.text = Number(res[i ++]).toFixed(0); + champ_formulaire_Efficacite_charge.text = Number(res[i ++]).toFixed(3); + champ_formulaire_Tension_charge_nulle.text = Number(res[i ++]).toFixed(2); + champ_formulaire_Temporisation_charge_nulle.text = Number(res[i ++]).toFixed(0); + champ_formulaire_Soh.text = Number(res[i ++]).toFixed(0); // En lecture seule + champ_formulaire_Nombre_cycles.text = Number(res[i ++]); // En lecture seule + champ_formulaire_Nombre_decharges_completes.text = Number(res[i ++]); // En lecture seule + id_famille = Number(res[i ++]); + } + else // Cas d'une création d'une batterie : + { + champ_formulaire_Nom.text = ""; + adresse_module = 0; + type_entrees = 0; + no_entree = 0; + type_batterie = 0; + tension_nominale = 0; + chaine_capacite_1 = "100/20"; + chaine_capacite_2 = ""; + id_famille = 0; + } + + + //--------------------------------------------------------------------------------------- + // Famille : + champ_formulaire_Famille.model.clear(); + champ_formulaire_Famille.model.append({"valeur": 0, "texte": "Non défini" }); + + req = 'SELECT Cle_primaire, Nom FROM TB_Familles WHERE Type_source=' + shipheart_type_source_batteries + ' 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) + { + champ_formulaire_Famille.model.append({"valeur": Number(res[0]), "texte": res[1] }); + } + } + + // Positionnement de l'index sur la valeur en cours : + i = recherche_index_valeur_modele(id_famille, champ_formulaire_Famille.model, "Famille"); + if (i === -1) champ_formulaire_Famille.currentIndex = 0; + else champ_formulaire_Famille.currentIndex = i; + + + //--------------------------------------------------------------------------------------- + // Type d'entrées : + + // Mise à zéro et rensignement de la première entrée du modèle de liste des types d'entrées : + champ_formulaire_Type_entrees.model.clear(); + champ_formulaire_Type_entrees.model.append({"module": 0, "type": 0, "no": 0, "type_carte": 0, "texte": qsTr("Non défini") }); + champ_formulaire_Type_entrees.currentIndex = 0; // Par défaut + + //========================================== + // Entrées prédéfinies des ShipBS présentes (les ShipBS sont prioritaires dans ce cas et sont traitées avant les autres) : + req = 'SELECT Adresse_k_bus, Type '; + req += 'FROM TB_Modules_config WHERE '; +// req += 'Presence=1 AND '; + req += 'Type=' + shipheart_type_module_shipBS + ' '; + req += 'ORDER BY Adresse_k_bus'; +//console.log("req = [ " + req + "; ]"); + nb = bdd.requete(req); + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + // Ajout de l'entrée dans le modèle : + champ_formulaire_Type_entrees.model.append({ "module": Number(res[0]), + "type": shipheart_batteries_type_entrees_ibs, + "no": 0, + "type_carte": shipheart_type_module_shipBS, + "texte": qsTr("ShipBS [@ %1]").arg(Number(res[0])) + }); + + // Mise à jour de l'index actuel de la combo box : + if ((type_entrees === shipheart_batteries_type_entrees_ibs) && + (adresse_module === Number(res[0]))) + { + champ_formulaire_Type_entrees.currentIndex = (champ_formulaire_Type_entrees.model.count - 1); + } + } + } + + //============================================================== + // Entrées prédéfinies des modules présents (autres que ShipBS) : + req = 'SELECT Adresse_k_bus, Type '; + req += 'FROM TB_Modules_config WHERE '; + req += 'Presence=1 '; + req += 'AND ('; + req += 'Type=' + shipheart_type_module_shipbase + ' '; + req += 'OR Type=' + shipheart_type_module_shippower812 + ' '; + req += 'OR Type=' + shipheart_type_module_shippower8DC + ' '; + req += ')'; + req += 'ORDER BY Adresse_k_bus'; +//console.log("req = [ " + req + "; ]"); + nb = bdd.requete(req); + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + champ_formulaire_Type_entrees.model.append({ "module": Number(res[0]), + "type": shipheart_batteries_type_entrees_predefinie, + "no": shipheart_capteur_predefini_in_v, + "type_carte": Number(res[1]), + "texte": qsTr("Alimentation %1").arg(Fonctions.nom_type_module(Number(res[1]))) + ((Number(res[1]) === shipheart_type_module_shipbase) ? "" : " [@ " + Number(res[0]) + "]") + }); + + // Mise à jour de l'index actuel de la combo box : + if ((type_entrees === shipheart_batteries_type_entrees_predefinie) && + (adresse_module === Number(res[0])) && + (no_entree === shipheart_capteur_predefini_in_v)) + { + champ_formulaire_Type_entrees.currentIndex = (champ_formulaire_Type_entrees.model.count - 1); + } + } + } + + //============================================================== + // Entrées VOLT : + for (i = 0; i < shipheart_entrees_volt_max_nombre; i ++) + { + champ_formulaire_Type_entrees.model.append({ "module": 0, + "type": shipheart_batteries_type_entrees_volt, + "no": (i+1), + "type_carte": shipheart_type_module_shipbase, + "texte": qsTr("Entrée VOLT n° %1").arg(i+1) + }); + if ((type_entrees === shipheart_batteries_type_entrees_volt) && + (no_entree === (i + 1))) + { + champ_formulaire_Type_entrees.currentIndex = (champ_formulaire_Type_entrees.model.count - 1); + } + } + + type_entrees_init = type_entrees; + no_entree_init = no_entree; + + //--------------------------------------------------------------------------------------- + // Type (de batterie) : + champ_formulaire_Type.model.clear(); + champ_formulaire_Type.model.append({"valeur": shipheart_batteries_type_indefini, "texte": qsTr("Non défini") }); + champ_formulaire_Type.model.append({"valeur": shipheart_batteries_type_plomb_acide_liquide, "texte": qsTr("Plomb - Acide liquide") }); + champ_formulaire_Type.model.append({"valeur": shipheart_batteries_type_plomb_agm_vrla, "texte": qsTr("Plomb - AGM / VRLA") }); + champ_formulaire_Type.model.append({"valeur": shipheart_batteries_type_plomb_gel, "texte": qsTr("Plomb - Gel") }); + champ_formulaire_Type.model.append({"valeur": shipheart_batteries_type_plomb_carbone, "texte": qsTr("Plomb - Carbone") }); + champ_formulaire_Type.model.append({"valeur": shipheart_batteries_type_lihium, "texte": qsTr("Lithium") }); + + // Positionnement de l'index sur la valeur en cours : + i = recherche_index_valeur_modele(type_batterie, champ_formulaire_Type.model, "Type"); + if (i === -1) champ_formulaire_Type.currentIndex = recherche_index_valeur_modele(0, champ_formulaire_Type.model, "Type"); + else champ_formulaire_Type.currentIndex = i; + + type_batterie_init = type_batterie; + + //--------------------------------------------------------------------------------------- + // Tension nominale : + champ_formulaire_Tension_nominale.model.clear(); + champ_formulaire_Tension_nominale.model.append({"valeur": 0, "texte": qsTr("Non définie") }); + champ_formulaire_Tension_nominale.model.append({"valeur": 12, "texte": qsTr("12V") }); + champ_formulaire_Tension_nominale.model.append({"valeur": 24, "texte": qsTr("24V") }); + champ_formulaire_Tension_nominale.model.append({"valeur": 48, "texte": qsTr("48V") }); + + // Positionnement de l'index sur la valeur en cours : + i = recherche_index_valeur_modele(tension_nominale, champ_formulaire_Tension_nominale.model, "Tension_nominale"); + if (i === -1) champ_formulaire_Tension_nominale.currentIndex = recherche_index_valeur_modele(0, champ_formulaire_Tension_nominale.model, "Tension_nominale"); + else champ_formulaire_Tension_nominale.currentIndex = i; + + tension_nominale_init = tension_nominale; + + //--------------------------------------------------------------------------------------- + // Entrées : + if (id_batterie > 0) // Cas d'une modification de batterie existante : + { + req = 'SELECT Type_entrees, Entrees FROM TB_Batteries WHERE Cle_primaire=' + id_batterie + ' '; +//console.log("req = [ " + req + "; ]"); + res = bdd.requete_unique(req); + if (Number(res[0]) === type_entrees) // On ne récupère la chaine 'Entrées' que si la batterie était déjà de ce type. Sinon, on part sur une liste vierge (idem création) + { + no_entree = Number(res[1]); + } + } + + //--------------------------------------------------------------------------------------- + // Capacités : + var chaines_capacite; + + if (chaine_capacite_1 !== "") + { + chaines_capacite = chaine_capacite_1.split('/'); + champ_formulaire_Capacite_1.text = chaines_capacite[0]; + champ_formulaire_Heures_capacite_1.text = chaines_capacite[1]; + } + else + { + champ_formulaire_Capacite_1.text = ""; + champ_formulaire_Heures_capacite_1.text = ""; + } + + if (chaine_capacite_2 !== "") + { + chaines_capacite = chaine_capacite_2.split('/'); + champ_formulaire_Capacite_2.text = chaines_capacite[0]; + champ_formulaire_Heures_capacite_2.text = chaines_capacite[1]; + } + else + { + champ_formulaire_Capacite_2.text = ""; + champ_formulaire_Heures_capacite_2.text = ""; + } + } + + + //============================================================================================================= + // Mise à jour des valeurs par défaut en fonction du choix du Type (de batterie) + //============================================================================================================= + function maj_valeurs_par_defaut_type_batterie() + { + var i; + + switch(type_batterie) + { + //------------------------------------- + default : + case shipheart_batteries_type_plomb_acide_liquide : + + champ_formulaire_Tension_gain.text = "1.000"; + champ_formulaire_Coeff_peukert.text = "1.20"; + champ_formulaire_Resistance_interne.text = "20"; // En mOhms + champ_formulaire_Tension_pleine_charge.text = "13.80"; // En V + champ_formulaire_Courant_pleine_charge.text = "3.00"; // En A (Nb calculé sur 3% de la capacité) + champ_formulaire_Temporisation_pleine_charge.text = "180"; // En s + champ_formulaire_Efficacite_charge.text = "0.9"; // Sans unité + champ_formulaire_Tension_charge_nulle.text = "11.0"; // En V + champ_formulaire_Temporisation_charge_nulle.text = "30"; // En s + champ_formulaire_Temperature_seuil_haut.text = "50.0"; // En °C + champ_formulaire_Temperature_seuil_bas.text = "5.0"; // En °C + + break; + + //------------------------------------- + case shipheart_batteries_type_plomb_agm_vrla : + + champ_formulaire_Tension_gain.text = "1.000"; + champ_formulaire_Coeff_peukert.text = "1.05"; + champ_formulaire_Resistance_interne.text = "3"; // En mOhms + champ_formulaire_Tension_pleine_charge.text = "13.50"; // En V + champ_formulaire_Courant_pleine_charge.text = "3.00"; // En A (Nb calculé sur 3% de la capacité) + champ_formulaire_Temporisation_pleine_charge.text = "180"; // En s + champ_formulaire_Efficacite_charge.text = "0.9"; // Sans unité + champ_formulaire_Tension_charge_nulle.text = "11.0"; // En V + champ_formulaire_Temporisation_charge_nulle.text = "30"; // En s + champ_formulaire_Temperature_seuil_haut.text = "50.0"; // En °C + champ_formulaire_Temperature_seuil_bas.text = "5.0"; // En °C + + break; + + //------------------------------------- + case shipheart_batteries_type_plomb_gel : + + champ_formulaire_Tension_gain.text = "1.000"; + champ_formulaire_Coeff_peukert.text = "1.1"; + champ_formulaire_Resistance_interne.text = "2"; // En mOhms + champ_formulaire_Tension_pleine_charge.text = "13.30"; // En V + champ_formulaire_Courant_pleine_charge.text = "3.00"; // En A (Nb calculé sur 3% de la capacité) + champ_formulaire_Temporisation_pleine_charge.text = "180"; // En s + champ_formulaire_Efficacite_charge.text = "0.92"; // Sans unité + champ_formulaire_Tension_charge_nulle.text = "11.0"; // En V + champ_formulaire_Temporisation_charge_nulle.text = "30"; // En s + champ_formulaire_Temperature_seuil_haut.text = "50.0"; // En °C + champ_formulaire_Temperature_seuil_bas.text = "5.0"; // En °C + + break; + + //------------------------------------- + case shipheart_batteries_type_plomb_carbone : + + champ_formulaire_Tension_gain.text = "1.000"; + champ_formulaire_Coeff_peukert.text = "1.1"; + champ_formulaire_Resistance_interne.text = "2"; // En mOhms + champ_formulaire_Tension_pleine_charge.text = "13.50"; // En V + champ_formulaire_Courant_pleine_charge.text = "3.00"; // En A (Nb calculé sur 3% de la capacité) + champ_formulaire_Temporisation_pleine_charge.text = "180"; // En s + champ_formulaire_Efficacite_charge.text = "0.92"; // Sans unité + champ_formulaire_Tension_charge_nulle.text = "11.0"; // En V + champ_formulaire_Temporisation_charge_nulle.text = "30"; // En s + champ_formulaire_Temperature_seuil_haut.text = "50.0"; // En °C + champ_formulaire_Temperature_seuil_bas.text = "5.0"; // En °C + + break; + + //------------------------------------- + case shipheart_batteries_type_lihium : + + champ_formulaire_Tension_gain.text = "1.000"; + champ_formulaire_Coeff_peukert.text = "1.00"; + champ_formulaire_Resistance_interne.text = "0.5"; // En mOhms + champ_formulaire_Tension_pleine_charge.text = "13.50"; // En V + champ_formulaire_Courant_pleine_charge.text = "3.00"; // En A (Nb calculé sur 3% de la capacité) + champ_formulaire_Temporisation_pleine_charge.text = "180"; // En s + champ_formulaire_Efficacite_charge.text = "0.95"; // Sans unité + champ_formulaire_Tension_charge_nulle.text = "11.5"; // En V + champ_formulaire_Temporisation_charge_nulle.text = "30"; // En s + champ_formulaire_Temperature_seuil_haut.text = "50.0"; // En °C + champ_formulaire_Temperature_seuil_bas.text = "5.0"; // En °C + + break; + } + } + + + //============================================================================================================= + // Mise à jour des valeurs saisies de la batterie + //============================================================================================================= + function mise_a_jour_batterie() + { + var req; + var i; + var capacite_1, capacite_2; + var heures_capacite_1, heures_capacite_2; + var chaine_capacite_1, chaine_capacite_2; + var coeff_peukert; + var sous_req_liste_tension_soc = ""; + + + //------------------------------------------------------------------------------------------------------- + // Capacités : + if (champ_formulaire_Capacite_1.text != "") capacite_1 = Number(champ_formulaire_Capacite_1.text); + else capacite_1 = 100; // Valeur par défaut (en Ah) + if (champ_formulaire_Heures_capacite_1.text != "") heures_capacite_1 = Number(champ_formulaire_Heures_capacite_1.text); + else heures_capacite_1 = 20; // Valeur par défaut (en h) + if (champ_formulaire_Capacite_2.text != "") capacite_2 = Number(champ_formulaire_Capacite_2.text); + else capacite_2 = 0; + if (champ_formulaire_Heures_capacite_2.text != "") heures_capacite_2 = Number(champ_formulaire_Heures_capacite_2.text); + else heures_capacite_2 = 0; + + // Mise à jour des chaines pour la BDD : + chaine_capacite_1 = capacite_1 + "/" + heures_capacite_1; // Pour la capacité 1, on enregistre toujours la chaine + if ((capacite_2 !== 0) && (heures_capacite_2 !== 0)) chaine_capacite_2 = capacite_2 + "/" + heures_capacite_2; + else chaine_capacite_2 = ""; + + //------------------------------------------------------------------------------------------------------- + // Calcul du coefficient de Peukert : + coeff_peukert = Fonctions_batteries.coefficient_de_peukert(type_batterie, capacite_1, heures_capacite_1, capacite_2, heures_capacite_2); +//console.log("Coeff de Peukert calculé = " + coeff_peukert); + + //------------------------------------------------------------------------------------------------------- + // Si la tension nominale de la batterie a été changée, on met obligatoirement à jour la liste valeurs/niveaux en version "usine" : + if (tension_nominale !== tension_nominale_init) + { + sous_req_liste_tension_soc = ', Liste_tension_soc="' + Fonctions_batteries.chaine_tension_niveau_batterie_usine(tension_nominale) + '" '; + } // Sinon, on ne fait rien sur cette liste. + + + //------------------------------------------------------------------------------------------------------- + // Mise à jour de l'entrée dans TB_Batteries : + req = 'UPDATE TB_Batteries SET Nom="' + champ_formulaire_Nom.text + '" '; + req += ', Type=' + type_batterie; + req += ', Tension_nominale=' + tension_nominale; + req += ', Adresse_module=' + adresse_module; + req += ', Type_entrees=' + type_entrees; + req += ', Entrees="' + no_entree + '" '; + req += ', Capacite_1="' + chaine_capacite_1 + '" '; + req += ', Capacite_2="' + chaine_capacite_2 + '" '; + req += ', Coeff_peukert=' + champ_formulaire_Coeff_peukert.text; + req += ', Resistance_interne=' + champ_formulaire_Resistance_interne.text; + req += ', Tension_pleine_charge=' + champ_formulaire_Tension_pleine_charge.text; + req += ', Courant_pleine_charge=' + champ_formulaire_Courant_pleine_charge.text; + req += ', Temporisation_pleine_charge=' + champ_formulaire_Temporisation_pleine_charge.text; + req += ', Efficacite_charge=' + champ_formulaire_Efficacite_charge.text; + req += ', Tension_charge_nulle=' + champ_formulaire_Tension_charge_nulle.text; + req += ', Temporisation_charge_nulle=' + champ_formulaire_Temporisation_charge_nulle.text; + req += ', Liste_temperature_resistance_interne="' + Fonctions_batteries.chaine_temperature_resistance_interne_usine(type_batterie) + '" '; + req += ', Tension_gain=' + champ_formulaire_Tension_gain.text; + req += ', ID_Famille=' + id_famille; + req += sous_req_liste_tension_soc; + req += ' WHERE Cle_primaire=' + id_batterie + ' ' +//console.log("req = [ " + req + "; ]"); + bdd.requete_unique(req); + + synchro_bdd(shipheart_type_synchro_config); + } + + //============================================================================================================= + // Création de la batterie + //============================================================================================================= + function creation_batterie() + { + var req, res; + var i; + var capacite_1, capacite_2; + var heures_capacite_1, heures_capacite_2; + var chaine_capacite_1, chaine_capacite_2; + var coeff_peukert; + + + //------------------------------------------------------------------------------------------------------- + // Capacités : + if (champ_formulaire_Capacite_1.text != "") capacite_1 = Number(champ_formulaire_Capacite_1.text); + else capacite_1 = 100; // Valeur par défaut (en Ah) + if (champ_formulaire_Heures_capacite_1.text != "") heures_capacite_1 = Number(champ_formulaire_Heures_capacite_1.text); + else heures_capacite_1 = 20; // Valeur par défaut (en h) + if (champ_formulaire_Capacite_2.text != "") capacite_2 = Number(champ_formulaire_Capacite_2.text); + else capacite_2 = 0; + if (champ_formulaire_Heures_capacite_2.text != "") heures_capacite_2 = Number(champ_formulaire_Heures_capacite_2.text); + else heures_capacite_2 = 0; + + // Mise à jour des chaines pour la BDD : + chaine_capacite_1 = capacite_1 + "/" + heures_capacite_1; // Pour la capacité 1, on enregistre toujours la chaine + if ((capacite_2 !== 0) && (heures_capacite_2 !== 0)) chaine_capacite_2 = capacite_2 + "/" + heures_capacite_2; + else chaine_capacite_2 = ""; + + //------------------------------------------------------------------------------------------------------- + // Calcul du coefficient de Peukert : + coeff_peukert = Fonctions_batteries.coefficient_de_peukert(type_batterie, capacite_1, heures_capacite_1, capacite_2, heures_capacite_2); +//console.log("Coeff de Peukert calculé = " + coeff_peukert); + + //------------------------------------------------------------------------------------------------------- + // Création de l'entrée dans TB_Batteries : + req = 'INSERT INTO TB_Batteries (Nom, '; + req += ' Type, '; + req += ' Tension_nominale, '; + req += ' Adresse_module, '; + req += ' Type_entrees, '; + req += ' Entrees, '; + req += ' Capacite_1, '; + req += ' Capacite_2, '; + req += ' Coeff_peukert, '; + req += ' Resistance_interne, '; + req += ' Tension_pleine_charge, '; + req += ' Courant_pleine_charge, '; + req += ' Temporisation_pleine_charge, '; + req += ' Efficacite_charge, '; + req += ' Tension_charge_nulle, ' + req += ' Temporisation_charge_nulle, '; + req += ' Tension_gain, '; + req += ' Liste_tension_soc, '; + req += ' Liste_temperature_resistance_interne, '; + req += ' ID_Famille '; + req += ' ) VALUES ("' + champ_formulaire_Nom.text + '"'; + req += ', ' + type_batterie; + req += ', ' + tension_nominale; + req += ', ' + adresse_module; + req += ', ' + type_entrees; + req += ', "' + no_entree + '" '; + req += ', "' + chaine_capacite_1 + '" '; + req += ', "' + chaine_capacite_2 + '" '; + req += ', ' + champ_formulaire_Coeff_peukert.text; + req += ', ' + champ_formulaire_Resistance_interne.text; + req += ', ' + champ_formulaire_Tension_pleine_charge.text; + req += ', ' + champ_formulaire_Courant_pleine_charge.text; + req += ', ' + champ_formulaire_Temporisation_pleine_charge.text; + req += ', ' + champ_formulaire_Efficacite_charge.text; + req += ', ' + champ_formulaire_Tension_charge_nulle.text; + req += ', ' + champ_formulaire_Temporisation_charge_nulle.text; + req += ', ' + champ_formulaire_Tension_gain.text; + req += ', "' + Fonctions_batteries.chaine_tension_niveau_batterie_usine(tension_nominale) + '" '; + req += ', "' + Fonctions_batteries.chaine_temperature_resistance_interne_usine(type_batterie) + '" '; + req += ', ' + id_famille; + req += ') '; +//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); + } + + + //============================================================================================================= + // Check suppression de la batterie + //============================================================================================================= + function check_avant_suppression() + { + var req, res; + var nb; + var i; + 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 sur les évènements : + req = 'SELECT Cle_primaire, Nom FROM TB_Events WHERE Type_source=' + shipheart_source_mesure_batterie + ' AND ID_Source=' + id_batterie + ' '; + req += ' ORDER BY Nom'; +//console.log("Requête = [ " + req + "; ]") + nb = bdd.requete(req); + + if (nb > 0) + { + if (nb === 1) message += "

" + qsTr("Cette batterie est utilisée par l'évènement ci-dessous.
Vous devez modifier ou supprimer cet évènement pour qu'il ne dépende plus de cette batterie avant de pouvoir la supprimer.") + "

"; + else message += "

" + qsTr("Cette batterie est utilisée par les %1 évènements ci-dessous.
Vous devez modifier ou supprimer ces évènements pour qu'ils ne dépendent plus de cette batterie avant de pouvoir la supprimer.").arg(nb) + "

"; + + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + message += "‣ " + (i+1) + " : " + res[1] + "
"; + } + } + } + + //========================================================================= + // Recherche de l'impact de cette suppression sur les capteurs calculés : + /* Retour de la forme : + +-------------+ + | Nom_capteur | + +-------------+ + | Calculation | + | Calcul 2 | + +-------------+ */ + req = 'SELECT Nom FROM TB_Capteurs '; + req += ' WHERE Type_entrees=' + shipheart_capteur_type_entrees_calculee_booleen + ' '; + req += ' AND Entrees LIKE "%/' + shipheart_source_mesure_batterie + ':' + id_batterie + '/%" '; +//console.log("Requête = [ " + req + "; ]") + nb = bdd.requete(req); + + if (nb > 0) + { + if (nb === 1) message += "

" + qsTr("Cette batterie est utilisée par le capteur calculé ci-dessous.
Vous devez modifier ou supprimer ce capteur calculé pour qu'il ne dépende plus de cette id_batterie avant de pouvoir la supprimer.") + "

"; + else message += "

" + qsTr("Cette id_batterie est utilisée par les %1 capteurs calculés ci-dessous.
Vous devez modifier ou supprimer ces capteurs calculés pour qu'ils ne dépendent plus de cette id_batterie avant de pouvoir la supprimer.").arg(nb) + "

"; + + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + message += "‣ " + (i+1) + " : " + res[0] + "
"; + } + } + } + + //========================================================================= + // 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.boutonOkTexte = qsTr("Ok") + boite_information.boutonAnnuler = false; + boite_information.alignementMessage = Text.AlignLeft + boite_information.type = type_boite_information_supprimer; + boite_information.open(); + + return(-1); + } + } + + //============================================================================================================= + // Suppression de la batterie + //============================================================================================================= + function suppression_batterie() + { + var req; + + // Suppression de la batterie dans TB_Batteries : + req = 'DELETE FROM TB_Batteries WHERE Cle_primaire=' + id_batterie + ' '; +//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); + + } + + + //============================================================================================================= + // Forçage pleine charge + //============================================================================================================= + function forcer_pleine_charge() + { + var req; + + // Suppression de la batterie dans TB_Batteries : + req = 'UPDATE TB_Batteries SET New_cde=' + shipheart_batteries_commande_forcage_pleine_charge + ' WHERE Cle_primaire=' + id_batterie + ' '; +//console.log("req = [ " + req + "; ]"); + bdd.requete_unique(req); + } + + //============================================================================================================= + // Reset du SOH + //============================================================================================================= + function reset_soh() + { + var req; + + // Suppression de la batterie dans TB_Batteries : + req = 'UPDATE TB_Batteries SET New_cde=' + shipheart_batteries_commande_reset_soh + ' WHERE Cle_primaire=' + id_batterie + ' '; +//console.log("req = [ " + req + "; ]"); + bdd.requete_unique(req); + + // Mise à jour des variables globales pour prise en compte immédiatement : + champ_formulaire_Soh.text = 100; + } + + //============================================================================================================= + // Reset des compteurs + //============================================================================================================= + function reset_compteurs() + { + var req; + + // Suppression de la batterie dans TB_Batteries : + req = 'UPDATE TB_Batteries SET New_cde=' + shipheart_batteries_commande_reset_compteurs + ' WHERE Cle_primaire=' + id_batterie + ' '; +//console.log("req = [ " + req + "; ]"); + bdd.requete_unique(req); + + // Mise à jour des variables globales pour prise en compte immédiatement : + champ_formulaire_Nombre_cycles.text = 0; + champ_formulaire_Nombre_decharges_completes.text = 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 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.... + } + } +} + diff --git a/config_capteur.qml b/config_capteur.qml new file mode 100644 index 0000000..3e4f840 --- /dev/null +++ b/config_capteur.qml @@ -0,0 +1,2555 @@ +//======================================================================================================================================================================== +// CONFIG_CAPTEUR.QML +// Ce fichier traite la configuration d'un capteur. La page permet notamment de : +// - Modifier la config du capteur (ou de le créer la première fois), +// - Supprimer le capteur +// La page est appelée depuis la page config_capteurs.qml, en cliquant sur le capteur à 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 +import"fonctions.js" as Fonctions + + +Shipheart_page { + id: page_config_capteur + + + // 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 + + + // 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_capteur: 0 + property int adresse_module: -1 + property int type_entrees : 0 + property string entrees: "" + property int nb_entrees: 0 + property int nb_libelles: 0 + property int entree_en_cours: 0 + property int mode_entrees: 0 + property int priorite_affichage_accueil: 0 + property int id_famille: 0 + property int id_variable: 0 + property string liste_valeurs_textes: "" + + property bool flag_affichage_mode_entrees: false + property bool flag_affichage_offset: false + property bool flag_nmea: false // Il est positionné dès qu'on "touche" à un paramètre NMEA pour demander une mise à jour NMEA + + + + // Modèles : + // Note : les modèles chargés dans 'main.qml' n'ont pas à être rechargés dans les pages suivantes + + + //=========================================================== + // Signaux : + //=========================================================== + + //---------------------------------------------------------------------------------- + // Connexion au signal de la page 'config_capteur_calcule_booleen.qml' : + 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 : + // ----------------------------------------------- + function onEnregistrer_config_capteur_calcule_booleen(new_entrees) + { + if (type_entrees === shipheart_capteur_type_entrees_calculee_booleen) // Normalement, ça n'arivera que dans ce cas mais... + { + champ_formulaire_Entrees.model.set(champ_formulaire_Entrees.currentIndex, {"entrees": new_entrees} ); + } + } + } + + //=========================================================== + // 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; + + // Suppression du capteur : + if (mousearea_bouton_supprimer.pressed) + { + if (check_avant_suppression() !== -1) + { + shipheart_clic(); + suppression_capteur(); // 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 + } + } + } + } + } + + // Titre de la page : + Shipheart_titre_1 {titre: (id_capteur === 0) ? qsTr("Création d'un capteur") : qsTr("Configuration du 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" + + //========================= + // 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 du capteur") + 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 : Type_entrees + Rectangle { + id: ligne_type_entrees + 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 capteur") + width: parent.width * pourcentage_largeur_labels_formulaire + couleur: (champ_formulaire_Type_entrees.currentIndex !== 0) + ? shipheart_formulaire_couleur_texte_par_defaut + : shipheart_formulaire_couleur_texte_en_erreur + } + + Shipheart_formulaire_combobox { + id: champ_formulaire_Type_entrees + model: ListModel { } + width: parent.width * (1 - pourcentage_largeur_labels_formulaire) + onActivated: { + shipheart_clic(); + if (type_entrees !== champ_formulaire_Type_entrees.model.get(champ_formulaire_Type_entrees.currentIndex).valeur) + { + type_entrees = champ_formulaire_Type_entrees.model.get(champ_formulaire_Type_entrees.currentIndex).valeur; + adresse_module = -1; + entrees = ""; + mode_entrees = 0; + + mise_a_jour_module_entrees(); + } + } + } + + Shipheart_formulaire_ligne_separation { + haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse + } + } + + //------------------------------------------------------------------------------- + // Ligne de formulaire : Adresse_module + Rectangle { + id: ligne_module_entrees + width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2) + height: visible ? hauteur_ligne_formulaire : 0 + color: "transparent" + visible: (champ_formulaire_Type_entrees.currentIndex !== 0) + && (type_entrees < shipheart_capteur_type_entrees_calculee_booleen) + + Shipheart_formulaire_label { + text: qsTr("Module") + width: parent.width * pourcentage_largeur_labels_formulaire + couleur: (champ_formulaire_Adresse_module.currentIndex !== 0) + ? shipheart_formulaire_couleur_texte_par_defaut + : shipheart_formulaire_couleur_texte_en_erreur + } + + Shipheart_formulaire_combobox { + id: champ_formulaire_Adresse_module + model: ListModel { } + width: parent.width * (1 - pourcentage_largeur_labels_formulaire) + onActivated: { + shipheart_clic(); + if (adresse_module !== champ_formulaire_Adresse_module.model.get(champ_formulaire_Adresse_module.currentIndex).valeur) + { + adresse_module = champ_formulaire_Adresse_module.model.get(champ_formulaire_Adresse_module.currentIndex).valeur; + entrees = ""; + mode_entrees = 0; + mise_a_jour_entrees(); + } + } + } + + Shipheart_formulaire_ligne_separation { + haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse + } + } + + //------------------------------------------------------------------------------- + // Ligne de formulaire : Entrees + Rectangle { + id: ligne_entrees + width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2) + height: visible ? (champ_formulaire_Entrees.height + 10) : 0 + color: "transparent" + visible: ligne_module_entrees.visible + && (champ_formulaire_Adresse_module.currentIndex !== 0) + && (type_entrees < shipheart_capteur_type_entrees_calculee_booleen) + + + Shipheart_formulaire_label { + text: qsTr("Affectation") + width: parent.width * pourcentage_largeur_labels_formulaire + couleur: ( (champ_formulaire_Entrees.currentIndex !== 0) || ((type_entrees === shipheart_capteur_type_entrees_aux) && (nb_entrees > 0)) ) + ? shipheart_formulaire_couleur_texte_par_defaut + : shipheart_formulaire_couleur_texte_en_erreur + } + + Shipheart_formulaire_combobox { + id: champ_formulaire_Entrees + visible: (type_entrees !== shipheart_capteur_type_entrees_aux) // On n'affiche pas dans le cas d'entrées AUX. + model: ListModel { } + width: parent.width * (1 - pourcentage_largeur_labels_formulaire) + onActivated: { + shipheart_clic(); + entrees = champ_formulaire_Entrees.model.get(champ_formulaire_Entrees.currentIndex).entrees; + if (flag_affichage_mode_entrees) mise_a_jour_mode_entrees(); // Cas "normal" où le Mode_entree doit être traité + else mise_a_jour_famille(); // Si pas de Mode_entree, on passe directement à la Famille. + } + } + + Shipheart_formulaire_ligne_separation { + visible: (type_entrees !== shipheart_capteur_type_entrees_aux) // On n'affiche pas dans le cas d'entrées AUX. + haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse + } + + } + + // Cas particulier des entrées AUX : + Rectangle { + id: ligne_entrees_aux + width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2) + height: visible ? ( hauteur_ligne_formulaire * (Math.trunc((shipheart_capteur_max_nombre_entrees_aux-1) / 4) + 1) ) : 0 + color: "transparent" + visible: ligne_entrees.visible + && (type_entrees === shipheart_capteur_type_entrees_aux) + + GridView { + id: entrees_aux_grid + + width: parent.width + height: parent.height + anchors.verticalCenter: parent.verticalCenter; + cellWidth: (shipheart_capteur_max_nombre_entrees_aux < 4) ? (width / shipheart_capteur_max_nombre_entrees_aux) : (width / 4) // On exclus le cas où shipheart_capteur_max_nombre_entrees_aux=0... + cellHeight: height / (Math.trunc((shipheart_capteur_max_nombre_entrees_aux-1) / 4) + 1) + 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: entrees_aux_grid.cellWidth - 5 + height: entrees_aux_grid.cellHeight - 5 + radius: shipheart_rayon_bouton + color: couleur_gris_tres_fonce_transparent + + Text { + anchors.fill: parent + horizontalAlignment: Qt.AlignHCenter + verticalAlignment: Qt.AlignVCenter + text: (model.no_entree_aux === 0) ? qsTr("%1 : Non définie").arg(model.no) : qsTr("%1 : %2").arg(model.no).arg(model.libelle) + color: (model.no_entree_aux === 0) ? couleur_gris_tres_pale_transparent : couleur_blanc_casse + font.pixelSize: 15 + wrapMode: Label.Wrap + } +/* Text { + anchors.fill: parent + horizontalAlignment: Qt.AlignHCenter + verticalAlignment: Qt.AlignBottom + bottomPadding: 5 + text: qsTr("Première entrée du capteur") + color: (model.no_entree_aux === 0) ? couleur_gris_tres_pale : couleur_blanc_casse + font.pixelSize: 10 + visible: model.no === 1 + } +*/ + MouseArea { + id: mouse_area_entree_aux + anchors.fill: parent + onClicked: { + shipheart_clic(); + entree_en_cours = model.no; + boite_selection_entree_aux.nom_equipement = Fonctions.nom_type_equipement(shipheart_source_mesure_capteur); + boite_selection_entree_aux.open(); + } + } + } + ScrollBar.vertical: ScrollBar { } + } + Shipheart_formulaire_ligne_separation { + haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse + } + } + + //------------------------------------------------------------------------------- + // Ligne de formulaire : Mode_entrees + Rectangle { + id: ligne_mode_entrees + width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2) + height: visible ? hauteur_ligne_formulaire : 0 + color: "transparent" + visible: ligne_entrees.visible + && ( (champ_formulaire_Entrees.currentIndex !== 0) || + ((type_entrees === shipheart_capteur_type_entrees_aux) && (nb_entrees > 0)) ) + && flag_affichage_mode_entrees + && (type_entrees < shipheart_capteur_type_entrees_calculee_booleen) + + + Shipheart_formulaire_label { + text: qsTr("Mode du capteur") + width: parent.width * pourcentage_largeur_labels_formulaire + couleur: ((champ_formulaire_Mode_entrees.currentIndex !== 0) || (type_entrees === shipheart_capteur_type_entrees_aux)) // Pour les entrées AUX, le cas de Mode_entrees=0 est Valide car corrrespond au mode NORMAL + ? shipheart_formulaire_couleur_texte_par_defaut + : shipheart_formulaire_couleur_texte_en_erreur + } + + Shipheart_formulaire_combobox { + id: champ_formulaire_Mode_entrees + model: ListModel { } + width: parent.width * (1 - pourcentage_largeur_labels_formulaire) + onActivated: { + shipheart_clic(); + mode_entrees = champ_formulaire_Mode_entrees.model.get(champ_formulaire_Mode_entrees.currentIndex).valeur; + mise_a_jour_famille(); + mise_a_jour_unite(); + } + } + + Shipheart_formulaire_ligne_separation { + haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse + } + } + + //------------------------------------------------------------------------------- + // Ligne de formulaire : Famille + Rectangle { + id: ligne_famille + width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2) + height: visible ? hauteur_ligne_formulaire : 0 + color: "transparent" + visible: (type_entrees >= shipheart_capteur_type_entrees_calculee_booleen) || + ( ligne_entrees.visible +// && (champ_formulaire_Entrees.currentIndex !== 0) + && ( (champ_formulaire_Entrees.currentIndex !== 0) || + ((type_entrees === shipheart_capteur_type_entrees_aux) && (nb_entrees > 0)) ) + && ( (champ_formulaire_Mode_entrees.currentIndex !== 0) + || (type_entrees === shipheart_capteur_type_entrees_aux) // Pour les entrées AUX, le cas de Mode_entrees=0 est Valide car corrrespond au mode NORMAL + || (!flag_affichage_mode_entrees) ) ) + + Shipheart_formulaire_label { + text: qsTr("Groupe de capteurs") + width: parent.width * pourcentage_largeur_labels_formulaire + couleur: (champ_formulaire_Famille.currentIndex !== 0) + ? shipheart_formulaire_couleur_texte_par_defaut + : shipheart_formulaire_couleur_texte_en_erreur + } + + Shipheart_formulaire_combobox { + id: champ_formulaire_Famille + model: ListModel { } + width: parent.width * (1 - pourcentage_largeur_labels_formulaire) + onActivated: { + shipheart_clic(); + if ( (type_entrees === shipheart_capteur_type_entrees_aux) || (type_entrees === shipheart_capteur_type_entrees_calculee_booleen) ) + { + mise_a_jour_libelles(); + } + } + } + + Shipheart_formulaire_ligne_separation { + haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse + } + } + + //------------------------------------------------------------------------------- + // Lignes de formulaire : Libelles des valeurs discrètes + ListView { + id: liste_libelles + visible: ligne_famille.visible + && (champ_formulaire_Famille.currentIndex !== 0) + && ( (type_entrees === shipheart_capteur_type_entrees_aux) + || (type_entrees === shipheart_capteur_type_entrees_calculee_booleen) ) + + width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2) + height: (hauteur_ligne_formulaire * nb_libelles) + 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: liste_libelles.width + height: (liste_libelles.height / nb_libelles) + color: "transparent" + + Rectangle { + width: liste_libelles.width + height: hauteur_ligne_formulaire + color: "transparent" + + Shipheart_formulaire_label { + text: qsTr("Libellé du capteur pour la valeur %1").arg(valeur) + width: parent.width * pourcentage_largeur_labels_formulaire + couleur: shipheart_formulaire_couleur_texte_par_defaut + } + + Shipheart_formulaire_textfield { + id: libelle_entrees + width: parent.width * (1 - pourcentage_largeur_labels_formulaire) + x: parent.width * pourcentage_largeur_labels_formulaire + text: libelle + placeholderText: valeur // Permet de faire apparaitre la valeur par défaut + onEditingFinished: { + liste_libelles.model.set(valeur, {"libelle": text}); // Mémorisation de la valeur entrée dans le TextField + } + } + + Shipheart_formulaire_ligne_separation { + haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse + } + } + } + ScrollBar.vertical: ScrollBar {} + } + + //------------------------------------------------------------------------------- + // Ligne de formulaire : Masquage + Rectangle { + id: ligne_masquage + width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2) + height: visible ? hauteur_ligne_formulaire : 0 + color: "transparent" + visible: ligne_famille.visible + && (champ_formulaire_Famille.currentIndex !== 0) + + Shipheart_formulaire_label { + text: qsTr("Masquer sur la page Capteurs") + width: parent.width * pourcentage_largeur_labels_formulaire + } + + Shipheart_formulaire_checkbox { + id: champ_formulaire_Masquage + width: parent.width * (1 - pourcentage_largeur_labels_formulaire) + onCheckedChanged: { + 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/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 + // Note: ligne revalidée pour 3.4.10 car la saisie des libellés de texte est perdue si on enregistre avant de sortir du focus OU de replier le clavier. + + (champ_formulaire_Nom.text !== "") // ... ou si le nom est vide, + && (champ_formulaire_Type_entrees.currentIndex !== 0) // ... ou si aucune affectation à un capteur n'a été faite, + && ( (type_entrees >= shipheart_capteur_type_entrees_calculee_booleen) // ... ou ce n'est pas un capteur calculé + || ( (champ_formulaire_Adresse_module.currentIndex !== 0) + && ( (champ_formulaire_Entrees.currentIndex !== 0) || + ((type_entrees === shipheart_capteur_type_entrees_aux) && (nb_entrees > 0)) ) // ... et aucune Entrée sélectionnée + && ((champ_formulaire_Mode_entrees.currentIndex !== 0) // ... ou aucun Mode sélectionné + || (type_entrees === shipheart_capteur_type_entrees_aux) // Sauf pour les entrées AUX, le cas de Mode_entrees=0 est Valide car corrrespond au mode NORMAL + || (!flag_affichage_mode_entrees) ) ) ) // Sauf si pas besoin de Mode + && (champ_formulaire_Famille.currentIndex !== 0) // ... ou si aucune affectation à un groupe n'a été faite, on n'autorise pas la'enregistrement/création. + Text { + anchors { + verticalCenter: parent.verticalCenter + horizontalCenter: parent.horizontalCenter + } + font.pixelSize: 20 + text: (id_capteur === 0) ? qsTr("Créer le capteur") : qsTr("Enregistrer") + color: couleur_blanc_casse + } + MouseArea { + anchors.fill: parent + onClicked: { + shipheart_clic(); + if (id_capteur !== 0) mise_a_jour_capteur(); // Mise à jour des données saisies dans la BDD et reconfiguration par l'application pour prise en compte. + else creation_capteur(); + timer_tempo_reconfiguration.restart(); + } + } + } + + //------------------------------------------------------- + // Bouton d'accès à l'équation + // NB : On donne l'accès à l'équation même si le capteur 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'équation. + //------------------------------------------------------- + Rectangle { + width: parent.width + height: hauteur_bouton_droit + color: shipheart_couleur_fond_bouton + radius: shipheart_rayon_bouton + visible: bouton_enregistrer_creer.visible + && (type_entrees >= shipheart_capteur_type_entrees_calculee_booleen) + + Text { + anchors { + verticalCenter: parent.verticalCenter + horizontalCenter: parent.horizontalCenter + } + font.pixelSize: 20 + text: qsTr("Equation") + color: couleur_blanc_casse + } + MouseArea { + anchors.fill: parent + onClicked: { + shipheart_clic(); + if (id_capteur === 0) creation_capteur(); // Si le capteur n'a pas encore été créé et qu'on demande l'éccès à l'équation, on commence par créer le capteur (sinon, on ne peut pas affecter les conditions à un ID_Capteur...) + stackView.push("config_capteur_calcule_booleen.qml", {"id_capteur": id_capteur}) + } + } + } + + + //------------------------------------------------------- + // 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_capteur !== 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; + } + } + } + + //------------------------------------------------------- + // Bouton Etalonnage : + //------------------------------------------------------- + Rectangle { + width: parent.width + height: hauteur_bouton_droit + color: shipheart_couleur_fond_bouton + radius: shipheart_rayon_bouton + visible: flag_affichage_offset && bouton_enregistrer_creer.visible + Text { + anchors { + verticalCenter: parent.verticalCenter + horizontalCenter: parent.horizontalCenter + } + font.pixelSize: 20 + text: qsTr("Etalonner") + color: couleur_blanc_casse + } + MouseArea { + anchors.fill: parent + onClicked: { + shipheart_clic(); + stackView.push("etalonnage_capteur.qml", {"id_capteur": id_capteur}) + } + } + } + + //------------------------------------------------------- + // 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 retournb_entrees + //................................................. + 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 sélection entrée aux : + //------------------------------------------------------- + Shipheart_boite_dialogue_entrees_aux { + id: boite_selection_entree_aux + + boutonAnnuler: true + boutonAnnulerTexte: "Annuler" + onClicked: { + + if (bouton === shipheart_boite_dialogue_bouton_1) + { + var groupe = recherche_groupe_entree_aux(no_entree - 1); + + if (modele_entrees_aux.get(groupe).valeurs.get((no_entree - 1) % 4).no_entree === entree_en_cours) // Si on reclique sur l'entrée déjà affectée, on supprime l'affectation. + { + entrees_aux_grid.model.set((entree_en_cours - 1), {"no_entree_aux" : 0, "libelle": ""}); + modele_entrees_aux.get(groupe).valeurs.set(((no_entree - 1) % 4), {"used": 0, "no_entree": 0}); + + nb_entrees --; + } + else // Si on clique sur une autre entrée... + { + // ... on vérifie si le n° était déjà affecté à une entrée aux. Si oui, on supprime cette affectation avant de créer la nouvelle : + var i = entrees_aux_grid.model.get(entree_en_cours - 1).no_entree_aux; + if (i !== 0) + { + var g = recherche_groupe_entree_aux(i - 1); + + modele_entrees_aux.get(g).valeurs.set(((i - 1) % 4), {"used": 0, "no_entree": 0}); + + nb_entrees --; + } + + // On met ensuite à jour la nouvelle affectation : + entrees_aux_grid.model.set((entree_en_cours - 1), {"no_entree_aux" : no_entree, "libelle": "AUX INPUT " + no_entree }); + modele_entrees_aux.get(groupe).valeurs.set(((no_entree - 1) % 4), {"used": 1, "no_entree": entree_en_cours}); + + nb_entrees ++; + } + + if (flag_affichage_mode_entrees) mise_a_jour_mode_entrees(); // Cas "normal" où le Mode_entree doit être traité + else mise_a_jour_famille(); // Si pas de Mode_entree, on passe directement à la Famille. + + boite_selection_entree_aux.close(); + } + } + } + ListModel { + id: modele_entrees_aux + } + + + //------------------------------------------------------- + // 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; + +//console.log("Id du capteur = " + id_capteur); + + //--------------------------------------------------------------------------------------- + // Caractéristiques du capteur en cours : + //--------------------------------------------------------------------------------------- + champ_formulaire_Nom.text = ""; + + if (id_capteur > 0) // Cas d'une modification de capteur existant : + { + req = 'SELECT Nom, '; + req += ' Adresse_module, '; + req += ' Type_entrees, '; + req += ' Entrees, '; + req += ' Mode_entrees, '; + req += ' Priorite_affichage_accueil, '; + req += ' ID_Famille, '; + req += ' ID_Variable, '; + req += ' Liste_valeurs_textes '; + req += ' FROM TB_Capteurs '; + req += ' WHERE Cle_primaire=' + id_capteur + ' '; +//console.log("Requête = [ " + req + "; ]"); + res = bdd.requete_unique(req); + + // Récupération des données : + i = 0; + champ_formulaire_Nom.text = res[i ++]; + adresse_module = Number(res[i ++]); + type_entrees = Number(res[i ++]); + entrees = res[i ++]; + mode_entrees = Number(res[i ++]); + priorite_affichage_accueil = Number(res[i ++]); + id_famille = Number(res[i ++]); + id_variable = Number(res[i ++]); + liste_valeurs_textes = res[i ++]; + + // Cas particulier d'un capteur sur entrée NMEA : + if (type_entrees === shipheart_capteur_type_entrees_nmea) flag_nmea = true; + + // Traitement de Masquage : + if (priorite_affichage_accueil <= 0) champ_formulaire_Masquage.checked = true; + else champ_formulaire_Masquage.checked = false; + + // Cas particulier d'accès au réglage de l'offset pour PAT uniquement : + if ((type_entrees === shipheart_capteur_type_entrees_predefinie) && (entrees === shipheart_capteur_predefini_pat + "")) flag_affichage_offset = true; + } + + // Remplissage des différents modèles, dasn l'ordre des priorités : + mise_a_jour_type_entrees(); + + flag_init = false; // Indique que l'init est terminée + } + + + //============================================================================================================= + // MAJ du type d'entrées + //============================================================================================================= + function mise_a_jour_type_entrees() + { + var i; + + //--------------------------------------------------------------------------------------- + // Type d'entrée : + //--------------------------------------------------------------------------------------- + + // Effacement du modèle et premier enregistrement avec 'Non défini' : + champ_formulaire_Type_entrees.model.clear(); + champ_formulaire_Type_entrees.model.append( { + "valeur": 0, + "texte": qsTr("Non défini"), + "actif": true }); + champ_formulaire_Type_entrees.model.append( { + "valeur": shipheart_capteur_type_entrees_aux, + "texte": qsTr("Entrées Auxiliaires (AUX INPUTS)"), + "actif": true }); + champ_formulaire_Type_entrees.model.append( { + "valeur": shipheart_capteur_type_entrees_level_sensor, + "texte": qsTr("Entrées Niveau (LEVEL SENSORS)"), + "actif": true }); + champ_formulaire_Type_entrees.model.append( { + "valeur": shipheart_capteur_type_entrees_volt, + "texte": qsTr("Entrées Tension (VOLTAGE INPUTS)"), + "actif": true }); + champ_formulaire_Type_entrees.model.append( { + "valeur": shipheart_capteur_type_entrees_ow, + "texte": qsTr("Capteurs de température (ONE WIRE)"), + "actif": true }); + champ_formulaire_Type_entrees.model.append( { + "valeur": shipheart_capteur_type_entrees_nmea, + "texte": qsTr("Entrées NMEA2000"), + "actif": true }); + champ_formulaire_Type_entrees.model.append( { + "valeur": shipheart_capteur_type_entrees_predefinie, + "texte": qsTr("Capteurs sur modules"), + "actif": true }); + champ_formulaire_Type_entrees.model.append( { + "valeur": shipheart_capteur_type_entrees_calculee_booleen, + "texte": qsTr("Calculé (conditions logiques)"), + "actif": true }); + /* champ_formulaire_Type_entrees.model.append( { + "valeur": shipheart_capteur_type_entrees_calculee_numerique, + "texte": qsTr("Calculé (valeur numérique)"), + "actif": true }); +*/ + // Mise à jour de l'index courant du modèle champ_formulaire_Type_entrees : + i = recherche_index_valeur_modele(type_entrees, champ_formulaire_Type_entrees.model, "Type_entrees"); + if (i === -1) champ_formulaire_Type_entrees.currentIndex = recherche_index_valeur_modele(0, champ_formulaire_Type_entrees.model, "Type_entrees"); + else champ_formulaire_Type_entrees.currentIndex = i; + + + // Appel du remplissage des modèles de niveau inférieur si cela est possible : + if (type_entrees !== 0) + { + mise_a_jour_module_entrees(); + } + + } + + //============================================================================================================= + // MAJ du module d'entrées + //============================================================================================================= + function mise_a_jour_module_entrees() + { + var req, res; + var nb; + var i; + var flag_valide; + + // Effacement du modèle : + champ_formulaire_Adresse_module.model.clear(); + champ_formulaire_Adresse_module.model.append({"valeur": -1, "texte": qsTr("Non défini"), "actif": true }); + + champ_formulaire_Adresse_module.currentIndex = 0; // Par défaut + + // Remplissage du modèle avec les modules en config : + req = 'SELECT Adresse_k_bus, Type FROM TB_Modules_config ORDER BY Adresse_k_bus'; + nb = bdd.requete(req); +//console.log("Requête = [ " + req + "; ]"); + + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + flag_valide = false; + switch(Number(res[1])) // Type de module + { + //-------------------------------------- + case shipheart_type_module_shipbase: + flag_valide = true; // Tous les types sont accessibles sur ShiBase donc inutile de tester... + + break; + + //-------------------------------------- + case shipheart_type_module_shippower812: + case shipheart_type_module_shipBS: + case shipheart_type_module_shippower4AC: + case shipheart_type_module_shippower8DC: + if (type_entrees === shipheart_capteur_type_entrees_predefinie) flag_valide = true; + else flag_valide = false; + + break; + + //-------------------------------------- + default: + flag_valide = false; // Le type est inconnu donc, dans le doute, on ne donne pas accès à ce module + break; + } + + // Ajout de l'entrée dans le modèle si le module est considéré comme compatible avec le type d'entrée sélectionné: + if (flag_valide) + { + champ_formulaire_Adresse_module.model.append({ + "valeur": Number(res[0]), + "texte": "@" + res[0] + " - " + Fonctions.nom_type_module(Number(res[1])), + "actif": true + }); + // Mise à jour de l'index du mdoèle si l'on est sur l'entrée en cours : + if (Number(res[0]) === adresse_module) champ_formulaire_Adresse_module.currentIndex = (i+1); + } + } + } + + // Si le Type_entrées est != de ENTREES_PREDEFINIES, on est sûr qu'il n'y aura que ShipBase (pour le moment au moins...) : + if (type_entrees !== shipheart_capteur_type_entrees_predefinie) adresse_module = 0; + + // Mise à jour de l'index courant du modèle champ_formulaire_Module_entrees : + i = recherche_index_valeur_modele(adresse_module, champ_formulaire_Adresse_module.model, "adresse_module"); + if (i === -1) champ_formulaire_Adresse_module.currentIndex = recherche_index_valeur_modele(-1, champ_formulaire_Adresse_module.model, "adresse_module"); + else champ_formulaire_Adresse_module.currentIndex = i; + + // Appel du remplissage des modèles de niveau inférieur si cela est possible : + if (adresse_module >= 0) mise_a_jour_entrees(); + } + + + //============================================================================================================= + // MAJ des Entrées + //============================================================================================================= + function mise_a_jour_entrees() + { + var req, res; + var nb; + var i, j; + var chaines_entrees; + var no; + + + //--------------------------------------------------------------------------------------- + // Mise à jour du modèle des entrées : + // + // Pour tous les types à l'exception de ENTREES AUX, on utilise le modèle 'champ_formulaire_Entrees' qui pointe vers une ComboBox. + // Ce modèle comprend donc une liste de choix parmi lesquel il faut en sélectionner 1. + // Pour le type ENTREES AUX, on utilise 2 modèles dédié : + // - 'entrees_aux_grid' qui contient les entrées du capteur (le nombre est le max possible, soit 4 a priori). + // - 'modele_entrees_aux' qui contient les 32 entrées AUX de ShipBase (et, demain, celles du module sélectionné...). + + champ_formulaire_Entrees.model.clear(); + champ_formulaire_Entrees.model.append({"entrees": "", "texte": qsTr("Non défini"), "actif": true }); + + champ_formulaire_Entrees.currentIndex = 0; // Si aucune entrée n'est trouvée (cas d'une création par exemple), l'index est égal à 0 + + switch(type_entrees) + { + //---------------------------------------- + // Entrées AUX : + //---------------------------------------- + case shipheart_capteur_type_entrees_aux: + var val; + + // Entrées AUX du capteur : + entrees_aux_grid.model.clear(); + + chaines_entrees = entrees.split(';'); + if (entrees !== "") nb_entrees = chaines_entrees.length // Si la chaine est vide, le split renvoi 1... Exactement comme dans le cas où il y a une seule valeur... + else nb_entrees = 0; + + for (i = 0; i < shipheart_capteur_max_nombre_entrees_aux; i ++) + { + if (i < nb_entrees) val = Number(chaines_entrees[i]); + else val = 0; + + entrees_aux_grid.model.append( { "no": (i + 1), + "no_entree_aux" : val, + "libelle": (val === 0) ? "FFFFF" : "AUX INPUT " + val }); + } + + //--------------------------------------------------------------------------------------- + // Entrées auxiliaires physiques : + // Les 32 entrées AUX de ShipBase par exemple + var entrees_aux = []; + + // remplissage par défaut de toutes les entrées AUX possibles : + for (i=0; i= 1) && (no <= shipheart_entrees_aux_max_nombre)) entrees_aux[no - 1]['used'] = 1; // le n° d'entrée doit être dans [1; 32] + } + } + } + + modele_entrees_aux.clear(); + + i = 17; + modele_entrees_aux.append({valeurs: [{no: i, used: entrees_aux[i-1]['used'], no_entree: entrees_aux[i-1]['no_entree'] }, + {no: (i+1), used: entrees_aux[i+0]['used'], no_entree: entrees_aux[i+0]['no_entree'] }, + {no: (i+2), used: entrees_aux[i+1]['used'], no_entree: entrees_aux[i+1]['no_entree'] }, + {no: (i+3), used: entrees_aux[i+2]['used'], no_entree: entrees_aux[i+2]['no_entree'] }] } ); + i = 21; + modele_entrees_aux.append({valeurs: [{no: i, used: entrees_aux[i-1]['used'], no_entree: entrees_aux[i-1]['no_entree'] }, + {no: (i+1), used: entrees_aux[i+0]['used'], no_entree: entrees_aux[i+0]['no_entree'] }, + {no: (i+2), used: entrees_aux[i+1]['used'], no_entree: entrees_aux[i+1]['no_entree'] }, + {no: (i+3), used: entrees_aux[i+2]['used'], no_entree: entrees_aux[i+2]['no_entree'] }] } ); + i = 25; + modele_entrees_aux.append({valeurs: [{no: i, used: entrees_aux[i-1]['used'], no_entree: entrees_aux[i-1]['no_entree'] }, + {no: (i+1), used: entrees_aux[i+0]['used'], no_entree: entrees_aux[i+0]['no_entree'] }, + {no: (i+2), used: entrees_aux[i+1]['used'], no_entree: entrees_aux[i+1]['no_entree'] }, + {no: (i+3), used: entrees_aux[i+2]['used'], no_entree: entrees_aux[i+2]['no_entree'] }] } ); + i = 29; + modele_entrees_aux.append({valeurs: [{no: i, used: entrees_aux[i-1]['used'], no_entree: entrees_aux[i-1]['no_entree'] }, + {no: (i+1), used: entrees_aux[i+0]['used'], no_entree: entrees_aux[i+0]['no_entree'] }, + {no: (i+2), used: entrees_aux[i+1]['used'], no_entree: entrees_aux[i+1]['no_entree'] }, + {no: (i+3), used: entrees_aux[i+2]['used'], no_entree: entrees_aux[i+2]['no_entree'] }] } ); + i = 1; + modele_entrees_aux.append({valeurs: [{no: i, used: entrees_aux[i-1]['used'], no_entree: entrees_aux[i-1]['no_entree'] }, + {no: (i+1), used: entrees_aux[i+0]['used'], no_entree: entrees_aux[i+0]['no_entree'] }, + {no: (i+2), used: entrees_aux[i+1]['used'], no_entree: entrees_aux[i+1]['no_entree'] }, + {no: (i+3), used: entrees_aux[i+2]['used'], no_entree: entrees_aux[i+2]['no_entree'] }] } ); + i = 5; + modele_entrees_aux.append({valeurs: [{no: i, used: entrees_aux[i-1]['used'], no_entree: entrees_aux[i-1]['no_entree'] }, + {no: (i+1), used: entrees_aux[i+0]['used'], no_entree: entrees_aux[i+0]['no_entree'] }, + {no: (i+2), used: entrees_aux[i+1]['used'], no_entree: entrees_aux[i+1]['no_entree'] }, + {no: (i+3), used: entrees_aux[i+2]['used'], no_entree: entrees_aux[i+2]['no_entree'] }] } ); + i = 9; + modele_entrees_aux.append({valeurs: [{no: i, used: entrees_aux[i-1]['used'], no_entree: entrees_aux[i-1]['no_entree'] }, + {no: (i+1), used: entrees_aux[i+0]['used'], no_entree: entrees_aux[i+0]['no_entree'] }, + {no: (i+2), used: entrees_aux[i+1]['used'], no_entree: entrees_aux[i+1]['no_entree'] }, + {no: (i+3), used: entrees_aux[i+2]['used'], no_entree: entrees_aux[i+2]['no_entree'] }] } ); + i = 13; + modele_entrees_aux.append({valeurs: [{no: i, used: entrees_aux[i-1]['used'], no_entree: entrees_aux[i-1]['no_entree'] }, + {no: (i+1), used: entrees_aux[i+0]['used'], no_entree: entrees_aux[i+0]['no_entree'] }, + {no: (i+2), used: entrees_aux[i+1]['used'], no_entree: entrees_aux[i+1]['no_entree'] }, + {no: (i+3), used: entrees_aux[i+2]['used'], no_entree: entrees_aux[i+2]['no_entree'] }] } ); + + // Mise à jour du flag d'utilisation du paramètre Mode_entrées : + flag_affichage_mode_entrees = true; // NB : pour les entrées AUX, on utilise une case à cocher + + break; + + //---------------------------------------- + // Entrées Level Sensor : + //---------------------------------------- + case shipheart_capteur_type_entrees_level_sensor: + + for (i=0; iEntrée non utilisée"), + "actif": true, + "code_variable": shipheart_capteur_sans_unite, // On ne sait pas le renseigner à ce stade. Sera renseigné lorsque le Mode_entree sera renseigné. + "mode_enregistrement_mesures": shipheart_mode_enregistrement_mesures_periodique, + "precision_affichage_accueil": 0, // Idem + "precision_affichage_mesures": 0 // Idem + }); + + // Mise à jour de l'index du mdoèle si l'on est sur l'entrée en cours : + if ((i+1) === Number(entrees)) champ_formulaire_Entrees.currentIndex = (i+1); // Le '+1' sur CurrenIndex car on a déjà ajouté une entrée NON DEFINIE + } + + // Mise à jour en fonction des entrées déjà utilisées par ailleurs (capteurs et réservoirs) : + req = '(SELECT ' + shipheart_source_mesure_reservoir + ' AS Type, Nom, Entrees, "'+ shipheart_reservoir_niveau+'" AS Code_variable, 0 AS Precision_affichage_accueil, 0 AS Precision_affichage_mesures '; + req += 'FROM TB_Reservoirs WHERE '; + req += 'Type_entrees=' + shipheart_reservoir_type_entrees_level_sensor + ') '; + req += ' UNION '; + req += '(SELECT ' + shipheart_source_mesure_capteur + ' AS Type, Nom, Entrees, '; + req += ' (SELECT Code FROM TB_Variables WHERE Cle_primaire=ID_Variable) AS Code_variable, Precision_affichage_accueil, Precision_affichage_mesures '; + req += 'FROM TB_Capteurs WHERE '; + req += 'Type_entrees=' + shipheart_capteur_type_entrees_level_sensor + ') '; +//console.log("Requête = [ " + req + "; ]"); + nb = bdd.requete(req); + + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + no = Number(res[2]); + + if ((no >= 1) && (no <= shipheart_entrees_level_sensor_max_nombre)) + { + if (no === Number(entrees)) // Si on est sur l'entrée en cours, on laisse 'actif' à TRUE (et on peut ajuster le texte au passage...) + { + champ_formulaire_Entrees.model.set(no, { + "texte": "# "+ no, + "code_variable": res[3], + "precision_affichage_accueil": Number(res[4]), + "precision_affichage_mesures": Number(res[5])} ) + } + else // Si on n'est pas sur l'entrée en cours, on positionne 'actif' à FALSE (et on ajuste le texte pou rinformation) + { + champ_formulaire_Entrees.model.set(no, { + "texte": "#"+ no + " - " + Fonctions.nom_type_equipement(Number(res[0])) + " \"" + res[1] + "\"", + "code_variable": res[3], + "precision_affichage_accueil": Number(res[4]), + "precision_affichage_mesures": Number(res[5]), + "actif": false} ) + } + } + } + } + + // Mise à jour du flag d'utilisation du paramètre Mode_entrées : + flag_affichage_mode_entrees = true; + + break; + + //---------------------------------------- + // Entrées Voltage Input : + //---------------------------------------- + case shipheart_capteur_type_entrees_volt: + + for (i=0; iEntrée non utilisée"), + "actif": true, + "code_variable": shipheart_capteur_tension_v, + "mode_enregistrement_mesures": shipheart_mode_enregistrement_mesures_periodique, + "precision_affichage_accueil": 1, + "precision_affichage_mesures": 2 + }); + + // Mise à jour de l'index du mdoèle si l'on est sur l'entrée en cours : + if ((i+1) === Number(entrees)) champ_formulaire_Entrees.currentIndex = (i+1); // Le '+1' sur CurrenIndex car on a déjà ajouté une entrée NON DEFINIE + } + + // Mise à jour en fonction des entrées déjà utilisées par ailleurs (capteurs et batteries) : + req = '(SELECT ' + shipheart_source_mesure_batterie + ' AS Type, Nom, Entrees '; + req += 'FROM TB_Batteries WHERE '; + req += 'Type_entrees=' + shipheart_batteries_type_entrees_volt + ') '; + req += ' UNION '; + req += '(SELECT ' + shipheart_source_mesure_capteur + ' AS Type, Nom, Entrees '; + req += 'FROM TB_Capteurs WHERE '; + req += 'Type_entrees=' + shipheart_capteur_type_entrees_volt + ') '; +//console.log("Requête = [ " + req + "; ]"); + nb = bdd.requete(req); + + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + no = Number(res[2]); + + if ((no >= 1) && (no <= shipheart_entrees_volt_max_nombre)) + { + if (no === Number(entrees)) // Si on est sur l'entrée en cours, on laisse 'actif' à TRUE (et on peut ajuster le texte au passage...) + { + champ_formulaire_Entrees.model.set(no, {"texte": "# "+ no} ) + } + else // Si on n'est pas sur l'entrée en cours, on positionne 'actif' à FALSE (et on ajuste le texte pou rinformation) + { + champ_formulaire_Entrees.model.set(no, {"texte": "#"+ no + " - " + Fonctions.nom_type_equipement(Number(res[0])) + " \"" + res[1] + "\"", "actif": false} ) + } + } + } + } + + // Mise à jour du flag d'utilisation du paramètre Mode_entrées : + flag_affichage_mode_entrees = false; + + break; + + //---------------------------------------- + // Entrées OW : + //---------------------------------------- + case shipheart_capteur_type_entrees_ow: + + // Recherche des capteurs de température physiquement présents : + req = 'SELECT Rom_code '; + req += ', Emplacement '; + req += ' FROM TB_One_wire '; + req += ' WHERE Presence=1 ' + req += ' ORDER BY Rom_code'; +//console.log("Requête = [ " + req + "; ]"); + nb = bdd.requete(req); + + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + champ_formulaire_Entrees.model.append({ + "entrees": res[0], + "texte": (res[1] === "") ? (res[0]) : (res[0] + "
[" + res[1] + "]"), + "actif": true, + "code_variable": shipheart_capteur_temperature, + "mode_enregistrement_mesures": shipheart_mode_enregistrement_mesures_periodique, + "precision_affichage_accueil": 1, + "precision_affichage_mesures": 2 + }); + + // Mise à jour de l'index du mdoèle si l'on est sur l'entrée en cours : + if (res[0] === entrees) champ_formulaire_Entrees.currentIndex = (i+1); // Le '+1' sur CurrenIndex car on a déjà ajouté une entrée NON DEFINIE + } + } + + // Mise à jour en fonction des entrées déjà utilisées par ailleurs (capteurs) : + req = '(SELECT ' + shipheart_source_mesure_capteur + ' AS Type, Nom, Entrees '; + req += 'FROM TB_Capteurs WHERE '; + req += 'Type_entrees=' + shipheart_capteur_type_entrees_ow + ') '; +//console.log("Requête = [ " + req + "; ]"); + nb = bdd.requete(req); + + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + for(j = 0; j < champ_formulaire_Entrees.model.count; j ++) + { + if (res[2] === champ_formulaire_Entrees.model.get(j).entrees) + { + if (res[2] === entrees) // Si on est sur l'entrée en cours, on laisse 'actif' à TRUE (et on peut ajuster le texte au passage...) + { +// champ_formulaire_Entrees.model.set(j, {"texte": "# "+ j} ) + champ_formulaire_Entrees.model.set(j, {"texte": res[2] + "
" + Fonctions.nom_type_equipement(Number(res[0])) + " \"" + res[1] + "\""} ) + } + else // Si on n'est pas sur l'entrée en cours, on positionne 'actif' à FALSE (et on ajuste le texte pou rinformation) + { + champ_formulaire_Entrees.model.set(j, {"texte": res[2] + "
" + Fonctions.nom_type_equipement(Number(res[0])) + " \"" + res[1] + "\"", "actif": false} ) + } + } + } + } + } + + // Mise à jour du flag d'utilisation du paramètre Mode_entrées : + flag_affichage_mode_entrees = false; + + break; + + //---------------------------------------- + // Entrées NMEA : + //---------------------------------------- + case shipheart_capteur_type_entrees_nmea: + + // Recherche des PGN/Fields physiquement présents : + req = 'SELECT Pgn, '; + req += 'Field, '; + req += 'Nom, '; + req += '(SELECT Code FROM TB_Variables WHERE Cle_primaire=ID_Variable) as Code, '; + req += 'Precision_affichage_accueil, '; + req += 'Precision_affichage_mesures '; + 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) + { + champ_formulaire_Entrees.model.append({ + "entrees": res[0] + ":" + res[1], + "texte": "PGN " + res[0] + " [# " + res[1] + "] :
" + res[2], + "actif": true, + "code_variable": res[3], + "mode_enregistrement_mesures": shipheart_mode_enregistrement_mesures_periodique, + "precision_affichage_accueil": Number(res[4]), + "precision_affichage_mesures": Number(res[5]), + }); + + // Mise à jour de l'index du modèle si l'on est sur l'entrée en cours : + if ((res[0] + ":" + res[1]) === entrees) champ_formulaire_Entrees.currentIndex = (i+1); // Le '+1' sur CurrenIndex car on a déjà ajouté une entrée NON DEFINIE + } + } + + // Mise à jour en fonction des entrées déjà utilisées par ailleurs (capteurs) : + req = '(SELECT ' + shipheart_source_mesure_capteur + ' AS Type, Nom, Entrees '; + req += 'FROM TB_Capteurs WHERE '; + req += 'Type_entrees=' + shipheart_capteur_type_entrees_nmea + ') '; +//console.log("Requête = [ " + req + "; ]"); + nb = bdd.requete(req); + + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + for(j = 0; j < champ_formulaire_Entrees.model.count; j ++) + { + if (res[2] === champ_formulaire_Entrees.model.get(j).entrees) + { + // Mise à jour du texte en ajoutant le nom du capteur en-dessous : + champ_formulaire_Entrees.model.set(j, {"texte": champ_formulaire_Entrees.model.get(j).texte + "
" + Fonctions.nom_type_equipement(Number(res[0])) + " \"" + res[1] + "\""} ); + + // Si on n'est pas sur l'entrée en cours, on pass l'entrée 'actif' à FALSE : + if (res[2] !== entrees) champ_formulaire_Entrees.model.set(j, {"actif": false} ); + } + } + } + } + + // Mise à jour du flag d'utilisation du paramètre Mode_entrées : + flag_affichage_mode_entrees = false; + + break; + + + //---------------------------------------- + // Entrées Prédéfinies : + //---------------------------------------- + case shipheart_capteur_type_entrees_predefinie: + + req = 'SELECT Type FROM TB_Modules_config WHERE Adresse_k_bus=' + adresse_module+ ' '; + res = bdd.requete_unique(req); +//console.log("Requête = [ " + req + "; ]"); + + + switch(Number(res[0])) // Type de module + { + //-------------------------------------- + case shipheart_type_module_shipbase: + + champ_formulaire_Entrees.model.append({ + "entrees": shipheart_capteur_predefini_pat + "", + "texte": qsTr("Pression Atmosphérique"), + "actif": true, + "code_variable": shipheart_capteur_pression_atm, + "mode_enregistrement_mesures": shipheart_mode_enregistrement_mesures_periodique, + "precision_affichage_accueil": 1, + "precision_affichage_mesures": 2 + }); + champ_formulaire_Entrees.model.append({ + "entrees": shipheart_capteur_predefini_hum + "", + "texte": qsTr("Humidité"), + "actif": true, + "code_variable": shipheart_capteur_humidite, + "mode_enregistrement_mesures": shipheart_mode_enregistrement_mesures_periodique, + "precision_affichage_accueil": 1, + "precision_affichage_mesures": 1 + }); + champ_formulaire_Entrees.model.append({ + "entrees": shipheart_capteur_predefini_temp + "", + "texte": qsTr("Température module"), + "actif": true, + "code_variable": shipheart_capteur_temperature, + "mode_enregistrement_mesures": shipheart_mode_enregistrement_mesures_periodique, + "precision_affichage_accueil": 1, + "precision_affichage_mesures": 2 + }); + + champ_formulaire_Entrees.model.append({ + "entrees": shipheart_capteur_predefini_in_v + "", + "texte": qsTr("Tension d'entrée module"), + "actif": true, + "code_variable": shipheart_capteur_tension_v, + "mode_enregistrement_mesures": shipheart_mode_enregistrement_mesures_periodique, + "precision_affichage_accueil": 1, + "precision_affichage_mesures": 2 + }); + champ_formulaire_Entrees.model.append({ + "entrees": shipheart_capteur_predefini_in_i + "", + "texte": qsTr("Consommation module"), + "actif": true, + "code_variable": shipheart_capteur_courant_a, + "mode_enregistrement_mesures": shipheart_mode_enregistrement_mesures_periodique, + "precision_affichage_accueil": 1, + "precision_affichage_mesures": 2 + }); + champ_formulaire_Entrees.model.append({ + "entrees": shipheart_capteur_predefini_usb_i + "", + "texte": qsTr("Consommation ports USB"), + "actif": true, + "code_variable": shipheart_capteur_courant_a, + "mode_enregistrement_mesures": shipheart_mode_enregistrement_mesures_periodique, + "precision_affichage_accueil": 1, + "precision_affichage_mesures": 2 + }); + + /* champ_formulaire_Entrees.model.append({ + "entrees": shipheart_capteur_predefini_edm + "", + "texte": qsTr("Etat de la mer"), + "actif": true, + "code_variable": shipheart_capteur_sans_unite, + "mode_enregistrement_mesures": shipheart_mode_enregistrement_mesures_changement_etat, + "precision_affichage_accueil": 0, + "precision_affichage_mesures": 0 + }); + */ + champ_formulaire_Entrees.model.append({ + "entrees": shipheart_capteur_predefini_acc_xyz + "", + "texte": qsTr("Chocs"), + "actif": true, + "code_variable": shipheart_capteur_acceleration, + "mode_enregistrement_mesures": shipheart_mode_enregistrement_mesures_periodique, + "precision_affichage_accueil": 1, + "precision_affichage_mesures": 2 + }); + champ_formulaire_Entrees.model.append({ + "entrees": shipheart_capteur_predefini_acc_x + "", + "texte": qsTr("Accélération X"), + "actif": true, + "code_variable": shipheart_capteur_acceleration, + "mode_enregistrement_mesures": shipheart_mode_enregistrement_mesures_periodique, + "precision_affichage_accueil": 1, + "precision_affichage_mesures": 2 + }); + champ_formulaire_Entrees.model.append({ + "entrees": shipheart_capteur_predefini_acc_y + "", + "texte": qsTr("Accélération Y"), + "actif": true, + "code_variable": shipheart_capteur_acceleration, + "mode_enregistrement_mesures": shipheart_mode_enregistrement_mesures_periodique, + "precision_affichage_accueil": 1, + "precision_affichage_mesures": 2 + }); + champ_formulaire_Entrees.model.append({ + "entrees": shipheart_capteur_predefini_acc_z + "", + "texte": qsTr("Accélération Z"), + "actif": true, + "code_variable": shipheart_capteur_acceleration, + "mode_enregistrement_mesures": shipheart_mode_enregistrement_mesures_periodique, + "precision_affichage_accueil": 1, + "precision_affichage_mesures": 2 + }); + + champ_formulaire_Entrees.model.append({ + "entrees": shipheart_capteur_predefini_lat + "", + "texte": qsTr("GNSS - Latitude"), + "actif": true, + "code_variable": shipheart_capteur_latitude, + "mode_enregistrement_mesures": shipheart_mode_enregistrement_mesures_periodique, + "precision_affichage_accueil": 0, + "precision_affichage_mesures": 0 + }); + champ_formulaire_Entrees.model.append({ + "entrees": shipheart_capteur_predefini_lon + "", + "texte": qsTr("GNSS - Longitude"), + "actif": true, + "code_variable": shipheart_capteur_longitude, + "mode_enregistrement_mesures": shipheart_mode_enregistrement_mesures_periodique, + "precision_affichage_accueil": 0, + "precision_affichage_mesures": 0 + }); + champ_formulaire_Entrees.model.append({ + "entrees": shipheart_capteur_predefini_alt + "", + "texte": qsTr("GNSS - Altitude"), + "actif": true, + "code_variable": shipheart_capteur_distance_m, + "mode_enregistrement_mesures": shipheart_mode_enregistrement_mesures_periodique, + "precision_affichage_accueil": 1, + "precision_affichage_mesures": 1 + }); + champ_formulaire_Entrees.model.append({ + "entrees": shipheart_capteur_predefini_sog + "", + "texte": qsTr("GNSS - SOG
Speed Over Ground"), + "actif": true, + "code_variable": shipheart_capteur_vitesse_kts, + "mode_enregistrement_mesures": shipheart_mode_enregistrement_mesures_periodique, + "precision_affichage_accueil": 1, + "precision_affichage_mesures": 2 + }); + champ_formulaire_Entrees.model.append({ + "entrees": shipheart_capteur_predefini_cog + "", + "texte": qsTr("GNSS - COG
Course Over Ground"), + "actif": true, + "code_variable": shipheart_capteur_angle_degres, + "mode_enregistrement_mesures": shipheart_mode_enregistrement_mesures_periodique, + "precision_affichage_accueil": 0, + "precision_affichage_mesures": 0 + }); + champ_formulaire_Entrees.model.append({ + "entrees": shipheart_capteur_predefini_siv + "", + "texte": qsTr("GNSS - SIV
Satellites In View"), + "actif": true, + "code_variable": shipheart_capteur_sans_unite, + "mode_enregistrement_mesures": shipheart_mode_enregistrement_mesures_periodique, // Choix fait après mure réflexion : inutile d'aller chercher de la précision sur ce paramètre alors que ce qui interresse est une tendance... + "precision_affichage_accueil": 0, + "precision_affichage_mesures": 0 + }); + champ_formulaire_Entrees.model.append({ + "entrees": shipheart_capteur_predefini_hpa + "", + "texte": qsTr("GNSS - HPA
Horizontal Precision Accuracy"), + "actif": true, + "code_variable": shipheart_capteur_distance_m, + "mode_enregistrement_mesures": shipheart_mode_enregistrement_mesures_periodique, + "precision_affichage_accueil": 1, + "precision_affichage_mesures": 1 + }); + champ_formulaire_Entrees.model.append({ + "entrees": shipheart_capteur_predefini_vpa + "", + "texte": qsTr("GNSS - VPA
Vertical Precision Accuracy"), + "actif": true, + "code_variable": shipheart_capteur_distance_m, + "mode_enregistrement_mesures": shipheart_mode_enregistrement_mesures_periodique, + "precision_affichage_accueil": 1, + "precision_affichage_mesures": 1 + }); + + if (shipheart_generation_shipbase === shipheart_generation_shipbase_v1) + { + champ_formulaire_Entrees.model.append({ + "entrees": shipheart_capteur_predefini_rssi + "", + "texte": qsTr("Modem 4G/LTE - RSSI
Received Signal Strength Indicator"), + "actif": true, + "code_variable": shipheart_capteur_puissance_db, + "mode_enregistrement_mesures": shipheart_mode_enregistrement_mesures_periodique, + "precision_affichage_accueil": 0, + "precision_affichage_mesures": 0 + }); + champ_formulaire_Entrees.model.append({ + "entrees": shipheart_capteur_predefini_sinr + "", + "texte": qsTr("Modem 4G/LTE - SINR
Signal to Interference & Noise Ratio"), + "actif": true, + "code_variable": shipheart_capteur_pourcentage, + "mode_enregistrement_mesures": shipheart_mode_enregistrement_mesures_periodique, + "precision_affichage_accueil": 0, + "precision_affichage_mesures": 0 + }); + } + + break; + + //-------------------------------------- + case shipheart_type_module_shippower812: + case shipheart_type_module_shippower8DC: + champ_formulaire_Entrees.model.append({ + "entrees": shipheart_capteur_predefini_temp + "", + "texte": qsTr("Température module"), + "actif": true, + "code_variable": shipheart_capteur_temperature, + "mode_enregistrement_mesures": shipheart_mode_enregistrement_mesures_periodique, + "precision_affichage_accueil": 1, + "precision_affichage_mesures": 2 + }); + champ_formulaire_Entrees.model.append({ + "entrees": shipheart_capteur_predefini_in_v + "", + "texte": qsTr("Tension d'entrée module"), + "actif": true, + "code_variable": shipheart_capteur_tension_v, + "mode_enregistrement_mesures": shipheart_mode_enregistrement_mesures_periodique, + "precision_affichage_accueil": 1, + "precision_affichage_mesures": 2 + }); + break; + + //-------------------------------------- + case shipheart_type_module_shipBS: + case shipheart_type_module_shippower4AC: + champ_formulaire_Entrees.model.append({ + "entrees": shipheart_capteur_predefini_temp + "", + "texte": qsTr("Température module"), + "actif": true, + "code_variable": shipheart_capteur_temperature, + "mode_enregistrement_mesures": shipheart_mode_enregistrement_mesures_periodique, + "precision_affichage_accueil": 1, + "precision_affichage_mesures": 2 + }); + break; + + //-------------------------------------- + default: + + break; + } + + + // Mise à jour de l'index du mdoèle si l'on est sur l'entrée en cours : + for(i = 0; i < champ_formulaire_Entrees.model.count; i ++) + { + if (entrees === champ_formulaire_Entrees.model.get(i).entrees) + { + champ_formulaire_Entrees.currentIndex = i; + break; // Inutile de poursuivre une fois qu'on a trouvé l'entrée en cours + } + } + + + // Mise à jour en fonction des entrées déjà utilisées par ailleurs (capteurs) : + req = '(SELECT ' + shipheart_source_mesure_capteur + ' AS Type, Nom, Entrees '; + req += ' FROM TB_Capteurs WHERE '; + req += ' Adresse_module=' + adresse_module + ' '; + req += ' AND Type_entrees=' + shipheart_capteur_type_entrees_predefinie + ') '; +//console.log("Requête = [ " + req + "; ]"); + nb = bdd.requete(req); + + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + for(j = 0; j < champ_formulaire_Entrees.model.count; j ++) + { + if (res[2] === champ_formulaire_Entrees.model.get(j).entrees) + { + if (res[2] === entrees) // Si on est sur l'entrée en cours, on laisse 'actif' à TRUE (et on peut ajuster le texte au passage...) + { +// champ_formulaire_Entrees.model.set(j, {"texte": "# "+ j} ) + } + else // Si on n'est pas sur l'entrée en cours, on positionne 'actif' à FALSE (et on ajuste le texte pou rinformation) + { + champ_formulaire_Entrees.model.set(j, {"texte": champ_formulaire_Entrees.model.get(j).texte + "
" + Fonctions.nom_type_equipement(Number(res[0])) + " \"" + res[1] + "\"", "actif": false} ) + } + } + } + } + } + + // Mise à jour du flag d'utilisation du paramètre Mode_entrées : + flag_affichage_mode_entrees = false; + + break; + + //---------------------------------------- + // Entrée Booléenne calculée : + //---------------------------------------- + case shipheart_capteur_type_entrees_calculee_booleen: + + // Même si l'entrée du modèle n'est jamais affichée pour ce type de capteur, l'ajout + // de cette entrée et sa sélection permet de "porter" les renseignements tels que 'code_variable' + // ou les 'pecision_affichage_xxx'. + + if (id_capteur === 0) entrees = "1/1/0:0/0/0/0;1/-1/0:0/0/0/0"; // Valeur par défaut d'ouverture et fermeture de niveau 0. NB : une chaine nulle fonctionne également mais comme cell-ci sera inévitablement créée, autant le faire directement + + champ_formulaire_Entrees.model.append({ + "entrees": entrees, + "texte": "Entrée calculée", // Texte jamais affiché... + "actif": true, + "code_variable": shipheart_capteur_sans_unite, + "mode_enregistrement_mesures": shipheart_mode_enregistrement_mesures_changement_etat, + "precision_affichage_accueil": 0, + "precision_affichage_mesures": 0 + }); + + // Mise à jour de l'index du modèle si l'on est sur l'entrée en cours : + champ_formulaire_Entrees.currentIndex = 1; // Le '1' sur CurrenIndex car on a déjà ajouté une entrée NON DEFINIE + + // Mise à jour du flag d'utilisation du paramètre Mode_entrées : + flag_affichage_mode_entrees = false; + + break; + + //---------------------------------------- + // Entrée numérique calculée : + //---------------------------------------- + case shipheart_capteur_type_entrees_calculee_numerique: + break; + } + + + //--------------------------------------------------------------------------------------- + // Appel du remplissage des modèles de niveau inférieur si cela est possible : + if ( (entrees !== "") + || (type_entrees >= shipheart_capteur_type_entrees_calculee_booleen)) // Si on est sur un capteur calculé, on avance quand même car le champ Entrees ne sera de toutes façons pas utile. + { + if (flag_affichage_mode_entrees) mise_a_jour_mode_entrees(); // Cas "normal" où le Mode_entree doit être traité + else mise_a_jour_famille(); // Si pas de Mode_entree, on passe directement à la Famille. + } + } + + + //============================================================================================================= + // MAJ du Mode des entrées + //============================================================================================================= + function mise_a_jour_mode_entrees() + { + var req, res; + var nb; + var i, j; + + //--------------------------------------------------------------------------------------- + // Mode : + //--------------------------------------------------------------------------------------- + champ_formulaire_Mode_entrees.model.clear(); + if (type_entrees !== shipheart_capteur_type_entrees_aux) // Pour les entrées AUX, on n'a pas accès à la valeur NON DEFINIE car NORMAL=0 (et pas utile !!) + { + champ_formulaire_Mode_entrees.model.append({"valeur": 0, "texte": qsTr("Non défini") }); + } + + switch(type_entrees) + { + //---------------------------------------- + // Entrées AUX : + //---------------------------------------- + case shipheart_capteur_type_entrees_aux: + + champ_formulaire_Mode_entrees.model.append({"valeur": shipheart_capteur_mode_entrees_aux_normal, "texte": qsTr("Normal") }); + champ_formulaire_Mode_entrees.model.append({"valeur": shipheart_capteur_mode_entrees_aux_inverse, "texte": qsTr("Inversé") }); + + break; + + //---------------------------------------- + // Entrées Level Sensor : + //---------------------------------------- + case shipheart_capteur_type_entrees_level_sensor: + + champ_formulaire_Mode_entrees.model.append({"valeur": shipheart_capteur_mode_entrees_level_sensor_0_10v, "texte": qsTr("Tension 0 - 10 V") }); + champ_formulaire_Mode_entrees.model.append({"valeur": shipheart_capteur_mode_entrees_level_sensor_500r, "texte": qsTr("Résistance 0 - 500 Ohms") }); + champ_formulaire_Mode_entrees.model.append({"valeur": shipheart_capteur_mode_entrees_level_sensor_4_20ma, "texte": qsTr("Courant 4 - 20 mA") }); +// champ_formulaire_Mode_entrees.model.append({"valeur": shipheart_capteur_mode_entrees_level_sensor_defaut_isolement_masse, "texte": qsTr("Défaut d'isolement 0V") }); +// champ_formulaire_Mode_entrees.model.append({"valeur": shipheart_capteur_mode_entrees_level_sensor_defaut_isolement_v_plus, "texte": qsTr("Défaut d'isolement V+") }); + champ_formulaire_Mode_entrees.model.append({"valeur": shipheart_capteur_mode_entrees_level_sensor_defaut_isolement_complet, "texte": qsTr("Défaut d'isolement") }); + + break; + + //---------------------------------------- + // Entrées Voltage Input : + //---------------------------------------- + case shipheart_capteur_type_entrees_volt: + break; + + //---------------------------------------- + // Entrées OW : + //---------------------------------------- + case shipheart_capteur_type_entrees_ow: + break; + + //---------------------------------------- + // Entrées NMEA2000 : + //---------------------------------------- + case shipheart_capteur_type_entrees_nmea: + break; + + //---------------------------------------- + // Entrées Prédéfinies : + //---------------------------------------- + case shipheart_capteur_type_entrees_predefinie: + break; + + //---------------------------------------- + // Entrée Booléenne calculée : + //---------------------------------------- + case shipheart_capteur_type_entrees_calculee_booleen: + break; + + //---------------------------------------- + // Entrée numérique calculée : + //---------------------------------------- + case shipheart_capteur_type_entrees_calculee_numerique: + break; + } + + + //--------------------------------------------------------------------------------------- + // Recherche de l'index du capteur en cours : + champ_formulaire_Mode_entrees.currentIndex = 0; // Si aucune entrée n'est trouvée (cas d'une création par exemple), l'index est égal à 0 + + for (i=0; i 0), on prend son opposé (comme ça, on est bien <0 mais on garde en plus la position initiale en mémoire) + } + else // Demande de ne pas le masquer : + { + if (priorite_affichage_accueil > 0) paa = priorite_affichage_accueil; // S'il était démasqué, on garde la même valeur + else if (priorite_affichage_accueil < 0) paa = - priorite_affichage_accueil; // S'il était masqué, avec une valeur mémorisée non nulle, on récupère la valur mémorisée (l'opposé donc) + else paa = 999; // S'il était masqué mais sans valeur mémorisée (donc nulle), on attribue arbitrairement une valeur très élevée pour mettre le circuit affiché mais en dernière position. + } + + // Requete de mise à jour : + req = 'UPDATE TB_Capteurs SET Nom="' + nom + '" '; + req += ', Adresse_module=' + adresse_module + ' '; + req += ', Type_entrees=' + type_entrees + ' '; + req += ', Entrees="' + entrees + '"'; + req += ', Mode_entrees=' + mode_entrees + ' '; + req += ', ID_Variable=' + id_variable + ' '; + req += ', Liste_valeurs_textes="' + liste_valeurs_textes + '" '; + req += ', ID_Famille=' + id_famille + ' '; + req += ', Mode_enregistrement_mesures=' + mode_enregistrement_mesures + ' '; + req += ', Priorite_affichage_accueil=' + paa + ' '; + req += ', Precision_affichage_accueil=' + precision_affichage_accueil + ' '; + req += ', Precision_affichage_mesures=' + precision_affichage_mesures + ' '; + req += ' WHERE Cle_primaire=' + id_capteur + ' ' +//console.log("Requête = [ " + req + "; ]"); + bdd.requete_unique(req); + + // Cas particulier d'un capteur sur entrée NMEA : + if (type_entrees === shipheart_capteur_type_entrees_nmea) flag_nmea = true; + if (flag_nmea) mise_a_jour_nmea2000(); + + // Demande de reconfiguration système via la BDD car on a modifié des valeurs de configuration : + synchro_bdd(shipheart_type_synchro_config); + + } + + //============================================================================================================= + // Création du capteur + //============================================================================================================= + function creation_capteur() + { + var req, res; + var nom; + var i, j; + var nb; + var code_variable, id_variable; + var id_famille; + var precision_affichage_accueil; + var precision_affichage_mesures; + var mode_enregistrement_mesures; + + + nom = champ_formulaire_Nom.text; + + if (flag_affichage_mode_entrees) mode_entrees = champ_formulaire_Mode_entrees.model.get(champ_formulaire_Mode_entrees.currentIndex).valeur; + else mode_entrees = 0; + + id_famille = champ_formulaire_Famille.model.get(champ_formulaire_Famille.currentIndex).valeur; + + if (type_entrees === shipheart_capteur_type_entrees_aux) + { + code_variable = shipheart_capteur_sans_unite; + mode_enregistrement_mesures = shipheart_mode_enregistrement_mesures_changement_etat; + precision_affichage_accueil = 0; + precision_affichage_mesures = 0; + } + else + { + code_variable = champ_formulaire_Entrees.model.get(champ_formulaire_Entrees.currentIndex).code_variable; + mode_enregistrement_mesures = champ_formulaire_Entrees.model.get(champ_formulaire_Entrees.currentIndex).mode_enregistrement_mesures; + precision_affichage_accueil = champ_formulaire_Entrees.model.get(champ_formulaire_Entrees.currentIndex).precision_affichage_accueil; + precision_affichage_mesures = champ_formulaire_Entrees.model.get(champ_formulaire_Entrees.currentIndex).precision_affichage_mesures; + } + + // Traitement de la chaine 'Entrées' : + if (type_entrees === shipheart_capteur_type_entrees_aux) + { + // Création de la chaine représentant les n° d'entrées utilisées par le réservoir : + entrees = ""; + for (i = 0; i < shipheart_capteur_max_nombre_entrees_aux; i ++) + { + j = entrees_aux_grid.model.get(i).no_entree_aux + if (j !== 0) + { + if (entrees !== "") entrees += ";"; + entrees += j; + } + } + } + else entrees = champ_formulaire_Entrees.model.get(champ_formulaire_Entrees.currentIndex).entrees; + + // Recherche de l'ID_Variable correspondant au code_variable : + req = ' SELECT Cle_primaire FROM TB_Variables WHERE Code="' + code_variable + '" '; +//console.log("Requête = [ " + req + "; ]"); + res = bdd.requete_unique(req); + id_variable = Number(res[0]); + + // Traitement des Liste_valeurs_textes pour le type ENTREES AUX et CALCULE_BOOLEEN : + liste_valeurs_textes = ""; + if ((type_entrees === shipheart_capteur_type_entrees_aux) || (type_entrees === shipheart_capteur_type_entrees_calculee_booleen)) + { + for (i=0; i 0) + { + if (nb === 1) message += "

" + qsTr("Ce capteur est utilisé par l'évènement ci-dessous.
Vous devez modifier ou supprimer cet évènement pour qu'il ne dépende plus de ce capteur avant de pouvoir le supprimer.") + "

"; + else message += "

" + qsTr("Ce capteur est utilisé par les %1 évènements ci-dessous.
Vous devez modifier ou supprimer ces évènements pour qu'ils ne dépendent plus de ce capteur avant de pouvoir le supprimer.").arg(nb) + "

"; + + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + message += "‣ " + (i+1) + " : " + res[1] + "
"; + } + } + } + + //========================================================================= + // Recherche de l'impact de cette suppression sur les capteurs calculés : + /* Retour de la forme : + +-------------+ + | Nom_capteur | + +-------------+ + | Calculation | + | Calcul 2 | + +-------------+ */ + req = 'SELECT Nom FROM TB_Capteurs '; + req += ' WHERE Type_entrees=' + shipheart_capteur_type_entrees_calculee_booleen + ' '; + req += ' AND Entrees LIKE "%/' + shipheart_source_mesure_capteur + ':' + id_capteur + '/%" '; +//console.log("Requête = [ " + req + "; ]"); + nb = bdd.requete(req); + + if (nb > 0) + { + if (nb === 1) message += "

" + qsTr("Ce capteur est utilisé par le capteur calculé ci-dessous.
Vous devez modifier ou supprimer ce capteur calculé pour qu'il ne dépende plus de ce capteur avant de pouvoir le supprimer.") + "

"; + else message += "

" + qsTr("Ce capteur est utilisé par les %1 capteurs calculés ci-dessous.
Vous devez modifier ou supprimer ces capteurs calculés pour qu'ils ne dépendent plus de ce capteur avant de pouvoir le supprimer.").arg(nb) + "

"; + + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + message += "‣ " + (i+1) + " : " + res[0] + "
"; + } + } + } + + //========================================================================= + // 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 du capteur + //============================================================================================================= + function suppression_capteur() + { + var req, res; + var nb; + var i; + var liste_cdes_auto, chaines_cdes_auto; + var type_entrees; + var entrees; + + // Recherche des informations actuelles du capteur : + req = 'SELECT Type_entrees, Entrees FROM TB_Capteurs WHERE Cle_primaire=' + id_capteur + ' '; + res = bdd.requete_unique(req); + type_entrees = Number(res[0]); + entrees = res[1]; // A ce stade, c'est une chaine. On ne fera la conversion en Number que lorsqu'on aura vérifié que 'Type_entrées' est de type OW. + + // Pour les capteurs utilisant les sondes OW, RAZ du nom de la sonde : + if (type_entrees === shipheart_capteur_type_entrees_ow) + { + req = 'UPDATE TB_One_wire SET Nom="---" WHERE Cle_primaire=' + Number(entrees) + ' '; + bdd.requete_unique(req); + } + + // Pour les capteurs utilisant les Entrees_aux : + // Il n'est pas utile de mettre à jour TB_Entrees_aux en fonction des changements effectués. En effet, on va juste après demander une "synchro" à l'appli et celle-ci + // va réinitialiser puis va le re-remplir en fonction de l'état des Capteurs et des Réservoirs. Donc si des Entrées AUX ne sont plus plus utilisées ou ont changé, elles + // seront mises à jour à ce moment-là. + + // Suppression du capteur : + req = 'DELETE FROM TB_Capteurs WHERE Cle_primaire=' + id_capteur + ' '; + bdd.requete_unique(req); + + // Cas particulier d'un capteur sur entrée NMEA : + if (type_entrees === shipheart_capteur_type_entrees_nmea) flag_nmea = true; + if (flag_nmea) mise_a_jour_nmea2000(); + + // Demande de reconfiguration système via la BDD car on a modifié des valeurs de configuration : + synchro_bdd(shipheart_type_synchro_config); + } + + + //============================================================================================================= + // Mise à jour de la table NMEA2000 après modifications de capteur + //============================================================================================================= + function mise_a_jour_nmea2000() + { + var req, res; + var i; + var nb; + + // RAZ de tous les flags Actifs (valeur par défaut plus rapide ; sans danger puisqu'on n'a pas demandé la mise à jour NMEA) : + req = 'UPDATE TB_Nmea2000 SET Actif=0 '; + bdd.requete_unique(req); + + // Mise à 1 des PGN/Fields qui sont effectivement utilisés sur des capteurs : + req = 'SELECT Entrees FROM TB_Capteurs WHERE Type_entrees=' + shipheart_capteur_type_entrees_nmea + ' '; +//console.log("Requête = [ " + req + "; ]"); + nb = bdd.requete(req); + + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + var x = res[0].split(':'); + req = 'UPDATE TB_Nmea2000 SET Actif=1 WHERE Pgn=' + x[0] + ' AND Field=' + x[1] + ' '; +//console.log("Requête = [ " + req + "; ]"); + bdd.requete_unique(req); + } + } + + // Demande de MAJ des paramètres NMEa par l'Appli : + req = 'UPDATE TB_Systeme SET Valeur=1 WHERE Nom="Demande_maj_nmea" '; + bdd.requete_unique(req); + } + + + //============================================================================================================= + // Recherche groupe d'une entrée AUX à partir de son numéro et renvoit le n° de grpupe (entre 0 et 7) + //============================================================================================================= + function recherche_groupe_entree_aux(entree) + { + switch(Math.trunc(entree/4)) + { + case 0: return(4); + case 1: return(5); + case 2: return(6); + case 3: return(7); + case 4: return(0); + case 5: return(1); + case 6: return(2); + case 7: return(3); + default: + console.log("Erreur de groupe d'entrée AUX") + 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 0) ? // ... mais décalé pour s'ligner avec le haut de '[' ou le bas de ']' + -7 : 9 + right: (model.type_condition > 0) ? parent.right : undefined // Permet de laisser la place à gauche au '[' + left: (model.type_condition < 0) ? parent.left : undefined // Permet de laisser la place à droite au ']' + } + width: parent.width - 10 // Le '-10' permet de laisser la place au '[' ou au ']' + height: 5 + border.width: height / 2 + border.color: +// couleur_gris_pale +model.valeur ? couleur_green_yellow : couleur_rouge + color: "transparent" + visible: (model.type_condition !== shipheart_type_condition_normale) // Ne s'applique qu'aux lignes de parenthèses (ouvrantes ou fermantes) + } + + //-------------------------------------------------------------------- + // Icone de la condition : + Image { + source: model.icone + sourceSize.height: parent.height * 0.8 + sourceSize.width: 30 + anchors { + verticalCenter: parent.verticalCenter + left: parent.left + leftMargin: 10 + } + visible: (model.type_condition === shipheart_type_condition_normale) + && (model.icone !== "") + + } + + //-------------------------------------------------------------------- + // Texte du bouton (soit le contenu de la condition, soit '['ou ']') : + Text { + anchors.fill: parent + horizontalAlignment: (model.type_condition < 0) ? Qt.AlignRight : Qt.AlignLeft + leftPadding: (model.type_condition === shipheart_type_condition_normale) ? 50 : 0 + verticalAlignment: Qt.AlignVCenter + textFormat: Text.RichText + text: (model.type_condition === shipheart_type_condition_normale) ? + //("Index= " + index + " -Niveau= " + model.niveau + " -type= " + model.type_condition + " -Clé= " + model.id) : + model.libelle : + ((model.type_condition > 0) ? "[" : "]" ) + color: (model.type_condition === shipheart_type_condition_normale) ? + couleur_blanc_casse : +// couleur_gris_pale +model.valeur ? couleur_green_yellow : couleur_rouge + font.weight: (model.type_condition === shipheart_type_condition_normale) ? Font.Normal : Font.Bold + font.pixelSize: (model.type_condition === shipheart_type_condition_normale) ? 18 : 24 + } + +//----------------------------------------- +// Ligne de séparation des parenthèses : +Rectangle { + anchors { + verticalCenter: parent.verticalCenter + right: parent.right + } + width: 5 + height: parent.height + color: model.valeur ? couleur_green_yellow : couleur_rouge + visible: (model.type_condition === shipheart_type_condition_normale) + && (model.validite) +//visible: (model.validite) +} + + + + Drag.active: drag_zone_bouton_condition.appui_en_cours + Drag.source: drag_zone_bouton_condition + Drag.hotSpot.x: width / 2 + Drag.hotSpot.y: height / 2 + + states: State{ + when: drag_zone_bouton_condition.appui_en_cours + ParentChange { + target: contenu_bouton_condition + parent: grille_conditions_booleennes + } + AnchorChanges { + target: contenu_bouton_condition + anchors { + horizontalCenter: undefined + verticalCenter: undefined + } + } + } + } + + //---------------------------------------------------------------------------------------------- + // Bouton de sélection de la ligne (petit bouton à droite de chaque ligne - hors parenthèses) : + Rectangle { + id: selection_bouton_condition + + anchors { + right: parent.right + verticalCenter: parent.verticalCenter + } + width: largeur_bouton_selection + height: drag_zone_bouton_condition.height - 5 + radius: shipheart_rayon_bouton + color: (index_condition_en_cours !== index) ? shipheart_couleur_fond_bouton : shipheart_couleur_fond_bouton_actif + opacity: drag_zone_bouton_condition.appui_en_cours ? 0.0 : 1.0 + visible: (model.type_condition >= 0) + + Image { + source: "/images/faux.png" + sourceSize.height: parent.height * 0.5 + anchors { + verticalCenter: parent.verticalCenter + horizontalCenter: parent.horizontalCenter + } + visible: (model.validite === 0) + } + + MouseArea { + anchors.fill: parent + pressAndHoldInterval: shipheart_mouse_press_and_hold_interval_long + onClicked: { + shipheart_clic(); + if (index_condition_en_cours === index) index_condition_en_cours = -1; + else index_condition_en_cours = index; + } + onPressAndHold: { + shipheart_clic(); + toggle_validation_condition(index); + } + } + } + + //------------------------------- + // Synthèse de début de ligne : + Rectangle { + id: bouton_operation + + visible: model.display_operation + anchors { + right: contenu_bouton_condition.left + rightMargin: 5 + verticalCenter: parent.verticalCenter + } + width: largeur_par_niveau - anchors.rightMargin + height: parent.height - 5 + radius: shipheart_rayon_bouton + color: (model.validite) ? shipheart_couleur_fond_bouton_actif : shipheart_couleur_fond_bouton + opacity: drag_zone_bouton_condition.appui_en_cours ? 0.0 : 1.0 + + Text { + anchors.fill: parent + horizontalAlignment: Qt.AlignHCenter + verticalAlignment: Qt.AlignVCenter + text: code_operation(model.operation) + color: couleur_blanc_casse + font.weight: (model.type_condition === shipheart_type_condition_normale) ? Font.Normal : Font.Bold + font.pixelSize: 18 + } + + MouseArea { + anchors.fill: parent + enabled: parent.visible + pressAndHoldInterval: shipheart_mouse_press_and_hold_interval_long + onPressAndHold: { + shipheart_clic(); + toggle_operation_groupe(index); + } + } + } + + //-------------------------------------------- + // Zone de déplacement : + DropArea { + enabled: (index !== 0) && // On interdit de déplacer une condition avant la première ligne (ouverture du groupe de niveau 0)... + (index !== (grille_conditions_booleennes.model.count - 1)) // ... et on interdit de déplacer une condition après la dernière ligne (fermeture du groupe de niveau 0) + anchors.fill: parent + onEntered: { + grille_conditions_booleennes.model.move(drag.source.DelegateModel.itemsIndex, drag_zone_bouton_condition.DelegateModel.itemsIndex, 1) + + // Ajout d'un élément en partie basse/haute pour avoir toujours une vision sur le prochain élément à "sauter" : + if (drag_zone_bouton_condition.vers_le_bas) grille_conditions_booleennes.currentIndex = drag_zone_bouton_condition.DelegateModel.itemsIndex + 1 + else grille_conditions_booleennes.currentIndex = drag_zone_bouton_condition.DelegateModel.itemsIndex - 1 + } + } + } + } + } // Fin de ListView des capteurs calculés booleens + } + + //------------------------------------------------------- + // 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: (index_condition_en_cours === -1) + 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_entrees(); + timer_tempo_reconfiguration.restart(); + } + } + } + + //....................................................... + // Bouton ajouter groupe + //....................................................... + Rectangle { + id: bouton_ajouter_groupe + width: parent.width + height: hauteur_bouton_droit + anchors.horizontalCenter: parent.horizontalCenter + color: shipheart_couleur_fond_bouton + radius: shipheart_rayon_bouton + visible: (index_condition_en_cours !== -1) + Text { + anchors.fill: parent + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + font.pixelSize: 28 +// text: "+
" + qsTr("parenthèse") + text: "[ + ]" + color: couleur_blanc_casse + } + MouseArea { + anchors.fill: parent + onClicked: { + shipheart_clic(); + if (grille_conditions_booleennes.model.count > (shipheart_max_nombre_conditions_par_capteur - 2)) // le '-2' tient compte du fait qu'on va crééer 2 conditions avec ce nouveau groupe + { + boite_information.type = type_boite_information_nombre_maxi_atteint; + boite_information.open(); + } + else ajout_groupe(index_condition_en_cours); + } + } + } + + //....................................................... + // Bouton ajouter condition + //....................................................... + Rectangle { + id: bouton_ajouter_condition + width: parent.width + height: hauteur_bouton_droit + anchors.horizontalCenter: parent.horizontalCenter + color: shipheart_couleur_fond_bouton + radius: shipheart_rayon_bouton + visible: (index_condition_en_cours !== -1) + Text { + anchors.fill: parent + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + font.pixelSize: 28 +// text: "+
" + qsTr("condition") + text: "+" + color: couleur_blanc_casse + } + MouseArea { + anchors.fill: parent + onClicked: { + shipheart_clic(); + if (grille_conditions_booleennes.model.count > (shipheart_max_nombre_conditions_par_capteur - 1)) + { + boite_information.type = type_boite_information_nombre_maxi_atteint; + boite_information.open(); + } + else + { + stackView.push("config_capteur_calcule_booleen_condition.qml", { + "nom_capteur": nom_capteur, + "type_source": 0, // Il faut que = 0... + "id_source": 0, // ... OU = 0... + "id_variable": 0, // ... OU = 0 pour que l'appel soit considéré comme une création. Sinon, ce sera une mise à jour. + + "test": 0, + "seuil": 0 }); + } + } + } + } + + //....................................................... + // Bouton modifier condition + //....................................................... + Rectangle { + id: bouton_modifier_condition + width: parent.width + height: hauteur_bouton_droit + anchors.horizontalCenter: parent.horizontalCenter + color: shipheart_couleur_fond_bouton + radius: shipheart_rayon_bouton + visible: (index_condition_en_cours !== -1) + && (grille_conditions_booleennes.model.get(index_condition_en_cours).type_condition === shipheart_type_condition_normale) + Text { + anchors.fill: parent + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + font.pixelSize: 20 +// text: "+
" + qsTr("condition") + text: "Modifier" + color: couleur_blanc_casse + } + MouseArea { + anchors.fill: parent + onClicked: { + shipheart_clic(); + stackView.push("config_capteur_calcule_booleen_condition.qml", { + "nom_capteur": nom_capteur, + "type_source": grille_conditions_booleennes.model.get(index_condition_en_cours).type_source, // Il faut que > 0... + "id_source": grille_conditions_booleennes.model.get(index_condition_en_cours).id_source, // ... ET > 0... + "id_variable": grille_conditions_booleennes.model.get(index_condition_en_cours).id_variable, // ... ET > 0 pour que l'appel soit considéré comme une mise à jour. Sinon, ce sera une création. + "test": grille_conditions_booleennes.model.get(index_condition_en_cours).test, + "seuil": grille_conditions_booleennes.model.get(index_condition_en_cours).seuil + }); + } + } + } + + //....................................................... + // Bouton de suppression + //....................................................... + Rectangle { + width: parent.width + height: hauteur_bouton_droit + anchors.horizontalCenter: parent.horizontalCenter + color: shipheart_couleur_fond_bouton + radius: shipheart_rayon_bouton + visible: (index_condition_en_cours !== -1) + && (index_condition_en_cours !== 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_suppression.pressed + } + + Text { + anchors.fill: parent + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + font.pixelSize: 20 + text: qsTr("Supprimer") + color: couleur_blanc_casse + } + + MouseArea { + id: mousearea_bouton_suppression + anchors.fill: parent + onPressed: { // Déclenché lors de l'appui inital + shipheart_clic(); + timer_appui_long.running = true; + valeur_timer_appui_long = 0; + } + 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(); + 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(); + recalcul_entrees(); // Mise à jour de la valeur de 'entrees' en fonction de l'état actuel du modèle (on ne fait cette mise à jour que sur demande...) + if (entrees !== entrees_init) // Si des modifications non enregistrées ont été faites : + { + boite_information.type = type_boite_information_sortir_sans_enregistrer; + boite_information.open(); + } + else stackView.pop(); // Sinon, on sort sans rien demander + } + } + } + } + + + //------------------------------------------------------- + // Boite d'info : + // Cette boite est utilisée dans 2 cas : + // - si l'on essaie de créer un nouveau groupe alors qu'on est > max-2 + // - si l'on essaie de créer une nouvelle condition alors qu'on est > max-1 + //------------------------------------------------------- + Shipheart_boite_dialogue { + id: boite_information + imageTitreSource: "/images/attention.png" + niveau: 1 + onOpened: { + switch (type) + { + case type_boite_information_nombre_maxi_atteint: + message = "

" + qsTr("Le nombre de conditions par capteur est limité à %1.

Vous ne pouvez pas ajouter de groupe ou de nouvelle condition avant d'en avoir supprimé préalablement.").arg(shipheart_max_nombre_conditions_par_capteur); + boutonAnnuler: false; + break; + + case type_boite_information_sortir_sans_enregistrer: + message = "

" + qsTr("Des modifications ont été apportées au capteur
mais n'ont pas été enregistrées.

Cliquer sur ANNULER pour revenir au menu en cours.

Cliquer sur Ok pour sortir sans enregistrer."); + boutonAnnuler: true; + break; + } + } + + onClicked: { + switch (type) + { + case type_boite_information_nombre_maxi_atteint: + break; + + case type_boite_information_sortir_sans_enregistrer: + if (bouton === shipheart_boite_dialogue_bouton_1) stackView.pop(); + else index_condition_en_cours = -1; // Permet de dévalider la condition en cours s'il y en a une et, ainsi, de faire apparaitre le bouton Enregistrer. + } + } + } + + + //=========================================================== + // 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 nb; + + var validite; + var type_condition; + var type_source; + var id_source; + var id_variable; + var test; + var seuil; + + +//console.log("Id du capteur = " + id_capteur); + + // Note : l'appel à cette page se fait SYSTEMATIQUEMENT avec un id_capteur existant ! + + // Récupération des données du capteur : + req = 'SELECT Nom, Entrees FROM TB_Capteurs WHERE Cle_primaire=' + id_capteur + ' AND Type_entrees=' + shipheart_capteur_type_entrees_calculee_booleen + ' '; +//console.log("Requête = [" + req + ']') + nb = bdd.requete(req); + + if (nb !== 1) + { + console.log("/!\\ La page Config_capteur_calcule_booleen.qml a été appelée avec un ID de capteur non valide (capteur inexistant OU Type_entrees!="+shipheart_capteur_type_entrees_calculee_booleen+")"); + StackView.pop(); + } + + + // Mise à jour du modèle des conditions de l'équation : + grille_conditions_booleennes.model.clear(); + + res = bdd.lecture_ligne(); // Si on arrive là, on est sûr que 'nb' = 1 + if (!res.isEmpty) + { + nom_capteur = res[0]; + entrees = res[1]; + entrees_init = entrees; + + // Recherche des Valeurs/textes existants : + var chaines_conditions = entrees.split(';'); // Segmentation des conditions du capteur sur séparateur ';' + + for (let chaine_condition of chaines_conditions) // [ validite / type_condition / type_source : id_source / id_variable / test / seuil ] + { + var troncons = chaine_condition.split(':'); // Récupération des 2 tronçons de chaine, de part et d'autre du ':' + if (troncons.length === 2) // Evite de traiter les cas invalides (notamment, une chaine totalement vide qui arrive ici avec un length de 1...) + { + // Traitement du premier tronçon : // [ validite / type_condition / type_source ] + var params = troncons[0].split('/'); + validite = Number(params[0]); + type_condition = Number(params[1]); + type_source = Number(params[2]); + + // Traitement du second tronçon : // [ id_source / id_variable / test / seuil ] + params = troncons[1].split('/'); + id_source = Number(params[0]); + id_variable = Number(params[1]); + test = Number(params[2]); + seuil = Number(params[3]); +//console.log("Condition #" + grille_conditions_booleennes.model.count + " : type_source="+type_source+", id_source="+id_source+", id_variable="+id_variable+", test="+test+", seuil="+seuil); + + grille_conditions_booleennes.model.append({ + "icone": icone_condition(type_source), // NB : si Type_source=0 (ligne de début ou fin de groupe), le retour sera "" + "libelle": libelle_condition(type_source, id_source, id_variable, test, seuil), // NB : si Type_source=0 (ligne de début ou fin de groupe), le retour sera "" + "validite": validite, + "type_condition": type_condition, + "operation": 0, + "display_operation": true, + "niveau": 0, + + "type_source": type_source, // Ces champs sont nécessaire pour appeler la page de config de ma conditoion si besoin + "id_source": id_source, + "id_variable": id_variable, + "test": test, + "seuil": seuil, + "valeur": false + }); + } + } + } + + // Remplissage par défaut, si aucune condition n'existe déjà sur ce capteur : + if (grille_conditions_booleennes.model.count === 0) + { + // Ajout de l'ouverture de groupe deplus haut niveau : + grille_conditions_booleennes.model.append({ + "icone": "", + "libelle": "", + "validite": 1, + "type_condition": shipheart_type_condition_debut_groupe_ou, + "operation": 0, + "display_operation": true, + "niveau": 0, + + "type_source": 0, // Ne sera pas utilisé sur des début ou fin de groupe mais permet d'être homogène + "id_source": 0, + "id_variable": 0, + "test": 0, + "seuil": 0, + "valeur": false + }); + + // Ajout de la fermeture de groupe de plus haut niveau : + grille_conditions_booleennes.model.append({ + "icone": "", + "libelle": "", + "validite": 1, + "type_condition": - shipheart_type_condition_debut_groupe_ou, + "operation": 0, + "display_operation": true, + "niveau": 0, + + "type_source": 0, // Ne sera pas utilisé sur des début ou fin de groupe mais permet d'être homogène + "id_source": 0, + "id_variable": 0, + "test": 0, + "seuil": 0, + "valeur": false + }); + } + + // Completion du modèle (notamment, opérations) puis enregistrement dans la BDD : + ordonnancement_modele_conditions(); + + flag_init = false; // Indique que l'init est terminée + } + + + //============================================================================================================= + // Mise à jour du modèle (suite à init ou déplacement par exemple) + //============================================================================================================= + function ordonnancement_modele_conditions() + { + var i; + var groupes = []; // Array à deux dimensions : [niveau, opération]. Il permet de stocker sous forme de pile (push et pop) les différents couples niveau/opération. + + // Le principe est qu'on affiche toujours l'opération sur la ligne SAUF : + // - si c'est la première ligne (qui ne peut pas être "opérée" avec une ligne précédente...) + // - si c'est une ligne de fin de groupe (il n'y a rien à faire sur une fin de groupe...) + // - si c'est une ligne de début de groupe (sauf la première) ou ligne normale dont le niveau est != de celui de la ligne précédente. + var flag_display_operation; + var niveau = 0; + + // Boucle sur tout le modèle : + for (i = 0; i < grille_conditions_booleennes.model.count; i ++) + { + flag_display_operation = true; // Valeur par défaut pour toutes les lignes + + //------------------------- + // Ouverture de groupe : + //------------------------- + if (grille_conditions_booleennes.model.get(i).type_condition > 0) + { + if (i === 0) // Note : Le principe est que la première entrée est toujours du type "début de groupe"... + { + groupes.push([0, grille_conditions_booleennes.model.get(i).type_condition]); // Tout premier niveau [0] avec [operation = Type_condition de la première ligne] + flag_display_operation = false; + } + + niveau = groupes[groupes.length-1][0]; + grille_conditions_booleennes.model.set(i, { + "operation": groupes[groupes.length-1][1], + "display_operation": flag_display_operation, + "niveau": niveau }); + + // Push pour les conditions à venir avec [niveau = niveau+1] et [operation = type_condition d'ouverture] : + groupes.push([ (groupes[groupes.length-1][0] + 1), grille_conditions_booleennes.model.get(i).type_condition ]); + } + + //------------------------- + // Fermeture de groupe : + //------------------------- + else if (grille_conditions_booleennes.model.get(i).type_condition < 0) + { + var type_condition_ouverture = groupes[groupes.length-1][1]; // On utilise l'opération du groupe que l'on va fermer comme valeur de 'Type_condition' de la ligne d'ouverture + groupes.pop(); // Permet de revenir au niveau de la condition d'ouverture du groupe + + niveau = groupes[groupes.length-1][0]; + grille_conditions_booleennes.model.set(i, { + "type_condition": (- type_condition_ouverture), // Permet de garantir que la ligne de fermeture est bien toujours la valeur négative du type d'ouverture (utile dans le cas d'un toggle d'opération qui ne met à jour que la ligne d'ouverture). + "operation": groupes[groupes.length-1][1], + "display_operation": false, // Toujours FALSE pour les fin de groupe + "niveau": niveau }); + } + //------------------------- + // Condition normale : + //------------------------- + else + { + // Calcul du flag de display de l'opération en fonction du niveau précédent et du niveau actuel : + if (niveau !== groupes[groupes.length-1][0]) + { + flag_display_operation = false; + niveau = groupes[groupes.length-1][0]; + } + + grille_conditions_booleennes.model.set(i, { + "operation": groupes[groupes.length-1][1], + "display_operation": flag_display_operation, + "niveau": niveau }); + } + } + } + + //============================================================================================================= + // Mise à jour des valeurs courantes de l'équation + //============================================================================================================= + function maj_valeurs_courantes() + { + var i; + var groupes = []; // Array à deux dimensions : [rang, opération, résultat]. Il permet de stocker sous forme de pile (push et pop) les différents couples rang(de la condition d'ouverture)/opération/résultat + var val; + + // Le principe est : + // A chaque '[', on : + // - push le rang de la condition d'ouverture du groupe & son opération & le résultat initialisé à une valeur neutre (FALSE pour OU et TRUE pour ET) + // A chaque condition normale : + // - on évalue la condition (si la condition est dévalidée, la valeur est remplacée par la valeur neutre correspondant à l'opération du niveau) , + // - on ajoute ce résultat au résultat du niveau (par '|=' si OU, par '&=' si ET) + // A chaque ']', on : + // - Si le niveau est > 0 : + // - on décrémente le niveau par pop() + // - on ajoute le résultat du niveau inférieur (qu'on vient de quitter) au résultat du niveau en cours avec l'opération du niveau en cours. + // -Si le niveau est = 0, le résultat du niveau 0 est égal au résultat de l'équation (et on doit être arrivé au bout du modèle...). + + + // Boucle sur tout le modèle : + for (i = 0; i < grille_conditions_booleennes.model.count; i ++) + { + + //------------------------- + // Ouverture de groupe : + //------------------------- + if (grille_conditions_booleennes.model.get(i).type_condition > 0) + { + groupes.push([ i, + grille_conditions_booleennes.model.get(i).type_condition, + (grille_conditions_booleennes.model.get(i).type_condition === shipheart_operation_condition_ou) ? false : true ]); + } + + //------------------------- + // Fermeture de groupe : + //------------------------- + else if (grille_conditions_booleennes.model.get(i).type_condition < 0) + { + if (groupes.length > 1) + { + var res_prec = groupes[groupes.length-1][2]; + var rang_ouverture = groupes[groupes.length-1][0]; + groupes.pop(); + + if (groupes[groupes.length-1][1] === shipheart_operation_condition_ou) groupes[groupes.length-1][2] |= res_prec; + else groupes[groupes.length-1][2] &= res_prec; + + // Renseignement de la 'valeur' de la condition d'ouverture du groupe : + grille_conditions_booleennes.model.set(rang_ouverture, { "valeur": (res_prec !== 0) }); + + // Renseignement de la valeur dans la condition de fermeture (condition actuelle) : + grille_conditions_booleennes.model.set(i, { "valeur": (res_prec !== 0) }); + } + else + { + // Renseignement de la 'valeur' de la condition d'ouverture du groupe : + grille_conditions_booleennes.model.set(groupes[groupes.length-1][0], { "valeur": (groupes[groupes.length-1][2] !== 0) }); + + // Renseignement de la valeur dans la condition de fermeture (condition actuelle) : + grille_conditions_booleennes.model.set(i, { "valeur": (groupes[groupes.length-1][2] !== 0) }); + } + } + //------------------------- + // Condition normale : + //------------------------- + else + { + if (grille_conditions_booleennes.model.get(i).validite) val = test_condition_capteur(i); + else val = (groupes[groupes.length-1][1] === shipheart_operation_condition_ou) ? false : true; + + if (groupes[groupes.length-1][1] === shipheart_operation_condition_ou) groupes[groupes.length-1][2] |= val; + else groupes[groupes.length-1][2] &= val; + + grille_conditions_booleennes.model.set(i, { "valeur": val }); + } + } + } + + + //============================================================================================================= + // Toggle de la validite d'une conditions + //============================================================================================================= + function toggle_validation_condition(index) + { + var type; + var cle; + var val; + var niveau; + var i; + + type = grille_conditions_booleennes.model.get(index).type_condition; + cle = grille_conditions_booleennes.model.get(index).id; + val = grille_conditions_booleennes.model.get(index).validite; + niveau = grille_conditions_booleennes.model.get(index).niveau; + + // Calcul de la nouvelle validité : + if (val === 0) val = 1; + else val = 0; + + // Mise à jour de l'index en cours dans le modèle : + grille_conditions_booleennes.model.set(index, {"validite": val}); + + // Mise à jour des lignes de niveau inférieur dans le cas où on est sur un début de groupe : + // Note : les boutons de fin de groupe ne sont pas traités (et, de toutes façons, ils n'ont pas de bouton...) + if (type > 0) + { + // Boucle depuis la position suivant la ligne en cours : + for (i = (index+1); i < grille_conditions_booleennes.model.count; i ++) + { + if ( (grille_conditions_booleennes.model.get(i).type_condition < 0) // On s'arrête si on trouve une fin de groupe... + && (grille_conditions_booleennes.model.get(i).niveau === niveau) ) break; // ... et du même niveau que la ligne en cours (sinon, ça peut être une fin de sous-groupe) + + grille_conditions_booleennes.model.set(i, {"validite": val}); // Tant qu'on n'est pas arrivé à la fin du groupe, on positionne toutes les lignes avec la nouvelle validité du début de groupe + } + } + } + + + //============================================================================================================= + // Insertion d'un groupe de conditions + //============================================================================================================= + function ajout_groupe(index) + { + var operation; + var niveau; + + niveau = grille_conditions_booleennes.model.get(index).niveau; + operation = grille_conditions_booleennes.model.get(index).operation; // Par défaut, le groupe créé hérite de l'opération de la ligne d'origine + + // Insertion du début et fin de groupe dans le modèle : + grille_conditions_booleennes.model.insert((index+1), { + "icone": "", + "libelle": "", + "validite": 1, + "type_condition": operation, // 'operation' correspond à la valeur du début de groupe + "operation": operation, + "niveau": niveau }); + grille_conditions_booleennes.model.insert((index+2), { + "icone": "", + "libelle": "", + "validite": 1, + "type_condition": - operation, // Valeur négative pour la fin de groupe + "operation": operation, + "niveau": niveau }); + } + + + //============================================================================================================= + // Basculement du type d'opération d'un groupe + //============================================================================================================= + function toggle_operation_groupe(index) + { + var i; + var type_condition; + var niveau; + + niveau = grille_conditions_booleennes.model.get(index).niveau; + + if (index === 0) return; // Ne devrait pas arriver car on ne peut changer qu'à partir d'une condition DANS un groupe (et celui de niveau 0 n'a que l'ouverture et la fermetude générale donc pas de contenu...) + + // Recherche de la tête du groupe : + // Soit : la PREMIERE ligne trouvée en remontant le modèle qui est une Ouverture de Groupe + // ET dont le Niveau est juste de 1 au dessus de celui de départ. + for (i=(index - 1); i >= 0; i --) // Parcours le modèle en remontant, depuis la ligne précédente, jusqu'au début si besoin + { + if ( (grille_conditions_booleennes.model.get(i).type_condition > 0) // Si début de groupe... + && (grille_conditions_booleennes.model.get(i).niveau === (niveau - 1)) ) // ... et niveau -1 par rapport à la ligne de départ, c'est qu'on est arrivé à la tête de groupe. + { + // Type de condition actuel (donc opération appliquée à tout le groupe) : + type_condition = grille_conditions_booleennes.model.get(i).type_condition; + + // Calcul de la nouvelle opération à appliquer : + if (type_condition === shipheart_type_condition_debut_groupe_ou) type_condition = shipheart_type_condition_debut_groupe_et; +// else if (type_condition === shipheart_type_condition_debut_groupe_et) type_condition = shipheart_type_condition_debut_groupe_ou_exclusif; + else type_condition = shipheart_type_condition_debut_groupe_ou; + + // Mise à jour du type de condition de la ligne d'ouverture : + grille_conditions_booleennes.model.set(i, {"type_condition": type_condition}); + + break; + } + } + + // Mise à jour du rang de toutes les lignes dans le modèle et dans la BDD : + ordonnancement_modele_conditions(); + } + + //============================================================================================================= + // Recalcule la chaine 'entrees' en focntion de l'état actuel du modèle + //============================================================================================================= + function recalcul_entrees() + { + var i; + + entrees = ""; + + for (i=0; i < grille_conditions_booleennes.model.count; i ++) + { + if (entrees !== "") entrees += ";"; + + entrees += grille_conditions_booleennes.model.get(i).validite; + entrees += "/" + grille_conditions_booleennes.model.get(i).type_condition; + entrees += "/" + grille_conditions_booleennes.model.get(i).type_source; + entrees += ":" + grille_conditions_booleennes.model.get(i).id_source; // Attention au séparateur ':' !!! + entrees += "/" + grille_conditions_booleennes.model.get(i).id_variable; + entrees += "/" + grille_conditions_booleennes.model.get(i).test; + entrees += "/" + grille_conditions_booleennes.model.get(i).seuil; + } +//console.log("Entrees recalculées = "+entrees); + } + + //============================================================================================================= + // Enregistre les conditions du capteur + //============================================================================================================= + function enregistrement_entrees() + { + var req; + + recalcul_entrees(); // Calcul de la chaine à enregistrer à partur de l'état actuel du modèle. + + req = 'UPDATE TB_Capteurs SET Entrees="' + entrees + '" WHERE Cle_primaire=' + id_capteur + ' '; +//console.log("Requête = [ " + req + "; ]") + bdd.requete_unique(req); + + // Miseà jour de l'état mémorisé des entrées : + entrees_init = entrees; + + // Emission du signal vers la page 'config_capteur.qml' : + page_config_capteur_calcule_booleen.enregistrer_config_capteur_calcule_booleen(entrees); + + // Demande de reconfiguration système via la BDD car on a modifié des valeurs de configuration : + synchro_bdd(shipheart_type_synchro_config); + } + + //============================================================================================================= + // Suppression de la condition en cours + //============================================================================================================= + function suppression_condition(index) + { + + // Suppression dans le modèle : + grille_conditions_booleennes.model.remove(index, 1); + + // Mise à jour du rang de toutes les lignes dans le modèle et dans la BDD : + ordonnancement_modele_conditions(); + + // Dévalidation de l'index suivant (puisqu'on a supprimé l'actuel) : + index_condition_en_cours = -1; + } + + //============================================================================================================= + // Suppression d'un groupe : Suppression de la ligne de début de groupe et de la ligne de fermeture, remontée + // d'un niveau de toutes les lignes entre les deux, mise à jour du modèle et de la BDD (pour les rangs qui ont + // été modifiés du fait des 2 suppressions et pour le type d'opérateur). + // Important : le groupe n'est pas forcément vide. Il peut également contenir des sous-groupes qui seront conservés. + //============================================================================================================= + function suppression_groupe(index) + { + var i; + var niveau; + var niveau_suppression; + var operation_suppression; + + + niveau_suppression = grille_conditions_booleennes.model.get(index).niveau; + operation_suppression = grille_conditions_booleennes.model.get(index).operation; +//console.log("Opérateur d'orgine =" + operation_suppression) + + // Remontée d'un niveau de toutes les conditions entre l'ouverture du groupe et sa fermeture : + for (i = (index + 1); i < grille_conditions_booleennes.model.count; i ++) + { + niveau = grille_conditions_booleennes.model.get(i).niveau; + + // Ajustement de l'opération de toutes les conditions situées JUSTE en dessous de groupe supprimé : + if (niveau === (niveau_suppression + 1)) + { + grille_conditions_booleennes.model.set(i, {"operation": operation_suppression}); + } + + // Ajustement des niveaux de toutes les conditions situées dans le groupe supprimé : + if ((grille_conditions_booleennes.model.get(i).type_condition >= 0) && + (niveau !== niveau_suppression)) + { + // Mise à jour des rangs du modèle : + grille_conditions_booleennes.model.set(i, {"niveau": (niveau - 1)}); + } + else // Ligne de fermeture du groupe : + { + // Suppression dans le modèle de la fermeture du groupe : + grille_conditions_booleennes.model.remove(i, 1); + + break; + } + } + + // Suppression dans le modèle de l'ouverture du groupe : + grille_conditions_booleennes.model.remove(index, 1); + + // Mise à jour du rang de toutes les lignes dans le modèle et dans la BDD : + ordonnancement_modele_conditions(); + + // Dévalidation de l'index suivant (puisqu'on a supprimé l'actuel) : + index_condition_en_cours = -1; + } + + //============================================================================================================= + // Défini le nom du fichier à utiliser comme icone de la condition + //============================================================================================================= + function icone_condition(type_source) + { + var image; + + // Sélection du fichier en fonction du Type de source : + switch(type_source) + { + case shipheart_source_mesure_circuit: + image = "/images/icone_consommation_electrique.png"; + break; + + case shipheart_source_mesure_capteur: + image = "/images/icone_auxiliaires.png"; + break; + + case shipheart_source_mesure_reservoir: + image = "/images/reservoir_eau.png"; + break; + + case shipheart_source_mesure_batterie: + image = "/images/batterie_moyen.png"; + break; + default: + image = ""; + break; + } + + return(image); + } + + + //============================================================================================================= + // Constitution du libellé de la condition + //============================================================================================================= + function libelle_condition(type_source, id_source, id_variable, test, seuil) + { + var req, res; + var i; + var nb; + var table; + var libelle; + + // Sélection de la table à utiliser en focntion du Type de source : + switch(type_source) + { + case shipheart_source_mesure_circuit: + table = "TB_Circuits"; + break; + + case shipheart_source_mesure_capteur: + table = "TB_Capteurs"; + break; + + case shipheart_source_mesure_reservoir: + table = "TB_Reservoirs"; + break; + + case shipheart_source_mesure_batterie: + table = "TB_Batteries"; + break; + + default: + table = ""; + break; + } + + // Génération du libellé : + if (table !== "") + { + // Chargement des infos de la BDD : + req = 'SELECT Nom'; + req += ', Code_variable '; + req += ', Libelle_unite '; + if (table === "TB_Capteurs") req += ', Type_entrees '; + req += 'FROM ' + table + ', '; + req += ' (SELECT Cle_primaire, Code AS Code_variable, Unite AS Libelle_unite FROM TB_Variables) AS TB_Variables '; + req += ' WHERE ' + table + '.Cle_primaire=' + id_source + ' AND TB_Variables.Cle_primaire=' + id_variable+ ' '; +//console.log("Requête = [ " + req + "; ]"); + res = bdd.requete_unique(req); + + // Nom de l'équipement : + libelle = " " + res[0]; // Attention, sans '+=' car premier accès... + + // Nom de la variable : + if ((type_source === shipheart_source_mesure_circuit) // On ne mentionne le nom de la variable que pour un circuit... + || (type_source === shipheart_source_mesure_batterie)) // ... ou une batterie + { + libelle += " - " + Fonctions.nom_variable(res[1]); // Nom de la variable + } + + // Cas particulier des capteurs binaires : + if ((type_source === shipheart_source_mesure_capteur) && + ((Number(res[3]) == shipheart_capteur_type_entrees_aux) || + (Number(res[3]) == shipheart_capteur_type_entrees_calculee_booleen)) ) + { + if (test === shipheart_test_strictement_superieur) libelle += qsTr(" est actif"); + else libelle += qsTr(" est inactif"); + } + else + { + // Test : + switch(test) + { + case shipheart_test_non_defini: + default: + libelle += " ? " + break; + case shipheart_test_strictement_inferieur: + libelle += " < " + break; + case shipheart_test_inferieur_ou_egal: + libelle += " ≤ " + break; + case shipheart_test_egal: + libelle += " = " + break; + case shipheart_test_superieur_ou_egal: + libelle += " ≥ " + break; + case shipheart_test_strictement_superieur: + libelle += " > " + break; + } + libelle += seuil; // Valeur de seuil + libelle += " " + res[2]; // Unité + } + } + else libelle = ""; + + return(libelle); + } + + + //============================================================================================================= + // Recherche du code d'une opération + //============================================================================================================= + function code_operation(operation) + { + + switch (operation) + { + case shipheart_operation_condition_non_definie: + return("?"); // Pas besoin de break; après le return. + + case shipheart_operation_condition_ou: + return(qsTr("Ou")); + + case shipheart_operation_condition_et: + return(qsTr("Et")); + + case shipheart_operation_condition_ou_exclusif: + return(qsTr("X-Ou")); + + case shipheart_operation_condition_plus: + return("+"); + + case shipheart_operation_condition_moins: + return("-"); + + case shipheart_operation_condition_multiplie: + return("x"); + + case shipheart_operation_condition_divise: + return("/"); + + } + } + + //============================================================================================================= + // Recherche du résultat d'une condition + //============================================================================================================= + function test_condition_capteur(no) + { + var type_source; + var id_source; + var id_variable; + var code_variable; + var test; + var seuil; + var valeur; + var req, res; + var champ; + + // Récupération des données de la condition : + type_source = grille_conditions_booleennes.model.get(no).type_source; + id_source = grille_conditions_booleennes.model.get(no).id_source; + id_variable = grille_conditions_booleennes.model.get(no).id_variable; + test = grille_conditions_booleennes.model.get(no).test; + seuil = grille_conditions_booleennes.model.get(no).seuil; + + + //=================================================== + // Récupération de la valeur de la source à tester : + //=================================================== + + // Récupération du code de la variable associée à la condition : + req = ' SELECT Code FROM TB_Variables WHERE Cle_primaire=' + id_variable + ' '; +//console.log("Requête = [ " + req + "; ]"); + res = bdd.requete_unique(req); + code_variable = res[0]; + + // Génération de la requête en fonction du type de source et de la variable concernée : + switch(type_source) + { + //------------------------------------- + case shipheart_source_mesure_circuit: + + switch(code_variable) + { + case shipheart_circuit_consigne: { champ = "Consigne"; break;} + case shipheart_circuit_tension: { champ = "Tension"; break;} + case shipheart_circuit_courant: { champ = "Intensite"; break;} + case shipheart_circuit_frequence: { champ = "Frequence"; break;} + case shipheart_circuit_puissance: { champ = "(Tension * Intensite) AS Puissance"; break;} +// case shipheart_circuit_energie: { champ = ""; break;} + case shipheart_circuit_tension_secteur: { champ = "Tension"; break;} + } + + // Requete de lecture de la valeur à analyser : + req = "SELECT " + champ + " FROM TB_Circuits WHERE Cle_primaire=" + id_source+ " "; +//console.log("Requête = [ " + req + "; ]"); + res = bdd.requete_unique(req); + valeur = res[0]; + + break; + + //------------------------------------- + case shipheart_source_mesure_capteur: + + // Requete de lecture de la valeur à analyser : + req = "SELECT Valeur FROM TB_Capteurs WHERE Cle_primaire=" + id_source+ " "; +//console.log("Requête = [ " + req + "; ]"); + res = bdd.requete_unique(req); + valeur = res[0]; + + break; + + //------------------------------------- + case shipheart_source_mesure_reservoir: + + // Requete de lecture de la valeur à analyser : + req = "SELECT Niveau FROM TB_Reservoirs WHERE Cle_primaire=" + id_source+ " "; +//console.log("Requête = [ " + req + "; ]"); + res = bdd.requete_unique(req); + valeur = res[0]; + + break; + + //------------------------------------- + case shipheart_source_mesure_batterie: + + switch(code_variable) + { + case shipheart_batterie_temperature: { champ = "Temperature"; break;} + case shipheart_batterie_tension: { champ = "Tension"; break;} + case shipheart_batterie_courant_differentiel: { champ = "Courant_differentiel"; break;} + case shipheart_batterie_courant_charge: { champ = "Courant_charge"; break;} + case shipheart_batterie_courant_decharge: { champ = "Courant_decharge"; break;} + case shipheart_batterie_soh: { champ = "Soh"; break;} + case shipheart_batterie_soc: { champ = "Soc"; break;} + case shipheart_batterie_autonomie: { champ = "Autonomie"; break;} + case shipheart_batterie_puissance: { champ = "(Tension * Courant_decharge) AS Puissance"; break;} +// case shipheart_batterie_energie: { champ = ""; break;} + } + + // Requete de lecture de la valeur à analyser : + req = "SELECT " + champ + " FROM TB_Batteries WHERE Cle_primaire=" + id_source+ " "; +//console.log("Requête = [ " + req + "; ]"); + res = bdd.requete_unique(req); + valeur = res[0]; + break; + + //------------------------------------- + default: + valeur = 0; + break; + } + + + //======================== + // Test proprement dit : + //======================== + switch(test) + { + case shipheart_test_non_defini: + default: + return(false); + + case shipheart_test_strictement_inferieur: + return(valeur < seuil); + + case shipheart_test_inferieur_ou_egal: + return(valeur <= seuil); + + case shipheart_test_egal: + return(valeur === seuil); + + case shipheart_test_superieur_ou_egal: + return(valeur >= seuil); + + case shipheart_test_strictement_superieur: + return(valeur > seuil); + } + } + + + //============================================================================================================= + // 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; iEntré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 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.... + } + + + + + + } + +} + diff --git a/config_circuit.qml b/config_circuit.qml new file mode 100644 index 0000000..0da01e6 --- /dev/null +++ b/config_circuit.qml @@ -0,0 +1,1714 @@ +//======================================================================================================================================================================== +// CONFIG_CIRCUIT.QML +// Ce fichier traite la configuration d'un circuit. La page permet notamment de : +// - Modifier la config du circuit (ou de le créer la première fois), +// - Supprimer le circuit +// La page est appelée depuis la page config_circuits_1, en cliquant sur le circuit à modifier (ou sur un circuit non affecté en vue de sa création) +//======================================================================================================================================================================== +import QtQuick 2.12 +import QtQml.Models + +import qt.koriolan.shipheart 1.0 + + + + +Shipheart_page { + id: page_config_circuit + + + // 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 + readonly property int step_timer_appui_long: 30 // en ms + + + readonly property int type_boite_information_alerte_changement_affectation: 0 + readonly property int type_boite_information_supprimer: 1 + + + + // 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 id_circuit: 0 + property int priorite_affichage_accueil: 0 + property int adresse_module: 0 + property int no_circuit: 0 + property int id_circuit_esclave: 0 + property string requete_differee: "" // Permet de mémoriser le contenu d'une resquête qui sera exécuté après expiration d'un timer dédié. + property int mode_commande_circuit: 0 + property int old_consigne: 0 + property var chaines_cdes_auto + property int nb_cdes_auto: 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 { + + + } + } + } + + //=========================================================== + // 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) + { + if (check_avant_suppression() !== -1) + { + suppression_circuit(); // Mise à jour des données saisies dans la BDD et reconfiguration par l'application pour prise en compte. + + if (requete_differee === "") timer_tempo_reconfiguration.restart(); // Si pas de requete différée, on lance le timer de reconfig immédiatement. + else // Si requete différée : + { + timer_requete_differee.restart(); // ... on lance en le timer de requete différée + shipheart_clic(); + } + } + } + } + } + } + + //=========================================================== + // Lorsque la page est sur le point d'être affichée dans la pile : + //=========================================================== +// StackView.onActivating: { +// } + + + // Titre de la page : + Shipheart_titre_1 {titre:qsTr("Configuration du circuit"); 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) + height: visible ? hauteur_ligne_formulaire : 0 + color: "transparent" + + Shipheart_formulaire_label { + text: qsTr("Nom du circuit") + 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 : Affectation + Rectangle { + width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2) + height: visible ? hauteur_ligne_formulaire : 0 + color: "transparent" + visible: (adresse_module !== 0) // On n'autorise pas le changement d'affectation sur ShipBase + + Shipheart_formulaire_label { + text: qsTr("Affectation") + width: parent.width * pourcentage_largeur_labels_formulaire + couleur: (champ_formulaire_Affectation.currentIndex !== 0) + ? shipheart_formulaire_couleur_texte_par_defaut + : shipheart_formulaire_couleur_texte_en_erreur + } + + Shipheart_formulaire_combobox { + id: champ_formulaire_Affectation + model: ListModel { } + width: parent.width * (1 - pourcentage_largeur_labels_formulaire) + prefixe_repos: flag_init ? "" : champ_formulaire_Affectation.model.get(champ_formulaire_Affectation.currentIndex).prefixe_repos + onActivated: { + shipheart_clic(); + // Mise à jour de la valeur de seuil de disjonction en accord avec l'intensité maxi par circuit de la nouvelle carte sélectionnée (SDIR #185) : + if (champ_formulaire_Affectation.model.get(champ_formulaire_Affectation.currentIndex).valeur !== "-1/0") // Permet de garder les valeurs déjà enregistrées pour utilisation futures + { + var new_affectation = champ_formulaire_Affectation.model.get(champ_formulaire_Affectation.currentIndex).valeur.split('/'); + raffraichissement_modele_intensite_seuil_haut(new_affectation[0], champ_formulaire_Intensite_seuil_haut.model.get(champ_formulaire_Intensite_seuil_haut.currentIndex).valeur, champ_formulaire_Circuit_esclave.model.get(champ_formulaire_Circuit_esclave.currentIndex).valeur); + } + } + } + + Shipheart_formulaire_ligne_separation { + haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse + } + } + + + //------------------------------------------------------------------------------- + // Ligne de formulaire : Circuit renfort + Rectangle { + width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2) + height: visible ? hauteur_ligne_formulaire : 0 + color: "transparent" + visible: !flag_init + && (adresse_module !== 0) // Non autorisé sur ShipBase + && (champ_formulaire_Affectation.currentIndex !== 0) + && ((champ_formulaire_Affectation.model.get(champ_formulaire_Affectation.currentIndex).type === shipheart_type_module_shippower812) || + (champ_formulaire_Affectation.model.get(champ_formulaire_Affectation.currentIndex).type === shipheart_type_module_shippower8DC) ) + // Si l'affectation a changée depuis le dernier enregistrement, on dévalide l'accès au circuit esclave car le module a pu être changé et le modèle des circuits escalves n'est plus forcément à jour... : + && (champ_formulaire_Affectation.model.get(champ_formulaire_Affectation.currentIndex).valeur === adresse_module + "/" + no_circuit) + && (id_circuit > 0) // SDIR #186 + + + Shipheart_formulaire_label { + text: qsTr("Circuit renfort") + width: parent.width * pourcentage_largeur_labels_formulaire + } + + Shipheart_formulaire_combobox { + id: champ_formulaire_Circuit_esclave + model: ListModel { } + width: parent.width * (1 - pourcentage_largeur_labels_formulaire) + prefixe_repos: flag_init ? "" : champ_formulaire_Circuit_esclave.model.get(champ_formulaire_Circuit_esclave.currentIndex).prefixe_repos + onActivated: { + shipheart_clic(); + // Mise à jour de la valeur de seuil de disjonction en accord avec l'intensité maxi par circuit du fait du changement de circuit renfort : + var new_affectation = champ_formulaire_Affectation.model.get(champ_formulaire_Affectation.currentIndex).valeur.split('/'); + raffraichissement_modele_intensite_seuil_haut(new_affectation[0], champ_formulaire_Intensite_seuil_haut.model.get(champ_formulaire_Intensite_seuil_haut.currentIndex).valeur, champ_formulaire_Circuit_esclave.model.get(champ_formulaire_Circuit_esclave.currentIndex).no); + // ATTENTION : le 3ème paramètre ci-dessus est le No et non l'ID de l'esclave (que l'on n'a pas à ce stade puisqu'il n'est pas forcément créé). On utilise donc le n° puisque ce que l'on va en faire est juste de savoir s'il existe ou non. On n'a pas besoin de son ID à proprement parler. + } + } + + Shipheart_formulaire_ligne_separation { + haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse + } + } + + //------------------------------------------------------------------------------- + // Ligne de formulaire : Famille + 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_Affectation.currentIndex !== 0) + + Shipheart_formulaire_label { + text: qsTr("Groupe de circuits") + width: parent.width * pourcentage_largeur_labels_formulaire + couleur: (champ_formulaire_Famille.currentIndex !== 0) + ? shipheart_formulaire_couleur_texte_par_defaut + : shipheart_formulaire_couleur_texte_en_erreur + } + + Shipheart_formulaire_combobox { + id: champ_formulaire_Famille + 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 de commande + Rectangle { + width: parent.width + height: visible ? hauteur_ligne_formulaire : 0 + color: "transparent" + visible: !flag_init + && (adresse_module !== 0) // Non autorisé sur ShipBase + && (champ_formulaire_Affectation.currentIndex !== 0) + && (champ_formulaire_Famille.currentIndex !== 0) + && ((champ_formulaire_Affectation.model.get(champ_formulaire_Affectation.currentIndex).type === shipheart_type_module_shippower812) || + (champ_formulaire_Affectation.model.get(champ_formulaire_Affectation.currentIndex).type === shipheart_type_module_shippower8DC) ) + + Shipheart_formulaire_label { + text: qsTr("Mode de commande") + width: parent.width * pourcentage_largeur_labels_formulaire + } + + Shipheart_formulaire_combobox { + id: champ_formulaire_Mode_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 : Vitesse de démarrage + Rectangle { + width: parent.width + height: visible ? hauteur_ligne_formulaire : 0 + color: "transparent" + visible: !flag_init + && (adresse_module !== 0) // Non autorisé sur ShipBase + && (champ_formulaire_Affectation.currentIndex !== 0) + && (champ_formulaire_Famille.currentIndex !== 0) + && ((champ_formulaire_Affectation.model.get(champ_formulaire_Affectation.currentIndex).type === shipheart_type_module_shippower812) || + (champ_formulaire_Affectation.model.get(champ_formulaire_Affectation.currentIndex).type === shipheart_type_module_shippower8DC) ) + && (champ_formulaire_Mode_commande.model.get(champ_formulaire_Mode_commande.currentIndex).valeur > 0) + + Shipheart_formulaire_label { + text: qsTr("Vitesse de démarrage/arrêt") + width: parent.width * pourcentage_largeur_labels_formulaire + } + + Shipheart_formulaire_combobox { + id: champ_formulaire_Step_time + 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 + Rectangle { + width: parent.width + height: visible ? hauteur_ligne_formulaire : 0 + color: "transparent" + visible: !flag_init + && (adresse_module !== 0) // Non autorisé sur ShipBase + && (champ_formulaire_Affectation.currentIndex !== 0) + && (champ_formulaire_Famille.currentIndex !== 0) + && (champ_formulaire_Affectation.model.get(champ_formulaire_Affectation.currentIndex).type !== shipheart_type_module_shipbase) + + Shipheart_formulaire_label { + text: qsTr("Commande impulsionnelle") + width: parent.width * pourcentage_largeur_labels_formulaire + } + + Shipheart_formulaire_combobox { + id: champ_formulaire_Time_out + 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 : Seuil de disjonction + Rectangle { + width: parent.width + height: visible ? hauteur_ligne_formulaire : 0 + color: "transparent" + visible: !flag_init + && (adresse_module !== 0) // Non autorisé sur ShipBase + && (champ_formulaire_Affectation.currentIndex !== 0) + && (champ_formulaire_Famille.currentIndex !== 0) + && ((champ_formulaire_Affectation.model.get(champ_formulaire_Affectation.currentIndex).type === shipheart_type_module_shippower812) || + (champ_formulaire_Affectation.model.get(champ_formulaire_Affectation.currentIndex).type === shipheart_type_module_shippower8DC) ) + + Shipheart_formulaire_label { + text: qsTr("Seuil de disjonction") + width: parent.width * pourcentage_largeur_labels_formulaire + } + + Shipheart_formulaire_combobox { + id: champ_formulaire_Intensite_seuil_haut + 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 : Intensite_seuil_haut_tempo + Rectangle { + width: parent.width + height: visible ? hauteur_ligne_formulaire : 0 + color: "transparent" + visible: !flag_init + && (adresse_module !== 0) // Non autorisé sur ShipBase + && (champ_formulaire_Affectation.currentIndex !== 0) + && (champ_formulaire_Famille.currentIndex !== 0) + && ((champ_formulaire_Affectation.model.get(champ_formulaire_Affectation.currentIndex).type === shipheart_type_module_shippower812) || + (champ_formulaire_Affectation.model.get(champ_formulaire_Affectation.currentIndex).type === shipheart_type_module_shippower8DC) ) + + Shipheart_formulaire_label { + text: qsTr("Vitesse de disjonction") + width: parent.width * pourcentage_largeur_labels_formulaire + } + + Shipheart_formulaire_combobox { + id: champ_formulaire_Intensite_seuil_haut_tempo + 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 : Intensite_coeff_filtrage + Rectangle { + width: parent.width + height: visible ? hauteur_ligne_formulaire : 0 + color: "transparent" +/* visible: !flag_init + && (champ_formulaire_Affectation.currentIndex !== 0) + && (champ_formulaire_Famille.currentIndex !== 0) +*/ +visible: false + Shipheart_formulaire_label { + text: qsTr("Filtrage du courant consommé") + width: parent.width * pourcentage_largeur_labels_formulaire + } + + Shipheart_formulaire_combobox { + id: champ_formulaire_Intensite_coeff_filtrage + 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 : Masquage + 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_Affectation.currentIndex !== 0) + && (champ_formulaire_Famille.currentIndex !== 0) + + Shipheart_formulaire_label { + text: qsTr("Masquer sur la page d'accueil") + width: parent.width * pourcentage_largeur_labels_formulaire + } + + Shipheart_formulaire_checkbox { + id: champ_formulaire_Masquage + width: parent.width * (1 - pourcentage_largeur_labels_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 + (champ_formulaire_Nom.text !== "") && + ( ( (champ_formulaire_Affectation.currentIndex !== 0) + && (champ_formulaire_Famille.currentIndex !== 0) ) + || ( (id_circuit > 0) // Pour un circuit existant, ... + && (champ_formulaire_Famille.currentIndex !== 0) ) ) // ... on autorise l'affectation à Aucune + + Text { + anchors { + verticalCenter: parent.verticalCenter + horizontalCenter: parent.horizontalCenter + } + font.pixelSize: 20 + text: (id_circuit === 0) ? qsTr("Créer le circuit") : qsTr("Enregistrer") + color: couleur_blanc_casse + } + MouseArea { + anchors.fill: parent + onClicked: { + shipheart_clic(); + if (id_circuit !== 0) mise_a_jour_circuit(); // Mise à jour des données saisies dans la BDD et reconfiguration par l'application pour prise en compte. + else creation_circuit(); + if (requete_differee === "") timer_tempo_reconfiguration.restart(); // Si pas de requete différée, on lance le timer de reconfig immédiatement. + else // Si requete différée : + { + shipheart_clic(); + boite_information.niveau = 1 + boite_information.imageTitreSource = "/images/ampoule.png" + boite_information.message = qsTr("L'affectation du circuit vient d'être modifiée alors que le circuit était actif. \nAvant d'effectuer ce changement, le circuit a été passé sur OFF.\n\nPensez à le réactiver si besoin...") + boite_information.type = type_boite_information_alerte_changement_affectation; + boite_information.open(); // - on affiche la boite d'info pour signaler la désactivation du circuit + + timer_requete_differee.restart(); // - On lance en // le timer de requete différée + } + } + } + } + + //....................................................... + // 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_circuit !== 0) && // ... ou si création + (adresse_module !== 0) // ... ou si circuit de ShipBase, on ne propose pas le bouton + + 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 + shipheart_clic(); + timer_appui_long.running = true; + valeur_timer_appui_long = 0; + } + 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 requêtes différées + //....................................................... + Timer { + id: timer_requete_differee // Timer lancé uniquement si une requete différée est à traiter + interval: 250 // Théoriquement, le traitement par l'appli de la requete précédente sera fait dans les 100ms. + triggeredOnStart: false + running: false + repeat: false + onTriggered: { + bdd.requete_unique(requete_differee); // A l'expiration du timer, la requete différée est exécutée + synchro_bdd(shipheart_type_synchro_config); // Demande de reconfiguration système via la BDD car on a modifié des valeurs de configuration... + timer_tempo_reconfiguration.restart(); // Lancement du timer d'attente de fin de reconfig + } + } + + //....................................................... + // 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 (requete_differee !== "") requete_differee = ""; // Par principe + if (boite_information.opened === false) stackView.pop(); // S'il y a eu une boite d'info ouverte, c'est le clic sur Ok sur la boite d'info qui fera le 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() + } + } + } + } + + + //------------------------------------------------------- + // Boite de validation : + //------------------------------------------------------- + Shipheart_boite_dialogue { + id: boite_information + onClicked: { +//console.log("Le Bouton [" + bouton + "] est appuyé"); + switch (type) + { + case type_boite_information_alerte_changement_affectation: + stackView.pop(); // Retour à la page de config des circuits (a priori, par appui sur Ok puisque c'est le seul bouton valide...) + break; + + case type_boite_information_supprimer: + break; + + default: ; + } + } + } + + + //=========================================================== + // 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 nb; + var i, j, k; + var type_carte; + var texte_carte; + var texte_circuit; + var nb_circuits; + var defaut_no_carte = -1; + var defaut_no_circuit = -1; + var defaut_circuit_esclave = 0; + var defaut_mode_commande = shipheart_mode_commande_circuit_tor; + var intensite_coeff_filtrage, defaut_intensite_coeff_filtrage = 16; + var intensite_seuil_haut; + var intensite_seuil_haut_tempo, defaut_intensite_seuil_haut_tempo = 500; + var step_time, defaut_step_time = 20; + var time_out, defaut_time_out = 0; + var id_famille, defaut_id_famille = 0; + + // Note préliminaire : + // Chaque circuit est affecté à un n° de module (entre O et ...) ET à un n° de circuit sur le module (entre 0 et ...). + // Le modèle d'affectation de cette page utilise donc 'adresse_module/no_circuit' comme valeur d'identification unique. + // La valeur d'affectation 'Aucune' utilise la valeur particulière '-1/-1' pour être identifiée. + // Dans la BDD, les valeurs de Adresse_module et No_circuit sont reportées telles qu'elles. + +//console.log("Id du circuit = " + id_circuit); + + if (id_circuit > 0) // Cas d'une modification de circuit existant : + { + req = 'SELECT Nom, '; + req += ' Adresse_module, '; + req += ' No_circuit, '; + req += ' ID_Circuit_esclave, '; + req += ' Mode_commande, '; + req += ' Old_consigne, '; + req += ' Intensite_coeff_filtrage, '; + req += ' Intensite_seuil_haut, '; + req += ' Intensite_seuil_haut_tempo, '; + req += ' Step_time, '; + req += ' Time_out, '; + req += ' ID_Famille, '; + req += ' Priorite_affichage_accueil '; + req += ' FROM TB_Circuits '; + req += ' WHERE Cle_primaire=' + id_circuit + ' '; +//console.log("Requête = " + req) + res = bdd.requete_unique(req); + + //--------------------------------------------------------------- + // Mise à jour du champs de saisie de chaque zone de formulaire : + i = 0; + champ_formulaire_Nom.text = res[i ++]; + adresse_module = Number(res[i ++]); + no_circuit = Number(res[i ++]); + id_circuit_esclave = Number(res[i ++]); + mode_commande_circuit = Number(res[i ++]); + old_consigne = Number(res[i ++]); + intensite_coeff_filtrage = Number(res[i ++]); + intensite_seuil_haut = Number(res[i ++]); + intensite_seuil_haut_tempo = Number(res[i ++]); + step_time = Number(res[i ++]); + time_out = Number(res[i ++]); + id_famille = Number(res[i ++]); + priorite_affichage_accueil = Number(res[i ++]); + if (priorite_affichage_accueil <= 0) champ_formulaire_Masquage.checked = true; + else champ_formulaire_Masquage.checked = false; + } + else // Cas d'une création de circuit : + { + champ_formulaire_Nom.text = ""; + adresse_module = defaut_no_carte; + no_circuit = defaut_no_circuit; + id_circuit_esclave = defaut_circuit_esclave; + mode_commande_circuit = defaut_mode_commande; + old_consigne = 0; + intensite_coeff_filtrage = defaut_intensite_coeff_filtrage; + intensite_seuil_haut = max_intensite_carte(adresse_module, id_circuit_esclave); // SDIR #185 + intensite_seuil_haut_tempo = defaut_intensite_seuil_haut_tempo; + step_time = defaut_step_time; + time_out = defaut_time_out; + id_famille = defaut_id_famille; + champ_formulaire_Masquage.checked = false; + } + +//console.log("circuit esclave = " + circuit_esclave); + + //--------------------------------------------------------------------------------------- + // Affectation et Circuit esclave : + champ_formulaire_Affectation.model.clear(); + champ_formulaire_Affectation.model.append( { + "type": -1, + "valeur": defaut_no_carte + "/" + defaut_no_circuit, + "texte": qsTr("Non affecté"), + "groupe": false, + "prefixe_repos": "", + "actif": true } ); + champ_formulaire_Circuit_esclave.model.clear(); + champ_formulaire_Circuit_esclave.model.append({ + "no": 0, + "valeur": 0, + "texte": qsTr("Aucun"), + "prefixe_repos": "", + "actif": true}); + + // Recherche des modules et création des enregistrements correspondant du modèle (ligne de groupe pour la carte + 8 lignes de circuits "non affectés" par défaut) : + req = 'SELECT Adresse_k_bus, '; + req += ' Type, '; + req += ' Presence '; + req += ' FROM TB_Modules_config '; + req += ' WHERE '; + req += ' ( Type=' + shipheart_type_module_shipbase + ' '; + req += ' OR Type='+shipheart_type_module_shippower812+' '; + req += ' OR Type='+shipheart_type_module_shippower4AC+' '; + req += ' OR Type='+shipheart_type_module_shippower8DC+') '; + req += ' AND '; + req += ' ( Presence=1 '; + req += ' OR Adresse_k_bus IN (SELECT Adresse_module FROM TB_Circuits GROUP BY Adresse_module ORDER BY Adresse_module) ) '; + req += ' ORDER BY Adresse_k_bus'; +//console.log("req = [ " + req + "; ]"); + nb = bdd.requete(req); + + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { +//console.log("carte trouvée : adresse= " + res[0] + " et Type=" + res[1]); + nb_circuits = 0; + switch(Number(res[1])) + { + //------------------------------- + case shipheart_type_module_shipbase: + type_carte = shipheart_type_module_shipbase; + texte_carte = "ShipBase"; + if (shipheart_generation_shipbase === shipheart_generation_shipbase_v2) nb_circuits = 3; + else nb_circuits = 2; + break; + + //------------------------------- + case shipheart_type_module_shippower812: + type_carte = shipheart_type_module_shippower812; + texte_carte = qsTr("ShipPower812 [@ %1]").arg(res[0]); + nb_circuits = 8; + break; + + //------------------------------- + case shipheart_type_module_shippower4AC: + type_carte = shipheart_type_module_shippower4AC; + texte_carte = qsTr("ShipPower4AC [@ %1]").arg(res[0]); + nb_circuits = 4; + break; + + //------------------------------- + case shipheart_type_module_shippower8DC: + type_carte = shipheart_type_module_shippower8DC; + texte_carte = qsTr("ShipPower8DC [@ %1]").arg(res[0]); + nb_circuits = 8; + break; + + //------------------------------- + default: + type_carte = -1; + console.log ("Type de carte inconnu dans 'init_page()'..."); + break; + } + + if (type_carte === -1) continue; + + // Ajout de l'entete du module : + champ_formulaire_Affectation.model.append({ + "type": type_carte, + "valeur": "", + "texte": texte_carte, + "groupe": true, + "prefixe_repos": "", + "actif": false } ); + + // Création des entrées du modèle pour tous les circuits du module : + for (j = 0; j < nb_circuits; j ++) + { + champ_formulaire_Affectation.model.append({ + "type": type_carte, + "valeur": Number(res[0]) + "/" + Number(j), + "texte": qsTr("Circuit %1").arg(Number(j+1)), + "groupe": false, + "prefixe_repos": texte_carte + " - ", +// "actif": true } ); + "actif": (Number(res[2]) !== 0) } ); + } + + // Si le module en cours est le module sur lequel le circuit est positionné, on rempli au passage le modèle des circuits renfort : + if (adresse_module === Number(res[0])) + { + for (j = 0; j < nb_circuits; j ++) + { + champ_formulaire_Circuit_esclave.model.append({ + "no": (j+1), + "valeur": 0, + "texte": qsTr("Circuit %1").arg(Number(j+1)), + "prefixe_repos": texte_carte + " - ", + "actif": true}); + } + } + } + } + + // Recherche des circuits présents et mise à jour des lignes correspondantes du modèle : + var actif; + req = 'SELECT '; + req += ' Nom, '; + req += ' Adresse_module, '; + req += ' No_circuit, '; + req += ' Cle_primaire '; + req += ' FROM TB_Circuits '; + req += ' WHERE Adresse_module>=0 '; // Evite qu'on "empile" sur le "Non affecté" tous les circuits non affectés... + req += ' ORDER BY Adresse_module, No_circuit'; +//console.log("req = [ " + req + "; ]"); + nb_circuits = bdd.requete(req); + + for (i = 0; i < nb_circuits; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + if (Number(res[3]) === id_circuit) actif = true; // On laisse actif le choix actuel. + else actif = false; // Les autres circuits présents sont par contre rendus inactifs. + + // On n'a pas d'autre choix que de parcourir toutes les entrées du modèle pour rechercher l'entrée dont le N° de carte / N° de circuit matche avec le circuit en cours : + for (k = 0; k < champ_formulaire_Affectation.count; k ++) + { + if (champ_formulaire_Affectation.model.get(k).valeur === (res[1] + "/" + res[2])) + { + if (actif) texte_circuit = champ_formulaire_Affectation.model.get(k).texte; + else texte_circuit = qsTr("%1 - %2").arg(champ_formulaire_Affectation.model.get(k).texte).arg(res[0]); + champ_formulaire_Affectation.model.set(k, { + "valeur": Number(res[1]) + "/" + Number(res[2]), + "texte": texte_circuit, + "actif": actif } ); + break; // Il est inutile de continuer à boucler dès qu'on a trouvé l'entrée recherchée... + } + } + + // Recherche pour cicuit esclave : + if (adresse_module === Number(res[1])) // Si on est sur la carte du circuit en cours + { + if (Number(res[3]) === id_circuit_esclave) actif = true; // On laisse actif le choix actuel. + else actif = false; // Les autres circuits présents sont par contre rendus inactifs. + + // On n'a pas d'autre choix que de parcourir toutes les entrées du modèle pour rechercher l'entrée dont le N° de carte / N° de circuit matche avec le circuit en cours : + for (k = 0; k < champ_formulaire_Circuit_esclave.count; k ++) + { + if (champ_formulaire_Circuit_esclave.model.get(k).no === (Number(res[2]) + 1)) + { + if (actif) texte_circuit = champ_formulaire_Circuit_esclave.model.get(k).texte; + else texte_circuit = qsTr("%1 - %2").arg(champ_formulaire_Circuit_esclave.model.get(k).texte).arg(res[0]); + champ_formulaire_Circuit_esclave.model.set(k, { + "no": (Number(res[2]) + 1), + "valeur": Number(res[3]), + "texte": texte_circuit, + "actif": actif } ); + break; // Il est inutile de continuer à boucler dès qu'on a trouvé l'entrée recherchée... + } + } + } + } + } + + // Positionnement de l'index sur la valeur en cours : + i = recherche_index_valeur_modele(adresse_module + "/" + no_circuit, champ_formulaire_Affectation.model, "Affectation"); + if (i === -1) champ_formulaire_Affectation.currentIndex = recherche_index_valeur_modele(defaut_no_carte + "/" + defaut_no_circuit, champ_formulaire_Affectation.model, "Affectation"); + else champ_formulaire_Affectation.currentIndex = i; + + // Positionnement de l'index sur la valeur en cours : + i = recherche_index_valeur_modele(id_circuit_esclave, champ_formulaire_Circuit_esclave.model, "Circuit_esclave"); + if (i === -1) champ_formulaire_Circuit_esclave.currentIndex = recherche_index_valeur_modele(defaut_circuit_esclave, champ_formulaire_Circuit_esclave.model, "Circuit_esclave"); + else champ_formulaire_Circuit_esclave.currentIndex = i; + + + //--------------------------------------------------------------------------------------- + // Mode de commande : + champ_formulaire_Mode_commande.model.clear(); + champ_formulaire_Mode_commande.model.append({"valeur": defaut_mode_commande, "texte": qsTr("On-Off") }); + champ_formulaire_Mode_commande.model.append({"valeur": shipheart_mode_commande_circuit_soft_tor, "texte": qsTr("On-Off progressif") }); + champ_formulaire_Mode_commande.model.append({"valeur": shipheart_mode_commande_circuit_soft_variable, "texte": qsTr("Variateur") }); + + // Positionnement de l'index sur la valeur en cours : + i = recherche_index_valeur_modele(mode_commande_circuit, champ_formulaire_Mode_commande.model, "Mode_commande"); + if (i === -1) champ_formulaire_Mode_commande.currentIndex = recherche_index_valeur_modele(defaut_mode_commande, champ_formulaire_Mode_commande.model, "Mode_commande"); + else champ_formulaire_Mode_commande.currentIndex = i; + + + //--------------------------------------------------------------------------------------- + // Coefficient de filtrage du courant (valeur en nombre d'échantillons ; mini = 1): + champ_formulaire_Intensite_coeff_filtrage.model.clear(); + champ_formulaire_Intensite_coeff_filtrage.model.append({"valeur": 1, "texte": qsTr("Aucun filtrage") }); + champ_formulaire_Intensite_coeff_filtrage.model.append({"valeur": 4, "texte": qsTr("Très faible") }); + champ_formulaire_Intensite_coeff_filtrage.model.append({"valeur": 8, "texte": qsTr("Faible") }); + champ_formulaire_Intensite_coeff_filtrage.model.append({"valeur": defaut_intensite_coeff_filtrage, "texte": qsTr("Moyen") }); + champ_formulaire_Intensite_coeff_filtrage.model.append({"valeur": 64, "texte": qsTr("Elevé") }); + champ_formulaire_Intensite_coeff_filtrage.model.append({"valeur": 96, "texte": qsTr("Très élevé") }); + + // Positionnement de l'index sur la valeur en cours : + i = recherche_index_valeur_modele(intensite_coeff_filtrage, champ_formulaire_Intensite_coeff_filtrage.model, "Intensite_coeff_filtrage"); + if (i === -1) champ_formulaire_Intensite_coeff_filtrage.currentIndex = recherche_index_valeur_modele(defaut_intensite_coeff_filtrage, champ_formulaire_Intensite_coeff_filtrage.model, "Intensite_coeff_filtrage"); + else champ_formulaire_Intensite_coeff_filtrage.currentIndex = i; + + + //--------------------------------------------------------------------------------------- + // Seuil de disjonction (en mA) : + intensite_seuil_haut = raffraichissement_modele_intensite_seuil_haut(adresse_module, intensite_seuil_haut, id_circuit_esclave); // L'intensité est ajustée au passage si nécessaire (notamment si le max de la nouvelle carte est < valeur courante) + + + //--------------------------------------------------------------------------------------- + // Vitesse de disjonction (valeur en ms): + champ_formulaire_Intensite_seuil_haut_tempo.model.clear(); + champ_formulaire_Intensite_seuil_haut_tempo.model.append({"valeur": 50, "texte": qsTr("Très rapide") }); + champ_formulaire_Intensite_seuil_haut_tempo.model.append({"valeur": 200, "texte": qsTr("Rapide") }); + champ_formulaire_Intensite_seuil_haut_tempo.model.append({"valeur": defaut_intensite_seuil_haut_tempo, "texte": qsTr("Moyenne") }); + champ_formulaire_Intensite_seuil_haut_tempo.model.append({"valeur": 2000, "texte": qsTr("Lente") }); + champ_formulaire_Intensite_seuil_haut_tempo.model.append({"valeur": 5000, "texte": qsTr("Très lente") }); + + // Positionnement de l'index sur la valeur en cours : + i = recherche_index_valeur_modele(intensite_seuil_haut_tempo, champ_formulaire_Intensite_seuil_haut_tempo.model, "Intensite_seuil_haut_tempo"); + if (i === -1) champ_formulaire_Intensite_seuil_haut_tempo.currentIndex = recherche_index_valeur_modele(defaut_intensite_seuil_haut_tempo, champ_formulaire_Intensite_seuil_haut_tempo.model, "Intensite_seuil_haut_tempo"); + else champ_formulaire_Intensite_seuil_haut_tempo.currentIndex = i; + + + //--------------------------------------------------------------------------------------- + // Vitesse démarrage : +// Note 26/01/2023 : pour les SP812, le nb de steps est passé ce jour à [nouvelle_consigne - ancienne_consigne] / 2 soit, en général, 50. Auparavant, le nb de steps était de 25. +// pour les SP8DC, le nombre de pas est fixé à 50 et il est réduit si [nouvelle_consigne - ancienne_consigne] < 50. + champ_formulaire_Step_time.model.clear(); + champ_formulaire_Step_time.model.append({"valeur": 5, "texte": qsTr("Très rapide") }); + champ_formulaire_Step_time.model.append({"valeur": 10, "texte": qsTr("Rapide") }); + champ_formulaire_Step_time.model.append({"valeur": defaut_step_time, "texte": qsTr("Moyenne") }); + champ_formulaire_Step_time.model.append({"valeur": 40, "texte": qsTr("Lente") }); + champ_formulaire_Step_time.model.append({"valeur": 80, "texte": qsTr("Très lente") }); + + // Positionnement de l'index sur la valeur en cours : + i = recherche_index_valeur_modele(step_time, champ_formulaire_Step_time.model, "Step-time"); + if (i === -1) champ_formulaire_Step_time.currentIndex = recherche_index_valeur_modele(defaut_step_time, champ_formulaire_Step_time.model, "Step-time"); + else champ_formulaire_Step_time.currentIndex = i; + + + //--------------------------------------------------------------------------------------- + // Time-out (en x 100ms) : + champ_formulaire_Time_out.model.clear(); + champ_formulaire_Time_out.model.append({"valeur": defaut_time_out, "texte": qsTr("Non") }); + champ_formulaire_Time_out.model.append({"valeur": (1), "texte": qsTr("1 seconde") }); + champ_formulaire_Time_out.model.append({"valeur": (2), "texte": qsTr("2 secondes") }); + champ_formulaire_Time_out.model.append({"valeur": (5), "texte": qsTr("5 secondes") }); + champ_formulaire_Time_out.model.append({"valeur": (15), "texte": qsTr("15 secondes") }); + champ_formulaire_Time_out.model.append({"valeur": (30), "texte": qsTr("30 secondes") }); + champ_formulaire_Time_out.model.append({"valeur": (45), "texte": qsTr("45 secondes") }); + champ_formulaire_Time_out.model.append({"valeur": (1*60), "texte": qsTr("1 minute") }); + champ_formulaire_Time_out.model.append({"valeur": (5*60), "texte": qsTr("5 minutes") }); + champ_formulaire_Time_out.model.append({"valeur": (15*60), "texte": qsTr("15 minutes") }); + champ_formulaire_Time_out.model.append({"valeur": (60*60), "texte": qsTr("1 heure") }); + champ_formulaire_Time_out.model.append({"valeur": (4*60*60), "texte": qsTr("4 heures") }); + + // Positionnement de l'index sur la valeur en cours : + i = recherche_index_valeur_modele(time_out, champ_formulaire_Time_out.model, "Time-out"); + if (i === -1) champ_formulaire_Time_out.currentIndex = recherche_index_valeur_modele(defaut_time_out, champ_formulaire_Time_out.model, "Time-out"); + else champ_formulaire_Time_out.currentIndex = i; + + //--------------------------------------------------------------------------------------- + // Famille : + champ_formulaire_Famille.model.clear(); + champ_formulaire_Famille.model.append({"valeur": defaut_id_famille, "texte": "Non défini" }); + + req = 'SELECT Cle_primaire, Nom FROM TB_Familles WHERE Type_source=' + shipheart_type_source_circuits + ' 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) + { + champ_formulaire_Famille.model.append({"valeur": Number(res[0]), "texte": res[1] }); + } + } + + // Positionnement de l'index sur la valeur en cours : + i = recherche_index_valeur_modele(id_famille, champ_formulaire_Famille.model, "Famille"); + if (i === -1) champ_formulaire_Famille.currentIndex = recherche_index_valeur_modele(defaut_id_famille, champ_formulaire_Famille.model, "Famille"); + else champ_formulaire_Famille.currentIndex = i; + + + flag_init = false; // Indique que l'init est terminée + } + + + //============================================================================================================= + // Raffraichissement de la liste cdes_auto du circuit + //============================================================================================================= + function raffraichissement_modele_intensite_seuil_haut(adresse_module, intensite_seuil_haut, id_circuit_esclave) + { + var i; + var max_intensite_seuil_haut; + + champ_formulaire_Intensite_seuil_haut.model.clear(); + + // Recherche du type de carte et de sa version pour déterminer la plage maximale possible : + max_intensite_seuil_haut = max_intensite_carte(adresse_module, id_circuit_esclave); // Retour de 0 si adresse_module=-1 + + if (max_intensite_seuil_haut > 0) + { + for (i = 1; i <= max_intensite_seuil_haut; i ++ ) champ_formulaire_Intensite_seuil_haut.model.append({"valeur": i, "texte": i + " A" }); + + // Positionnement de l'index sur la valeur en cours : + i = recherche_index_valeur_modele(intensite_seuil_haut, champ_formulaire_Intensite_seuil_haut.model, "Intensite_seuil_haut"); + if (i !== -1) + { + champ_formulaire_Intensite_seuil_haut.currentIndex = i; +//console.log("Retour de mise à jour modèle Intensité seuil haut = " + intensite_seuil_haut); + return(intensite_seuil_haut); + } + else + { + champ_formulaire_Intensite_seuil_haut.currentIndex = recherche_index_valeur_modele(max_intensite_seuil_haut, champ_formulaire_Intensite_seuil_haut.model, "Intensite_seuil_haut"); +//console.log("Retour de mise à jour modèle Intensité seuil haut = " + max_intensite_seuil_haut); + return(max_intensite_seuil_haut); + } + } + else // Cas où le type de carte n'est pas connu (permet d'éviter des erreurs mais ce cas n'est normalement jamais affiché)... + { + champ_formulaire_Intensite_seuil_haut.model.append({"valeur": 0, "texte": "Aucun" }); + champ_formulaire_Intensite_seuil_haut.currentIndex = 0; +//console.log("Retour de mise à jour modèle Intensité seuil haut = " + max_intensite_seuil_haut); + return(max_intensite_seuil_haut); + } + } + + + //============================================================================================================= + // Mise à jour des valeurs saisies du circuit + // Important : on considère qu'après exécution de cette fonction, on quitte la page (les propriétés globales + // peuvent en effet être affectées et/ou pas à jour après cette fonction). + //============================================================================================================= + function mise_a_jour_circuit() + { + var req, res; + + // Traitement de Affectation : + var valeur = champ_formulaire_Affectation.model.get(champ_formulaire_Affectation.currentIndex).valeur + const valeurs = valeur.split('/'); + var new_no_carte = Number(valeurs[0]); + var new_no_circuit_carte = Number(valeurs[1]); + var paa; + var mode = champ_formulaire_Mode_commande.model.get(champ_formulaire_Mode_commande.currentIndex).valeur; + var step_time = champ_formulaire_Step_time.model.get(champ_formulaire_Step_time.currentIndex).valeur; + var intensite_seuil_haut = champ_formulaire_Intensite_seuil_haut.model.get(champ_formulaire_Intensite_seuil_haut.currentIndex).valeur; + var intensite_coeff_filtrage = champ_formulaire_Intensite_coeff_filtrage.model.get(champ_formulaire_Intensite_coeff_filtrage.currentIndex).valeur; + + + // Traitement du circuit esclave : + var new_id_circuit_esclave = champ_formulaire_Circuit_esclave.model.get(champ_formulaire_Circuit_esclave.currentIndex).valeur; + var new_no_circuit_esclave = champ_formulaire_Circuit_esclave.model.get(champ_formulaire_Circuit_esclave.currentIndex).no; + + //-------------------------------------------------------------------------------------------------- + // Changement d'affectation du circuit : + if ((new_no_carte !== adresse_module) || (new_no_circuit_carte !== no_circuit)) + { + extinction_circuit_garantie(id_circuit); // L'extinction du circuit éteindra aussi (l'ancien) esclave s'il y en avait un. + + // Impact sur le circuit esclave : + if (new_no_carte !== adresse_module) // Qu'il y en ait eu un ou pas, il ne peut y en avoir suite à un changement de module (puisqu'on n'a pas pu proposer un circuit esclave sur le nouveau module) + { + new_id_circuit_esclave = 0; + new_no_circuit_esclave = 0; // C'est ce qui permettra sa suppression ensuite s'il y en avait un. + } + } + + //-------------------------------------------------------------------------------------------------- + // Mise à jour de N° de carte et du n° de circuit : + adresse_module = new_no_carte; + no_circuit = new_no_circuit_carte; + + //-------------------------------------------------------------------------------------------------- + // Vérification des paramètres spécifiques au type de module support du circuit : + switch(type_carte(adresse_module)) + { + //------------------------------------------- + case shipheart_type_module_shippower812: + intensite_coeff_filtrage = 16; + if (mode !== shipheart_mode_commande_circuit_soft_variable) old_consigne = 0; // SDIR #184 + break; + + //------------------------------------------- + case shipheart_type_module_shippower4AC: + intensite_coeff_filtrage = 4; + mode = shipheart_mode_commande_circuit_tor; + // step_time = defaut_step_time; // SDIR #193 : mise en commentaire de la ligne car 'defaut_step_time' n'existe pas et met la page en erreur... + new_id_circuit_esclave = 0; // Normalement ne doit pas arriver car déjà pris en compte de façon plus générale au § précédent (si on arrive sur un SP4AC, c'est qu'il y a eu changement de carte donc le circuit esclave a été déjà sucré...) + new_no_circuit_esclave = 0; + break; + + //------------------------------------------- + case shipheart_type_module_shippower8DC: + intensite_coeff_filtrage = 16; + if (mode !== shipheart_mode_commande_circuit_soft_variable) old_consigne = 0; // SDIR #184 + break; + + //------------------------------------------- + default: // Ce cas correspond notamment aux circuits Non Affectés... + intensite_coeff_filtrage = 16; + break; + } + + //-------------------------------------------------------------------------------------------------- + // Vérification que le seuil de disjonction est compatible avec le module support : + // NB : ce test ne peut pas être intégré au § précédent car la fonction 'max_intensite_carte()' teste non seulement le type mais aussi la version hardware (cas des SP812)... + var max_intensite_seuil_haut = max_intensite_carte(adresse_module, new_id_circuit_esclave); + if (intensite_seuil_haut > max_intensite_seuil_haut) intensite_seuil_haut = max_intensite_seuil_haut; + + //-------------------------------------------------------------------------------------------------- + if (champ_formulaire_Masquage.checked) // Demande de masquage : + { + if (priorite_affichage_accueil <= 0) paa = priorite_affichage_accueil; // S'il était masqué, on garde la même valeur. + else paa = - priorite_affichage_accueil; // S'il était démasqué (donc > 0), on prend son opposé (comme ça, on est bien <0 mais on garde en plus la position initiale en mémoire) + } + else // Demande de ne pas le masquer : + { + if (priorite_affichage_accueil > 0) paa = priorite_affichage_accueil; // S'il était démasqué, on garde la même valeur + else if (priorite_affichage_accueil < 0) paa = - priorite_affichage_accueil; // S'il était masqué, avec une valeur mémorisée non nulle, on récupère la valeur mémorisée (l'opposé donc) + else paa = 999; // S'il était masqué mais sans valeur mémorisée (donc nulle), on attribue arbitrairement une valeur très élevée pour mettre le circuit affiché mais en dernière position. + } + + + //-------------------------------------------------------------------------------------------------- + // Traitement du circuit esclave avec, pour l'essentiel, les mêmes paramètres que le circuit maitre : +//console.log("new_id_circuit_esclave = " + new_id_circuit_esclave + " et id_cicuit_esclave = " + id_circuit_esclave); + + // Suppression de l'ancien circuit esclave si besoin : + if (id_circuit_esclave > 0) // Il y avait un circuit esclave : + { + if (new_id_circuit_esclave !== id_circuit_esclave) // Le nouveau circuit esclave est différent de l'ancien => Il faut supprimer l'ancien + { + // Suppression de la commande de l'ancien circuit esclave dans tous les cas) : + extinction_circuit_garantie(id_circuit_esclave); + + // Suppression de l'ancien circuit esclave (dans tous les cas) : + req = 'DELETE FROM TB_Circuits WHERE Cle_primaire=' + id_circuit_esclave + ' '; + bdd.requete_unique(req); + } + } + + // Création du nouveau circuit esclave si besoin : + if ( ((id_circuit_esclave > 0) && // Il y avait un circuit esclave... + (new_id_circuit_esclave !== id_circuit_esclave) && // ... et le nouveau est différent de l'ancien... + (new_no_circuit_esclave !== 0)) || // ... et le nouveau n'est pas nul OU + ((id_circuit_esclave === 0) && // Il n'y avait pas de circuit esclave... + (new_no_circuit_esclave !== 0)) ) // ... et le nouveau n'est pas nul + { + req = 'INSERT INTO TB_Circuits (Nom, Adresse_module, No_circuit, ID_Circuit_esclave, Mode_commande, Intensite_coeff_filtrage, Intensite_seuil_haut, Intensite_seuil_haut_tempo, Step_time, Time_out, ID_Famille, Priorite_affichage_accueil) ' + req += ' VALUES ("' + champ_formulaire_Nom.text + '"'; + req += ', ' + adresse_module; + req += ', ' + (new_no_circuit_esclave - 1); + req += ', ' + (id_circuit * (-1)); + req += ', ' + mode; + req += ', ' + intensite_coeff_filtrage; + req += ', ' + intensite_seuil_haut; + req += ', ' + champ_formulaire_Intensite_seuil_haut_tempo.model.get(champ_formulaire_Intensite_seuil_haut_tempo.currentIndex).valeur; + req += ', ' + step_time; + req += ', ' + champ_formulaire_Time_out.model.get(champ_formulaire_Time_out.currentIndex).valeur; + req += ', ' + champ_formulaire_Famille.model.get(champ_formulaire_Famille.currentIndex).valeur; + req += ', 0'; // Le circuit esclave est toujours masqué ! + req += ') '; +//console.log("Requête = " + req) + bdd.requete_unique(req); + + // Récupération de la clé primaire du circuit esclave créé : + req = 'SELECT Cle_primaire FROM TB_Circuits ORDER BY Cle_primaire DESC LIMIT 1'; + res = bdd.requete_unique(req); +// id_circuit_esclave = Number(res[0]); + new_id_circuit_esclave = Number(res[0]); // SDIR #325 + } + + // Interdiction de mode variateur si on a un circuit esclave : + if (new_id_circuit_esclave > 0) + { + if (mode === shipheart_mode_commande_circuit_soft_variable) + { + mode = shipheart_mode_commande_circuit_soft_tor; + old_consigne = 0; // SDIR #184 +// SDIR #325 req = 'UPDATE TB_Circuits SET Mode_commande=' + mode + ' WHERE Cle_primaire=' + id_circuit_esclave + ' '; // Maj de l'esclave qui a été créé avec le "mauvais" mode + req = 'UPDATE TB_Circuits SET Mode_commande=' + mode + ' WHERE Cle_primaire=' + new_id_circuit_esclave + ' '; // Maj de l'esclave qui a été créé avec le "mauvais" mode + bdd.requete_unique(req); + + // Définition des paramètres de la boite de dialogue : + boite_information.niveau = 1; + boite_information.imageTitreSource = "/images/ampoule.png" + boite_information.message = qsTr("L'utilisation d'un circuit de renfort rend l'utilisation du mode de commande [Variateur] impossible.

Le mode de commande vient donc d'être ramené à [On-Off Progressif]."); + boite_information.open(); + } + } + + //-------------------------------------------------------------------------------------------------- + // Génération de la requête de mise à jour du circuit : + req = 'UPDATE TB_Circuits SET Nom="' + champ_formulaire_Nom.text + '" '; + req += ', Adresse_module=' + adresse_module + ' '; + req += ', No_circuit=' + no_circuit + ' '; + req += ', ID_Circuit_esclave=' + new_id_circuit_esclave + ' '; // SDIR #325 + req += ', Mode_commande=' + mode + ' '; + req += ', Old_consigne=' + old_consigne + ' '; + req += ', Intensite_coeff_filtrage=' + intensite_coeff_filtrage + ' '; + req += ', Intensite_seuil_haut=' + champ_formulaire_Intensite_seuil_haut.model.get(champ_formulaire_Intensite_seuil_haut.currentIndex).valeur + ' '; + req += ', Intensite_seuil_haut_tempo=' + champ_formulaire_Intensite_seuil_haut_tempo.model.get(champ_formulaire_Intensite_seuil_haut_tempo.currentIndex).valeur + ' '; + req += ', Step_time=' + champ_formulaire_Step_time.model.get(champ_formulaire_Step_time.currentIndex).valeur + ' '; + req += ', Time_out=' + champ_formulaire_Time_out.model.get(champ_formulaire_Time_out.currentIndex).valeur + ' '; + req += ', ID_Famille=' + champ_formulaire_Famille.model.get(champ_formulaire_Famille.currentIndex).valeur + ' '; + req += ', Priorite_affichage_accueil=' + paa + ' '; + req += ' WHERE Cle_primaire=' + id_circuit + ' ' +//console.log("Requête = " + req) + bdd.requete_unique(req); + + // Demande de synchro : + synchro_bdd(shipheart_type_synchro_config); + } + + + //============================================================================================================= + // Création du circuit + // Note : l'utilisation d'un circuit esclave est impossible lors de la création du circuit... + //============================================================================================================= + function creation_circuit() + { + var req, res; + + // Traitement de Affectation : + var valeur = champ_formulaire_Affectation.model.get(champ_formulaire_Affectation.currentIndex).valeur + const valeurs = valeur.split('/'); + var adresse_module = Number(valeurs[0]); + var no_circuit = Number(valeurs[1]); + var paa; + var mode = champ_formulaire_Mode_commande.model.get(champ_formulaire_Mode_commande.currentIndex).valeur; + var intensite_coeff_filtrage = champ_formulaire_Intensite_coeff_filtrage.model.get(champ_formulaire_Intensite_coeff_filtrage.currentIndex).valeur; + + //-------------------------------------------------------------------------------------------------- + // Vérification des paramètres spécifiques au type de module support du circuit : + switch(type_carte(adresse_module)) + { + //------------------------------------------- + case shipheart_type_module_shipbase: + intensite_coeff_filtrage = 16; + break; + + //------------------------------------------- + case shipheart_type_module_shippower812: + intensite_coeff_filtrage = 16; + break; + + //------------------------------------------- + case shipheart_type_module_shippower4AC: + intensite_coeff_filtrage = 4; + break; + + //------------------------------------------- + case shipheart_type_module_shippower8DC: + intensite_coeff_filtrage = 16; + break; + + //------------------------------------------- + default: // Ce cas correspond notamment aux circuits Non Affectés... + intensite_coeff_filtrage = 16; + break; + } + + if (champ_formulaire_Masquage.checked) paa = 0; + else paa = 999; + + + req = 'INSERT INTO TB_Circuits (Nom, Adresse_module, No_circuit, ID_Circuit_esclave, Mode_commande, Intensite_coeff_filtrage, Intensite_seuil_haut, Intensite_seuil_haut_tempo, Step_time, Time_out, ID_Famille, Priorite_affichage_accueil) ' + req += ' VALUES ("' + champ_formulaire_Nom.text + '"'; + req += ', ' + adresse_module; + req += ', ' + no_circuit; + req += ', ' + 0; + req += ', ' + mode; + req += ', ' + intensite_coeff_filtrage; + req += ', ' + champ_formulaire_Intensite_seuil_haut.model.get(champ_formulaire_Intensite_seuil_haut.currentIndex).valeur; + req += ', ' + champ_formulaire_Intensite_seuil_haut_tempo.model.get(champ_formulaire_Intensite_seuil_haut_tempo.currentIndex).valeur; + req += ', ' + champ_formulaire_Step_time.model.get(champ_formulaire_Step_time.currentIndex).valeur; + req += ', ' + champ_formulaire_Time_out.model.get(champ_formulaire_Time_out.currentIndex).valeur; + req += ', ' + champ_formulaire_Famille.model.get(champ_formulaire_Famille.currentIndex).valeur; + req += ', ' + paa; + req += ') '; +//console.log("Requête = " + req) + bdd.requete_unique(req); + + // Récupération de la clé primaire du circuit maitre : + var id_circuit_maitre; + req = 'SELECT Cle_primaire FROM TB_Circuits ORDER BY Cle_primaire DESC LIMIT 1'; + res = bdd.requete_unique(req); + id_circuit_maitre = Number(res[0]); + + // Demande de synchro : + synchro_bdd(shipheart_type_synchro_config); + } + + //============================================================================================================= + // Recherche du type de carte à partir de son n° sur K-Bus + //============================================================================================================= + function type_carte(adresse_module) + { + var req, res; + var max = 0; + + if (adresse_module >= 0) + { + req = 'SELECT Type FROM TB_Modules_config WHERE Presence=1 AND Adresse_k_bus=' + adresse_module + ' '; + res = bdd.requete_unique(req); + + return(Number(res[0])); + } + else return (-1); // Cas d'un circuit non affecté + } + + //============================================================================================================= + // Calcul de l'intensité maxi pour une carte + //============================================================================================================= + function max_intensite_carte(adresse_module, id_circuit_esclave) + { + var req, res; + var max = 0; + + if (adresse_module < 0) return(0); // Cas d'un circuit non affecté + + req = 'SELECT Type, Hardware_version FROM TB_Modules_physiques WHERE Presence=1 AND Adresse_k_bus=' + adresse_module + ' '; +//console.log("req = [ " + req + "; ]"); + res = bdd.requete_unique(req); + + switch(Number(res[0])) + { + //------------------------------------------- + case shipheart_type_module_shipbase: + max = 0; + break; + + //------------------------------------------- + case shipheart_type_module_shippower812: + if (Number(res[1]) === 0) // Hardware version = 0 : + { + if (id_circuit_esclave > 0) max = 35; // Cas d'un circuit avec circuit esclave + else max = 20; + } + else // Hardware version >= 1 : + { + if (id_circuit_esclave > 0) max = 40; // Cas d'un circuit avec circuit esclave + else max = 25; + } + break; + + //------------------------------------------- + case shipheart_type_module_shippower4AC: + max = 32; + break; + + //------------------------------------------- + case shipheart_type_module_shippower8DC: + if (id_circuit_esclave > 0) max = 40; // Cas d'un circuit avec circuit esclave + else return(25); + break; + + //------------------------------------------- + default: + console.log ("Type de carte inconnu dans 'max_intensite_carte()'..."); + max = 0; + break; + } + + return(max); + } + + //============================================================================================================= + // Check suppression du circuit + //============================================================================================================= + function check_avant_suppression() + { + var req, res; + var nb; + var i; + 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") + for (i = 1; i < shipheart_specifique_client.length; i ++) // On commence à 1 car le premier champ est déjà traité... + { + var parametre = shipheart_specifique_client[i].split('='); + switch(parametre[0]) + { + //-------------------------------------------------------- + case 'id_circuit_activation_moteur': + + if (id_circuit === Number(parametre[1])) // Cas où le circuit qu'on envisage de supprimer est celui utilisé pour démarrer le moteur.... + { + message = qsTr("Ce circuit est utilisé pour la commande du moteur.
Vous devez d'abord affecter la commande moteur à un autre circuit avant de pouvoir supprimer celui-ci. ") + } + + break; + + //-------------------------------------------------------- + default : + break; + } + } + + break; + } + + //========================================================================= + // Recherche de l'impact de cette suppression sur les évènements : + req = 'SELECT Cle_primaire, Nom FROM TB_Events WHERE Type_source=' + shipheart_source_mesure_circuit + ' AND ID_Source=' + id_circuit + ' '; + req += ' UNION'; + req += ' SELECT Cle_primaire, Nom FROM TB_Events WHERE Action_circuits LIKE "%' + id_circuit + '/%"'; + req += ' ORDER BY Nom'; +//console.log("Requête = [ " + req + "; ]") + nb = bdd.requete(req); + + if (nb > 0) + { + if (nb === 1) message += "

" + qsTr("Ce circuit est utilisé par l'évènement ci-dessous.
Vous devez modifier ou supprimer cet évènement pour qu'il ne dépende plus de ce circuit avant de pouvoir le supprimer.") + "

"; + else message += "

" + qsTr("Ce circuit est utilisé par les %1 évènements ci-dessous.
Vous devez modifier ou supprimer ces évènements pour qu'ils ne dépendent plus de ce circuit avant de pouvoir le supprimer.").arg(nb) + "

"; + + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + message += "‣ " + (i+1) + " : " + res[1] + "
"; + } + } + } + + //========================================================================= + // Recherche de l'impact de cette suppression sur les capteurs calculés : + /* Retour de la forme : + +-------------+ + | Nom_capteur | + +-------------+ + | Calculation | + | Calcul 2 | + +-------------+ */ + req = 'SELECT Nom FROM TB_Capteurs '; + req += ' WHERE Type_entrees=' + shipheart_capteur_type_entrees_calculee_booleen + ' '; + req += ' AND Entrees LIKE "%/' + shipheart_source_mesure_circuit + ':' + id_circuit + '/%" '; +//console.log("Requête = [ " + req + "; ]") + nb = bdd.requete(req); + + if (nb > 0) + { + if (nb === 1) message += "

" + qsTr("Ce circuit est utilisé par le capteur calculé ci-dessous.
Vous devez modifier ou supprimer ce capteur calculé pour qu'il ne dépende plus de ce circuit avant de pouvoir le supprimer.") + "

"; + else message += "

" + qsTr("Ce circuit est utilisé par les %1 capteurs calculés ci-dessous.
Vous devez modifier ou supprimer ces capteurs calculés pour qu'ils ne dépendent plus de ce circuit avant de pouvoir le supprimer.").arg(nb) + "

"; + + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + message += "‣ " + (i+1) + " : " + res[0] + "
"; + } + } + } + + //========================================================================= + // 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 = 1; + boite_information.imageTitreSource = "/images/attention.png" + boite_information.message = message; + boite_information.alignementMessage = Text.AlignLeft + boite_information.type = type_boite_information_supprimer; + boite_information.open(); + + return(-1); + } + } + + + //============================================================================================================= + // Suppression du circuit + //============================================================================================================= + function suppression_circuit() + { + var req, res; + + // Mise à l'arret du circuit (et donc de son éventuel esclave) : + extinction_circuit_garantie(id_circuit); + + // Recherche d'un éventuel circuit esclave : + req = 'SELECT ID_Circuit_esclave FROM TB_Circuits WHERE Cle_primaire=' + id_circuit + ' '; + res = bdd.requete_unique(req); + if (Number(res[0]) > 0) // ..; et supression s'il y en a un + { + req = 'DELETE FROM TB_Circuits WHERE Cle_primaire=' + Number(res[0]) + ' '; + bdd.requete_unique(req); + } + + // Suppression du circuit : + req = 'DELETE FROM TB_Circuits WHERE Cle_primaire=' + id_circuit + ' '; + bdd.requete_unique(req); + + // Demande de synchro : + synchro_bdd(shipheart_type_synchro_config); + } + + //============================================================================================================= + // Extinction garantie du circuit + // Cela se traduit par l'envoi d'une demande d'extinction puis une boucle d'attente (avec time out) jusqu'à ce + // que le circuit ait effectivement sa consigne à 0. + //============================================================================================================= + function extinction_circuit_garantie(id_circuit) + { + var req, res; + var i; + var limite = 200; + + // Mise à l'arret du circuit : + bdd.requete_unique("UPDATE TB_Circuits SET New_consigne=0, Old_consigne=0 WHERE Cle_primaire='" + id_circuit + "'") // Ajout de la RAZ de Old_consigne (SDIR # 184) + synchro_bdd(shipheart_type_synchro_data); // Avec cette synchro, le traitement par l'appli sera fait dans 100ms maxi. + + // Boucle d'attente du passage effectif à 0 : + for (i = 0; i < limite; i ++) + { + req = "SELECT Consigne FROM TB_Circuits WHERE Cle_primaire='" + id_circuit + "' "; + res = bdd.requete_unique(req); + if (Number(res[0]) === 0) break; + } + + if (i === limite) console.log("La boucle d'extinction garantie n'a pas pu effectuer la RAZ avant l'expiration de son time out (" + limite + " boucles)"); + else console.log("L'extinction garantie s'est déroulée correctement et est sortie après " + i + " boucles"); + } + + //============================================================================================================= + // 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= 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.... + } + } + + + +} + diff --git a/config_event.qml b/config_event.qml new file mode 100644 index 0000000..13fc779 --- /dev/null +++ b/config_event.qml @@ -0,0 +1,2164 @@ +//======================================================================================================================================================================== +// CONFIG_EVENT.QML +// Ce fichier traite la configuration d'un évènement. La page permet notamment de : +// - Modifier la config de l'évènement (ou de le créer la première fois), +// - Supprimer l'évènement +// La page est appelée depuis la page config_events.qml, en cliquant sur l'évènement à 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 +import"fonctions.js" as Fonctions +import"fonctions_date_heure.js" as Fonctions_date_heure + + +Shipheart_page { + id: page_config_evenement + + + // 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 int id_event: 0 + + property string nom: "" + 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 int tempo: 0 + property string conditions_horaires: "" + property string action_circuits: "" + + property int index_condition_horaire_en_cours: -1 + property int index_circuit_en_cours: -1 + + property bool flag_test_binaire: false // Indique si l'évènement porte sur une condition binaire ou non (exemple: Capteur>Entrée AUX) + property int nombre_action_circuits: 0 // Stocke le nombre d'actions sur des circuits (autre que "Aucune action") car on est limité à 'shipheart_max_nombre_action_circuits_par_event' + + // 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_supprimer.pressed) + { + suppression_event(); + timer_tempo_reconfiguration.restart(); // Lancement du timer pour attendre la fin de la reconfiguration + } + } + } + } + + // Titre de la page : + Shipheart_titre_1 {titre: (id_event === 0) ? qsTr("Création d'un évènement") : qsTr("Configuration de l'évènement"); 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 : 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 l'évènement") + 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 : 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 = 0; + id_variable = 0; + if (type_source > 0) mise_a_jour_source(); + else if (type_source === 0) mise_a_jour_parametres_generaux(); // Conditions horaires seulement... + } + } + } + + 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: (champ_formulaire_Type_source.currentIndex !== 0) + && (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_variable(); + } + } + + Shipheart_formulaire_ligne_separation { + haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse + } + } + + //------------------------------------------------------------------------------- + // Ligne de formulaire : ID_Variable + Rectangle { + id: ligne_variable + width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2) + height: visible ? hauteur_ligne_formulaire : 0 + color: "transparent" + visible: ligne_source.visible + && (champ_formulaire_Source.currentIndex !== 0) + && (type_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 de la source") + 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(); + 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_parametres_generaux(); + } + } + + Shipheart_formulaire_ligne_separation { + haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse + } + } + + //------------------------------------------------------------------------------- + // Ligne de formulaire : Test + Rectangle { + id: ligne_test + width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2) + height: visible ? hauteur_ligne_formulaire : 0 + color: "transparent" + visible: (ligne_variable.visible || + ( ligne_source.visible + && (champ_formulaire_Source.currentIndex !== 0) + && (type_source !== 0) + && (champ_formulaire_Variable.model.count <= 2)) ) + && (champ_formulaire_Variable.currentIndex !== 0) + && (type_source !== 0) + + Shipheart_formulaire_label { + text: qsTr("Déclenchement si") + 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 { + id: ligne_seuil + width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2) + height: visible ? hauteur_ligne_formulaire : 0 + color: "transparent" + visible: ligne_test.visible + && (champ_formulaire_Test.currentIndex !== 0) + && (type_source !== 0) + && (!flag_test_binaire) // Si on est sur un test binaire, il est inutile d'afficher le seuil... + + Shipheart_formulaire_label { // Label : + text: qsTr("Seuil de déclenchement") + width: parent.width * pourcentage_largeur_labels_formulaire + } + + Shipheart_formulaire_textfield { // Champ de saisie : + 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 + } + } + + //------------------------------------------------------------------------------- + // Ligne de formulaire : Tempo + Rectangle { + id: ligne_tempo + width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2) + height: visible ? hauteur_ligne_formulaire : 0 + color: "transparent" + visible: ligne_test.visible // NB : On remonte au niveau du Test car le Seuil peut ne pas être affiché (cas des tests binaires) + && (champ_formulaire_Test.currentIndex !== 0) + && (type_source !== 0) + + Shipheart_formulaire_label { // Label : + text: qsTr("Temporisation de déclenchement") + width: parent.width * pourcentage_largeur_labels_formulaire + } + + Shipheart_formulaire_textfield { // Champ de saisie : + id: champ_formulaire_Tempo + 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: qsTr("s") + width: parent.width * pourcentage_largeur_unites_formulaire + } + + Shipheart_formulaire_ligne_separation { + haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse + } + } + + //------------------------------------------------------------------------------- + // Ligne de formulaire : Visibilite + Rectangle { + id: ligne_visibilite + width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2) + height: visible ? hauteur_ligne_formulaire : 0 + color: "transparent" + visible: (ligne_tempo.visible) || (type_source === 0) // SDIR #240 + + Shipheart_formulaire_label { + text: qsTr("Masquer sur la page d'accueil") + width: parent.width * pourcentage_largeur_labels_formulaire + } + + Shipheart_formulaire_checkbox { + id: champ_formulaire_Visibilite + width: parent.width * (1 - pourcentage_largeur_labels_formulaire) + } + + Shipheart_formulaire_ligne_separation { + haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse + } + } + + //=========================================================== + // Séparation : + //=========================================================== + Rectangle { + width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2) + height: 20 + color: "transparent" + + Shipheart_formulaire_ligne_separation { + visible: zone_conditions_horaires.visible + haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse + epaisseur_ligne: 3 + force: shipheart_formulaire_ligne_separation_force_elevee + } + } + + Shipheart_titre_2 { + titre:qsTr("Conditions horaire"); + hauteur: shipheart_hauteur_bandeau_haut + visible: zone_conditions_horaires.visible + } + + + //=========================================================== + // Conditions horaires de la commande : + //=========================================================== + Rectangle { + id: zone_conditions_horaires + width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2) + height: grille_conditions_horaires.model.count * (hauteur_ligne_formulaire + spacing) + + color: "transparent" + visible: ((type_source !== 0) && (ligne_tempo.visible)) + || (type_source === 0) + + 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 + interactive: false // (cf SDIR #223). Comme on affiche tous les éléments du modèle, il est inutile de la laisser interactive (ce qui peut compliquer le défilement entre la liste principale et celle-ci). + + model: ListModel { } + delegate: Rectangle { + width: grille_conditions_horaires.cellWidth + height: grille_conditions_horaires.cellHeight + color: "transparent" + + Rectangle { + height: parent.height - 10 + width: parent.width - 10 + visible: (!model.bouton) || // On n'afficha pas le bouton '+'... + ((grille_conditions_horaires.model.count - 1) < shipheart_max_nombre_conditions_horaires_par_event) // ... si le nombre de conditions est trop important + 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.open(); + } + } + } + Text { + anchors.fill: parent + visible: (model.bouton) && // Affiche à la place du bouton '+'... + ((grille_conditions_horaires.model.count - 1) >= shipheart_max_nombre_conditions_horaires_par_event) // ... et si le nombre de conditions est trop important + verticalAlignment: Qt.AlignVCenter + horizontalAlignment: Qt.AlignHCenter + text: qsTr("Le nombre maximal de conditions horaires [%1] est atteint : ajout impossible...").arg(shipheart_max_nombre_conditions_horaires_par_event) + color: couleur_orange + font.pixelSize: 15 + opacity: 0.7 + } + } + + Label { + anchors.fill: parent + horizontalAlignment: Qt.AlignHCenter + verticalAlignment: Qt.AlignVCenter + visible: parent.count === 0 + text: qsTr("Aucune condition horaire n'est configurée pour cet évènement...") + color: couleur_rouge_transparent + font.pixelSize: 15 + font.bold: true + wrapMode: Label.Wrap + } + } // Fin de Gridview + } // Fin des conditions horaires + + + //=========================================================== + // Séparation : + //=========================================================== + Rectangle { + width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2) + height: 20 + color: "transparent" + + Shipheart_formulaire_ligne_separation { + visible: zone_conditions_horaires.visible + haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse + epaisseur_ligne: 3 + force: shipheart_formulaire_ligne_separation_force_elevee + } + } + + Shipheart_titre_2 { + titre:qsTr("Signalisation"); + hauteur: shipheart_hauteur_bandeau_haut + visible: zone_conditions_horaires.visible + } + + + //=========================================================== + // Alarmes : + //=========================================================== + + //------------------------------------------------------------------------------- + // Ligne de formulaire : Alarme_son + Rectangle { + id: ligne_alarme_son + width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2) + height: visible ? hauteur_ligne_formulaire : 0 + color: "transparent" + visible: zone_conditions_horaires.visible + + Shipheart_formulaire_label { + text: qsTr("Alarme sonore") + width: parent.width * pourcentage_largeur_labels_formulaire + } + + Shipheart_formulaire_checkbox { + id: champ_formulaire_Alarme_son + width: parent.width * (1 - pourcentage_largeur_labels_formulaire) + onCheckedChanged: { + if (!flag_init && champ_formulaire_Alarme_son.checked) // Si on veut une alarme sur son... + { + if (!champ_formulaire_Alarme_message.checked) + { + champ_formulaire_Alarme_message.checked = true; // ... il FAUT que l'alarme par message soit validée + + boite_information.niveau = 0; + boite_information.imageTitreSource = "/images/ampoule.png" + boite_information.message = qsTr("La validation des alarmes sonores a nécessité de valider également l'affichage des messages liés à cet évènement.

Cet affichage est en effet nécessaire au fonctionnement des alarmes sonores, afin de pouvoir les acquitter."); + boite_information.alignementMessage = Text.AlignHCenter + boite_information.open(); + } + } + } + } + + Shipheart_formulaire_ligne_separation { + haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse + } + } + + //------------------------------------------------------------------------------- + // Ligne de formulaire : Alarme_led + Rectangle { + id: ligne_alarme_led + width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2) + height: visible ? hauteur_ligne_formulaire : 0 + color: "transparent" + visible: ligne_alarme_son.visible + + Shipheart_formulaire_label { + text: qsTr("Alarme sur LED") + width: parent.width * pourcentage_largeur_labels_formulaire + } + + Shipheart_formulaire_checkbox { + id: champ_formulaire_Alarme_led + width: parent.width * (1 - pourcentage_largeur_labels_formulaire) + onCheckedChanged: { + if (!flag_init && champ_formulaire_Alarme_led.checked) // Si on veut une alarme sur led... + { + if (!champ_formulaire_Alarme_message.checked) + { + champ_formulaire_Alarme_message.checked = true; // ... il FAUT que l'alarme par message soit validée + + boite_information.niveau = 0; + boite_information.imageTitreSource = "/images/ampoule.png" + boite_information.message = qsTr("La validation des alarmes sur LED a nécessité de valider également l'affichage des messages liés à cet évènement.

Cet affichage est en effet nécessaire au fonctionnement des alarmes sur LED, afin de pouvoir les acquitter."); + boite_information.alignementMessage = Text.AlignHCenter + boite_information.open(); + } + } + } + } + + Shipheart_formulaire_ligne_separation { + haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse + } + } + + //------------------------------------------------------------------------------- + // Ligne de formulaire : Alarme_soutien + Rectangle { + id: ligne_alarme_soutien + width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2) + height: visible ? hauteur_ligne_formulaire : 0 + color: "transparent" +// visible: ligne_alarme_son.visible +visible: false + Shipheart_formulaire_label { + text: qsTr("Alarme sur sortie(s) de soutien") + width: parent.width * pourcentage_largeur_labels_formulaire + } + + Shipheart_formulaire_checkbox { + id: champ_formulaire_Alarme_soutien + width: parent.width * (1 - pourcentage_largeur_labels_formulaire) + onCheckedChanged: { + if (!flag_init && champ_formulaire_Alarme_led.checked) // Si on veut une alarme sur soutien... + { + if (!champ_formulaire_Alarme_message.checked) + { + champ_formulaire_Alarme_message.checked = true; // ... il FAUT que l'alarme par message soit validée + + boite_information.niveau = 0; + boite_information.imageTitreSource = "/images/ampoule.png" + boite_information.message = qsTr("La validation des alarmes sur sortie(s) de soutien a nécessité de valider également l'affichage des messages liés à cet évènement.

Cet affichage est en effet nécessaire au fonctionnement des alarmes sur sortie(s) de soutien, afin de pouvoir les acquitter."); + boite_information.alignementMessage = Text.AlignHCenter + boite_information.open(); + } + } + } + } + + Shipheart_formulaire_ligne_separation { + haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse + } + } + + //------------------------------------------------------------------------------- + // Ligne de formulaire : Alarme_source + Rectangle { + id: ligne_alarme_source + width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2) + height: visible ? hauteur_ligne_formulaire : 0 + color: "transparent" + visible: ligne_alarme_son.visible + + Shipheart_formulaire_label { + text: qsTr("Alarme sur la source") + width: parent.width * pourcentage_largeur_labels_formulaire + } + + Shipheart_formulaire_checkbox { + id: champ_formulaire_Alarme_source + width: parent.width * (1 - pourcentage_largeur_labels_formulaire) + } + + Shipheart_formulaire_ligne_separation { + haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse + } + } + + //------------------------------------------------------------------------------- + // Ligne de formulaire : Alarme_message + Rectangle { + id: ligne_alarme_message_checkbox + width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2) + height: visible ? hauteur_ligne_formulaire : 0 + color: "transparent" + visible: ligne_alarme_son.visible + Shipheart_formulaire_label { + text: qsTr("Affichage message sur ShipBase") + width: parent.width * pourcentage_largeur_labels_formulaire + } + + Shipheart_formulaire_checkbox { + id: champ_formulaire_Alarme_message + width: parent.width * (1 - pourcentage_largeur_labels_formulaire) + onCheckedChanged: { + if (!flag_init && !champ_formulaire_Alarme_message.checked) // Si l'alarme par message est dévalidée... + { + if (champ_formulaire_Alarme_son.checked + || champ_formulaire_Alarme_led.checked + || champ_formulaire_Alarme_soutien.checked) + { + champ_formulaire_Alarme_son.checked = false; // ... on est obligé de dévaliser l'alarme son + champ_formulaire_Alarme_led.checked = false; // ... et l'alarme LED + champ_formulaire_Alarme_soutien.checked = false; // ... et l'alarme soutien car on ne pourrait pas ensuite les acquitter... + + boite_information.niveau = 0; + boite_information.imageTitreSource = "/images/ampoule.png" + boite_information.message = qsTr("La dévalidation de l'affichage des messages a nécessité de dévalider également :
  • les alarmes sonores,
  • les alarmes sur led
  • et les alarmes sur sortie(s) de soutien

L'affichage de message est en effet nécessaire à leur fonctionnement, afin de pouvoir les acquitter."); + boite_information.alignementMessage = Text.AlignLeft + boite_information.open(); + } + } + } + } + + Shipheart_formulaire_ligne_separation { + haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse + } + } + + //------------------------------------------------------------------------------- + // Ligne de formulaire : Texte_message + Rectangle { + id: ligne_alarme_message + width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2) + implicitHeight: champ_formulaire_Texte_message.implicitHeight + height: visible ? undefined : 0 // Le 'undefined' permet de ne pas perturber le 'implicitHeight' en temps normal. Le 0 mpermet de forcer la hauteur si non visible. + color: "transparent" + visible: ligne_alarme_message_checkbox.visible + && champ_formulaire_Alarme_message.checked + + Shipheart_formulaire_label { + text: qsTr("Texte du message à afficher") + width: parent.width * pourcentage_largeur_labels_formulaire + } + + Shipheart_formulaire_textarea { + id: champ_formulaire_Texte_message + width: parent.width * (1 - pourcentage_largeur_labels_formulaire) + horizontalAlignment: Text.AlignJustify + wrapMode: Label.Wrap + } + } + + //------------------------------------------------------------------------------- + // Ligne de formulaire : Alarme_sms + Rectangle { + id: ligne_alarme_sms_checkbox + width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2) + height: visible ? hauteur_ligne_formulaire : 0 + color: "transparent" +// visible: ligne_alarme_son.visible +visible: false + + Shipheart_formulaire_label { + text: qsTr("Emission SMS") + width: parent.width * pourcentage_largeur_labels_formulaire + } + + Shipheart_formulaire_checkbox { + id: champ_formulaire_Alarme_sms + width: parent.width * (1 - pourcentage_largeur_labels_formulaire) + } + + Shipheart_formulaire_ligne_separation { + haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse + } + } + + //------------------------------------------------------------------------------- + // Ligne de formulaire : Texte_sms + Rectangle { + id: ligne_alarme_sms + width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2) + implicitHeight: champ_formulaire_Texte_sms.implicitHeight + height: visible ? undefined : 0 // Le 'undefined' permet de ne pas perturber le 'implicitHeight' en temps normal. Le 0 mpermet de forcer la hauteur si non visible. + color: "transparent" +// visible: ligne_alarme_sms_checkbox.visible +// && champ_formulaire_Alarme_sms_checkbox.checked +visible: false + + Shipheart_formulaire_label { + text: qsTr("Texte du SMS à envoyer") + width: parent.width * pourcentage_largeur_labels_formulaire + } + + Shipheart_formulaire_textarea { + id: champ_formulaire_Texte_sms + width: parent.width * (1 - pourcentage_largeur_labels_formulaire) + horizontalAlignment: Text.AlignJustify + wrapMode: Label.Wrap + } + } + + //------------------------------------------------------------------------------- + // Ligne de formulaire : Alarme_email + Rectangle { + id: ligne_alarme_email_checkbox + width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2) + height: visible ? hauteur_ligne_formulaire : 0 + color: "transparent" +// visible: ligne_alarme_son.visible +visible: false + + Shipheart_formulaire_label { + text: qsTr("Emission Email") + width: parent.width * pourcentage_largeur_labels_formulaire + } + + Shipheart_formulaire_checkbox { + id: champ_formulaire_Alarme_email + width: parent.width * (1 - pourcentage_largeur_labels_formulaire) + } + + Shipheart_formulaire_ligne_separation { + haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse + } + } + + //------------------------------------------------------------------------------- + // Ligne de formulaire : Texte_email + Rectangle { + id: ligne_alarme_email + width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2) + implicitHeight: champ_formulaire_Texte_email.implicitHeight + height: visible ? undefined : 0 // Le 'undefined' permet de ne pas perturber le 'implicitHeight' en temps normal. Le 0 mpermet de forcer la hauteur si non visible. + color: "transparent" +// visible: ligne_alarme_email_checkbox.visible +// && champ_formulaire_Alarme_email_checkbox.checked +visible: false + + Shipheart_formulaire_label { + text: qsTr("Texte de l'email à envoyer") + width: parent.width * pourcentage_largeur_labels_formulaire + } + + Shipheart_formulaire_textarea { + id: champ_formulaire_Texte_email + width: parent.width * (1 - pourcentage_largeur_labels_formulaire) + horizontalAlignment: Text.AlignJustify + wrapMode: Label.Wrap + } + } + + + + //=========================================================== + // Séparation : + //=========================================================== + Rectangle { + width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2) + height: 20 + color: "transparent" + + Shipheart_formulaire_ligne_separation { + id: ligne_separation_bas_alarme + visible: zone_conditions_horaires.visible + haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse + epaisseur_ligne: 3 + force: shipheart_formulaire_ligne_separation_force_elevee + } + } + + Shipheart_titre_2 { + titre:qsTr("Action sur circuits"); + hauteur: shipheart_hauteur_bandeau_haut + visible: zone_conditions_horaires.visible + width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2) + } + + + //=========================================================== + // Actions : + //=========================================================== + Rectangle { + width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2) + height: (grille_actions.model.count + 1) * (hauteur_ligne_formulaire + spacing) + + color: "transparent" + visible: zone_conditions_horaires.visible + + ListView { + id: grille_actions + + width: parent.width + height: parent.height + spacing: 5 + interactive: false // SDIR # 223 : Permet de bloquer le 'flickable' de la ListView et facilite le déroulé de la liste principale (sinon, on a deux listes, l'une dans l'autre et le déroulé peut-être compliqué parfois). + + model: ListModel { } + delegate: Rectangle { + id: bouton_action + + // Ligne de nom de famille : + Shipheart_titre_3 {titre:model.nom_famille; hauteur: hauteur_ligne_formulaire; visible: (model.nom_famille !== "")} + + width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2) + height: visible ? hauteur_ligne_formulaire : 0 + color: "transparent" + visible: ligne_alarme_son.visible + + Shipheart_formulaire_label { + visible: (model.nom_famille === "") + text: model.nom_circuit + width: parent.width * pourcentage_largeur_labels_formulaire + } + + Shipheart_formulaire_bouton { + visible: (model.nom_famille === "") + titre: (model.action === -2) ? // Affichage en clair de l'action configure pour ce circuit + qsTr("Aucune") : + (model.action === -1) ? + qsTr("Le circuit \"bascule\" ") : + (model.action === 0) ? + qsTr("Le circuit passe à OFF") : + qsTr("Le circuit passe à ON") + ( (model.action === 100) ? "" : (" @" + model.action + "%") ) + + actif: (model.action !== -2) // Affichzg du bouton en mode ACTIF si l'action est différente de Aucune + couleur_titre: (model.action !== -2) ? couleur_blanc_casse : couleur_gris_moyen + + width: parent.width * (1 - pourcentage_largeur_labels_formulaire) + x: parent.width * pourcentage_largeur_labels_formulaire + + MouseArea{ + anchors.fill : parent + onClicked: { + shipheart_clic(); + + // Ouverture de la boite de dialogue pour sélectionner une action sur le circuit : + if ((nombre_action_circuits < shipheart_max_nombre_action_circuits_par_event) || // Si le nombre d'actions sur circuits n'a pas atteint son maxi... + (model.action > -2)) // ... ou que le circuit sélectionné est déjà affecté à une action (autre que "Aucune") : + { + index_circuit_en_cours = index; // Permet de retrouver l'index à mettre à jour au retour du popup + boite_selection_action_circuit.nom_circuit = model.nom_circuit; // Permet l'affichage du nom du circuit dans le popup + boite_selection_action_circuit.mode_cde = model.mode_cde_circuit; // Permet d'afficher les valeurs intermédiaires de consigne (10%, 25%,...) dans le cas d'un circuit configuré en Variateur + boite_selection_action_circuit.action_en_cours = model.action; // Contient l'action actuellement configurée + boite_selection_action_circuit.open(); + } + // Ouverture de la boite d'info si le nombre d'actions sur circuits est trop élevée : + else + { + boite_information.niveau = 1; + boite_information.imageTitreSource = "/images/attention.png" + boite_information.message = qsTr("Le nombre de circuits commandés par un évènement est limité à %1.

Vous ne pouvez pas ajouter d'action sur un nouveau circuit avant d'en avoir supprimé préalablement.").arg(shipheart_max_nombre_action_circuits_par_event); + boite_information.alignementMessage = Text.AlignHCenter + boite_information.open(); + } + } + } + } + + Shipheart_formulaire_ligne_separation { + visible: (model.nom_famille === "") + haut_bas_hautbas: shipheart_formulaire_ligne_separation_basse + } + } + } + } // Fin de Actions + + } // 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: +// !clavier.active && // Si le clavier est déplié, // SDIR #255 + (champ_formulaire_Nom.text !== "") && // ... ou si le nom est vide, + (champ_formulaire_Type_source.currentIndex !== 0) && // ... ou si aucune affectation à un capteur n'a été faite, + ((type_source !== 0) || ((grille_conditions_horaires.model.count - 1) > 0)) // ... ou si l'affectations est "Condition horaire seule" et qu'aucune condition horaire n'a été complètement renseignée. + + Text { + anchors { + verticalCenter: parent.verticalCenter + horizontalCenter: parent.horizontalCenter + } + font.pixelSize: 20 + text: (id_event === 0) ? qsTr("Créer l'évènement") : qsTr("Enregistrer") + color: couleur_blanc_casse + } + MouseArea { + anchors.fill: parent + onClicked: { + shipheart_clic(); + if (id_event !== 0) mise_a_jour_event(); // Mise à jour des données saisies dans la BDD et reconfiguration par l'application pour prise en compte. + else creation_event(); + timer_tempo_reconfiguration.restart(); + } + } + } + + //....................................................... + // Bouton de suppression + //....................................................... + Rectangle { + width: parent.width + height: hauteur_bouton_droit + color: shipheart_couleur_fond_bouton + radius: shipheart_rayon_bouton + visible: (id_event !== 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(); + 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() + } + } + } + } + + //------------------------------------------------------- + // 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, + "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) + } + } + + + //------------------------------------------------------- + // Boite de sélection action circuit : + //------------------------------------------------------- + Shipheart_boite_dialogue_action_circuit { + id: boite_selection_action_circuit + + boutonAnnuler: true + boutonAnnulerTexte: "Annuler" + onClicked: { +//console.log("Le Bouton [" + bouton + "] est appuyé"); + if (bouton === shipheart_boite_dialogue_bouton_1) + { +//console.log("Action = " + action); + // Mise à jour du nombre d'action sur circuits : + if (grille_actions.model.get(index_circuit_en_cours).action === -2) // Si l'action précédente du circuit était "Aucune"... + { + if (action > -2) nombre_action_circuits ++; // ... et que la nouvelle est toggle ou une consigne, on incrémente le nb d'actions. + } + else // Si l'action précédente n'était PAS "Aucune"... + { + if (action === -2) nombre_action_circuits --; // ... et que la nouvelle est "Aucune", on décrémente le nb d'actions + } + + // Mise à jour de la nouvelle action dans la grille : + grille_actions.model.set(index_circuit_en_cours, {"action": action}); + } + + boite_selection_action_circuit.close(); // Dans tous les cas... (notamment si ANNULER) + } + } + + //------------------------------------------------------- + // 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; + +//console.log("Id de l'évènement = " + id_event); + + //--------------------------------------------------------------------------------------- + // Caractéristiques de l'évènement en cours : + //--------------------------------------------------------------------------------------- + nom = ""; + type_source = -1; + id_source = 0; + id_variable = 0; + test = 0; + seuil = 0; + tempo = 0; + champ_formulaire_Seuil.text = 0; + champ_formulaire_Tempo.text = 0; + champ_formulaire_Visibilite.checked = false; + conditions_horaires = ""; + champ_formulaire_Alarme_son.checked = false; + champ_formulaire_Alarme_led.checked = false; + champ_formulaire_Alarme_soutien.checked = false; + champ_formulaire_Alarme_source.checked = false; + champ_formulaire_Texte_sms.text = ""; + champ_formulaire_Alarme_sms.checked = false; + champ_formulaire_Texte_email.text = ""; + champ_formulaire_Alarme_email.checked = false; + champ_formulaire_Texte_message.text = ""; + champ_formulaire_Alarme_message.checked = false; + action_circuits = ""; + + if (id_event > 0) // Cas d'une modification de capteur existant : + { + req = 'SELECT '; + req += 'Visibilite, '; + req += 'Nom, '; + req += 'Type_Source, '; + req += 'ID_Source, '; + req += 'ID_Variable, '; + req += 'Test, '; + req += 'Seuil, '; + req += 'Tempo, '; + req += 'Conditions_horaires, '; + req += 'Alarme_son, '; + req += 'Alarme_led, '; + req += 'Alarme_soutien, '; + req += 'Alarme_source, '; + req += 'Alarme_message, '; + req += 'Alarme_sms, '; + req += 'Alarme_email, '; + req += 'Texte_message, '; + req += 'Texte_sms, '; + req += 'Texte_email, '; + req += 'Action_circuits '; + req += 'FROM TB_Events WHERE Cle_primaire=' + id_event + ' '; +//console.log("Requête = [ " + req + "; ]"); + res = bdd.requete_unique(req); + + // Récupération des données : + i = 0; + champ_formulaire_Visibilite.checked = (Number(res[i ++]) === 1) ? false : true; // Comme il s'agit d'un intitulé "masquage", on inverse la logique + nom = res[i ++]; + type_source = Number(res[i ++]); + id_source = Number(res[i ++]); + id_variable = Number(res[i ++]); + test = Number(res[i ++]); + seuil = Number(res[i ++]); + tempo = Number(res[i ++]); + conditions_horaires = res[i ++]; + champ_formulaire_Alarme_son.checked = (Number(res[i ++]) === 1) ? true : false; + champ_formulaire_Alarme_led.checked = (Number(res[i ++]) === 1) ? true : false; + champ_formulaire_Alarme_soutien.checked = (Number(res[i ++]) === 1) ? true : false; + champ_formulaire_Alarme_source.checked = (Number(res[i ++]) === 1) ? true : false; + champ_formulaire_Alarme_message.checked = (Number(res[i ++]) === 1) ? true : false; + champ_formulaire_Alarme_sms.checked = (Number(res[i ++]) === 1) ? true : false; + champ_formulaire_Alarme_email.checked = (Number(res[i ++]) === 1) ? true : false; + champ_formulaire_Texte_message.text = res[i ++]; + champ_formulaire_Texte_sms.text = res[i ++]; + champ_formulaire_Texte_email.text = res[i ++]; + action_circuits = res[i ++]; + } + + // Remplissage des modèles de type texte : + champ_formulaire_Nom.text = nom; + champ_formulaire_Seuil.text = seuil; + champ_formulaire_Tempo.text = tempo; + + // Remplissage des différents modèles, dans l'ordre des priorités : + mise_a_jour_type_source(); + + + 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": 0, + "texte": qsTr("Condition horaire seule"), + "actif": true }); + champ_formulaire_Type_source.model.append( { + "valeur": shipheart_source_mesure_circuit, + "texte": qsTr("Circuit"), + "actif": true }); + champ_formulaire_Type_source.model.append( { + "valeur": shipheart_source_mesure_capteur, + "texte": qsTr("Capteur"), + "actif": true }); + champ_formulaire_Type_source.model.append( { + "valeur": shipheart_source_mesure_reservoir, + "texte": qsTr("Réservoir"), + "actif": true }); + champ_formulaire_Type_source.model.append( { + "valeur": shipheart_source_mesure_batterie, + "texte": qsTr("Batterie"), + "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(); + else if (type_source === 0) mise_a_jour_parametres_generaux(); // Conditions horaires seulement... + + } + + + //============================================================================================================= + // 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": 0, + "texte": qsTr("Non défini"), + "actif": true }); + switch(type_source) + { + case shipheart_source_mesure_circuit: + 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_source_mesure_capteur: + 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_source_mesure_reservoir: + 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_source_mesure_batterie: + req = 'SELECT Cle_primaire, '; + req += 'Nom, '; + 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_Batteries '; + req += ' ORDER BY ABS(Priorite_affichage_accueil)'; + + 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 : + champ_formulaire_Source.model.append( { + "groupe": false, + "valeur": Number(res[0]), + "texte": res[1], + "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 !== 0) mise_a_jour_variable(); + + } + + + //============================================================================================================= + // MAJ de la variable à utiliser + //============================================================================================================= + 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]); + + // Recherche des informations de la varoable 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; + + // Appel du remplissage des modèles de niveau inférieur si cela est possible : + if (id_variable !== 0) mise_a_jour_parametres_generaux(); + } + + + //============================================================================================================= + // MAJ des paramètres généraux + //============================================================================================================= + function mise_a_jour_parametres_generaux() + { + var i; + + //----------------------------------------------- + // Test : + //----------------------------------------------- + champ_formulaire_Test.model.clear(); + champ_formulaire_Test.model.append( { + "valeur": 0, + "texte": qsTr("Non défini"), + "actif": true }); + if (flag_test_binaire) + { + champ_formulaire_Test.model.append( { + "valeur": 5, + "texte": qsTr("Passage à actif"), + "actif": true }); + champ_formulaire_Test.model.append( { + "valeur": 1, + "texte": qsTr("Passage à inactif"), + "actif": true }); + } + else + { + champ_formulaire_Test.model.append( { + "valeur": 1, + "texte": qsTr("< au seuil"), + "actif": true }); + champ_formulaire_Test.model.append( { + "valeur": 2, + "texte": qsTr("≤ au seuil"), + "actif": true }); + champ_formulaire_Test.model.append( { + "valeur": 3, + "texte": qsTr("= au seuil"), + "actif": true }); + champ_formulaire_Test.model.append( { + "valeur": 4, + "texte": qsTr("≥ au seuil"), + "actif": true }); + champ_formulaire_Test.model.append( { + "valeur": 5, + "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; + + + //----------------------------------------------- + // Condition horaire : + //----------------------------------------------- + var conditions; + var condition + var jour; + var heure; + var minute; + + grille_conditions_horaires.model.clear(); + + // Décomposition de la la chaine de conditions : + if (conditions_horaires !== "") + { + conditions = conditions_horaires.split(';'); + + for (i = 0; i < conditions.length; i ++) + { + condition = conditions[i].split('/'); + + if (condition.length === 3) + { + jour = Number(condition[0]); + heure = Number(condition[1]); + minute = Number(condition[2]); +//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, + "bouton": false }); + } + } + } + + // Ajout du bouton "+" : + // NB : le bouton est toujours créé [permet simplement qu'il soit réaffiché dynamiquement si on supprime des conditions], + // mais n'est affiché que si le nombre de conditions horaires n'est pas trop important. + grille_conditions_horaires.model.append( { "libelle": "+", "jour": 0, "heure": 0, "minute": 0, "bouton": true }); + + // Fin des condtions horaires + + mise_a_jour_actions(); + } + + + //============================================================================================================= + // MAJ du modèle des actions + //============================================================================================================= + function mise_a_jour_actions() + { + var req, res; + var nb; + var i; + var chaines; + var liste_circuits = []; + var liste_actions = []; + + + grille_actions.model.clear(); + nombre_action_circuits = 0; + + // Décomposition de la la chaine des actions sur les circuits : + if (action_circuits !== "") + { + chaines = action_circuits.split(';'); + i = 0; + for (var chaine of chaines) // Balayage de tous les couples 'ID_circuit/Action' + { + // Récupération des informations sur la commande : + var couple = chaine.split('/'); // Recherche des 2 éléments du couple 'ID_circuit/Action' + liste_circuits[i] = Number(couple[0]); + liste_actions[i] = Number(couple[1]); + i ++; + + if ((liste_actions[i] >= -1) && (liste_actions[i] <= 100)) nombre_action_circuits ++; + } + } + + // NB : l'utilisation de ABS dans la requete ci-dessous permet de trier correctement même les capteurs masqués... + req = 'SELECT Cle_primaire, '; + req += 'Nom, '; + req += 'Mode_commande, '; + 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)' +//console.log("req = [ " + req + " ;]"); + nb = bdd.requete(req); + + var prec_famille = ""; + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + // Recherche de l'index dans la liste des actions déjà existantes : + var index = liste_circuits.indexOf(Number(res[0])); // Si l'ID du circuit est trouvé dans la liste, l'index dans la liste est retournée. Sinon, le retour est -1. + + // Ajout de le ligne de famille : + if (prec_famille !== res[3]) + { + grille_actions.model.append( { + "nom_famille": res[3], + "id_circuit": 0, + "nom_circuit": "", + "mode_cde_circuit": 0, + "action": 0 }); + prec_famille = res[3]; + } + + // Entrée normale : + grille_actions.model.append( { + "nom_famille": "", + "id_circuit": Number(res[0]), + "nom_circuit": res[1], + "mode_cde_circuit": Number(res[2]), + "action": (index !== -1) ? liste_actions[index] : -2 }); // '-2' est la valeur de "Aucune action" + } + } + } + + + //============================================================================================================= + // Mise à jour des valeurs saisies de l'évènement + //============================================================================================================= + function mise_a_jour_event() + { + var req, res; + var i; + var flag_first; + + nom = champ_formulaire_Nom.text; +// type_source = champ_formulaire_Type_source.model.get(champ_formulaire_Type_source.currentIndex).valeur; +// id_source = champ_formulaire_Source.model.get(champ_formulaire_Source.currentIndex).valeur; +// id_variable = champ_formulaire_Variable.model.get(champ_formulaire_Variable.currentIndex).valeur; +// test = champ_formulaire_Test.model.get(champ_formulaire_Test.currentIndex).valeur; + seuil = champ_formulaire_Seuil.text; + tempo = champ_formulaire_Tempo.text; + + //---------------------------------------------------- + // Traitement particulier des Tests de type binaire : + if (flag_test_binaire) seuil = 0.5 + + //---------------------------------------------------- + // Création de la chaine de conditions horaires, si besoin : + conditions_horaires = ""; + if ((grille_conditions_horaires.model.count - 1) > 0) // Le '-1' permet de neutraliser le bouton '+' qui est toujours présents (mais parfois, pas affiché) + { + 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; + } + } + } + else console.log("Aucune condition horaire n'a été configurée. La chaine 'Conditions_horaires' est laissée vide.") +//console.log("Conditions horaires = [ " + conditions_horaires + " ]") + + //---------------------------------------------------- + // Calcul de la chaine des actions sur les circuits : + action_circuits = ""; + flag_first = true; + for (i = 0; i < grille_actions.model.count; i ++) // Parcours du modèle existant + { + if ((grille_actions.model.get(i).nom_famille === "") && // On ne prend pas en compte les entêtes de famille... + (grille_actions.model.get(i).action !== -2)) // ... ni les circuits pour lesquels l'action vaut '-2', qui signifie "Aucune action" + { + if (flag_first) flag_first = false; + else action_circuits += ";" + + action_circuits += grille_actions.model.get(i).id_circuit; + action_circuits += "/"; + action_circuits += grille_actions.model.get(i).action; + } + } +//console.log("Action sur circuits = [ " + action_circuits + " ]") + + //---------------------------------------------------- + // Mise à jour de l'évènement dans la BDD : + req = 'UPDATE TB_Events SET '; + req += ' Visibilite=' + (champ_formulaire_Visibilite.checked ? 0 : 1) + ', '; // Comme il s'agit d'un intitulé "masquage", on inverse la logique + req += ' Nom="' + nom + '", '; + req += ' Type_source=' + type_source + ', '; + req += ' ID_Source=' + id_source + ', '; + req += ' ID_Variable=' + id_variable + ', '; + req += ' Test=' + test + ', '; + req += ' Seuil=' + seuil + ', '; + req += ' Tempo=' + tempo + ', '; + req += ' Conditions_horaires="' + conditions_horaires + '", '; + req += ' Alarme_son=' + (champ_formulaire_Alarme_son.checked ? 1 : 0) + ', '; + req += ' Alarme_led=' + (champ_formulaire_Alarme_led.checked ? 1 : 0) + ', '; + req += ' Alarme_soutien=' + (champ_formulaire_Alarme_soutien.checked ? 1 : 0) + ', '; + req += ' Alarme_source=' + (champ_formulaire_Alarme_source.checked ? 1 : 0) + ', '; + req += ' Alarme_message=' + (champ_formulaire_Alarme_message.checked ? 1 : 0) + ', '; + req += ' Alarme_sms=' + (champ_formulaire_Alarme_sms.checked ? 1 : 0) + ', '; + req += ' Alarme_email=' + (champ_formulaire_Alarme_email.checked ? 1 : 0) + ', '; + req += ' Texte_message="' + champ_formulaire_Texte_message.text + '", '; + req += ' Texte_sms="' + champ_formulaire_Texte_sms.text + '", '; + req += ' Texte_email="' + champ_formulaire_Texte_email.text + '", '; + req += ' Action_circuits="' + action_circuits + '" '; + req += ' WHERE Cle_primaire=' + id_event + ' ' +//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); + + } + + //============================================================================================================= + // Création de l'évènement + //============================================================================================================= + function creation_event() + { + var req, res; + var i; + var flag_first; + + nom = champ_formulaire_Nom.text; +// type_source = champ_formulaire_Type_source.model.get(champ_formulaire_Type_source.currentIndex).valeur; +// id_source = champ_formulaire_Source.model.get(champ_formulaire_Source.currentIndex).valeur; +// id_variable = champ_formulaire_Variable.model.get(champ_formulaire_Variable.currentIndex).valeur; +// test = champ_formulaire_Test.model.get(champ_formulaire_Test.currentIndex).valeur; + seuil = champ_formulaire_Seuil.text; + tempo = champ_formulaire_Tempo.text; + + //---------------------------------------------------- + // Traitement particulier des Tests de type binaire : + if (flag_test_binaire) seuil = 0.5 // SDIR #335 + + //---------------------------------------------------- + // Création de la chaine de condition horaire, si besoin : + conditions_horaires = ""; + if ((grille_conditions_horaires.model.count - 1) > 0) // Le '-1' permet de neutraliser le bouton '+' qui est toujours présents (mais parfois, pas affiché) + { + 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; + } + } + } + else console.log("Aucune condition horaire n'a été configurée. La chaine 'Conditions_horaires' est laissée vide.") +//console.log("Conditions horaires = [ " + conditions_horaires + " ]") + + + //---------------------------------------------------- + // Calcul de la chaine des actions sur les circuits : + action_circuits = ""; + flag_first = true; + for (i = 0; i < grille_actions.model.count; i ++) // Parcours du modèle existant + { + if ((grille_actions.model.get(i).nom_famille === "") && // On ne prend pas en compte les entêtes de famille... + (grille_actions.model.get(i).action !== -2)) // ... ni les circuits pour lesquels l'action vaut '-2', qui signifie "Aucune action" + { + if (flag_first) flag_first = false; + else action_circuits += ";" + + action_circuits += grille_actions.model.get(i).id_circuit; + action_circuits += "/"; + action_circuits += grille_actions.model.get(i).action; + } + } +//console.log("Action sur circuits = [ " + action_circuits + " ]") + + + //---------------------------------------------------- + // Création dans la BDD : + req = 'INSERT INTO TB_Events ('; + req += ' Visibilite, '; + req += ' Nom, '; + req += ' Type_source, '; + req += ' ID_Source, '; + req += ' ID_Variable, '; + req += ' Test, '; + req += ' Seuil, '; + req += ' Tempo, '; + req += ' Conditions_horaires, '; + req += 'Alarme_son, '; + req += 'Alarme_led, '; + req += 'Alarme_soutien, '; + req += 'Alarme_source, '; + req += 'Alarme_message, '; + req += 'Alarme_sms, '; + req += 'Alarme_email, '; + req += 'Texte_message, '; + req += 'Texte_sms, '; + req += 'Texte_email, '; + req += 'Action_circuits) ' + req += ' VALUES ('; + req += ' ' + (champ_formulaire_Visibilite.checked ? 0 : 1); // Comme il s'agit d'un intitulé "masquage", on inverse la logique + req += ', "' + nom + '"'; + req += ', ' + type_source; + req += ', ' + id_source; + req += ', ' + id_variable ; + req += ', ' + test + ' '; + req += ', ' + seuil + ' '; + req += ', ' + tempo + ' '; + req += ', "' + conditions_horaires + '"'; + req += ', ' + (champ_formulaire_Alarme_son.checked ? 1 : 0); + req += ', ' + (champ_formulaire_Alarme_led.checked ? 1 : 0); + req += ', ' + (champ_formulaire_Alarme_soutien.checked ? 1 : 0); + req += ', ' + (champ_formulaire_Alarme_source.checked ? 1 : 0); + req += ', ' + (champ_formulaire_Alarme_message.checked ? 1 : 0); + req += ', ' + (champ_formulaire_Alarme_sms.checked ? 1 : 0); + req += ', ' + (champ_formulaire_Alarme_email.checked ? 1 : 0); + req += ', "' + champ_formulaire_Texte_message.text + '"'; + req += ', "' + champ_formulaire_Texte_sms.text + '"'; + req += ', "' + champ_formulaire_Texte_email.text + '"'; + req += ', "' + action_circuits + '"'; + req += ') '; +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); + } + + + //============================================================================================================= + // Suppression de l'évènement + //============================================================================================================= + function suppression_event() + { + var req; + + // Suppression de l'évènement : + req = 'DELETE FROM TB_Events WHERE Cle_primaire=' + id_event + ' '; +//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
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); + } + + +} + diff --git a/config_fichiers.qml b/config_fichiers.qml new file mode 100644 index 0000000..13e64ad --- /dev/null +++ b/config_fichiers.qml @@ -0,0 +1,2148 @@ +//======================================================================================================================================================================== +// CONFIG_FICHIER.QML +// Ce fichier permet de gérer d'une part des fichier sur ShipBase, dans un répertpoire interne et, d'autre part, des fichiers sur une clé externe. +// Il peut être utilisé dans plusieurs configurations différentes : +// - image d'accueil ('shipheart_mode_config_fichiers_image_accueil') +// - silhouette d'une page personnalisée ('shipheart_mode_config_fichiers_silhouette') +// - rapports d'installation ('shipheart_mode_config_fichiers_rapports') +// - Sauvegardes ('shipheart_mode_config_fichiers_sauvegardes') +// Le choix de l'un de ces modes se fait en passant la propriété 'mode_config_fichiers' qui peut prendre l'une des valeurs indquées ci-dessus. +//======================================================================================================================================================================== +import QtQuick 2.12 +import QtQuick.Controls 2.12 +import Qt.labs.folderlistmodel 2.12 + +import qt.koriolan.shipheart 1.0 +import"fonctions.js" as Fonctions + + + +Shipheart_page { + id: page_config_fichiers + + + // Mis en forme : + readonly property double pourcentage_largeur_colonne_gauche: 0.40 + readonly property double pourcentage_largeur_colonne_centre: (1 - pourcentage_largeur_colonne_gauche - pourcentage_largeur_colonne_droite) + readonly property double pourcentage_largeur_colonne_droite: 0.40 + readonly property double espace_colonnes_principales: 20 + readonly property double espace_colonnes_secondaires: 10 + readonly property double affichage_hauteur_utile: shipheart_hauteur_page - shipheart_hauteur_bandeau_haut - shipheart_hauteur_bandeau_bas + readonly property double pourcentage_largeur_labels_formulaire: 0.4 + readonly property double pourcentage_bandeau_bas_largeur_zone_retour: 1 + + readonly property int hauteur_ligne_formulaire: 60 + readonly property int hauteur_bouton: 80 + + readonly property int periode_init_raffraichissement_parametres: 500 // En ms Cette durée est volontairement longue car cela permet l'affichage du fond de la page avant la première mise à jour (qui peut être "bloquante" sir la clé est déjà là est qu'un montage est demandé) + readonly property int periode_raffraichissement_parametres_montage_port_usb: 1 // En ms Doit être une valeur différente des autres tempo utilisées + readonly property int periode_raffraichissement_parametres: 1000 // En ms + readonly property int step_timer_appui_long: 30 // en ms + + readonly property int etat_cle_absente: 0 + readonly property int etat_cle_presente: 1 + readonly property int etat_cle_presente_partition: 2 + readonly property int etat_cle_presente_montee: 3 + readonly property int etat_cle_presente_demontee: 4 + + + + // Données : + property bool flag_init: true + property int mode_config_fichiers: shipheart_mode_config_fichiers_inconnu + property int id_page: 0 + property int valeur_timer_appui_long: 0 + property int port_usb_en_cours: -1 + property int etat_initial_port_usb_avant: -1 + property int etat_initial_port_usb_arrière: -1 + property int etat_cle: 0 // Cf les différente svaleurs possibles ci-dessus ('etat_cle_absente', etc...) + property bool flag_sortie_en_attente: false; + property bool flag_new_file_en_attente: false; + property string sous_repertoire_cle: "" + property string sens: "" // Soit vide, soit "cle_vers_shipheart", soit "shipheart_vers_cle" + property int index_fichier_local_actif: -1 + property int index_fichier_cle_actif: -1 + property string nom_fichier_local_selectionne: "" + + property string titre_page: "" + property string nom_repertoire_local: "" + property bool flag_selection_locale_multiple_enabled: true + + property string texte_bouton_action_sens_vide: "" + property string texte_bouton_action_sens_non_vide: "" + property int max_taille_fichier: 0 + property string texte_types_fichiers_valides: "" + + + + // Modèles : + // Note : les modèles chargés dans 'main.qml' n'ont pas à être rechargés dans les pages suivantes + + + //=========================================================== + // Modèles de lecture de répertoire : + // Attention : pour que les modèles maintiennent à jour leur données, + // il faut que le répertoire cible (le contenant) ne soient pas modifié. + // Par exemple, le fait de supprimer le répertoire (pour le vider) + // puis de le recréer avec le même nom fait perdre le lien au modèle + // qui ne se met alors plus à jour... + //=========================================================== + FolderListModel { + id: repertoire_local +// nameFilters: ["*.png", "*.PNG", "*.jpg", "*.JPG", "*.jpeg", "*.JPEG"] +// nameFilters: ["*.enc"] + showDirs: false + sortField: FolderListModel.Time // Tri sur l'heure du fichier + folder: "file://" + nom_repertoire_local // Pour un fichier, il faut obligatoirement ajouter 'file:' devant. Ou 'qrc:' pour une URL. Le message d'alerte de QT Creator est toujours là... + + onStatusChanged: { + if ((status === FolderListModel.Ready) && + (!flag_init) && + (!boite_information.opened)) mise_a_jour_modele_fichiers_locaux(); + } + + onRowsInserted: (parent, first, last) => { // Ce sont les 3 arguments du signel : le parent n'est pas utulisé en l'occurence car FolderListModel est un modèle "à plat" mais les 2ème et 3ème sont les index des nouveaux enregistrement dans le répertoire. + if ((!flag_init) && (flag_new_file_en_attente)) + { + var nom_fichier_cree; + + flag_new_file_en_attente = false; // Pour utilisation ultérieure + mise_a_jour_modele_fichiers_locaux(); // Comme 'onRowsInserted' est généralement déclenché AVANT OnStatusChanged, on fait une mise à jour du modèle sinon on ne trouvera pas le nouveau fichier créé à la fin de cette fonction... + busy_indicator_centre.running = false; // Arrêt du sablier + + var i; + for (i = first; i <= last; i ++) // En pratique, si on attend un nouveau fichier en cours de cration, on ne va probablement recevoir qu'UN fichier (et si plusieurs, on ne traitera que le dernier...) + { + nom_fichier_cree = repertoire_local.get(i, "fileName").replace(/\s\s+/g, ''); // Le REPLACE permet la suppression de tous les espaces, TAB, etc.... + } + + // Affichage du fichier généré dans le popup d'info : + switch(mode_config_fichiers) // Le message à afficher dépend du contexte d'utilisation du fichier : + { + //---------------------------------------------------- + case shipheart_mode_config_fichiers_rapports: + { + boite_information.message = qsTr("Le rapport d'installation

%1

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

%1

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

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

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

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

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

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.

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,
dont %3 configuré(s) comme \"masqué(s)\".

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); + } + +} + + diff --git a/config_installateur.qml b/config_installateur.qml new file mode 100644 index 0000000..be1e0c0 --- /dev/null +++ b/config_installateur.qml @@ -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); + + } + +} + diff --git a/config_koriolan.qml b/config_koriolan.qml new file mode 100644 index 0000000..9c516e2 --- /dev/null +++ b/config_koriolan.qml @@ -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 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 + textFormat: Text.RichText + 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 modifier les informations du module : + 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: qsTr("Modifier") + color: couleur_blanc_casse + } + MouseArea { + anchors.fill: parent + onClicked: { + shipheart_clic(); + stackView.push("config_module_modification.qml", {"adresse_module": adresse_module}) + } + } + } + + //------------------------------------------------ + // 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_module !== 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); + } + } + } + + //------------------------------------------------ + // Bouton de suppression : + Rectangle { + width: parent.width + height: hauteur_bouton_droit + color: shipheart_couleur_fond_bouton + radius: shipheart_rayon_bouton + visible: !clavier.active && (type_module !== shipheart_type_module_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_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(); + stackView.pop(); // Retour à la page de config des circuits + } + else timer_tempo_reconfiguration.interval = 100 // Tempo plus courte pour les lectures suivantes + +//console.log("Passage dans le timer_tempo_reconfiguration") + } + } + } + } + + + //------------------------------------------------------- + // 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() + } + } + } + } + + //------------------------------------------------------- + // 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 : + suppression_module(); // 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 + break; + + case shipheart_boite_dialogue_bouton_2: // Annuler : on revient sur la page pour que l'on puisse enregistrer. + break; + + default: + } + boite_validation_securisee.close(); + } + } + + + // Modèle utilisé pour stocker les usages (directs et indirects) liés à ce module : + // Note : ce modèle n'est pas affiché directement (c'est pourquoi il n'est pas intégré à un ListView par exemple) + // mais il sert à générer le texte d'utilisation du module puis, en cas de demande de suppression du module, + // à lancer les suppressions en cascades. + ListModel { + id: modele_usage + } + + + + // 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 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", + "Nom", + "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_config 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_module = 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_module === shipheart_type_module_shipbase) titre_page = qsTr("Paramètres du module [%1]").arg(Fonctions.nom_type_module(type_module)) + else titre_page = qsTr("Paramètres du module [%1] à l'adresse [%2]").arg(Fonctions.nom_type_module(type_module)).arg(Number(res[i])); + continue; + case "Nom" : nom_champ = qsTr("Nom du module"); 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, "
"); // Remplace les '\n' par '
'. 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. + } +*/ + + //================================================== + // Usage du module : + modele_grille_informations.append({"nom_champ": qsTr("Affectations"), "valeur_champ": usage_module()}); + + + //========================================================= + // Cas particulier des champs Emplacement et Commentaires à faire apparaitre à la fin : + req = 'SELECT Emplacement, Commentaires FROM TB_Modules_config WHERE Adresse_k_bus=' + adresse_module + ' '; + res = bdd.requete_unique(req); + + modele_grille_informations.append({"nom_champ": qsTr("Emplacement du module à bord"), "valeur_champ": (res[0].length === 0) ? "--" : res[0].replace(/\n/g, "
") }); + + modele_grille_informations.append({"nom_champ": qsTr("Commentaires"), "valeur_champ": (res[1].length === 0) ? "--" : res[1].replace(/\n/g, "
") }); + + mise_a_jour(); + + flag_init = false; + } + + + //============================================================================================================= + // Mise à jour des informations variables + //============================================================================================================= + function mise_a_jour() + { + var req, res; + + 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); + } + + + //============================================================================================================= + // Usage du module + // Liste tous les éléments (circuits, capteurs, réservoirs, batteries, events) qui sont affectés par le module + // en cours. Cette liste est d'abord utilisée pour afficher les éléments liés au module. Elle est aussi utilisée + // en cas de suppression du module pour aleter sur les effets + supprimer tous les éléments liés si la suppression + // est confirmée. + //============================================================================================================= + function usage_module() + { + var req, res; + var nb; + var i; + var s; + + + modele_usage.clear(); + + + //----------------------------------------------------------------------------------- + // Recherche des affectations directe d'un objet au module en cours : + // La recherche dépend du type de module en cours (on ne cherche pas + // les circuits sur un ShipBS par exemple). + // Note : dans cette partie, on utilise directement des appels à 'modele.append()' ou + // 'modele.set()' plutôt que 'ajout_modele_usage()' car on contourne le principe + // d'ajout dans la liste en créant des entrées "fake" (avec id=-1 par exemple) + // et la fonction d'ajout utilisée plus bas ne fonctionnerait pas telle qu'elle ; + // sans compter qu'elle est fait e pour des ajouts et non des modifications. Ce + // focntionnement ne pose pas de soucis car, dans cette partie, il ne doit pas y + // avoir de risque de doublons. + //----------------------------------------------------------------------------------- + switch(type_module) + { + //======================================================== + case shipheart_type_module_shippower812: + case shipheart_type_module_shippower4AC: + case shipheart_type_module_shippower8DC: + + //---------------------------------------------------- + // Init du nom des circuits affectés au module : + // (Ne sert que pour l'affichage) + if ((type_module === shipheart_type_module_shippower812) || (type_module === shipheart_type_module_shippower8DC)) nb = shipheart_max_circuits_par_module_sp8xx; + else nb = shipheart_max_circuits_par_module_sp4ac; + for (i = 0; i < nb; i ++) + { + modele_usage.append({ + "type": 0, // Ce type n'existe pas... + "id": -1, // Cet ID n'existe pas... + "libelle": qsTr("Circuit #%1 : ---").arg(i+1) }); + } + + modele_usage.append({ + "type": 0, // Ce type n'existe pas... + "id": -1, // Cet ID n'existe pas... + "libelle": "" }); // Ligne vide utilisée pour l'affichage + + + //---------------------------------------------------- + // Recherche des circuits affectés à ce n° de module : + req = 'SELECT Cle_primaire, No_circuit, Nom, ID_Circuit_esclave FROM TB_Circuits WHERE Adresse_module=' + adresse_module + ' ORDER BY No_circuit '; +//console.log("req = [ " + req + "; ]"); + nb = bdd.requete(req); + + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + // Mise à jour du circuit dans la liste des usages : + modele_usage.set( Number(res[1]), { + "type": shipheart_type_source_circuits, + "id": Number(res[0]), + "libelle": qsTr("‣ Circuit #%1 : %2").arg(Number(res[1])).arg(res[2]) + ((Number(res[3] >= 0) ? "" : " " + qsTr("[renfort]") + "")) }); + } + else break; + } + + + //---------------------------------------------------- + // Recherche des capteurs affectés à ce module : + req = 'SELECT Cle_primaire, Nom FROM TB_Capteurs WHERE Adresse_module=' + adresse_module + ' '; +//console.log("req = [ " + req + "; ]"); + nb = bdd.requete(req); + + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + // Ajout du capteur à la liste des usages : + modele_usage.append({ + "type": shipheart_type_source_capteurs, + "id": Number(res[0]), + "libelle": qsTr("‣ Capteur : %1").arg(res[1]) }); + } + else break; + } + + break; + + //======================================================== + case shipheart_type_module_shipBS: + + + //---------------------------------------------------- + // Init du nom de la batterie affectée au module : + // (Ne sert que pour l'affichage) + modele_usage.append({ + "type": 0, // Ce type n'existe pas... + "id": -1, // Cet ID n'existe pas... + "libelle": qsTr("Parc de batteries : ---") }); + + modele_usage.append({ + "type": 0, // Ce type n'existe pas... + "id": -1, // Cet ID n'existe pas... + "libelle": "" }); // Ligne vide utilisée pour l'affichage + + //---------------------------------------------------- + // Recherche de la batterie affecté à ce n° de module : + req = 'SELECT Cle_primaire, Nom FROM TB_Batteries WHERE Type_entrees=' + shipheart_batteries_type_entrees_ibs + ' AND Adresse_module=' + adresse_module + ' '; +//console.log("req = [ " + req + "; ]"); + nb = bdd.requete(req); + + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + // Mise à jour de la batterie dans la liste des usages : + modele_usage.set( 0, { + "type": shipheart_type_source_batteries, + "id": Number(res[0]), + "libelle": qsTr("‣ Parc de batteries : %1").arg(res[1]) }); + } + else break; + } + + //---------------------------------------------------- + // Recherche des capteurs affectés à ce module : + req = 'SELECT Cle_primaire, Nom FROM TB_Capteurs WHERE Adresse_module=' + adresse_module + ' '; +//console.log("req = [ " + req + "; ]"); + nb = bdd.requete(req); + + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + // Ajout du capteur à la liste des usages : + modele_usage.append({ + "type": shipheart_type_source_capteurs, + "id": Number(res[0]), + "libelle": qsTr("‣ Capteur : %1").arg(res[1]) }); + } + else break; + } + + + break; + + //======================================================== + case shipheart_type_module_shipbase: // On ne peut pas supprimer ShipBase.... + default: + break; + } + + + + + //----------------------------------------------------------------------------------- + // Traitement récursif(*) de toutes les entrées de la liste des usages : + // (*) : chaque recherche identifiant un élément lié au module en cours ajoute l'élément + // à la liste en cours d'analyse. Le nouvel élément sera donc lui aussi analysé à la fin + // pour déterminer si d'autres éléments lui sont liés. + // NB : On vérifie à chaque ajout si l'élément n'est pas déjà présent afin d'éviter les risques + // de boucles infinies... + //----------------------------------------------------------------------------------- + for (s = 0; s < modele_usage.count; s++) + { + +//console.log("Boucle sur type:" + modele_usage.get(s).type + " / id:" + modele_usage.get(s).id); + switch(modele_usage.get(s).type) + { + //====================================== + case shipheart_type_source_circuits: + + //------------------------------------------------------------------------------------------------ + // Recherche de events qui utilisent le circuit comme déclencheur OU dans leurs 'Actions_circuits' : + req = 'SELECT Cle_primaire, Nom FROM TB_Events WHERE '; + req += ' (Type_source=' + shipheart_type_source_circuits + ' AND ID_Source=' + modele_usage.get(s).id + ') '; + req += ' OR '; + req += ' (Action_circuits LIKE "' + modele_usage.get(s).id + '/%")'; // Cas où le n° d'ID apparait en première position dans la liste (ex. avec '123' : "123/1;12/1;..." + req += ' OR '; + req += ' (Action_circuits LIKE "%;' + modele_usage.get(s).id + '/%")'; // Cas où le n° d'ID n'est pas en première position dans la liste (ex. avec '123' : "5/1;123/1;..." +//console.log("Requête = [ " + req + "; ]") + nb = bdd.requete(req); + + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + // Ajout de l'event à la liste des usages : + ajout_modele_usage(shipheart_type_source_events, + Number(res[0]), + qsTr("‣ Evènement : %1").arg(res[1]) ); + } + else break; + } + + //------------------------------------------------------------------------------------------------ + // Recherche de capteurs qui utilisent le circuit : + req = 'SELECT Cle_primaire, Nom FROM TB_Capteurs WHERE '; + req += ' (Type_entrees=' + shipheart_capteur_type_entrees_calculee_booleen + ' OR Type_entrees=' + shipheart_capteur_type_entrees_calculee_numerique + ') '; + req += ' AND '; + req += ' (Entrees LIKE "%/' + shipheart_type_source_circuits + ':' + modele_usage.get(s).id + '/%")'; +//console.log("Requête = [ " + req + "; ]") + nb = bdd.requete(req); + + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + // Ajout du capteur à la liste des usages : + ajout_modele_usage(shipheart_type_source_capteurs, + Number(res[0]), + qsTr("‣ Capteur : %1").arg(res[1]) ); + } + else break; + } + + break; + + //====================================== + case shipheart_type_source_capteurs: + + //------------------------------------------------------------------------------------------------ + // Recherche de events qui utilisent le capteur comme déclencheur : + req = 'SELECT Cle_primaire, Nom FROM TB_Events WHERE '; + req += ' (Type_source=' + shipheart_type_source_capteurs + ' AND ID_Source=' + modele_usage.get(s).id + ') '; +//console.log("Requête = [ " + req + "; ]") + nb = bdd.requete(req); + + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + // Ajout de l'event à la liste des usages : + ajout_modele_usage(shipheart_type_source_events, + Number(res[0]), + qsTr("‣ Evènement : %1").arg(res[1]) ); + } + else break; + } + + //------------------------------------------------------------------------------------------------ + // Recherche de capteurs qui utilisent le capteur : + req = 'SELECT Cle_primaire, Nom FROM TB_Capteurs WHERE '; + req += ' (Type_entrees=' + shipheart_capteur_type_entrees_calculee_booleen + ' OR Type_entrees=' + shipheart_capteur_type_entrees_calculee_numerique + ') '; + req += ' AND '; + req += ' (Entrees LIKE "%/' + shipheart_type_source_capteurs + ':' + modele_usage.get(s).id + '/%")'; +//console.log("Requête = [ " + req + "; ]") + nb = bdd.requete(req); + + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + // Ajout du capteur à la liste des usages : + ajout_modele_usage(shipheart_type_source_capteurs, + Number(res[0]), + qsTr("‣ Capteur : %1").arg(res[1]) ); + } + else break; + } + + break; + + //====================================== + case shipheart_type_source_reservoirs: + + //------------------------------------------------------------------------------------------------ + // Recherche de events qui utilisent le réservoir comme déclencheur : + req = 'SELECT Cle_primaire, Nom FROM TB_Events WHERE '; + req += ' (Type_source=' + shipheart_type_source_reservoirs + ' AND ID_Source=' + modele_usage.get(s).id + ') '; +//console.log("Requête = [ " + req + "; ]") + nb = bdd.requete(req); + + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + // Ajout de l'event à la liste des usages : + ajout_modele_usage(shipheart_type_source_events, + Number(res[0]), + qsTr("‣ Evènement : %1").arg(res[1]) ); + } + else break; + } + + //------------------------------------------------------------------------------------------------ + // Recherche de capteurs qui utilisent le réservoir : + req = 'SELECT Cle_primaire, Nom FROM TB_Capteurs WHERE '; + req += ' (Type_entrees=' + shipheart_capteur_type_entrees_calculee_booleen + ' OR Type_entrees=' + shipheart_capteur_type_entrees_calculee_numerique + ') '; + req += ' AND '; + req += ' (Entrees LIKE "%/' + shipheart_type_source_reservoirs + ':' + modele_usage.get(s).id + '/%")'; +//console.log("Requête = [ " + req + "; ]") + nb = bdd.requete(req); + + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + // Ajout du capteur à la liste des usages : + ajout_modele_usage(shipheart_type_source_capteurs, + Number(res[0]), + qsTr("‣ Capteur : %1").arg(res[1]) ); + } + else break; + } + + break; + + //====================================== + case shipheart_type_source_batteries: + + //------------------------------------------------------------------------------------------------ + // Recherche de events qui utilisent la batterie comme déclencheur : + req = 'SELECT Cle_primaire, Nom FROM TB_Events WHERE '; + req += ' (Type_source=' + shipheart_type_source_batteries + ' AND ID_Source=' + modele_usage.get(s).id + ') '; +//console.log("Requête = [ " + req + "; ]") + nb = bdd.requete(req); + + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + // Ajout de l'event à la liste des usages : + ajout_modele_usage(shipheart_type_source_events, + Number(res[0]), + qsTr("‣ Evènement : %1").arg(res[1]) ); + } + else break; + } + + //------------------------------------------------------------------------------------------------ + // Recherche de capteurs qui utilisent la batterie : + req = 'SELECT Cle_primaire, Nom FROM TB_Capteurs WHERE '; + req += ' (Type_entrees=' + shipheart_capteur_type_entrees_calculee_booleen + ' OR Type_entrees=' + shipheart_capteur_type_entrees_calculee_numerique + ') '; + req += ' AND '; + req += ' (Entrees LIKE "%/' + shipheart_type_source_batteries + ':' + modele_usage.get(s).id + '/%")'; +//console.log("Requête = [ " + req + "; ]") + nb = bdd.requete(req); + + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + // Ajout du capteur à la liste des usages : + ajout_modele_usage(shipheart_type_source_capteurs, + Number(res[0]), + qsTr("‣ Capteur : %1").arg(res[1]) ); + } + else break; + } + + break; + + //====================================== + case shipheart_type_source_modules: + default: + break; + } + } + + //------------------------------------------------------------- + // Création du texte d'utilisation des circuits : + var usage = ""; + for (i=0; i
Confirmez-vous la suppression ?

") + for (i=0; i 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, "
"); // Remplace les '\n' par '
'. 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); + } + + + + + +} + diff --git a/config_ordre_elements.qml b/config_ordre_elements.qml new file mode 100644 index 0000000..7cb3d73 --- /dev/null +++ b/config_ordre_elements.qml @@ -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.
Pour modifier ou supprimer un groupe, double-cliquer sur le groupe.
Pour ajouter un groupe, cliquer sur '+'.

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. + } +} diff --git a/config_page.qml b/config_page.qml new file mode 100644 index 0000000..80f1b27 --- /dev/null +++ b/config_page.qml @@ -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 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
Cliquer sur Annuler pour revenir en arrière et les enregistrer.
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); + } +} diff --git a/config_page_point.qml b/config_page_point.qml new file mode 100644 index 0000000..ba4a927 --- /dev/null +++ b/config_page_point.qml @@ -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= 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); + } +} + diff --git a/config_reseau_ethernet_wifi.qml b/config_reseau_ethernet_wifi.qml new file mode 100644 index 0000000..2a601e1 --- /dev/null +++ b/config_reseau_ethernet_wifi.qml @@ -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= grille_modules_configures.count) && // Si le module affiché est à une adresse > à l'adresse la plus élevée des modules configurés, on n'afficha plue la liste configurée (sinon, on reste bloqué sur le dernier module configuré qui est alors décalé par rapport au module physique affiché en face) + (grille_modules_configures.count !== 0)) // Utile à l'ouverture de la page car on passe par l'état ou COUNT=0 et la liste configurée n'est plus visible avant le premier mouvement + { + grille_modules_configures.visible = false; + } + else grille_modules_configures.visible = true; // Si on revient à la situation où le module physique affiché a une adresse < nombre de modules configurés (donc plus de risque de décalage) + } + } + } + + + //------------------------------------------------------- + // Barre de séparation verticale : + //------------------------------------------------------- + + Rectangle { + id: separation_verticale + x: zone_affichage_gauche.width + (espace_colonnes_principales / 2) - (width / 2) + y: shipheart_hauteur_bandeau_haut; + + width: 3 + height: affichage_hauteur_utile + color: couleur_gris_tres_pale_transparent + } + + + //------------------------------------------------------- + // Ecran central (modules utilisés par la configuration actuelle) : + //------------------------------------------------------- + Rectangle { + id: zone_affichage_centre + x: zone_affichage_gauche.width + (espace_colonnes_principales) + y: shipheart_hauteur_bandeau_haut; + width: (shipheart_largeur_page * pourcentage_largeur_colonne_centre) - (espace_colonnes_principales) + height: affichage_hauteur_utile + color: "transparent" + + //------------------------------------------------------------------- + // Titre de la liste : + Rectangle { + width: parent.width + height: hauteur_ligne_formulaire + color: "transparent" + + Text { + anchors.fill: parent + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Qt.AlignVCenter + text: qsTr("Modules utilisés par la configuration actuelle") + color: couleur_gris_pale + font.pixelSize: 18 + wrapMode: Label.Wrap + } + } + + //------------------------------------------------------------------- + // 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_modules_configures + + x: 0 + y: hauteur_ligne_formulaire // Permet d'échapper la ligne de titre + width: parent.width + height: parent.height - hauteur_ligne_formulaire + + 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é (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_modules_configures + delegate: bouton_module + + 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_module + + + MouseArea { + id: dragArea // Zone correspondant à un seul bouton (on est dans le Delegate) + + width: grille_modules_configures.width + height: grille_modules_configures.height / nombre_modules_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_module : undefined + drag.axis: Drag.YAxis // On ne se déplace que sur l'axe Y + onClicked: { + shipheart_clic(); + stackView.push("config_module.qml", {"adresse_module": adresse}) + } + onPressAndHold: { + if (adresse !== 0) // ShipBase n'est pas "bougeable" + { + bouton_appuye = true // Indication (au niveau du bouton seul) du début de l'appui long donc du déplacement + grille_modules_configures.deplacement_en_cours = true // Indication (au niveau de ListView) du début du déplacement + grille_modules_configures.save_current_index = grille_modules_configures.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_modules_configures.deplacement_en_cours = false // Indication (au niveau de ListView) de la fin du déplacement + grille_modules_configures.currentIndex = grille_modules_configures.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") + enregistrement(); // Le principe est denregistrer après chaque déplacement ; sinon, les appels aux menus inférieurs (détails de modume physique ou config) deviennent très compliqués... + } + + Rectangle { + id: contenu_bouton_module + + anchors { + horizontalCenter: parent.horizontalCenter + verticalCenter: parent.verticalCenter + } + width: dragArea.width - 10 + height: dragArea.height - 10 + radius: shipheart_rayon_bouton + color: (adresse ===0) + ? "transparent" // Incolore pour ShipBase (on ne peut pas le bouger) + : ((model.erreur === 0) + ? shipheart_couleur_fond_bouton // Couleur par défaut si pas d'erreur + : (model.affecte === 0 + ? couleur_orange_transparent // Orange si aucune affectation sur ce module + : couleur_rouge_transparent)) // Rouge s'il y a une affectation sur ce module + + border.width: 2 + border.color: shipheart_couleur_fond_bouton + opacity: dragArea.bouton_appuye ? 0.5 : 0.8 + + + //----------------------- + // Adresse : + Rectangle { + id: zone_adresse_module + x: 0 + y: 0 + width: 50 + height: parent.height + color: "transparent" + radius: shipheart_rayon_bouton + border.width: 2 + border.color: shipheart_couleur_fond_bouton + + Text { + anchors.fill: parent + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + text: model.adresse + color: (affecte === 1) ? couleur_blanc_casse : couleur_gris_fonce + font.pixelSize: 28 + font.bold: true + } + } + + //----------------------- + // Nom : + Rectangle { + id: zone_nom_module + x: zone_adresse_module.width + y: 0 + width: parent.width - zone_adresse_module.width + height: parent.height / 3 + color: "transparent" + + Text { // Type et nom du module + anchors.verticalCenter: parent.verticalCenter + anchors.left: parent.left + leftPadding: 10 + rightPadding: 20 + text: Fonctions.nom_type_module(model.type) + (model.nom === "" ? "" : " [" + model.nom + "]") + color: (affecte === 1) ? couleur_blanc_casse : couleur_gris_fonce + font.pixelSize: 18 + font.bold: true + } + } + + //----------------------- + // Usages principaux : + Rectangle { + id: zone_usage_principal + x: zone_adresse_module.width + y: (parent.height / 3) + width: parent.width - zone_adresse_module.width + height: parent.height / 3 + color: "transparent" + visible: (usage_principal !== "") + + Rectangle { + id: icone_usage_principal + x: 10 + width: 20 + height: parent.height + color: "transparent" + Image { + source: (type === shipheart_type_module_shipBS) + ? "/images/batterie_moyen.png" + : "/images/icone_consommation_electrique.png" + anchors.fill: parent + fillMode: Image.PreserveAspectFit + opacity: 0.7 + } + } + + Text { // Utilisation du module en config (liste des circuits, nom de la batterie, ...) + anchors.verticalCenter: parent.verticalCenter + anchors.left: icone_usage_principal.right + leftPadding: 10 + rightPadding: 20 + width: zone_usage_principal.width - icone_usage_principal.width // Nécessaire pour que 'elide' fonctionne + wrapMode: Text.Wrap // Utile si 'maximumLineCount' > 1 + maximumLineCount: 1 // Nb de lignes sur lequel le texte sera affiché avant l'elide + elide: Text.ElideRight // Affiche des [...] lorsque le texte est trop long + text: usage_principal + color: (affecte === 1) ? couleur_gris_tres_pale : couleur_gris_fonce + font.pixelSize: 15 + } + } + + //----------------------- + // Usages secondaires : + Rectangle { + id: zone_usage_secondaire + x: zone_adresse_module.width + y: (2 * parent.height / 3) + width: parent.width - zone_adresse_module.width + height: parent.height / 3 + color: "transparent" + visible: (usage_secondaire !== "") + + Rectangle { + id: icone_usage_secondaire + x: 10 + width: 20 + height: parent.height + color: "transparent" + Image { + source: "/images/icone_auxiliaires.png" + anchors.fill: parent + fillMode: Image.PreserveAspectFit + opacity: 0.7 + } + } + + Text { // Utilisation du module en config (liste des circuits, nom de la batterie, ...) + anchors.verticalCenter: parent.verticalCenter + anchors.left: icone_usage_secondaire.right + leftPadding: 10 + rightPadding: 20 + width: zone_usage_secondaire.width - icone_usage_secondaire.width // Nécessaire pour que 'elide' fonctionne + wrapMode: Text.Wrap // Utile si 'maximumLineCount' > 1 + maximumLineCount: 1 // Nb de lignes sur lequel le texte sera affiché avant l'elide + elide: Text.ElideRight // Affiche des [...] lorsque le texte est trop long + text: usage_secondaire + color: (affecte === 1) ? couleur_gris_tres_pale : couleur_gris_fonce + font.pixelSize: 15 + } + } + + Drag.active: dragArea.bouton_appuye + Drag.source: dragArea + Drag.hotSpot.x: width / 2 + Drag.hotSpot.y: height / 2 + + states: State{ + when: dragArea.bouton_appuye + ParentChange { + target: contenu_bouton_module + parent: grille_modules_configures + } + AnchorChanges { + target: contenu_bouton_module + anchors { // Necessaire pour autoriser le mouvement + horizontalCenter: undefined + verticalCenter: undefined + } + } + } + } + + DropArea { + enabled: (adresse !== 0) // Interdit de déposer un module sur l'adresse 0 (ShipBase) + + anchors.fill: parent + onEntered: { + + if (drag.source.DelegateModel.itemsIndex !== dragArea.DelegateModel.itemsIndex) + { +//console.log("\tMouvement de Source index = " + drag.source.DelegateModel.itemsIndex + " vers Dest index = " + dragArea.DelegateModel.itemsIndex) + modele_modules_configures.move(drag.source.DelegateModel.itemsIndex, dragArea.DelegateModel.itemsIndex, 1) + mise_a_jour_modules_config(); // Mise à jour des flags d'erreur (donc les modules teintés de rouge) suite au dernier déplacement. + } + } + } + } + } + + ListModel { + id: modele_modules_configures + } + + onCurrentIndexChanged: { + if (grille_modules_configures.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. + + if ( (currentIndex >= grille_modules_physiques.count) && // Si le module affiché est à une adresse > à l'adresse la plus élevée des modules physiques, on n'afficha plue la liste physique (sinon, on reste bloqué sur le dernier module physique qui est alors décalé par rapport au module config affiché en face) + (grille_modules_physiques.count !== 0)) // Utile à l'ouverture de la page car on passe par l'état ou COUNT=0 et la liste physique n'est plus visible avant le premier mouvement + { + grille_modules_physiques.visible = false; + } + else grille_modules_physiques.visible = true; // SI on revient à la situation où le module config affiché a une adresse < nombre de modules physiques (donc plus de risque de décalage) + } + else + { + grille_modules_configures.currentIndex = grille_modules_configures.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. + } + } + } + + + //------------------------------------------------------------------- + // Message si liste vide : + Label { + anchors.fill: parent + horizontalAlignment: Qt.AlignHCenter + verticalAlignment: Qt.AlignVCenter + visible: modele_modules_configures.count === 0 + text: qsTr("La configuration actuelle ne fait appel à aucun autre module que ShipBase...") + 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 + zone_affichage_centre.width + espace_colonnes_principales; + y: shipheart_hauteur_bandeau_haut + hauteur_ligne_formulaire + 5; + width: (shipheart_largeur_page * (1 - pourcentage_largeur_colonne_gauche - pourcentage_largeur_colonne_centre)) - (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_module_creation.qml", {"adresse_module": modele_modules_configures.count}); + } + } + } + + //----------------------------------- + // Bouton de rechargement de config : + Rectangle { + width: parent.width + height: hauteur_bouton_droit + color: shipheart_couleur_fond_bouton + radius: shipheart_rayon_bouton + visible: !clavier.active + Image { + source: "/images/cycle.png" + sourceSize.height: (parent.height * 0.5) + anchors { + verticalCenter: parent.verticalCenter + horizontalCenter: parent.horizontalCenter + } + } + MouseArea { + anchors.fill: parent + onClicked: { + shipheart_clic(); + synchro_bdd(shipheart_type_synchro_config); + timer_tempo_reconfiguration.restart(); // Lancement du timer d'attente de fin de reconfig + } + } + } + } + } + + + //------------------------------------------------------- + // 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: 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(); + } + } + } + + //................................................. + // 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(); + maj_flag_defaut_config_k_bus(); + init_modules_configures(); + } + else timer_tempo_reconfiguration.interval = 100 // Tempo plus courte pour les lectures suivantes") + } + } + } + + //=========================================================== + // 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() + { + modele_modules_physiques.clear(); // Doit être ici car la maj est appelée régulièrement + mise_a_jour_modules_physiques(); // L'init des modules de config est lancée directement à la fin de la mise à jour des modules physiques + + flag_init = false; + } + + //============================================================================================================= + // Mise à jour périodique (et à l'init) des informations des modules physiquement présents + //============================================================================================================= + function mise_a_jour_modules_physiques() + { + var req, res; + var i; + var nb; + + + //-------------------------------------------------------------------- + // Vérification de la dispo du CM3+/CM4 : + //-------------------------------------------------------------------- + // Vérification que le CM3+/CM4 est bien On (sinon, il est fort probable qu'il soit en cours de démarrage ou de raffraichissement de son annuaire et + // on va récupérer des données partielles... + req = 'SELECT Valeur FROM TB_Systeme WHERE Nom="Etat_cm3p" '; + res = bdd.requete_unique(req); + if (Number(res[0]) === 0) + { +//console.log("CM3+/CM4 non disponible. La mise à jour est avortée...") + return; + } + + flag_maj_en_cours = true; + + //-------------------------------------------------------------------- + // Mise à jour de la liste des modules physiques : + //-------------------------------------------------------------------- + req = 'SELECT Adresse_k_bus, Type FROM TB_Modules_physiques ORDER BY Adresse_k_bus'; +//console.log("req =" + req); + nb = bdd.requete(req); + + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + if (Number(res[0]) > modele_modules_physiques.count) + { + modele_modules_physiques.append({"adresse": Number(res[0]), "nom": Fonctions.nom_type_module(Number(res[1])), "type": Number(res[1])}); + } + else + { + modele_modules_physiques.set(Number(res[0]), {"adresse": Number(res[0]), "nom": Fonctions.nom_type_module(Number(res[1])), "type": Number(res[1])}); + } + } + else break; // Ne devrait pas arriver.... + } + + //-------------------------------------------------------------------- + // Suppression du modèle des éventuels modules physiques supprimés : + //-------------------------------------------------------------------- + while(modele_modules_physiques.count > nb) + { + modele_modules_physiques.remove((modele_modules_physiques.count - 1), 1); + } + + //-------------------------------------------------------------------- + // Détection d'un changement de nombre de modules physiques : + //-------------------------------------------------------------------- + if (nb_modules_physiques !== modele_modules_physiques.count) + { + nb_modules_physiques = modele_modules_physiques.count; + } + + flag_maj_en_cours = false; + } + + + + //============================================================================================================= + // Mise à jour périodique des informations sur l'utilisation des modules par la config actuelle + //============================================================================================================= + function mise_a_jour_modules_config() + { + var req, res; + var i; + var nb; + var erreur; + + + //-------------------------------------------------------------------- + // Vérification de la dispo du CM3+/CM4 : + //-------------------------------------------------------------------- + // Vérification que le CM3+/CM4 est bien On (sinon, il est fort probable qu'il soit en cours de démarrage ou de raffraichissement de son annuaire et + // on va récupérer des données partielles... + req = 'SELECT Valeur FROM TB_Systeme WHERE Nom="Etat_cm3p" '; + res = bdd.requete_unique(req); + if (Number(res[0]) === 0) + { +//console.log("CM3+/CM4 non disponible. La mise à jour est avortée...") + return; + } + + flag_maj_en_cours = true; + + //-------------------------------------------------------------------- + // Recherche des modules en erreur (différence entre le type réellement présent et le type en config) : + //-------------------------------------------------------------------- + // NB : on ne peut pas utiliser le flag Presence dand TB_Modules_config comme à l'init car on a pu bouger les modules de mise_a_jour_modules_config() + // sans avoir encore mis à jour la BDD (tant qu'on n'a pas enregistré les modifs). Il faut donc faire cette vérification entre le modèle physique + // qui, lui, est mis à jour en temps réel via TB_Modules_physiques et le modèle config qui est mis à jour par les déplacements après l'init. + for (i=0; i 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... + } + } + + + } + + + +} + diff --git a/config_reseau_one_wire.qml b/config_reseau_one_wire.qml new file mode 100644 index 0000000..255b85d --- /dev/null +++ b/config_reseau_one_wire.qml @@ -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.
Cet état ne présente aucun danger mais l'empêche de fonctionner.

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 = "" + qsTr("Type inconnu") + ""; 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); + } + + + +} + diff --git a/config_reseau_one_wire_modification.qml b/config_reseau_one_wire_modification.qml new file mode 100644 index 0000000..24563e8 --- /dev/null +++ b/config_reseau_one_wire_modification.qml @@ -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); + + } + + +} + diff --git a/config_reseau_wifi_ap.qml b/config_reseau_wifi_ap.qml new file mode 100644 index 0000000..8c326dd --- /dev/null +++ b/config_reseau_wifi_ap.qml @@ -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.
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.
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 :
- des lettres majuscules [A - Z],
- des lettres minuscules [a - z],
- des chiffres [0 - 9]
- les caractères spéciaux [%1].

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 :
- des lettres majuscules [A - Z],
- des lettres minuscules [a - z],
- des chiffres [0 - 9]
- les caractères spéciaux [%1].

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 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": "
" + res[2] + "
" + res[0] + "" + ((Number(res[4]) < 20) ? "2.4GHz" : "5GHz") + " - Channel " + res[4] + "[" + Number(res[5]) + " %]
", + "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.
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.
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 :
- des lettres majuscules [A - Z],
- des lettres minuscules [a - z],
- des chiffres [0 - 9]
- les caractères spéciaux [%1].

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 :
- des lettres majuscules [A - Z],
- des lettres minuscules [a - z],
- des chiffres [0 - 9]
- les caractères spéciaux [%1].

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; itype de capteur va nécessiter la remise en configuration usine de tous les paramètres du réservoir.

Si vous ne souhaitez pas que cette reconfiguration soit effectuée, cliquez sur ANNULER.

Sinon, cliquez sur CONFIRMER pour valider le changement."); + boutonAnnuler: true + boutonOkTexte: qsTr("Confirmer") + onClicked: { +//console.log("Le Bouton [" + bouton + "] est appuyé"); + if (bouton === shipheart_boite_dialogue_bouton_1) + { + if (champ_formulaire_Type_entrees.model.get(champ_formulaire_Type_entrees.currentIndex).valeur !== type_entrees) + { + // RAZ des entrées si on a change de type (il est dangereux de garder des n° d'entrées AUX pour les considérer comme des entrées Level Sensor ou réciproquement...) : + if (champ_formulaire_Type_entrees.model.get(champ_formulaire_Type_entrees.currentIndex).valeur !== type_entrees_init) + { + entrees = ""; + nb_entrees_reservoir = 0; + } + else // Si on revient au type d'entrée initial, on reprend les entrées initiales : + { + entrees = entrees_init; + nb_entrees_reservoir = nb_entrees_reservoir_init; + } + + type_entrees = champ_formulaire_Type_entrees.model.get(champ_formulaire_Type_entrees.currentIndex).valeur; + } + + mode_entrees = champ_formulaire_Type_entrees.model.get(champ_formulaire_Type_entrees.currentIndex).mode; // Le fait de changer de Mode_entrees ne nécessite pas de RAZ le n° d'entrée qui reste, a priori, valable + type_sonde_entrees = champ_formulaire_Type_entrees.model.get(champ_formulaire_Type_entrees.currentIndex).sous_mode; // Le fait de changer de type_sonde_entrees ne nécessite pas de RAZ le n° d'entrée qui reste, a priori, valable + + if (type_entrees === shipheart_reservoir_type_entrees_aux) init_entrees_aux(); + else if (type_entrees === shipheart_reservoir_type_entrees_level_sensor) init_entrees_level_sensor(); + } + if (bouton === shipheart_boite_dialogue_bouton_2) + { + // Repositionnement à la valeur d'origine : + champ_formulaire_Type_entrees.currentIndex = recherche_index_type_entree(type_entrees, mode_entrees, type_sonde_entrees); + } + } + } + + //------------------------------------------------------- + // 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 nb; + var i; + + var niveau_coeff_filtrage, defaut_niveau_coeff_filtrage = 16; + var logique, defaut_logique = -1; + var id_famille; + + +//console.log("Id du réservoir = " + id_reservoir); + + if (id_reservoir > 0) // Cas d'une modification de circuit existant : + { + req = 'SELECT Nom, '; + req += ' Adresse_module, '; + req += ' Type_entrees, '; + req += ' Entrees, '; + req += ' Mode_entrees, '; + req += ' Type_sonde_entrees, '; + req += ' ID_Famille, '; + req += ' Niveau_coeff_filtrage, '; + req += ' Liste_valeurs_niveaux, '; + req += ' Capacite, '; + req += ' Logique '; + req += ' FROM TB_Reservoirs '; + req += ' WHERE Cle_primaire=' + id_reservoir + ' '; +//console.log("req = [ " + req + "; ]"); + res = bdd.requete_unique(req); + + //--------------------------------------------------------------- + // Mise à jour du champs de saisie de chaque zone de formulaire : + i = 0; + champ_formulaire_Nom.text = res[i ++]; + adresse_module = Number(res[i ++]); + type_entrees = Number(res[i ++]); + entrees = res[i ++]; + mode_entrees = Number(res[i ++]); + type_sonde_entrees = Number(res[i ++]); + id_famille = Number(res[i ++]); + niveau_coeff_filtrage = Number(res[i ++]); +i++; // liste valeurs niveaux non utilisée ici (soit on n'y touche pas quand on ne change pas le nombre d'entrées du réservoir ; soit on la regénère automatiquement si changement de nombre d'entrées) + champ_formulaire_Capacite.text = res[i ++]; + logique = Number(res[i ++]); + } + else // Cas d'une création de circuit : + { + adresse_module = 0; + type_entrees = 0; + entrees = ""; + mode_entrees = 0; + type_sonde_entrees = 0; + champ_formulaire_Nom.text = ""; + id_famille = 0; + champ_formulaire_Capacite.text = "0"; + niveau_coeff_filtrage = defaut_niveau_coeff_filtrage; + logique = defaut_logique; + } + + // Init des entrés selon leur type ; + if (type_entrees === shipheart_reservoir_type_entrees_aux) init_entrees_aux(); + else if (type_entrees === shipheart_reservoir_type_entrees_level_sensor) init_entrees_level_sensor(); + + // Mémorisation des valeurs d'init : + adresse_module_init = adresse_module; + type_entrees_init = type_entrees; + entrees_init = entrees; + nb_entrees_reservoir_init = nb_entrees_reservoir; + mode_entrees_init = mode_entrees; + type_sonde_entrees_init = type_sonde_entrees; + + + //--------------------------------------------------------------------------------------- + // Type d'entrées : + champ_formulaire_Type_entrees.model.clear(); + champ_formulaire_Type_entrees.model.append({"valeur": 0, "mode": 0, "sous_mode": 0, "texte": qsTr("Non défini") }); + champ_formulaire_Type_entrees.model.append({"valeur": shipheart_reservoir_type_entrees_aux, "mode": 0, "sous_mode": 0, "texte": qsTr("Electrodes plongées ou contacts secs") }); + champ_formulaire_Type_entrees.model.append({"valeur": shipheart_reservoir_type_entrees_level_sensor, "mode": 2, "sous_mode": 1, "texte": qsTr("Résistif 0 - 190Ω") }); + champ_formulaire_Type_entrees.model.append({"valeur": shipheart_reservoir_type_entrees_level_sensor, "mode": 2, "sous_mode": 2, "texte": qsTr("Résistif 240 - 30Ω") }); + champ_formulaire_Type_entrees.model.append({"valeur": shipheart_reservoir_type_entrees_level_sensor, "mode": 2, "sous_mode": 0, "texte": qsTr("Résistif 0 - 700Ω") }); + champ_formulaire_Type_entrees.model.append({"valeur": shipheart_reservoir_type_entrees_level_sensor, "mode": 3, "sous_mode": 0, "texte": qsTr("Boucle de courant 4 - 20mA") }); + champ_formulaire_Type_entrees.model.append({"valeur": shipheart_reservoir_type_entrees_level_sensor, "mode": 1, "sous_mode": 0, "texte": qsTr("Tension 0 - 10V") }); + + // Positionnement de l'index sur la valeur en cours : + champ_formulaire_Type_entrees.currentIndex = recherche_index_type_entree(type_entrees, mode_entrees, type_sonde_entrees); + + + //--------------------------------------------------------------------------------------- + // Logique inversée des entrées AUX : + if (type_entrees === shipheart_reservoir_type_entrees_aux) + { + if (mode_entrees === shipheart_reservoir_mode_entrees_aux_inverse) champ_formulaire_Logique_inversee.checked = true; + else champ_formulaire_Logique_inversee.checked = false; + } + + //--------------------------------------------------------------------------------------- + // Coefficient de filtrage des mesures (valeur en nombre d'échantillons ; mini = 1): + champ_formulaire_Niveau_coeff_filtrage.model.clear(); + champ_formulaire_Niveau_coeff_filtrage.model.append({"valeur": 1, "texte": qsTr("Aucun filtrage") }); + champ_formulaire_Niveau_coeff_filtrage.model.append({"valeur": 4, "texte": qsTr("Très faible") }); + champ_formulaire_Niveau_coeff_filtrage.model.append({"valeur": 8, "texte": qsTr("Faible") }); + champ_formulaire_Niveau_coeff_filtrage.model.append({"valeur": defaut_niveau_coeff_filtrage, "texte": qsTr("Moyen") }); + champ_formulaire_Niveau_coeff_filtrage.model.append({"valeur": 64, "texte": qsTr("Elevé") }); + champ_formulaire_Niveau_coeff_filtrage.model.append({"valeur": 96, "texte": qsTr("Très élevé") }); + + // Positionnement de l'index sur la valeur en cours : + i = recherche_index_valeur_modele(niveau_coeff_filtrage, champ_formulaire_Niveau_coeff_filtrage.model, "Niveau_coeff_filtrage"); + if (i === -1) champ_formulaire_Niveau_coeff_filtrage.currentIndex = recherche_index_valeur_modele(defaut_niveau_coeff_filtrage, champ_formulaire_Niveau_coeff_filtrage.model, "Niveau_coeff_filtrage"); + else champ_formulaire_Niveau_coeff_filtrage.currentIndex = i; + + + //--------------------------------------------------------------------------------------- + // Logique : + champ_formulaire_Logique.model.clear(); + champ_formulaire_Logique.model.append({"valeur": defaut_logique, "texte": qsTr("Alerte sur niveau faible") }); + champ_formulaire_Logique.model.append({"valeur": 1, "texte": qsTr("Alerte sur niveau élevé") }); +// champ_formulaire_Logique.model.append({"valeur": 0, "texte": qsTr("Alerte sur niveau faible ou élevé") }); + + // Positionnement de l'index sur la valeur en cours : + i = recherche_index_valeur_modele(logique, champ_formulaire_Logique.model, "Logique"); + if (i === -1) champ_formulaire_Logique.currentIndex = recherche_index_valeur_modele(defaut_logique, champ_formulaire_Logique.model, "Logique"); + else champ_formulaire_Logique.currentIndex = i; + + //--------------------------------------------------------------------------------------- + // Famille : + champ_formulaire_Famille.model.clear(); + champ_formulaire_Famille.model.append({"valeur": 0, "texte": "Non défini" }); + req = 'SELECT Cle_primaire, Nom FROM TB_Familles WHERE Type_source=' + shipheart_type_source_reservoirs + ' ORDER BY Priorite_affichage '; +//console.log("req = [ " + req + "; ]"); + nb = bdd.requete(req); + + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + champ_formulaire_Famille.model.append({"valeur": Number(res[0]), "texte": res[1] }); + } + } + + // Positionnement de l'index sur la valeur en cours : + i = recherche_index_valeur_modele(id_famille, champ_formulaire_Famille.model, "Famille"); + if (i === -1) champ_formulaire_Famille.currentIndex = 0; + else champ_formulaire_Famille.currentIndex = i; + + flag_init = false; + } + + + //============================================================================================================= + // Init des valeurs initiales des modèles liées aux entrées du réservoir lorsqu'il est dans l'un des modes utilisant les entrées AUX + // Il est important de noter l'utilisation de DEUX modèles de données : + // - 'entrees_aux_reservoir_grid.model' qui contient (a priori) 12 entrées ; chacune représentant l'une des entrée + // configurée sur ce réservoir. + // - 'modele_entrees_aux' qui contient les 32 AUX INPUTS disponibles sur ShipBase. + //============================================================================================================= + function init_entrees_aux() + { + var req, res; + var nb; + var i; + var val; + var chaines_entrees = []; + + + // Traitement de la chaine "entrees" pour définir les entrées actuelles du réservoir : + if (entrees !== "") + { + chaines_entrees = entrees.split(';'); + nb_entrees_reservoir = chaines_entrees.length; + } + else + { + chaines_entrees[0] = ""; + nb_entrees_reservoir = 0; + } + + + //--------------------------------------------------------------------------------------- + // Entrées réservoir : + // Les 12 entrées qui sont affectables au réservoir + entrees_aux_reservoir_grid.model.clear(); + for (i = 0; i < shipheart_reservoir_max_nombre_entrees_aux; i ++) + { + if (i < nb_entrees_reservoir) val = Number(chaines_entrees[i]); + else val = 0; + + entrees_aux_reservoir_grid.model.append({"no": (i + 1), "no_entree_aux" : val, "libelle": (val === 0) ? "FFFFF" : qsTr("AUX INPUT %1").arg(val) }); + } + + //--------------------------------------------------------------------------------------- + // Entrées auxiliaires : + // Les 32 entrées AUX de ShipBase par exemple + var entrees_aux = []; + + // remplissage par défaut de toutes les entrées AUX possibles : + for (i=0; i= 1) && (no <= shipheart_entrees_aux_max_nombre)) entrees_aux[no - 1]['used'] = 1; // le n° d'entrée doit être dans [1; 32] + } + } + } + + + modele_entrees_aux.clear(); + + i = 17; + modele_entrees_aux.append({valeurs: [{no: i, used: entrees_aux[i-1]['used'], no_entree: entrees_aux[i-1]['no_entree'] }, + {no: (i+1), used: entrees_aux[i+0]['used'], no_entree: entrees_aux[i+0]['no_entree'] }, + {no: (i+2), used: entrees_aux[i+1]['used'], no_entree: entrees_aux[i+1]['no_entree'] }, + {no: (i+3), used: entrees_aux[i+2]['used'], no_entree: entrees_aux[i+2]['no_entree'] }] } ); + i = 21; + modele_entrees_aux.append({valeurs: [{no: i, used: entrees_aux[i-1]['used'], no_entree: entrees_aux[i-1]['no_entree'] }, + {no: (i+1), used: entrees_aux[i+0]['used'], no_entree: entrees_aux[i+0]['no_entree'] }, + {no: (i+2), used: entrees_aux[i+1]['used'], no_entree: entrees_aux[i+1]['no_entree'] }, + {no: (i+3), used: entrees_aux[i+2]['used'], no_entree: entrees_aux[i+2]['no_entree'] }] } ); + i = 25; + modele_entrees_aux.append({valeurs: [{no: i, used: entrees_aux[i-1]['used'], no_entree: entrees_aux[i-1]['no_entree'] }, + {no: (i+1), used: entrees_aux[i+0]['used'], no_entree: entrees_aux[i+0]['no_entree'] }, + {no: (i+2), used: entrees_aux[i+1]['used'], no_entree: entrees_aux[i+1]['no_entree'] }, + {no: (i+3), used: entrees_aux[i+2]['used'], no_entree: entrees_aux[i+2]['no_entree'] }] } ); + i = 29; + modele_entrees_aux.append({valeurs: [{no: i, used: entrees_aux[i-1]['used'], no_entree: entrees_aux[i-1]['no_entree'] }, + {no: (i+1), used: entrees_aux[i+0]['used'], no_entree: entrees_aux[i+0]['no_entree'] }, + {no: (i+2), used: entrees_aux[i+1]['used'], no_entree: entrees_aux[i+1]['no_entree'] }, + {no: (i+3), used: entrees_aux[i+2]['used'], no_entree: entrees_aux[i+2]['no_entree'] }] } ); + i = 1; + modele_entrees_aux.append({valeurs: [{no: i, used: entrees_aux[i-1]['used'], no_entree: entrees_aux[i-1]['no_entree'] }, + {no: (i+1), used: entrees_aux[i+0]['used'], no_entree: entrees_aux[i+0]['no_entree'] }, + {no: (i+2), used: entrees_aux[i+1]['used'], no_entree: entrees_aux[i+1]['no_entree'] }, + {no: (i+3), used: entrees_aux[i+2]['used'], no_entree: entrees_aux[i+2]['no_entree'] }] } ); + i = 5; + modele_entrees_aux.append({valeurs: [{no: i, used: entrees_aux[i-1]['used'], no_entree: entrees_aux[i-1]['no_entree'] }, + {no: (i+1), used: entrees_aux[i+0]['used'], no_entree: entrees_aux[i+0]['no_entree'] }, + {no: (i+2), used: entrees_aux[i+1]['used'], no_entree: entrees_aux[i+1]['no_entree'] }, + {no: (i+3), used: entrees_aux[i+2]['used'], no_entree: entrees_aux[i+2]['no_entree'] }] } ); + i = 9; + modele_entrees_aux.append({valeurs: [{no: i, used: entrees_aux[i-1]['used'], no_entree: entrees_aux[i-1]['no_entree'] }, + {no: (i+1), used: entrees_aux[i+0]['used'], no_entree: entrees_aux[i+0]['no_entree'] }, + {no: (i+2), used: entrees_aux[i+1]['used'], no_entree: entrees_aux[i+1]['no_entree'] }, + {no: (i+3), used: entrees_aux[i+2]['used'], no_entree: entrees_aux[i+2]['no_entree'] }] } ); + i = 13; + modele_entrees_aux.append({valeurs: [{no: i, used: entrees_aux[i-1]['used'], no_entree: entrees_aux[i-1]['no_entree'] }, + {no: (i+1), used: entrees_aux[i+0]['used'], no_entree: entrees_aux[i+0]['no_entree'] }, + {no: (i+2), used: entrees_aux[i+1]['used'], no_entree: entrees_aux[i+1]['no_entree'] }, + {no: (i+3), used: entrees_aux[i+2]['used'], no_entree: entrees_aux[i+2]['no_entree'] }] } ); + + } + + + + //============================================================================================================= + // Init des valeurs initiales des modèles liées aux entrées du réservoir lorsqu'il est dans l'un des modes utilisant une entrée Level Sensor + //============================================================================================================= + function init_entrees_level_sensor() + { + var req, res; + var nb; + var i; + var entree; + + + // Traitement de la chaine "entrees" pour définir les entrées actuelles du réservoir : + if (entrees !== "") + { + entree = Number(entrees); + nb_entrees_reservoir = 1; + } + else + { + entree = 0; + nb_entrees_reservoir = 0; + } + + + //--------------------------------------------------------------------------------------- + // Entrée réservoir : + entree_level_sensor_reservoir_grid.model.clear(); + entree_level_sensor_reservoir_grid.model.append({"no": 1, "no_entree_level_sensor" : entree, "libelle": (entree === 0) ? "" : qsTr("LEVEL SENSOR %1").arg(entree) }); + + + //--------------------------------------------------------------------------------------- + // Entrées Level Sensor : + var entrees_level_sensor = []; + for (i=0; i= 1) && (no <= shipheart_entrees_level_sensor_max_nombre)) entrees_level_sensor[no - 1]['used'] = 1; + } + } + + + modele_entrees_level_sensor.clear(); + i = 1; + modele_entrees_level_sensor.append({valeurs: [{no: i, used: entrees_level_sensor[i-1]['used'], no_entree: entrees_level_sensor[i-1]['no_entree'] }, + {no: (i+1), used: entrees_level_sensor[i+0]['used'], no_entree: entrees_level_sensor[i+0]['no_entree'] }, + {no: (i+2), used: entrees_level_sensor[i+1]['used'], no_entree: entrees_level_sensor[i+1]['no_entree'] }, + {no: (i+3), used: entrees_level_sensor[i+2]['used'], no_entree: entrees_level_sensor[i+2]['no_entree'] }] } ); + i = 5; + modele_entrees_level_sensor.append({valeurs: [{no: i, used: entrees_level_sensor[i-1]['used'], no_entree: entrees_level_sensor[i-1]['no_entree'] }, + {no: (i+1), used: entrees_level_sensor[i+0]['used'], no_entree: entrees_level_sensor[i+0]['no_entree'] }, + {no: (i+2), used: entrees_level_sensor[i+1]['used'], no_entree: entrees_level_sensor[i+1]['no_entree'] }, + {no: (i+3), used: entrees_level_sensor[i+2]['used'], no_entree: entrees_level_sensor[i+2]['no_entree'] }] } ); + } + + + //============================================================================================================= + // Mise à jour des valeurs saisies du réservoir + //============================================================================================================= + function mise_a_jour_reservoir() + { + var req; + var i, j; + var chaine_entrees = ""; + var groupe; + + + // Création de la chaine représentant les n° d'entrées utilisées par le réservoir : + //------------------------------------------------------------------------------------------------------- + if (type_entrees === shipheart_reservoir_type_entrees_aux) + { + for (i = 0; i < shipheart_reservoir_max_nombre_entrees_aux; i ++) + { + j = entrees_aux_reservoir_grid.model.get(i).no_entree_aux + if (j !== 0) + { + if (chaine_entrees === "") chaine_entrees = j; + else chaine_entrees += ';' + j; + } + } +//console.log("chaine entrées = " + chaine_entrees); + + // Mise à jour du champ Mode_entrees en fonction de la check-box d'inversion des entrées AUX : + // Pour mémoire, le champ 'Mode_entrees' : Si Type_entrees=1, 0=Normal, 1=logique inversée sur les entrées. + if (champ_formulaire_Logique_inversee.checked) mode_entrees = shipheart_reservoir_mode_entrees_aux_inverse; + else mode_entrees = shipheart_reservoir_mode_entrees_aux_normal; + } + //------------------------------------------------------------------------------------------------------- + else if (type_entrees === shipheart_reservoir_type_entrees_level_sensor) + { + j = entree_level_sensor_reservoir_grid.model.get(0).no_entree_level_sensor + if (j !== 0) + { + chaine_entrees = j; + } + else return; // On ne peut pas enregistrer un réservoir avec un # de Level sensor = 0 +//console.log("chaine entrées = " + chaine_entrees); + } + + // Mise à jour de l'entrée dans TB_Réservoirs : + req = 'UPDATE TB_Reservoirs SET Nom="' + champ_formulaire_Nom.text + '" '; + req += ', Adresse_module=' + adresse_module; + req += ', Type_entrees=' + type_entrees; // champ_formulaire_Type_entrees.model.get(champ_formulaire_Type_entrees.currentIndex).valeur; + req += ', Entrees="' + chaine_entrees + '" '; + req += ', Mode_entrees=' + mode_entrees; + req += ', Type_sonde_entrees=' + type_sonde_entrees; + req += ', ID_Famille=' + champ_formulaire_Famille.model.get(champ_formulaire_Famille.currentIndex).valeur; + req += ', Niveau_coeff_filtrage=' + champ_formulaire_Niveau_coeff_filtrage.model.get(champ_formulaire_Niveau_coeff_filtrage.currentIndex).valeur; + req += ', Capacite=' + Number(champ_formulaire_Capacite.text); + req += ', Logique=' + champ_formulaire_Logique.model.get(champ_formulaire_Logique.currentIndex).valeur; + + if (type_entrees === shipheart_reservoir_type_entrees_aux) + { + if (nb_entrees_reservoir_init !== nb_entrees_reservoir) req += ', Liste_valeurs_niveaux="' + Fonctions_reservoirs.chaine_valeur_niveau_reservoir_usine(shipheart_reservoir_type_entrees_aux, nb_entrees_reservoir) + '" '; // On ne met à jour la table d'étalonnage que si le nombre d'entrées à changé... + } + else if (type_entrees === shipheart_reservoir_type_entrees_level_sensor) + { + if ((mode_entrees_init !== champ_formulaire_Type_entrees.model.get(champ_formulaire_Type_entrees.currentIndex).mode) || + (type_sonde_entrees_init !== champ_formulaire_Type_entrees.model.get(champ_formulaire_Type_entrees.currentIndex).sous_mode)) + { + req += ', Liste_valeurs_niveaux="' + Fonctions_reservoirs.chaine_valeur_niveau_reservoir_usine(shipheart_reservoir_type_entrees_level_sensor, champ_formulaire_Type_entrees.model.get(champ_formulaire_Type_entrees.currentIndex).mode, champ_formulaire_Type_entrees.model.get(champ_formulaire_Type_entrees.currentIndex).sous_mode) + '" '; // On ne met à jour la table d'étalonnage que si le mode ou le sous-mode à changé... + } + } + + req += ' WHERE Cle_primaire=' + id_reservoir + ' ' +//console.log("req = [ " + req + "; ]"); + bdd.requete_unique(req); + + + synchro_bdd(shipheart_type_synchro_config); + } + + //============================================================================================================= + // Création du réservoir + //============================================================================================================= + function creation_reservoir() + { + var req, res; + var i, j; + var chaine_entrees = ""; + var nb_entrees; + + //----------------------------------------------------------------------------------------------------------- + if (type_entrees === shipheart_reservoir_type_entrees_aux) + { + // Création de la chaine représentant les n° d'entrées utilisées par le réservoir : + nb_entrees = 0; + for (i = 0; i < shipheart_reservoir_max_nombre_entrees_aux; i ++) + { + j = entrees_aux_reservoir_grid.model.get(i).no_entree_aux + if (j !== 0) + { + if (chaine_entrees === "") chaine_entrees = j; + else chaine_entrees += ';' + j; + + nb_entrees ++; // Nécessaire pour appeler la fonction 'create_liste_valeurs_niveaux()' + } + } +//console.log("chaine entrées = " + chaine_entrees); + + // Mise à jour du champ Mode_entrees en fonction de la check-box d'inversion des entrées AUX : + // Pour mémoire, le champ 'Mode_entrees' : Si Type_entrees=1, 0=Normal, 1=logique inversée sur les entrées. + if (champ_formulaire_Logique_inversee.checked) mode_entrees = shipheart_reservoir_mode_entrees_aux_inverse; + else mode_entrees = shipheart_reservoir_mode_entrees_aux_normal; + } + //----------------------------------------------------------------------------------------------------------- + else if (type_entrees === shipheart_reservoir_type_entrees_level_sensor) + { + // Création de la chaine représentant les n° d'entrées utilisées par le réservoir : + j = entree_level_sensor_reservoir_grid.model.get(0).no_entree_level_sensor + if (j !== 0) + { + chaine_entrees = j; + } + else return; // On ne peut pas créer un réservoir avec un # de Level sensor = 0 + } + + + // Création de l'entrée dans TB_Réservoirs : + req = 'INSERT INTO TB_Reservoirs '; + req += ' (Nom, '; + req += ' Adresse_module, '; + req += ' Type_entrees, '; + req += ' Entrees, '; + req += ' Mode_entrees, '; + req += ' Type_sonde_entrees, '; + req += ' ID_Famille, '; + req += ' Niveau_coeff_filtrage, '; + req += ' Liste_valeurs_niveaux, '; + req += ' Capacite, '; + req += ' Logique) ' + req += ' VALUES ('; + req += ' "' + champ_formulaire_Nom.text + '"'; + req += ', ' + adresse_module + ' '; + req += ', ' + type_entrees; // champ_formulaire_Type_entrees.model.get(champ_formulaire_Type_entrees.currentIndex).valeur; + req += ', "' + chaine_entrees + '" '; + req += ', ' + mode_entrees + ' '; + req += ', ' + type_sonde_entrees + ' '; + req += ', ' + champ_formulaire_Famille.model.get(champ_formulaire_Famille.currentIndex).valeur; + req += ', ' + champ_formulaire_Niveau_coeff_filtrage.model.get(champ_formulaire_Niveau_coeff_filtrage.currentIndex).valeur; + if (type_entrees === shipheart_reservoir_type_entrees_aux) req += ', "' + Fonctions_reservoirs.chaine_valeur_niveau_reservoir_usine(shipheart_reservoir_type_entrees_aux, nb_entrees) + '" '; + else req += ', "' + Fonctions_reservoirs.chaine_valeur_niveau_reservoir_usine(shipheart_reservoir_type_entrees_level_sensor, champ_formulaire_Type_entrees.model.get(champ_formulaire_Type_entrees.currentIndex).mode, champ_formulaire_Type_entrees.model.get(champ_formulaire_Type_entrees.currentIndex).sous_mode) + '" '; + req += ', ' + Number(champ_formulaire_Capacite.text); + req += ', ' + champ_formulaire_Logique.model.get(champ_formulaire_Logique.currentIndex).valeur; + req += ') '; +//console.log("req = [ " + req + "; ]"); + bdd.requete_unique(req); + + + // Mise à jour des entrées (après l'insertion du réservoir pour avoir sa nouvelle clé_primaire) : + req = 'SELECT Cle_primaire FROM TB_Reservoirs ORDER BY Cle_primaire DESC LIMIT 1 '; +//console.log("req = [ " + req + "; ]"); + res = bdd.requete_unique(req); + id_reservoir = Number(res[0]); + + + // Demande de reconfiguration système via la BDD car on a modifié des valeurs de configuration : + synchro_bdd(shipheart_type_synchro_config); + } + + + //============================================================================================================= + // Check suppression du réservoir + //============================================================================================================= + function check_avant_suppression() + { + var req, res; + var nb; + var i; + 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 sur les évènements : + req = 'SELECT Cle_primaire, Nom FROM TB_Events WHERE Type_source=' + shipheart_source_mesure_reservoir + ' AND ID_Source=' + id_reservoir + ' '; + req += ' ORDER BY Nom'; +//console.log("Requête = [ " + req + "; ]") + nb = bdd.requete(req); + + if (nb > 0) + { + if (nb === 1) message += "

" + qsTr("Ce réservoir est utilisé par l'évènement ci-dessous.
Vous devez modifier ou supprimer cet évènement pour qu'il ne dépende plus de ce réservoir avant de pouvoir le supprimer.") + "

"; + else message += "

" + qsTr("Ce réservoir est utilisé par les %1 évènements ci-dessous.
Vous devez modifier ou supprimer ces évènements pour qu'ils ne dépendent plus de ce réservoir avant de pouvoir le supprimer.").arg(nb) + "

"; + + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + message += "‣ " + (i+1) + " : " + res[1] + "
"; + } + } + } + + //========================================================================= + // Recherche de l'impact de cette suppression sur les capteurs calculés : + /* Retour de la forme : + +-------------+ + | Nom_capteur | + +-------------+ + | Calculation | + | Calcul 2 | + +-------------+ */ + req = 'SELECT Nom FROM TB_Capteurs '; + req += ' WHERE Type_entrees=' + shipheart_capteur_type_entrees_calculee_booleen + ' '; + req += ' AND Entrees LIKE "%/' + shipheart_source_mesure_reservoir + ':' + id_reservoir + '/%" '; +//console.log("Requête = [ " + req + "; ]") + nb = bdd.requete(req); + + if (nb > 0) + { + if (nb === 1) message += "

" + qsTr("Ce réservoir est utilisé par le capteur calculé ci-dessous.
Vous devez modifier ou supprimer ce capteur calculé pour qu'il ne dépende plus de ce réservoir avant de pouvoir le supprimer.") + "

"; + else message += "

" + qsTr("Ce réservoir est utilisé par les %1 capteurs calculés ci-dessous.
Vous devez modifier ou supprimer ces capteurs calculés pour qu'ils ne dépendent plus de ce réservoir avant de pouvoir le supprimer.").arg(nb) + "

"; + + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + message += "‣ " + (i+1) + " : " + res[0] + "
"; + } + } + } + + //========================================================================= + // 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 = 1; + boite_information.imageTitreSource = "/images/attention.png"; + boite_information.message = message; + boite_information.alignementMessage = Text.AlignLeft + boite_information.open(); + + return(-1); + } + } + + + //============================================================================================================= + // Suppression du réservoir + //============================================================================================================= + function suppression_reservoir() + { + var req; + var i, j; + + // Suppression du réservoir dans TB_Réservoirs : + req = 'DELETE FROM TB_Reservoirs WHERE Cle_primaire=' + id_reservoir + ' '; +//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 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.... + } + } + + + +} + diff --git a/config_ship2net.qml b/config_ship2net.qml new file mode 100644 index 0000000..fd2970a --- /dev/null +++ b/config_ship2net.qml @@ -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; iunknown" + 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é.
\ +Vérifiez avant tout que ShipBase est bien sous tension et qu'il est bien connecté au réseau local.
\ +Vérifiez ensuite que ShipRS est également connecté au réseau local via son port Ethernet.
\ +Enfin, assurez-vous que l'adresse IP de ShipBase sur le réseau local est bien celle renseignée ci-dessous.
\ +Dans le cas contraire, vous pouvez la mettre à jour puis cliquer sur [Enregistrer].
\ +Attention : La prise en compte de cette nouvelle adresse ne sera prise en compte qu'après un redémarrage de ShipRS.

+The connection to ShipBase has failed.
+First of all, check that ShipBase is switched on and connected to the local network.
+Then check that ShipRS is also connected to the local network via its Ethernet port.
+Finally, make sure that the IP address of ShipBase on the local network is the one given below.
+If not, you can update it and click on [Save].
+Please note: The new address will only be taken into account after a restart of ShipRS.
"; + 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
ShipBase IP address on local network" + 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
Screen size" + 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
Save" + 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
Restart ShipRS" + 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
/!\\ ShipRS config file can't be accessed"; + } + + //----------------------------------------------------------------------------------------- + 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.
/!\\ 'shiprs.conf' file cannot be written to"; + } + else + { + configuration_modifiee = true; + message_info = "Les nouveaux paramètres ont été enregistrés.
Vous pouvez maintenant maintenir appuyé le bouton [Redémarrer ShipRS] jusqu'au redémarrage pour que ces nouveaux paramètres soient pris en compte.
The new settings have been saved.
You can now press and hold the [Restart ShipRS] button until the system restarts to take these new settings into account.
"; + } +//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...
The [192.168.4.1] IP address is not authorized. Please enter a different address..."; + + + } + //----------------------------------------------------------- + // 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...
The IP address entered is invalid and cannot be saved. Please enter a valid string..."; + + // 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 "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 niveaux (batteries et réservoirs). La page permet de visualiser ou modifier +// des points et d'afficher la courbe de conversion résultante. Il est aussi possible de recharger la config usine. +// 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, en cliquant sur le bouton "courbe de conversion" +//======================================================================================================================================================================== + +import QtQuick 2.12 +import QtQuick.Controls 2.12 +import QtQml.Models 2.1 +import QtCharts 2.3 + + +import qt.koriolan.shipheart 1.0 +import"fonctions.js" as Fonctions +import"fonctions_batteries.js" as Fonctions_batteries +import"fonctions_reservoirs.js" as Fonctions_reservoirs + + +Shipheart_page { + id: page_config_valeurs_niveaux + + + // Mis en forme : + readonly property double pourcentage_largeur_colonne_gauche: 0.25 + readonly property double pourcentage_hauteur_ligne_haut: 0.70 + 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 nombre_lignes_points_visibles: 6 + readonly property int diametre_points_deplacables: 200 + readonly property double coeff_fleche_reglage_fin: 0.8 + + 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 string texte_titre: "Courbe de conversion" + property string texte_aucun_element: "Aucun élément n'est actuellement configuré" + property bool courbe_flag_vide: 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_nombre_max_points_atteint: false + property bool flag_affichage_reglage_fin: false + property int point_en_cours: -1 + property int point_a_supprimer: -1 + + + // Données : + property string table: "" + property int id: 0 + property string champ_liste: "" // Permet de conserver le nom du champ utilisé pour stocker la liste dans la table TB_Batteries ou TB_Reservoirs + property int nb_points: 0 + property string unite_x: "" + property int precision_x: 3 + property int precision_x_graphique: 2 + property int tension_nominale: 12 + property int type_entrees_reservoir: 0 + property int mode_reservoir: 0 + property int sous_mode_reservoir: 0 + property int capacite: 0 + property int valeur_timer_appui_long: 0 + + property real xMin + property real xMax + property real yMin + property real yMax + property bool flag_yMax_hors_limite: false + property bool flag_valeurs_discretes: false // Indique que les capteurs en cours d'utilisation ne peuvent prendre que des valeurs discretes (a priori, uniquement le cas d'Entrées Aux) + property int nb_intervalles_graphique: 10 // Nb : cela se traduit par N+1 valeurs d'absice + property int etat_entrees: 0 // 0=Ok, 1=Electrodes plongées dans le désordre + + property double step_reglage_fin_vertical: 0.1 + property double step_reglage_fin_horizontal: 0.1 + + // 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_valeur_actuelle(); + } + } + } + + //=========================================================== + // 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 point : + if (point_a_supprimer !== -1) supprimer_point(); // On ne peut pas utiliser 'mousearea_bouton_suppression_point.pressed' car il ya 1 bouton pour chaque délégué et cela génère une erreur (à juste raison car on ne saurait pas lequel) + + //--------------------------------------------- + // Enregistrement : + if (mousearea_bouton_enregistrer.pressed) + { + if (flag_nouvelles_valeurs) enregistrement(); + } + + //--------------------------------------------- + // Config usine : + if (mousearea_bouton_courbe_usine.pressed) + { + flag_init = true; + courbe_usine(); + mise_a_jour_valeur_actuelle(); + enregistrement(); + flag_init = false; + } + } + } + } + + // Titre de la page : + Shipheart_titre_1 {titre:texte_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) + clip:true // Evite que le ListView suivant ne puisse dépasser du rectangle + color: "transparent" + + ListModel { + id: modele_points + } + + ListView { + id: liste_points + anchors.fill: parent + model: modele_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 + + 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_suppression_point.pressed + } + Text { + id: no_ligne // Premier élément du bouton : n° de ligne + width: parent.width * 0.2; + anchors.verticalCenter: parent.verticalCenter + horizontalAlignment: Text.AlignHCenter + text: index + 1 + font.pixelSize: 14 + font.bold: true + color: couleur_gris_moyen + } + Text { + id: xs // Deuxième élément du bouton : la valeur de X + x: no_ligne.width; + width: parent.width * 0.4; + anchors.verticalCenter: parent.verticalCenter + horizontalAlignment: Text.AlignHCenter + text: Number(model.x).toLocaleString(Qt.locale(),'f',precision_x) + " " + unite_x + font.pixelSize: 14 + color: couleur_blanc_casse + } + Text { + id: ys_pc // Troisième élément du bouton : valeur de Y en % + x: no_ligne.width + xs.width; + width: parent.width - no_ligne.width - xs.width; + anchors { + verticalCenter: parent.verticalCenter + verticalCenterOffset: (table === "TB_Reservoirs") ? -10 : 0 + } + horizontalAlignment: Text.AlignHCenter + text: Number(model.y).toLocaleString(Qt.locale(),'f',1) + " %" + font.pixelSize: 14 + rightPadding: 20 + color: couleur_blanc_casse + } + Text { + id: ys_l // Troisième élément du bouton : valeur de Y en litres (ou unité de volume en cours) + visible: (table === "TB_Reservoirs") + x: no_ligne.width + xs.width; + width: parent.width - no_ligne.width - xs.width; + anchors { + verticalCenter: parent.verticalCenter + verticalCenterOffset: 10 + } + horizontalAlignment: Text.AlignHCenter + text: Fonctions.conversion_volume((Number(model.y) * capacite / 100), shipheart_unite_volume, shipheart_unite_volume_symbole, 1); + font.pixelSize: 14 + rightPadding: 20 + color: couleur_blanc_casse + } + 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 ? true : false + } + MouseArea { + id: mousearea_bouton_suppression_point + anchors.fill: parent + onPressed: { // Déclenché lors de l'appui inital + if ((index === point_en_cours) && // On n'autorise la suppression d'un point que s'il est sélectionnés depuis le graphique (évite que les tentative de suppression se traduisent par un toggle de la sélection) + (!flag_valeurs_discretes) && // On ne peut pas supprimer de points sur des électrodes plongées + (nb_points > 2)) // On n'accepte pas de supprimer des points s'il n'y en a plus que 2 (ou moins)... + { + timer_appui_long.running = true; + valeur_timer_appui_long = 0; + point_a_supprimer = point_en_cours; + } + 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; + point_a_supprimer = -1; + + // Sélection du point : + if (point_en_cours !== -1) modele_points.setProperty(point_en_cours, "actif", false); // Déselection du point en cours précédent + modele_points.setProperty(index, "actif", true); // Sélection du nouveau point en cours + point_en_cours = index; // Mémorisation du point en cours + } + onDoubleClicked: { + flag_affichage_reglage_fin = !flag_affichage_reglage_fin; + } + + 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; + point_a_supprimer = -1; + } + } + } + + Label { + anchors.fill: parent + horizontalAlignment: Qt.AlignHCenter + verticalAlignment: Qt.AlignVCenter + text: qsTr("Aucun point de conversion n'est configuré pour le moment...") + color: couleur_rouge_transparent + font.pixelSize: 15 + font.bold: true + wrapMode: Label.Wrap + visible: courbe_flag_vide + } + } + } + + //------------------------------------------------------- + // 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 + + //----------------------- + // Ajout d'un point : + Rectangle { + width: parent.width + height: (parent.height/3) - (parent.spacing/3) + color: shipheart_couleur_fond_bouton + radius: shipheart_rayon_bouton + visible: !flag_valeurs_discretes // On ne peut pas ajouter de points sur des électrodes plongées + + Text { + anchors { + verticalCenter: parent.verticalCenter + horizontalCenter: parent.horizontalCenter + } + text: "+" + font.pixelSize: 40 + font.bold: true + color: !flag_nombre_max_points_atteint ? couleur_blanc_casse : couleur_gris_fonce + } + MouseArea{ + id: mousearea_ajout_point + anchors.fill : parent + onClicked: { + if (!flag_nombre_max_points_atteint) ajouter_point(); + else + { + boite_nombre_max_points_atteint.imageTitreSource = "/images/ampoule.png"; + boite_nombre_max_points_atteint.message = qsTr("Le nombre maximal de points d'étalonnage a été atteint (%1 points)
Vous ne pouvez pas en ajouter sans en avoir prélablement supprimé.").arg(courbe_etalonnage_max_points); + boite_nombre_max_points_atteint.open(); + } + } + onPressed: shipheart_clic(); + enabled: point_en_cours !== -1 // Si aucun point n'est sélectionné, on n'autorise pas l'ajout (car on ne sait pas où insérer le nouveau point). NB : ce cas ne doit pas arriver car on fait en sorte d'avoir toujours un point actif... + } + } + + //----------------------- + // Paramètres usine : + Rectangle { + width: parent.width + height: (parent.height/3) - (parent.spacing/3) + color: shipheart_couleur_fond_bouton + radius: shipheart_rayon_bouton + + 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_courbe_usine.pressed + } + Text { + anchors { + verticalCenter: parent.verticalCenter + horizontalCenter: parent.horizontalCenter + } + font.pixelSize: 20 + text: qsTr("Courbe usine") + color: couleur_blanc_casse + } + MouseArea { + id: mousearea_bouton_courbe_usine + 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; + } + } + } + + //----------------------- + // Bouton Enregistrer : + Rectangle { + width: parent.width + height: (parent.height/3) - (parent.spacing/3) + color: shipheart_couleur_fond_bouton + radius: shipheart_rayon_bouton + + 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_vert_transparent + radius: shipheart_rayon_bouton + visible: mousearea_bouton_enregistrer.pressed + } + 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 { + id: mousearea_bouton_enregistrer + 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; + } + } + } + } + } + + + //------------------------------------------------------- + // 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" + + //======================== + // Graphique : + ChartView { + id: graphique + antialiasing: true + anchors.fill: parent + margins { // Attention : ces marges représentent l'espace entre le ChartView et sa plotArea (c'est donc plutôt un padding...) + right: 50 + bottom: 10 + left: 0 + top: 20 + } + width: parent.width + backgroundColor: "transparent" + legend { + visible: false + } + + ValueAxis { + id: axisX + min: xMin // Défini pendant l'init + max: xMax // Idem + tickCount: nb_intervalles_graphique + 1 // Il faut N+1 pour avoir N intervalles + labelFormat: "%." + precision_x_graphique + "f" + labelsFont:Qt.font({pointSize: 10}) + color: couleur_gris_moyen + shadesVisible: false + gridVisible: true + gridLineColor: couleur_gris_tres_fonce + labelsColor: couleur_gris_tres_tres_pale + titleText: "" + unite_x + "" + } + ValueAxis { + id: axisY + min: yMin // Défini pendant l'init + max: yMax // idem + tickCount: 11 + labelFormat: "%.0f" + labelsFont:Qt.font({pointSize: 10}) + color: couleur_gris_moyen + shadesColor: courbes_couleur_shades_fond + shadesVisible: true + gridVisible: true + gridLineColor: couleur_gris_tres_fonce + labelsColor: couleur_gris_tres_tres_pale + titleText: "%" + } + + LineSeries { + id: courbe // Courbe fin bleue représentant la courbe finale (elle suit donc les modifications au fur et à mesure) + axisX: axisX + axisY: axisY + capStyle: Qt.RoundCap + style: Qt.SolidLine + width: courbes_epaisseur_bordure // On reprend les valeurs standard des courbes de ShipHeart + color: shipheart_couleur_bordure_courbes // Idem pour la couleur + } + ScatterSeries { + id: points_originaux // Uniquement les points. De plus, ils ne bougent pas au fur et à mesure et représentent donc la version initiale. + axisX: axisX + axisY: axisY + } + ScatterSeries { + id: points_nouveaux // Uniquement les points. Mais ceux-ci changent avec les modifications. Ils suivent donc la 'courbe' et sont utilisés juste pour la renforcer. + axisX: axisX + axisY: axisY + borderColor: couleur_rouge + borderWidth: 3 + markerSize: 4 + markerShape: ScatterSeries.MarkerShapeRectangle + } + LineSeries { + id: croix_h // Trace horizontale de la croix de valeur actuelle + axisX: axisX + axisY: axisY + style: Qt.DashLine + width: 1 + color: couleur_jaune_post_it + visible: !etat_entrees && !courbe_flag_vide + } + LineSeries { + id: croix_v // Trace verticale de la croix de valeur actuelle + axisX: axisX + axisY: axisY + style: Qt.DashDotLine + width: 1 + color: couleur_jaune_post_it + visible: !etat_entrees && !courbe_flag_vide + } + + Text { // Contient la valeur actuelle sur l'axe X + id: texte_valeur_x + anchors.top: parent.top + font.pixelSize: 18 + font.weight: Font.Bold + color: !flag_yMax_hors_limite ? couleur_jaune_post_it : couleur_rouge + visible: !etat_entrees && !courbe_flag_vide + } + Text { // Contient la valeur actuelle sur l'axe Y + id: texte_valeur_y + anchors.right: parent.right + font.pixelSize: 18 + font.weight: Font.Bold + color: couleur_jaune_post_it + visible: !etat_entrees && !courbe_flag_vide + } + + Rectangle { + id: rectangle_remplissage + x: graphique.plotArea.x + + width: graphique.plotArea.width + color: couleur_bleu_koriolan_transparent + visible: !etat_entrees && !courbe_flag_vide + } + + // Ajout des points dragables : + // On utilise un répéteur qui se base sur le même modèle que l'écran de gauche. + // Chaque délégué est un rectangle retaillé en cercle (!) sur lequel on superpose un mouseArea. + // C'est ce MouseArea qui est dragable avec comme target le rectangle/cercle sur lequel il est. + // Quand on bouge la Mouserarea, elle bouge le rectangle/cercle. Et quand on détecte un changement + // de coordonnées du rectangle/cercle, on lance une fonction de mise à jour du modèle de 'courbe' et 'points_nouveaux' + // qui sont donc mis à jour en temps réel. + // En plus, dès qu'on touche l'une des MouseArea, on met en actif le bouton correspondant de l'écran de gauche via OnPressed de MouseArea. + Repeater { + model: modele_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 et qu'il fait aligner le rectangle/cerlce sur ces nouvelles coordonnées. + + radius: diametre_points_deplacables // Défini dans l'entete + width: radius / 2 // Rectangle => devient cercle + height: width + border { + width: 5 + color: (!flag_valeurs_discretes || (etat_entrees === 0)) ? + "transparent" : + (modele_points.get(index).etat_entree_discrete ? couleur_bleu_koriolan : couleur_bleu_koriolan_tres_tres_transparent) + } + color: modele_points.get(index).actif ? couleur_bleu_koriolan_transparent : couleur_bleu_koriolan_tres_tres_transparent + + 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_gris_tres_pale + } + onXChanged: { // Si le rectangle/cercle a bougé (avec le doigt), on met à jour les valeurs de 'courbe', 'points_nouveaux' et 'modèle_points' (ce dernier correspondant à la liste gauche) + if(mouse_area_point_deplacable.drag.active) { + point_deplacable.adjustValue(this, index) + } + } + onYChanged: { // Iem pour l'axe Y + if(mouse_area_point_deplacable.drag.active) { + point_deplacable.adjustValue(this, index) + } + } + + + + + MouseArea { + id: mouse_area_point_deplacable // Zone dragable + enabled: !flag_affichage_reglage_fin || (index === point_en_cours) // On dévalide les zones dragables des autres points lorsqu'on est en mode 'réglage fin' car sinon ils interceptent les clicks sur les flèches de direction (pas trouvé comment gérer cela avec le paramètre Z...) + anchors.fill: parent + drag.target: point_deplacable + drag.axis: flag_valeurs_discretes ? Drag.YAxis : Drag.XAndYAxis + + // Limitation des mouvements à la zone du graphique. Les valeurs de Min et Max du graphique sont donc importantes car on ne pourra pas aller au-delà... +// Pour les mouvements X, on limite en plus aux positions X entre le point précédent et le point suivant (cela permet de n'avoir jamais une courbe qui "revient" sur elle même). +/* drag.minimumX: Math.max( graphique.plotArea.x , + Math.min( ((index > 0) ? (graphique.mapToPosition(courbe.at(index-1), courbe).x) : (graphique.plotArea.x + graphique.plotArea.width)), + ((index < modele_points.count) ? (graphique.mapToPosition(courbe.at(index+1), courbe).x) : (graphique.plotArea.x + graphique.plotArea.width))) ) + - (point_deplacable.width / 2) +*/ + drag.minimumX: graphique.plotArea.x - (point_deplacable.width / 2) +/* drag.maximumX: Math.min( (graphique.plotArea.x + graphique.plotArea.width) , + Math.max( ((index > 0) ? (graphique.mapToPosition(courbe.at(index-1), courbe).x) : (graphique.plotArea.x)), + ((index < modele_points.count) ? (graphique.mapToPosition(courbe.at(index+1), courbe).x) : (graphique.plotArea.x))) ) + - (point_deplacable.width / 2) +*/ + drag.maximumX: graphique.plotArea.x + graphique.plotArea.width - (point_deplacable.width / 2) + + drag.minimumY: graphique.plotArea.y - (point_deplacable.height / 2) // + drag.maximumY: graphique.plotArea.y + graphique.plotArea.height - (point_deplacable.height / 2) // importantes car on ne pourra pas aller au-delà... + + onClicked: { + if (point_en_cours !== -1) modele_points.setProperty(point_en_cours, "actif", false); + modele_points.setProperty(index, "actif", true); + point_en_cours = index; + liste_points.currentIndex = index // Permet de ramener le bouton correspondant dans la zone visible du ListView de gauche + } + } + onFlag_init_point_deplacableChanged: { + adjustPosition(this, index) // Activé en fin d'init : Positionne le rectangle/cercle sur la valeur initiale du modèle. + } + + 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é... + adjustPosition(this, index) // Ajuste la position du rectangle/cercle selon les coordonnées présentes dans 'modele_points' + } + } + function adjustPosition(item, index) { + let point = Qt.point(modele_points.get(index).x, modele_points.get(index).y) + let position = graphique.mapToPosition(point, courbe) + item.x = position.x - item.width / 2 + item.y = position.y - item.height / 2 + + } + function adjustValue(item, index) { + let position = Qt.point(item.x + item.width / 2, item.y + item.height / 2) + let point = graphique.mapToValue(position, courbe) + modele_points.setProperty(index, "x", point.x) + modele_points.setProperty(index, "y", point.y) + modele_points.setProperty(index, "changed", true) + courbe.replace(courbe.at(index).x, courbe.at(index).y, point.x, point.y) + points_nouveaux.replace(points_nouveaux.at(index).x, points_nouveaux.at(index).y, point.x, point.y) + flag_nouvelles_valeurs = true; + } + + //------------------------------------------------------------ + // Flèches de réglage fin : + Rectangle { // Flèche vers le haut : + id: bouton_reglage_fin_haut + width: (diametre_points_deplacables / 2) + height: (diametre_points_deplacables / 4) + y: -(diametre_points_deplacables / 4) + color: "transparent" + visible: flag_affichage_reglage_fin && (index === point_en_cours) + Image { + anchors { + horizontalCenter: parent.horizontalCenter + verticalCenter: parent.verticalCenter + } + source: "/images/fleche_suite_haut.png" + width: parent.width * coeff_fleche_reglage_fin + height: parent.height * coeff_fleche_reglage_fin + opacity: 0.5 + } + MouseArea { + id: mouse_area_reglage_fin_haut + anchors.fill: parent + onClicked: { + var new_val = modele_points.get(point_en_cours).y + step_reglage_fin_vertical; + if (new_val > yMax) new_val = yMax; + modele_points.setProperty(point_en_cours, "y", new_val); + modele_points.setProperty(point_en_cours, "changed", true); + courbe.replace(courbe.at(point_en_cours).x, courbe.at(point_en_cours).y, modele_points.get(point_en_cours).x, modele_points.get(point_en_cours).y); + points_nouveaux.replace(points_nouveaux.at(point_en_cours).x, points_nouveaux.at(point_en_cours).y, modele_points.get(point_en_cours).x, modele_points.get(point_en_cours).y); + point_deplacable.y = graphique.plotArea.y + (graphique.plotArea.height * (100 - modele_points.get(point_en_cours).y) / 100) - (diametre_points_deplacables / 4); + flag_nouvelles_valeurs = true; + } + } + } + Rectangle { // Flèche vers le bas : + id: bouton_reglage_fin_bas + width: (diametre_points_deplacables / 2) + height: (diametre_points_deplacables / 4) + y: (diametre_points_deplacables / 2) + color: "transparent" + visible: flag_affichage_reglage_fin && (index === point_en_cours) + Image { + anchors { + horizontalCenter: parent.horizontalCenter + verticalCenter: parent.verticalCenter + } + source: "/images/fleche_suite_bas.png" + width: parent.width * coeff_fleche_reglage_fin + height: parent.height * coeff_fleche_reglage_fin + opacity: 0.5 + } + MouseArea { + id: mouse_area_reglage_fin_bas + anchors.fill: parent + onClicked: { + var new_val = modele_points.get(point_en_cours).y - step_reglage_fin_vertical; + if (new_val < yMin) new_val = yMin; + modele_points.setProperty(point_en_cours, "y", new_val) + modele_points.setProperty(point_en_cours, "changed", true) + courbe.replace(courbe.at(point_en_cours).x, courbe.at(point_en_cours).y, modele_points.get(point_en_cours).x, modele_points.get(point_en_cours).y) + points_nouveaux.replace(points_nouveaux.at(point_en_cours).x, points_nouveaux.at(point_en_cours).y, modele_points.get(point_en_cours).x, modele_points.get(point_en_cours).y) + point_deplacable.y = graphique.plotArea.y + (graphique.plotArea.height * (100 - modele_points.get(point_en_cours).y) / 100) - (diametre_points_deplacables / 4) + flag_nouvelles_valeurs = true; + } + } + } + Rectangle { // Flèche vers la gauche : + id: bouton_reglage_fin_gauche + width: (diametre_points_deplacables / 4) + height: (diametre_points_deplacables / 2) + x: -(diametre_points_deplacables / 4) + color: "transparent" + visible: flag_affichage_reglage_fin && (index === point_en_cours) && !flag_valeurs_discretes + Image { + anchors { + horizontalCenter: parent.horizontalCenter + verticalCenter: parent.verticalCenter + } + source: "/images/fleche_suite_gauche.png" + width: parent.width * coeff_fleche_reglage_fin + height: parent.height * coeff_fleche_reglage_fin + opacity: 0.5 + } + MouseArea { + id: mouse_area_reglage_fin_gauche + anchors.fill: parent + onClicked: { + var new_val = modele_points.get(point_en_cours).x - step_reglage_fin_horizontal; + if (new_val < xMin) new_val = xMin; + modele_points.setProperty(point_en_cours, "x", new_val) + modele_points.setProperty(point_en_cours, "changed", true) + courbe.replace(courbe.at(point_en_cours).x, courbe.at(point_en_cours).y, modele_points.get(point_en_cours).x, modele_points.get(point_en_cours).y) + points_nouveaux.replace(points_nouveaux.at(point_en_cours).x, points_nouveaux.at(point_en_cours).y, modele_points.get(point_en_cours).x, modele_points.get(point_en_cours).y) + point_deplacable.x = graphique.plotArea.x + (graphique.plotArea.width * (modele_points.get(point_en_cours).x - xMin) / (xMax - xMin)) - (diametre_points_deplacables / 4) + flag_nouvelles_valeurs = true; + } + } + } + Rectangle { // Flèche vers la droite : + id: bouton_reglage_fin_droite + width: (diametre_points_deplacables / 4) + height: (diametre_points_deplacables / 2) + x: (diametre_points_deplacables / 2) + color: "transparent" + visible: flag_affichage_reglage_fin && (index === point_en_cours) && !flag_valeurs_discretes + Image { + anchors { + horizontalCenter: parent.horizontalCenter + verticalCenter: parent.verticalCenter + } + source: "/images/fleche_suite_droite.png" + width: parent.width * coeff_fleche_reglage_fin + height: parent.height * coeff_fleche_reglage_fin + opacity: 0.5 + } + MouseArea { + id: mouse_area_reglage_fin_droite + anchors.fill: parent + onClicked: { + var new_val = modele_points.get(point_en_cours).x + step_reglage_fin_horizontal; + if (new_val > xMax) new_val = xMax; + modele_points.setProperty(point_en_cours, "x", new_val) + modele_points.setProperty(point_en_cours, "changed", true) + courbe.replace(courbe.at(point_en_cours).x, courbe.at(point_en_cours).y, modele_points.get(point_en_cours).x, modele_points.get(point_en_cours).y) + points_nouveaux.replace(points_nouveaux.at(point_en_cours).x, points_nouveaux.at(point_en_cours).y, modele_points.get(point_en_cours).x, modele_points.get(point_en_cours).y) + point_deplacable.x = graphique.plotArea.x + (graphique.plotArea.width * (modele_points.get(point_en_cours).x - xMin) / (xMax - xMin)) - (diametre_points_deplacables / 4) + flag_nouvelles_valeurs = true; + } + } + } + } + } + + Text { + id: texte_etat_entrees_invalide // Utilisé si aucune valeur n'est dispo, ce qui ne doit pas arriver trop souvent.... + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + width: graphique.plotArea.width + text: qsTr("La valeur lue sur les electrodes plongées de ce réservoir est incohérente.
Vérifier l'ordre de cablage des électrodes sur les entrées auxiliaires à l'arrière de ShipBase. ") + font.pixelSize: 20 + wrapMode: Text.Wrap + horizontalAlignment: Text.AlignHCenter + font.weight: Font.Bold + color: couleur_rouge + visible: etat_entrees + } + Text { + id: texte_courbe_vide // Utilisé si aucune valeur n'est dispo, ce qui ne doit pas arriver trop souvent.... + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + text: qsTr("Aucune donnée n'est disponible...") + font.pixelSize: 20 + font.weight: Font.Bold + color: couleur_rouge + visible: courbe_flag_vide + } + + } // Fin du graphique + } + + + //------------------------------------------------------- + // 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(); + + 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
Cliquer sur Annuler pour revenir en arrière et les enregistrer.
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: + } + } + } + + //------------------------------------------------------- + // Boite d'e validation'info sur nombre max de points atteint : + // 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_nombre_max_points_atteint + niveau: 0 + onClicked: { + switch(bouton) + { + case shipheart_boite_dialogue_bouton_1: // Si Ok + break; + case shipheart_boite_dialogue_bouton_2: // Si Annuler + 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; + var champs; + var nom, liste; + var chaines_entrees; + + flag_nouvelles_valeurs = false; + + // Paramètres spécifiques AVANT init : + switch(table) + { + case "TB_Batteries": + champ_liste = "Liste_tension_soc"; + champs = "Nom , Tension_nominale, " + champ_liste; + break; + case "TB_Reservoirs": + champ_liste = "Liste_valeurs_niveaux"; + champs = "Nom , Type_entrees, Entrees, Mode_entrees, Type_sonde_entrees, Capacite, " + champ_liste; + break; + default: + console.log("/!\\ Le type de table demandé n'est pas connu. La page est refermée..."); + stackView.pop(); // Il est inutile de rester si le type d'objet n'est pas connu... + break; + } + + + i = 0; + // Récupération des infos correspondant à l'élément concerné : + req = 'SELECT ' + champs + ' FROM ' + table + ' WHERE Cle_primaire=' + id; +//console.log("Requête = [ " + req + " ]"); + res = bdd.requete_unique(req); + // Récupération des données selon le type d'objet : + switch(table) + { + case "TB_Batteries": + nom = res[i++]; + tension_nominale = Number(res[i++]); + liste = res[i++]; + flag_valeurs_discretes = false; + break; + + case "TB_Reservoirs": + nom = res[i++]; + type_entrees_reservoir = Number(res[i++]); + chaines_entrees = res[i++].split(';'); + mode_reservoir = Number(res[i++]); + sous_mode_reservoir = Number(res[i++]); + capacite = Number(res[i++]); + liste = res[i++]; + if (type_entrees_reservoir === shipheart_reservoir_type_entrees_aux) flag_valeurs_discretes = true; + else flag_valeurs_discretes = false; + break; + + // Pas de défaut car on a purgé ce cas au switch précédent... + } + + // Remplissage des courbes et modèles : + if (liste !== "") creation_courbes(liste.split(';')); + else creation_courbes(""); // L'appel avec un array vide (cas du résultat de split sur une chaine vide) donne des résultats pas très clairs... + + // Sélection du premier point à l'ouverture : + if (!courbe_flag_vide) + { + modele_points.setProperty(0, "actif", true); + point_en_cours = 0; + } + + // Paramètres spécifiques APRES init : + switch(table) + { + case "TB_Batteries": + texte_aucun_element = qsTr("Aucun point n'est actuellement configuré pour cette batterie...") + texte_titre = qsTr("Courbe de conversion de [%1]").arg(nom) + + // Valeurs de min et de max du graphique : + // Attention : ces valeurs sont utilisées pour limiter la zone dragable ! + // Donc les valeurs au-delà de ces min/max ne sont pas atteignables...!! + switch(tension_nominale) + { + default: + case 12: + xMin = 9.5; + xMax = 14.5; + break; + case 24: + xMin = 19; + xMax = 29; + break; + case 48: + xMin = 40; + xMax = 56; + break; + } + yMin = 0; + yMax = 100; + unite_x = "Volts"; + precision_x = 2; + precision_x_graphique = 2; + step_reglage_fin_vertical = 0.1; // En %, donc 0.1% + step_reglage_fin_horizontal = 0.01; // En V, donc 10mV + + break; + + case "TB_Reservoirs": + texte_aucun_element = qsTr("Aucun réservoir n'est actuellement configuré...") + texte_titre = qsTr("Courbe de conversion de [%1]").arg(nom) + + // Valeurs de min et de max du graphique : + // Attention : ces valeurs sont utilisées pour limiter la zone dragable ! + // Donc les valeurs au-delà de ces min/max ne sont pas atteignables...!! + switch(type_entrees_reservoir) + { + case shipheart_reservoir_type_entrees_aux : + xMin = 0; + xMax = 0; + for (i = 0; i < shipheart_reservoir_max_nombre_entrees_aux; i ++) + { + if (chaines_entrees[i]) xMax ++; + else break; + } + mode_reservoir = xMax; // Est utilisé pouer appeler 'Fonctions_reservoirs.chaine_valeur_niveau_reservoir_usine()' + sous_mode_reservoir = 0; + nb_intervalles_graphique = xMax; // Permet d'ajuster le nombre d'intervalles au nombre d'entrées utilisé dans ce cas + + unite_x = ""; + precision_x = 0; + precision_x_graphique = 0; + step_reglage_fin_vertical = (0.1) * 100 / capacite; + step_reglage_fin_horizontal = 0.1; // Non utilisé avec ce type de sondes... + break; + + case shipheart_reservoir_type_entrees_level_sensor: + switch (mode_reservoir) // Mode : + { + case shipheart_reservoir_mode_entrees_level_sensor_0_10v: // 0-10V + sous_mode_reservoir = 0; + xMin = 0.0; + xMax = 12.0; + unite_x = "Volts"; + precision_x = 2; + precision_x_graphique = 1; + step_reglage_fin_vertical = (0.1) * 100 / capacite; + step_reglage_fin_horizontal = 0.01; + + break; + case shipheart_reservoir_mode_entrees_level_sensor_500r: // 0-500R + switch(sous_mode_reservoir) // Sous-mode : + { + case shipheart_reservoir_mode_entrees_level_sensor_500r_0_190r: // 0-190R + xMin = 0; + xMax = 200; + break; + case shipheart_reservoir_mode_entrees_level_sensor_500r_240_30r: // 240-30R + xMin = 0; + xMax = 260; + break; + case shipheart_reservoir_mode_entrees_level_sensor_500r_0_500r: // 0-500R + default: + xMin = 0; + xMax = 700; + break; + } + unite_x = String.fromCharCode(unicode_omega); //"Ohms"; + precision_x = 1; + precision_x_graphique = 0; + step_reglage_fin_vertical = (0.1) * 100 / capacite; + step_reglage_fin_horizontal = 0.1; + break; + case shipheart_reservoir_mode_entrees_level_sensor_4_20ma: // 4-20mA + sous_mode_reservoir = 0; + xMin = 0; + xMax = 22.0; + unite_x = "mA"; + precision_x = 1; + precision_x_graphique = 1; + step_reglage_fin_vertical = (0.1) * 100 / capacite; + step_reglage_fin_horizontal = 0.1; + break; + } + + break; + + default: + console.log("/!\\ Le type d'entrée est incorrect. La page est refermée...") + stackView.pop(); // Il est inutile de rester si le type d'objet n'est pas connu... + break; + } + yMin = 0; + yMax = 100; + + break; + + default: + texte_aucun_element = qsTr("Aucun point n'est actuellement configuré pour cet élément...") + texte_titre = qsTr("Courbe de conversion de type INCONNU") + } + + // Mise à jour des données actuelles (forcément en fin de traitement car nécessite de connaitre les min et max) : + mise_a_jour_valeur_actuelle(); + + flag_init = false; // Indique que l'init est terminée + } + + //============================================================================================================= + // Met à jour 'modele_points', 'courbe' et 'points_nouveaux' avec les paramètres contenu dans 'chaines_points' + //============================================================================================================= + function creation_courbes(chaines_points) + { + var i; + var chaine_point; + var point; + var x,y; + + // RAZ des courbes : + nb_points = 0; + modele_points.clear(); + courbe.clear(); + points_originaux.clear(); + points_nouveaux.clear(); + courbe_flag_vide = true; + point_en_cours = -1; + point_a_supprimer = -1; + + 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 : + i = 0; + for (chaine_point of chaines_points) + { + point = chaine_point.split('/'); + x = Number(point[0]); + y = Number(point[1]); + + if (flag_valeurs_discretes) x = i ++; + + modele_points.append({ "x": x, // Modèle pour la liste de gauche + les rectangle/cercles utilisés pour les bouger + "y": y, + "actif": false, + "etat_entree_discrete": false, + "changed": false}); + courbe.append(x, y); // Courbe linéaire bleue + points_originaux.append(x, y); // Points d'origine (qui ne bougeront plus) + points_nouveaux.append(x, y); // Points nouveaux (qui bougeront dès qu'ils sont dragués) + + courbe_flag_vide = false; // Utilisé pour afficher le message "aucune données...' + + if (++nb_points >= courbe_etalonnage_max_points) + { + flag_nombre_max_points_atteint = true; + break; + } + } + + 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. + } + + //============================================================================================================= + // Met à jour de la valeur actuelle (notamment, la croix H et V) + //============================================================================================================= + function mise_a_jour_valeur_actuelle() + { + var req, res; + var champs; + var val_x, val_y; + var valeurs_brutes, valeur_brute; + var i; + + // RAZ des deux modèles : + croix_h.clear(); + croix_v.clear(); + + switch(table) + { + //------------------------------- + case "TB_Batteries": + req = 'SELECT Tension, Soc FROM TB_Batteries WHERE Cle_primaire=' + id; +//console.log("Requête = [ " + req + " ]"); + res = bdd.requete_unique(req); + + val_x = Number(res[0]); + val_y = Number(res[1]); + texte_valeur_x.text = val_x.toFixed(precision_x) + " " + unite_x; + texte_valeur_y.text = val_y.toFixed(0) + "%"; + + break; + + //------------------------------- + case "TB_Reservoirs": + req = 'SELECT Capacite, Valeur_brute, Niveau, Etat_entrees FROM TB_Reservoirs WHERE Cle_primaire=' + id; +//console.log("Requête = [ " + req + " ]"); + res = bdd.requete_unique(req); + + val_x = Number(res[1]); + val_y = Number(res[2]); + etat_entrees = Number(res[3]); + + // Mise à jour de l'état de chaque entrée AUX dans le cas d'électrodes plongées : + switch(type_entrees_reservoir) + { + case shipheart_reservoir_type_entrees_aux : + + // Mise à jour de l'état réel de chaque entrée AUX : + var masque = 1; + modele_points.setProperty(0, "etat_entree_discrete", false); // La valeur '0' est toujours inactive (car c'est un état par absence des autres entrées) + for (i = 1; i < nb_points; i++) + { + if ((val_x & masque) == 0) modele_points.setProperty(i, "etat_entree_discrete", false); + else modele_points.setProperty(i, "etat_entree_discrete", true); + masque <<= 1; + } + + // Recalcul de val_x pour le ramener à des puissances de 2 : + val_x = Math.log2(Number(res[1]) + 1); // Les valeurs de 0 à 15 par exemple, deviennent 1 à 16 donc 0-4 pour le log2(). NB : si la valeur est incohérente, le résultat ne sera pas entier mais cela ne pose pas de pb puisqu'il n'est pas affiché dans ce cas. + + break; + + case shipheart_reservoir_type_entrees_level_sensor: + default: + break; + } + + // Texte de la valeur X : + if (val_x > xMax) // Si la valeur est hors de l'intervalle affiché (notamment, une sonde résistive non branchée...) + { + texte_valeur_x.text = "[" + String.fromCharCode(unicode_fleche_demi_epaisse_discontinue_droite) + " " + val_x.toFixed(precision_x) + " " + unite_x + "]"; // La valeur est affichée entre [] + val_x = xMax; // On cape la position en bout de graphique + flag_yMax_hors_limite = true; + } + else + { + texte_valeur_x.text = val_x.toFixed(precision_x) + " " + unite_x; // Affichage normal + flag_yMax_hors_limite = false; + } + + // Texte de la valeur Y mis en forme avec conversion d'unité si nécessaire : + texte_valeur_y.text = val_y.toFixed(0) + "%
" + Fonctions.conversion_volume((val_y * Number(res[0]) / 100), shipheart_unite_volume, shipheart_unite_volume_symbole, 0); + + break; + + default: // Ne devrait pas arriver car déjà testé à l'init... + break; + } + + // Points de la croix de valeur actuelle : + croix_h.append(xMin, val_y); + croix_h.append(xMax, val_y); + croix_v.append(val_x, yMin); + croix_v.append(val_x, yMax); + + // Positionnement des textes X et Y surle graphique (alignés sur la croix) : + texte_valeur_x.leftPadding = graphique.mapToPosition(croix_v.at(0), croix_v).x - (texte_valeur_x.contentWidth / 2); + texte_valeur_y.topPadding = graphique.mapToPosition(croix_h.at(0), croix_h).y - (texte_valeur_y.contentHeight / 2); + + // Paramètres de hauteur et position du rectangle de remplissage : + rectangle_remplissage.height = graphique.plotArea.height * val_y / 100; + rectangle_remplissage.y = graphique.plotArea.y + (graphique.plotArea.height * (100 - val_y) / 100) + } + + //============================================================================================================= + // Met à jour 'modele_points', 'courbe' et 'points_nouveaux' avec les paramètres usines. + // NB : on ne met PAS à jour la BDD avec ces valeurs. Il faudra ensuite cliquer sur Enregistrer pour que ce soit fait. + //============================================================================================================= + function courbe_usine() + { + var i; + var chaines_points; + + switch(table) + { + case "TB_Batteries": + chaines_points = Fonctions_batteries.chaine_tension_niveau_batterie_usine(tension_nominale).split(';'); + break; + + case "TB_Reservoirs": + chaines_points = Fonctions_reservoirs.chaine_valeur_niveau_reservoir_usine(type_entrees_reservoir, mode_reservoir, sous_mode_reservoir).split(';'); + break; + + default : return; + } + + flag_nouvelles_valeurs = true; // En pratique, on n'est pas sûr que les valeurs seront différentes après la config usine c'est le principe de précaution... + + // Remplissage des courbes et modèles : + creation_courbes(chaines_points); + + // Sélection du premier point à l'ouverture : + if (!courbe_flag_vide) + { + modele_points.setProperty(0, "actif", true); + point_en_cours = 0; + } + + flag_affichage_reglage_fin = false; + } + + //============================================================================================================= + // Ajoute un point à la courbe existante + //============================================================================================================= + function ajouter_point() + { + var x, y; + var nb; + + if (point_en_cours === (modele_points.count - 1)) // Cas où on est sur le dernier point + { + if (point_en_cours > 0) + { + modele_points.setProperty(point_en_cours, "actif", false); // Dévalidation du dernier point (le nouveau point créé sera validé après sa création) + point_en_cours --; // S'il y a au moins 2 points, on se met sur le point précédent le dernier. + } + else return; // Ne doit pas arriver car on interdit la suppression dès qu'il ne rest plus que 2 points... + } + + x = modele_points.get(point_en_cours).x + ((modele_points.get(point_en_cours + 1).x - modele_points.get(point_en_cours).x) / 2); + y = modele_points.get(point_en_cours).y + ((modele_points.get(point_en_cours + 1).y - modele_points.get(point_en_cours).y) / 2); + + modele_points.insert(point_en_cours + 1, + { "x": x, // Modèle pour la liste de gauche + les rectangle/cercles utilisés pour les bouger + "y": y, + "actif": true, + "etat_entree_discrete": false, + "changed": true}); + + courbe.insert((point_en_cours + 1), x, y); // Courbe linéaire bleue + points_originaux.insert((point_en_cours + 1), x, y); // Points d'origine (qui ne bougeront plus) + points_nouveaux.insert((point_en_cours + 1), x, y); // Points nouveaux (qui bougeront dès qu'ils sont dragués) + + modele_points.setProperty(point_en_cours, "actif", false); + point_en_cours ++; // On se positionne sur le nouveau point + + flag_nouvelles_valeurs = true; // Le nouveau point, à ce stade, n'est pas enregistré ! + + if (++nb_points >= courbe_etalonnage_max_points) flag_nombre_max_points_atteint = true; + + courbe_flag_vide = false; // Utilisé pour afficher le message "aucune données...' + + 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. + } + + + //============================================================================================================= + // Supprime le point de la courbe correspondant à l'index passé en paramètre + //============================================================================================================= + function supprimer_point() + { + var x, y; + var nb; + + flag_init = true; + + if (point_a_supprimer === -1) return; + + modele_points.remove(point_a_supprimer, 1); // Modèle pour la liste de gauche + les rectangle/cercles utilisés pour les bouger + courbe.remove(point_a_supprimer); // Courbe linéaire bleue + points_originaux.remove(point_a_supprimer); // Points d'origine (qui ne bougeront plus) + points_nouveaux.remove(point_a_supprimer); // Points nouveaux (qui bougeront dès qu'ils sont dragués) + + if (--nb_points < courbe_etalonnage_max_points) flag_nombre_max_points_atteint = false; // Maj du 'nb_points' et réaffichage du bouton '+' si on est passé en-dessous du max. + if (nb_points < 1) + { + nb_points = 0; // Ne devrait pas être utile mais par précaution... + courbe_flag_vide = true; // Utilisé pour afficher le message "aucune données...' + } + + flag_nouvelles_valeurs = true; // Donne accès au bouton d'enregistrement et permet d'alerter si tentative de sortie sans avoir enregistré. + + 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. + + flag_affichage_reglage_fin = false; + + // Mise à jour du point en cours afin qu'il y en ait toujours un d'actif : + if (point_a_supprimer >= 1) point_en_cours = point_a_supprimer - 1; + else point_en_cours = 0; + modele_points.setProperty(point_en_cours, "actif", true); // On sait que le 'point_en_cours' AVANT la suppression est celui qui a été supprimé ; il n'est donc pas utile d'essayer de le rendre inactif. + + point_a_supprimer = -1; + + flag_init = false; + } + + //============================================================================================================= + // Enregistre dans la BDD les nouvelles valeurs + //============================================================================================================= + function enregistrement() + { + var i; + var req; + var chaine = ""; + var val, niv; + + // Génération de la chaine de valeurs/niveaux (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") + for(i = 0; i < modele_points.count; i++) { + if (chaine !== "") chaine += ";"; + + if (flag_valeurs_discretes) val = Math.pow(2, modele_points.get(i).x) - 1; + else val = modele_points.get(i).x.toFixed(3); + niv= modele_points.get(i).y.toFixed(2); + + chaine += val + "/" + niv; + + modele_points.setProperty(i, "changed", false) // On en profite pour RAZ tous les flags Changed + + points_originaux.replace(points_originaux.at(i).x, points_originaux.at(i).y, modele_points.get(i).x, modele_points.get(i).y) + points_nouveaux.replace(points_nouveaux.at(i).x, points_nouveaux.at(i).y, modele_points.get(i).x, modele_points.get(i).y) + } + flag_nouvelles_valeurs = false; // ainsi que le flag de nouvelles valeurs +//console.log("Chaine valeurs/niveaux = [" + chaine + " ]") + + flag_affichage_reglage_fin = false; + + // Mise à jour de l'entrée dans la table : + req = 'UPDATE ' + table + ' SET ' + champ_liste + '="' + chaine + '" WHERE Cle_primaire=' + 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); + + // NB : on ne gère pas la fin de le reconfiguration comme sur la plupart des autres pages de ce type car on ne sort pas directement de la page (après l'enregistrement, + // il faut cliquer sur BACK). De plus, même si on le fait pendant la reconfiguration, clea n'empèchera pas celle-ci de se poursuivre. + + } +} diff --git a/config_version.qml b/config_version.qml new file mode 100644 index 0000000..40dabc9 --- /dev/null +++ b/config_version.qml @@ -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("Mise à jour immédiate

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

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

Cliquez sur Annuler pour revenir en arrière et effectuer cette installation ultérieurement.") + boite_validation_securisee.alignementMessage = Text.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.
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("Suppression de version

Si vous confirmez, cette mise à jour sera définitivement supprimée.
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("Réinitialisation Usine

Si vous confirmez, tous les paramètres de ShipHeart seront complètement et définitivement effacés !

Aucune sauvegarde ne sera conservée et tout retour en arrière sera impossible...

Cliquez sur Annuler pour revenir en arrière si vous n'êtes pas certain de votre décision.

Note : En cas de doute, vous pouvez effectuer une Sauvegarde et la stocker sur une clé externe 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 %1 est disponible.

Souhaitez-vous : ").arg(version_nouvelle); + break; + + //----------------------------- + // Fichier dans A_CHARGER : + case shipheart_demande_maj_soft_chargement: + message = qsTr("La version %1 est disponible.

Elle sera automatiquement installée lors du prochain démarrage de ShipHeart.
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. + } +} + diff --git a/ephemeride.qml b/ephemeride.qml new file mode 100644 index 0000000..9c01671 --- /dev/null +++ b/ephemeride.qml @@ -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 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' + } +} + diff --git a/etalonnage_capteur.qml b/etalonnage_capteur.qml new file mode 100644 index 0000000..eee4300 --- /dev/null +++ b/etalonnage_capteur.qml @@ -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); + } + +} + diff --git a/etalonnage_carte.qml b/etalonnage_carte.qml new file mode 100644 index 0000000..d2168e2 --- /dev/null +++ b/etalonnage_carte.qml @@ -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.

+ Essayer de modifier au moins l'un des deux points de référence en jouant sur la commande des circuits ci-dessous.
") + } + + //=========================================================== + // 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 2 points différents 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.
+ 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).
+
Très important : pendant toute la phase d'étalonnage aucun courant de charge ne doit être appliqué sur ShipBS ! + 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...

+ Remarques :
+ - 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.
+ - les valeurs de courant n'ont pas d'importance.
+ - 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).
+ - 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); + } + +} + diff --git a/fonctions.js b/fonctions.js new file mode 100755 index 0000000..5e98393 --- /dev/null +++ b/fonctions.js @@ -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); +} + + + diff --git a/fonctions_batteries.js b/fonctions_batteries.js new file mode 100755 index 0000000..fb16461 --- /dev/null +++ b/fonctions_batteries.js @@ -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); +} + + diff --git a/fonctions_circuits.js b/fonctions_circuits.js new file mode 100755 index 0000000..b469b38 --- /dev/null +++ b/fonctions_circuits.js @@ -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); + +} + + diff --git a/fonctions_couleurs.js b/fonctions_couleurs.js new file mode 100755 index 0000000..b82944a --- /dev/null +++ b/fonctions_couleurs.js @@ -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); +} + + + diff --git a/fonctions_date_heure.js b/fonctions_date_heure.js new file mode 100755 index 0000000..d505abc --- /dev/null +++ b/fonctions_date_heure.js @@ -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 = "1er"; + 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 + "st"; + else if ((jour === 1) || (jour === 22)) texte_jour = jour + "nd"; + else if ((jour === 3) || (jour === 23)) texte_jour = jour + "rd"; + 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("---") +} + + diff --git a/fonctions_historique.js b/fonctions_historique.js new file mode 100755 index 0000000..0ffa914 --- /dev/null +++ b/fonctions_historique.js @@ -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); +} diff --git a/fonctions_localisation.js b/fonctions_localisation.js new file mode 100755 index 0000000..498db5f --- /dev/null +++ b/fonctions_localisation.js @@ -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]); +} + + + + + diff --git a/fonctions_reservoirs.js b/fonctions_reservoirs.js new file mode 100755 index 0000000..bf141a1 --- /dev/null +++ b/fonctions_reservoirs.js @@ -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); +} diff --git a/generate_version.cmake b/generate_version.cmake new file mode 100755 index 0000000..1e0360d --- /dev/null +++ b/generate_version.cmake @@ -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}") diff --git a/home.qml b/home.qml new file mode 100644 index 0000000..4270a67 --- /dev/null +++ b/home.qml @@ -0,0 +1,3880 @@ +import QtQuick 2.12 +import QtQuick.Controls 2.12 +import QtQuick.Layouts 1.12 +import Qt.labs.folderlistmodel 2.12 + +import qt.koriolan.shipheart 1.0 +import"fonctions.js" as Fonctions +import"fonctions_date_heure.js" as Fonctions_date_heure +import"fonctions_localisation.js" as Fonctions_localisation +import"suncalc.js" as Suncalc + +import "." + + +Shipheart_page { + id: page_accueil + + // Mis en forme : + readonly property double pourcentage_largeur_page_affichage_circuit: 0.7 + readonly property int espace_colonnes_principales: 30 + readonly property int espace_colonnes_secondaires: 10 + readonly property bool flag_fleches_suite_onglets: false // Permet de simplement dévalider les flèches si besoin + readonly property int largeur_bouton_suite: flag_fleches_suite_onglets ? 15 : 0 + readonly property int espace_bouton_suite: flag_fleches_suite_onglets ? 10 : 0 + + readonly property int deport_haut_masquage_onglets: 20 + readonly property int espace_onglets_circuits: 10 + readonly property int espace_onglets_reservoirs: 10 + readonly property int espace_onglets_batteries: 10 + readonly property int espace_onglets_capteurs: 10 + readonly property int rayon_onglets: 20 + + readonly property int onglet_page_top_margin_texte_haut: 15 + readonly property int onglet_page_bottom_margin_texte_bas: 10 + + readonly property int espace_lignes_principales: 30 + readonly property int espace_lignes_secondaires: 10 + + readonly property double bandeau_bas_spacing: 5 + readonly property double bandeau_bas_largeur_zone_status_connexions: 65 + readonly property double bandeau_bas_largeur_zone_pages: shipheart_largeur_page - bandeau_bas_largeur_zone_status_connexions - bandeau_bas_largeur_zone_parametres + readonly property double bandeau_bas_largeur_zone_parametres: 85 + + readonly property int periode_init_timer_principal: 1 // En ms + readonly property int step_timer_appui_long: 30 // en ms + readonly property int periode_timer_chrono: 100 // En ms + readonly property int periode_timer_minuteur: 1000 // En ms + + + // Affichage : + property int nombre_colonnes_affichage_circuits: 2 + property int nombre_circuits_affiches_sur_une_colonne: 4 + property int nombre_colonnes_affichage_capteurs: 3 + + // Données : + property bool flag_init_tache_de_fond: true // Permet de traiter jsute après le démarrage une première tâche de fond (pour la partie "toute les minutes") avant de se synchroniser sur les changements de minutes + property int valeur_timer_appui_long: 0 + property int id_groupe_circuits: 0 + property int id_groupe_reservoirs: 0 + property int id_groupe_batteries: 0 + property int id_groupe_capteurs: 0 + property double pourcentage_hauteur_zone_haut_vs_bas: 0.5 + property string image_etat_connexion_1: "" + property string image_etat_connexion_2: "" + property string image_etat_connexion_3: "" + property string image_etat_connexion_4: "" + property string date_courante: "----" + property string heure_courante: "--:--:--" + + property int id_message_users: 0 + property int message_users_code: shipheart_message_users_code_aucun + + property int compteur_chrono: 0 + property bool flag_mouse_area_chrono_pressed: false // Nécessaire car le mousearea est dans un delegate de pages et on ne peut donc pas lui donner un ID unique. + property int compteur_minuteur: 0 + property int compteur_initial_minuteur: 0 + property bool flag_mouse_area_minuteur_pressed: false // Nécessaire car le mousearea est dans un delegate de pages et on ne peut donc pas lui donner un ID unique. + property int etat_minuteur: 0 // 0=Off, 1=On + property int reveils_next_jour: 0 // entre 1 (lundi) et 7 (dimanche) voire 8 (tous les jours). Note : 0 indique qu'il n'y a aucune condition valide actuellement. + property int reveils_next_heure: 0 + property int reveils_next_minute: 0 + property int reveils_next_distance: 0 + + // Modèles : + // Note : les modèles chargés dans 'main.qml' n'ont pas à être rechargés dans les pages suivantes + + + //=========================================================== + // Modèles de lecture de répertoire : + // Attention : pour que les modèles maintiennent à jour leur données, + // il faut que le répertoire cible (le contenant) ne soient pas modifié. + // Par exemple, le fait de supprimer le répertoire (pour le vider) + // puis de le recréer avec le même nom fait perdre le lien au modèle + // qui ne se met alors plus à jour... + //=========================================================== + FolderListModel { + id: repertoire_a_valider + nameFilters: ["*.enc"] + showDirs: false + sortField: FolderListModel.Time // Tri sur l'heure du fichier + folder: "file://" + shipheart_repertoire_versions_a_valider // Pour un fichier, il faut obligatoirement ajouter 'file:' devant. Ou 'qrc:' pour une URL. Le message d'alerte de QT Creator est toujours là... + onStatusChanged: { + // Suppression de fichiers les plus anciens pour ne garder que le plus récent : + for (let i=0; i < repertoire_a_valider.count; i++) + { + if (i > 0) // Le fichier de rang 0 est le plus récent du fait du tri par date + { + let commande = "rm " + shipheart_repertoire_versions_a_valider + "/" + repertoire_a_valider.get(i, "fileName"); +console.log("Exécution de la commande [ " + commande + " ]"); + systeme.commande_shell(commande, ""); + } + } + + // Mise à jour de 'shipheart_fichier_a_valider' utilisé pour les mises àjour à distance : + if ((repertoire_a_valider.count > 0) && + (!repertoire_a_valider.get(0, "fileName").includes("_new")) && // On ignore les fichiers de config usine car trop dangereux et probablement pas utile (si besoin d'une Factory Reset, le faire directement depuis le bouton dédié) + (!repertoire_a_valider.get(0, "fileName").includes("_restore")) ) // On élimine les fichiers de restoration car ils ne sont pas utile pour les mises à jour à distance + { + shipheart_fichier_a_valider = repertoire_a_valider.get(0, "fileName"); + } + else shipheart_fichier_a_valider = ""; + } + } + + FolderListModel { + id: repertoire_a_charger + nameFilters: ["*.enc"] + showDirs: false + sortField: FolderListModel.Time // Tri sur l'heure du fichier + folder: "file://" + shipheart_repertoire_versions_a_charger // Pour un fichier, il faut obligatoirement ajouter 'file:' devant. Ou 'qrc:' pour une URL. Le message d'alerte de QT Creator est toujours là... + onStatusChanged: { + // Suppression de fichiers les plus anciens pour ne garder que le plus récent : + for (let i=0; i < repertoire_a_charger.count; i++) + { +//console.log("A_CHARGER : "+ i +"- fichier = "+ repertoire_a_charger.get(i, "fileName")+" / "+ repertoire_a_charger.get(i, "fileModified")); + if (i > 0) // Le fichier de rang 0 est le plus récent du fait du tri par date + { + let commande = "rm " + shipheart_repertoire_versions_a_charger + "/" + repertoire_a_charger.get(i, "fileName"); + systeme.commande_shell(commande, ""); + } + } + + // Mise à jour de 'shipheart_fichier_a_charger' utilisé pour les mises àjour à distance : + if ((repertoire_a_charger.count > 0) && + (!repertoire_a_charger.get(0, "fileName").includes("_new")) && // On ignore les fichiers de config usine car trop dangereux et probablement pas utile (si besoin d'une Factory Reset, le faire directement depuis le bouton dédié) + (!repertoire_a_charger.get(0, "fileName").includes("_restore")) ) // On élimine les fichiers de restoration car ils ne sont pas utile pour les mises à jour à distance + + { + shipheart_fichier_a_charger = repertoire_a_charger.get(0, "fileName"); + } + else shipheart_fichier_a_charger = ""; + + shipheart_nb_fichiers_a_charger = repertoire_a_charger.count; + } + } + + //=========================================================== + // Economiseur : + // Il n'est mis que sur cette page qui est toujours présente. + // NB : si on le met dans Shipheart_page, une instance est créée + // pour chaque page de niveau inférieur (et alors, on décrémente + // plusieurs fois par seconde en fonction du niveau de pages...). + //=========================================================== + Timer { + id: timer_economiseur + interval: 1000 + running: true + repeat: true + onTriggered: { + if ((shipheart_compteur_economiseur > 0) && + (message_users_code === shipheart_message_users_code_aucun) && // Si un message user est affiché, on ne décrémente pas le compteur d'économiseur... + (shipheart_flag_blocage_compteurs_pendant_config === false) && // Permet de ne pas décompter tant qu'on est en configuration (SDIR #221) + !shipheart_flag_nettoyage_ecran_en_cours ) // SDIR #244 + { + if (-- shipheart_compteur_economiseur === 0) mise_en_veille(1); + } + } + } + + + //=========================================================== + // Timer principal (a priori, 1 seconde) : + //=========================================================== + Timer { + id: timer_home + interval: periode_init_timer_principal // Cette valeur n'est utilisée qu'une fois au démarrage. Ensuite, elle est fixée à 1s + triggeredOnStart: false // Cette valeur est importante car, si TRUE, on a des soucis lors du réarmement suite à un appui sur un bouton (exemple : consigne dans 'Shipheart_bouton_circuit') + running: true + repeat: true + onTriggered: { + //------------------------------------------------ + // Init puis adaptation de la période du timer : + if (interval === periode_init_timer_principal) { // Premier passage, 1ms après le premier chargement + init_page(); + interval = shipheart_periode_timer_home; + } + else // Hors phase d'init : + { + //---------------------------------------------------------------- + // Mises à jour des données selon que la page est visible ou non : + if (stackView.depth === (shipheart_niveau_home + 1)) // Désactive le raffraichissement quand la page n'est pas activée dans la pile + { + mise_a_jour(); + if (boite_information_reseaux.opened) boite_information_reseaux.message = maj_message_reseaux(); + } + + //------------------------------------------------ + // Suivi du time-out de niveau d'accès : + if ((shipheart_compteur_time_out_niveau_acces > 0) && + (shipheart_flag_blocage_compteurs_pendant_config === false)) // Permet de ne pas décompter tant qu'on est en configuration (SDIR #187) + { + if (-- shipheart_compteur_time_out_niveau_acces === 0) + { + shipheart_niveau_acces_en_cours = shipheart_niveau_acces_aucun; + } + } + + //------------------------------------------------ + // Mise à jour des messages users : + if (boite_message_user.visible) maj_messages_users(); + + //------------------------------------------------ + // Tâche de fond : + tache_de_fond(); + } + } + } + + //=========================================================== + // Timer pour gérer les appuis longs : + //=========================================================== + Timer { + id: timer_appui_long + interval: step_timer_appui_long + triggeredOnStart: false + running: 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; + + if (flag_mouse_area_chrono_pressed) + { + timer_chrono.stop(); // Normalement déjà arrêté... + compteur_chrono = 0; + } + if (flag_mouse_area_minuteur_pressed) + { + timer_minuteur.stop(); // Normalement déjà arrêté... + etat_minuteur = 0; + compteur_minuteur = 0; + } + } + } + } + + //=========================================================== + // Timer chrono : + //=========================================================== + Timer { + id: timer_chrono + interval: periode_timer_chrono + triggeredOnStart: false + running: false + repeat: true + onTriggered: { + compteur_chrono ++; + + if (compteur_chrono >= (24 * 60 * 60 * 10)) compteur_chrono = 0; // Rebouclage au bout de 24h + } + } + + //=========================================================== + // Timer minuteur : + //=========================================================== + Timer { + id: timer_minuteur + interval: periode_timer_minuteur + triggeredOnStart: false + running: false + repeat: true + onTriggered: { + compteur_minuteur --; + if (compteur_minuteur <= 0) + { + timer_minuteur.stop(); + traitement_fin_minuteur(); + } + } + } + + + //=========================================================== + // Lorsque la page est sur le point d'être affichée dans la pile : + //=========================================================== + 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 +// StackView.onActivated: { // Le 'onActivated' laisse voir la mise à jour (puisqu'elle est lancée quand la page est complètement affichée + init_circuits(); // Utile au démarrage ET au retour d'autres pages si on a modifié la config des groupes de circuits entre temps... + init_reservoirs(); + init_batteries(); + init_capteurs(); + init_pages(); + } + + + //=========================================================== + // Grille principale : + //=========================================================== + GridLayout { + id: home_grid + columns: 2 + columnSpacing: espace_colonnes_principales + rowSpacing: 0 + + //------------------------------------------------------- + // Zone de gauche : + //------------------------------------------------------- + Rectangle { + width: (shipheart_largeur_page * pourcentage_largeur_page_affichage_circuit) - (espace_colonnes_principales / 2) + height: shipheart_hauteur_page - shipheart_hauteur_bandeau_bas - home_grid.rowSpacing; + color: "transparent" + + //................................................................................. + // Circuits + //................................................................................. + Rectangle { + id: zone_circuits + + width: parent.width + height: (parent.height * pourcentage_hauteur_zone_haut_vs_bas) - (espace_lignes_principales / 2) + color: "transparent" + + //----------------------------------------------------------- + // Onglets : + Rectangle { + id: onglets_circuits + + width: parent.width + height: shipheart_hauteur_bandeau_haut + color: "transparent" + visible: (modele_onglets_circuits.count > 1) ? true : false + + ListModel { + id: modele_onglets_circuits + } + + GridView { + id: grille_onglets_circuits + + property int index_base_en_cours: 0 // Utilsé pour stocker l'index du premier widget affiché à gauche + + x: largeur_bouton_suite + espace_bouton_suite + y: -deport_haut_masquage_onglets + width: parent.width - (2 * (largeur_bouton_suite + espace_bouton_suite)) + height: parent.height + deport_haut_masquage_onglets + cellWidth: width / ((modele_onglets_circuits.count > 0) ? Math.min(modele_onglets_circuits.count, 5) : 1) + cellHeight: shipheart_hauteur_bandeau_haut + deport_haut_masquage_onglets + + highlightRangeMode: flag_fleches_suite_onglets + ? GridView.StrictlyEnforceRange // Nécessaire pour que 'index_base_en_cours' soit mis à jour. Au passage, autorise de faire défiler les widgets jusqu'à ne garder que le dernier visible (pas génant et même plutôt sympa...) + : GridView.NoHighlightRange + flow: GridView.FlowTopToBottom // Items are laid out from top to bottom, and the view scrolls horizontally + 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_onglets_circuits + + onMovementEnded: { + index_base_en_cours = currentIndex; // Capte la valeur de currentIndex aà la fin du mouvement (la valeur vaut alors l'index du widget le plus à gauche). Si on ne le capte pas, la valeur de CurrentIndex repasse à 0 après l'arrêt du flicker (pourquoi...???) + } + + delegate: Rectangle { + width: grille_onglets_circuits.cellWidth - 2 + height: grille_onglets_circuits.cellHeight + radius: 20 + color: model.actif ? shipheart_couleur_fond_bouton_actif : shipheart_couleur_fond_bouton + + Text { + text: model.libelle + font.pixelSize: 14 + font.bold: model.actif + opacity: model.actif ? 1.0 : 0.8 + color: couleur_blanc_casse + anchors.fill: parent + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + topPadding: deport_haut_masquage_onglets + wrapMode: Text.WordWrap + // elide: Text.ElideRight + } + Image { + source: (model.etat === 1) ? "/images/coin_bas_droite_orange.png" : "/images/coin_bas_droite_rouge.png" + sourceSize.height: 20 + anchors { + bottom: parent.bottom + right: parent.right + } + visible: model.etat !== 0 + } + MouseArea { + anchors.fill: parent + onClicked: { + shipheart_clic(); + id_groupe_circuits = model.id; + init_circuits(); + } + } + } + ScrollBar.vertical: ScrollBar {} + } // Fin de Gridview des onglets + + // Flèche de suite gauche : + Image { + anchors { + bottom: grille_onglets_circuits.bottom + right: grille_onglets_circuits.left + rightMargin: espace_bouton_suite + } + source: "/images/fleche_suite_gauche_sombre.png" + width: largeur_bouton_suite + height: grille_onglets_circuits.height - deport_haut_masquage_onglets + opacity: 0.5 + visible: (!grille_onglets_circuits.moving) // Permet de ne pas afficher la flèche pendant le mouvement (surtout génant à cause du lag généré par la fin du mouvement qui est assez lent). + && (grille_onglets_circuits.index_base_en_cours > 0) + && flag_fleches_suite_onglets + } + + // Flèche de suite droite : + Image { + anchors { + bottom: grille_onglets_circuits.bottom + left: grille_onglets_circuits.right + leftMargin: espace_bouton_suite + } + source: "/images/fleche_suite_droite_sombre.png" + width: largeur_bouton_suite + height: grille_onglets_circuits.height - deport_haut_masquage_onglets + opacity: 0.5 + visible: (!grille_onglets_circuits.moving) // Permet de ne pas afficher la flèche pendant le mouvement (surtout génant à cause du lag généré par la fin du mouvement qui est assez lent). + && ((grille_onglets_circuits.count - grille_onglets_circuits.index_base_en_cours) > (modele_onglets_circuits.count * (grille_onglets_circuits.height / grille_onglets_circuits.cellHeight))) // le calcul 'height/cellheight' donne le nombre de lignes de widget (généralement, 1 ou 2) + && flag_fleches_suite_onglets + } + } + + //----------------------------------------------------------- + // Boutons de circuits : + Rectangle { + Layout.row: 1 + Layout.column: 1 + width: parent.width + espace_colonnes_secondaires + height : (onglets_circuits.visible) ? (parent.height - shipheart_hauteur_bandeau_haut - espace_onglets_batteries) : parent.height + y: (onglets_circuits.visible) ? (shipheart_hauteur_bandeau_haut + espace_onglets_batteries) : 0 + color: "transparent" + + ListModel { + id: modele_circuits + } + + GridView { + id: circuits_grid + + x: 0 + width: parent.width + height: parent.height + cellWidth: parent.width / nombre_colonnes_affichage_circuits; + 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_circuits + + delegate: Shipheart_bouton_circuit { + } + + ScrollBar.vertical: ScrollBar {} + + // Texte si aucun circuit n'est configuré sur cet onglet : + Label { + width: parent.width - espace_colonnes_secondaires // Le 'espace_colonnes_secondaires' permet e compenser l'augmentation de taille permettant d'annuler la perte d'un espace en fin de ligne de grille + height: parent.height + horizontalAlignment: Qt.AlignHCenter + verticalAlignment: Qt.AlignVCenter + visible: parent.count === 0 + text: qsTr("Aucun circuit n'est configuré pour ce groupe...

Si ce groupe n'a pas d'utilité, vous pouvez le supprimer dans le menu [Circuits] des Paramètres Avancés.") + color: couleur_rouge_transparent + font.pixelSize: 15 + font.bold: true + wrapMode: Label.Wrap + } + } + } + } + + + //................................................................................. + // Capteurs + //................................................................................. + Rectangle { + id: zone_capteurs + + y: zone_circuits.height + espace_lignes_principales + width: parent.width + height: (parent.height * (1 - pourcentage_hauteur_zone_haut_vs_bas)) - (espace_lignes_principales / 2) + color: "transparent" + + //----------------------------------------------------------- + // Onglets : + Rectangle { + id: onglets_capteurs + + width: parent.width + height: shipheart_hauteur_bandeau_haut + color: "transparent" + visible: (modele_onglets_capteurs.count > 1) ? true : false + clip: true // Permet de limiter l'affichage des éléments enfants à ce rectangle (utile pour la partie haute des onglets à masquer...) + + ListModel { + id: modele_onglets_capteurs + } + + GridView { + id: grille_onglets_capteurs + + x: largeur_bouton_suite + espace_bouton_suite + y: -deport_haut_masquage_onglets + width: parent.width + height: parent.height + deport_haut_masquage_onglets + cellWidth: width / ((modele_onglets_capteurs.count > 0) ? Math.min(modele_onglets_capteurs.count, 5) : 1) + cellHeight: shipheart_hauteur_bandeau_haut + deport_haut_masquage_onglets + + highlightRangeMode: GridView.NoHighlightRange + flow: GridView.FlowTopToBottom // Items are laid out from top to bottom, and the view scrolls horizontally + 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_onglets_capteurs + + delegate: Rectangle { + width: grille_onglets_capteurs.cellWidth - 2 + height: grille_onglets_capteurs.cellHeight + radius: 20 + color: model.actif ? shipheart_couleur_fond_bouton_actif : shipheart_couleur_fond_bouton + + Text { + text: model.libelle + font.pixelSize: 14 + font.bold: model.actif + opacity: model.actif ? 1.0 : 0.8 + color: couleur_blanc_casse + anchors.fill: parent + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + topPadding: deport_haut_masquage_onglets + wrapMode: Text.WordWrap + } + Image { + source: (model.etat === 1) ? "/images/coin_bas_droite_orange.png" : "/images/coin_bas_droite_rouge.png" + sourceSize.height: 20 + anchors { + bottom: parent.bottom + right: parent.right + } + visible: model.etat !== 0 + } + MouseArea { + anchors.fill: parent + onClicked: { + shipheart_clic(); + id_groupe_capteurs = model.id; + init_capteurs(); + } + } + } + ScrollBar.vertical: ScrollBar {} + } // Fin de Gridview des onglets + + } + + + //----------------------------------------------------------- + // Boutons de capteurs : + Rectangle { + Layout.row: 1 + Layout.column: 1 + width: parent.width + espace_colonnes_secondaires + height : (onglets_capteurs.visible) ? (parent.height - shipheart_hauteur_bandeau_haut - espace_onglets_batteries) : parent.height + y: (onglets_capteurs.visible) ? (shipheart_hauteur_bandeau_haut + espace_onglets_batteries) : 0 + color: "transparent" + + ListModel { + id: modele_capteurs + } + + GridView { + id: capteurs_grid + + y: 0 + width: parent.width + height: parent.height + cellWidth: parent.width / nombre_colonnes_affichage_capteurs; + cellHeight: (circuits_grid.cellHeight * 2) // Garanti que tous les boutons ont la même hauteur en prenant la hauteur d'un circuit comme référénce pour la batterie + 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_capteurs + delegate: Shipheart_bouton_capteur { + } + + ScrollBar.vertical: ScrollBar {} + + // Texte si aucun capteur n'est configuré pour cet onglet : + Label { + width: parent.width - espace_colonnes_secondaires // Le 'espace_colonnes_secondaires' permet de compenser l'augmentation de taille permettant d'annuler la perte d'un espace en fin de ligne de grille + height: parent.height + horizontalAlignment: Qt.AlignHCenter + verticalAlignment: Qt.AlignVCenter + visible: parent.count === 0 + text: qsTr("Aucun capteur n'est configuré pour ce groupe...

Si ce groupe n'a pas d'utilité, vous pouvez le supprimer dans le menu [Capteurs] des Paramètres Avancés.") + color: couleur_rouge_transparent + font.pixelSize: 15 + font.bold: true + wrapMode: Label.Wrap + } + } + } + } + } + + //------------------------------------------------------- + // Zone Droite : + //------------------------------------------------------- + Rectangle { + width: (shipheart_largeur_page * (1 - pourcentage_largeur_page_affichage_circuit)) - (espace_colonnes_principales / 2) + height: shipheart_hauteur_page - shipheart_hauteur_bandeau_bas - home_grid.rowSpacing; + color: "transparent" + + //................................................................................. + // Réservoirs + //................................................................................. + Rectangle { + id: zone_reservoirs + + width: parent.width + height: (parent.height * pourcentage_hauteur_zone_haut_vs_bas) - (espace_lignes_principales / 2) + color: "transparent" + + //----------------------------------------------------------- + // Onglets : + Rectangle { + id: onglets_reservoirs + + width: parent.width + height: shipheart_hauteur_bandeau_haut + color: "transparent" + visible: (modele_onglets_reservoirs.count > 1) ? true : false + + ListModel { + id: modele_onglets_reservoirs + } + + GridView { + id: grille_onglets_reservoirs + + x: largeur_bouton_suite + espace_bouton_suite + y: -deport_haut_masquage_onglets + width: parent.width - (2 * (largeur_bouton_suite + espace_bouton_suite)) + height: parent.height + deport_haut_masquage_onglets + cellWidth: width / ((modele_onglets_reservoirs.count > 0) ? Math.min(modele_onglets_reservoirs.count, 3) : 1) + cellHeight: shipheart_hauteur_bandeau_haut + deport_haut_masquage_onglets + + highlightRangeMode: GridView.NoHighlightRange + flow: GridView.FlowTopToBottom // Items are laid out from top to bottom, and the view scrolls horizontally + 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_onglets_reservoirs + + delegate: Rectangle { + width: grille_onglets_reservoirs.cellWidth - 2 + height: grille_onglets_reservoirs.cellHeight + radius: 20 + color: model.actif ? shipheart_couleur_fond_bouton_actif : shipheart_couleur_fond_bouton + + Text { + text: model.libelle + font.pixelSize: 14 + font.bold: model.actif + opacity: model.actif ? 1.0 : 0.8 + color: couleur_blanc_casse + anchors.fill: parent + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + topPadding: deport_haut_masquage_onglets + wrapMode: Text.WordWrap + } + Image { + source: (model.etat === 1) ? "/images/coin_bas_droite_orange.png" : "/images/coin_bas_droite_rouge.png" + sourceSize.height: 20 + anchors { + bottom: parent.bottom + right: parent.right + } + visible: model.etat !== 0 + } + MouseArea { + anchors.fill: parent + onClicked: { + shipheart_clic(); + id_groupe_reservoirs = model.id; + init_reservoirs(); + } + } + } + ScrollBar.vertical: ScrollBar {} + } // Fin de Gridview des onglets + + } + + //----------------------------------------------------------- + // Boutons de réservoirs : + Rectangle { + Layout.row: 1 + Layout.column: 1 + width: parent.width + espace_colonnes_secondaires + height : (onglets_reservoirs.visible) ? (parent.height - shipheart_hauteur_bandeau_haut - espace_onglets_batteries) : parent.height + y: (onglets_reservoirs.visible) ? (shipheart_hauteur_bandeau_haut + espace_onglets_batteries) : 0 + + color: "transparent" + + ListModel { + id: modele_reservoirs + } + + GridView { + id: reservoirs_grid + + width: parent.width + height: parent.height + cellWidth: parent.width; + cellHeight: circuits_grid.cellHeight // Garanti que tous les boutons ont la même hauteur en prenant la hauteur d'un circuit comme référénce pour le réservoir + 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_reservoirs + delegate: Shipheart_bouton_reservoir { + } + + ScrollBar.vertical: ScrollBar {} + + // Texte si aucun réservoir n'est configuré sur cet onglet : + Label { + width: parent.width - espace_colonnes_secondaires // Le 'espace_colonnes_secondaires' permet e compenser l'augmentation de taille permettant d'annuler la perte d'un espace en fin de ligne de grille + height: parent.height + horizontalAlignment: Qt.AlignHCenter + verticalAlignment: Qt.AlignVCenter + visible: parent.count === 0 + text: qsTr("Aucun réservoir n'est configuré pour ce groupe...

Si ce groupe n'a pas d'utilité, vous pouvez le supprimer dans le menu [Réservoirs] des Paramètres Avancés.") + color: couleur_rouge_transparent + font.pixelSize: 15 + font.bold: true + wrapMode: Label.Wrap + } + } + } + } + + //................................................................................. + // Batteries + //................................................................................. + Rectangle { + id: zone_batteries + + y: zone_reservoirs.height + espace_lignes_principales + width: parent.width + height: (parent.height * (1 - pourcentage_hauteur_zone_haut_vs_bas)) - (espace_lignes_principales / 2) + color: "transparent" + + //----------------------------------------------------------- + // Onglets : + Rectangle { + id: onglets_batteries + + width: parent.width + height: shipheart_hauteur_bandeau_haut + color: "transparent" + visible: (modele_onglets_batteries.count > 1) ? true : false + clip: true // Permet de limiter l'affichage des éléments enfants à ce rectangle (utile pour la partie haute des onglets à masquer...) + + ListModel { + id: modele_onglets_batteries + } + + GridView { + id: grille_onglets_batteries + + x: largeur_bouton_suite + espace_bouton_suite + y: -deport_haut_masquage_onglets + width: parent.width - (2 * (largeur_bouton_suite + espace_bouton_suite)) + height: parent.height + deport_haut_masquage_onglets + cellWidth: width / ((modele_onglets_batteries.count > 0) ? Math.min(modele_onglets_batteries.count, 3) : 1) + cellHeight: shipheart_hauteur_bandeau_haut + deport_haut_masquage_onglets + + highlightRangeMode: GridView.NoHighlightRange + flow: GridView.FlowTopToBottom // Items are laid out from top to bottom, and the view scrolls horizontally + 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_onglets_batteries + + delegate: Rectangle { + width: grille_onglets_batteries.cellWidth - 2 + height: grille_onglets_batteries.cellHeight + radius: 20 + color: model.actif ? shipheart_couleur_fond_bouton_actif : shipheart_couleur_fond_bouton + + Text { + text: model.libelle + font.pixelSize: 14 + font.bold: model.actif + opacity: model.actif ? 1.0 : 0.8 + color: couleur_blanc_casse + anchors.fill: parent + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + topPadding: deport_haut_masquage_onglets + wrapMode: Text.WordWrap + } + Image { + source: (model.etat === 1) ? "/images/coin_bas_droite_orange.png" : "/images/coin_bas_droite_rouge.png" + sourceSize.height: 20 + anchors { + bottom: parent.bottom + right: parent.right + } + visible: model.etat !== 0 + } + MouseArea { + anchors.fill: parent + onClicked: { + shipheart_clic(); + id_groupe_batteries = model.id; + init_batteries(); + } + } + } + ScrollBar.vertical: ScrollBar {} + } // Fin de Gridview des onglets + + } + + + //----------------------------------------------------------- + // Boutons de batteries : + Rectangle { + Layout.row: 1 + Layout.column: 1 + width: parent.width + espace_colonnes_secondaires + height : (onglets_batteries.visible) ? (parent.height - shipheart_hauteur_bandeau_haut - espace_onglets_batteries) : parent.height + y: (onglets_batteries.visible) ? (shipheart_hauteur_bandeau_haut + espace_onglets_batteries) : 0 + color: "transparent" + + ListModel { + id: modele_batteries + } + + GridView { + id: batteries_grid + + y: 0 + width: parent.width + height: parent.height + cellWidth: parent.width; + cellHeight: circuits_grid.cellHeight // Garanti que tous les boutons ont la même hauteur en prenant la hauteur d'un circuit comme référénce pour la batterie + 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_batteries + delegate: Shipheart_bouton_batterie { + } + + ScrollBar.vertical: ScrollBar {} + + // Texte si aucune batterie n'est configurée pour cet onglet : + Label { + width: parent.width - espace_colonnes_secondaires // Le 'espace_colonnes_secondaires' permet e compenser l'augmentation de taille permettant d'annuler la perte d'un espace en fin de ligne de grille + height: parent.height + horizontalAlignment: Qt.AlignHCenter + verticalAlignment: Qt.AlignVCenter + visible: parent.count === 0 + text: qsTr("Aucun parc de batterie n'est configuré pour ce groupe...

Si ce groupe n'a pas d'utilité, vous pouvez le supprimer dans le menu [Batteries] des Paramètres Avancés.") + color: couleur_rouge_transparent + font.pixelSize: 15 + font.bold: true + wrapMode: Label.Wrap + } + } + } + } + } + + //------------------------------------------------------- + // Bandeau bas : + //------------------------------------------------------- + Rectangle { + Layout.columnSpan: 2 // Regroupe les deux colonnes principales (circuits/capteurs à gauche et réservoirs/batteries à droite) + + width: shipheart_largeur_page; + height: shipheart_hauteur_bandeau_bas; + color: "transparent" + + + //................................................. + // Zone d'état des connexions + //................................................. + Rectangle { + id: bandeau_bas_zone_status_connexions + + width: bandeau_bas_largeur_zone_status_connexions; + height: shipheart_hauteur_bandeau_bas + radius: shipheart_rayon_bouton + color: shipheart_couleur_fond_bouton + + Image { + source: image_etat_connexion_1 + sourceSize.height: parent.height * 0.35; + sourceSize.width: bandeau_bas_largeur_zone_status_connexions + anchors.top: parent.top + anchors.topMargin: 10 + anchors.left: parent.left + anchors.leftMargin: (shipheart_generation_shipbase < shipheart_generation_shipbase_v2) ? (parent.width - width)/2 : 0 + } + Image { + source: image_etat_connexion_2 + sourceSize.height: parent.height * 0.3; + sourceSize.width: bandeau_bas_largeur_zone_status_connexions + anchors.bottom: parent.bottom + anchors.bottomMargin: 10 + anchors.left: parent.left + anchors.leftMargin: (shipheart_generation_shipbase < shipheart_generation_shipbase_v2) ? (parent.width - width)/2 : 0 + } + Image { + source: image_etat_connexion_3 + sourceSize.height: parent.height * 0.35; + sourceSize.width: bandeau_bas_largeur_zone_status_connexions + anchors.top: parent.top + anchors.topMargin: 10 + anchors.right: parent.right + } + Image { + source: image_etat_connexion_4 + sourceSize.height: parent.height * 0.3; + sourceSize.width: bandeau_bas_largeur_zone_status_connexions + anchors.bottom: parent.bottom + anchors.bottomMargin: 10 + anchors.right: parent.right + } + MouseArea { + anchors.fill: parent + onClicked: { + shipheart_clic(); + boite_information_reseaux.message = maj_message_reseaux(); + boite_information_reseaux.open(); + } + } + } + + //----------------------------------------------------------- + // Onglets : + Rectangle { + id: onglets_pages + + x: bandeau_bas_zone_status_connexions.width + bandeau_bas_spacing + width: bandeau_bas_largeur_zone_pages + height: shipheart_hauteur_bandeau_bas + color: "transparent" + + ListModel { + id: modele_onglets_pages + } + + GridView { + id: grille_onglets_pages + + property int index_base_en_cours: 0 // Utilsé pour stocker l'index du premier widget affiché à gauche + + x: largeur_bouton_suite + espace_bouton_suite + width: parent.width - (2 * (largeur_bouton_suite + espace_bouton_suite)) + height: parent.height + cellWidth: width / ((modele_onglets_pages.count > 0) ? Math.min(modele_onglets_pages.count, 5) : 1) + cellHeight: height + + highlightRangeMode: flag_fleches_suite_onglets + ? GridView.StrictlyEnforceRange // Nécessaire pour que 'index_base_en_cours' soit mis à jour. Au passage, autorise de faire défiler les widgets jusqu'à ne garder que le dernier visible (pas génant et même plutôt sympa...) + : GridView.NoHighlightRange + flow: GridView.FlowTopToBottom // Items are laid out from top to bottom, and the view scrolls horizontally + 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_onglets_pages + + onMovementEnded: { + index_base_en_cours = currentIndex; // Capte la valeur de currentIndex aà la fin du mouvement (la valeur vaut alors l'index du widget le plus à gauche). Si on ne le capte pas, la valeur de CurrentIndex repasse à 0 après l'arrêt du flicker (pourquoi...???) + } + + delegate: Rectangle { + x: 5 + width: grille_onglets_pages.cellWidth - 5 + height: grille_onglets_pages.cellHeight + radius: shipheart_rayon_bouton + color: model.actif ? shipheart_couleur_fond_bouton_actif : shipheart_couleur_fond_bouton + + //================================================== + // Ephéméride : + Rectangle { + anchors.fill: parent + color: "transparent" + visible: model.type === shipheart_type_page_preconfiguree_ephemeride + + Text { + id: texte_date + text: date_courante + textFormat: Text.RichText // Autorise la prise en compte de par exemple... + anchors { + top: parent.top + topMargin: onglet_page_top_margin_texte_haut + horizontalCenter: parent.horizontalCenter + } + font.pixelSize: 15 + color: couleur_blanc_casse + } + Text { + id: texte_heure + text: heure_courante + anchors { + bottom: parent.bottom + bottomMargin: onglet_page_bottom_margin_texte_bas + horizontalCenter: parent.horizontalCenter + } + font.pixelSize: 18 + font.weight: Font.Bold + color: couleur_blanc_casse + } + + 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_date_heure + anchors.fill: parent + onClicked: { + shipheart_clic(); + stackView.push("ephemeride.qml") + } + } + } + + //================================================== + // Chronomètre : + Rectangle { + anchors.fill: parent + color: "transparent" + visible: model.type === shipheart_type_page_preconfiguree_chronometre + + Image { + source: "/images/chronometre.png" + sourceSize.height: 25 + anchors { + top: parent.top + topMargin: onglet_page_top_margin_texte_haut + horizontalCenter: parent.horizontalCenter + } + } + Text { + text: Math.trunc(compteur_chrono / (60 * 60 * 10)).toString().padStart(2, '0') + ":" + Math.trunc((compteur_chrono / (60 * 10)) % 60).toString().padStart(2, '0') + ":" + Math.trunc((compteur_chrono / 10) % 60).toString().padStart(2, '0') + "," + (compteur_chrono % 10) + anchors { + bottom: parent.bottom + bottomMargin: onglet_page_bottom_margin_texte_bas + horizontalCenter: parent.horizontalCenter + } + horizontalAlignment: Text.AlignHCenter + font.pixelSize: 18 + font.weight: Font.Bold + color: couleur_blanc_casse + visible: (compteur_chrono !== 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: (mouse_area_chrono.pressed) + && ((valeur_timer_appui_long / shipheart_mouse_press_and_hold_interval_tres_long) > 0.05) // Permet de ne pas commencer à afficher la barre défilante dans le cas d'un appui simple + } + + 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_chrono + anchors.fill: parent + onClicked: { + shipheart_clic(); + if (timer_chrono.running) timer_chrono.stop(); + else timer_chrono.start(); + + timer_appui_long.running = false; + valeur_timer_appui_long = 0; + } + // Attention : la ligne suivante est nécessaire pour que dès que l'appui est supérieur au délai + // d'appui long (500ms en standard), le 'onClicked' ne soit PAS déclenché. Utile notamment lors + // d'un appui long "incomplet" qui ne RAZ pas le compteur mais qui ne relance pas non plus le comptage... + onPressAndHold: { + if (timer_chrono.running) + { + boite_dialogue_affichage_duree.type = "chrono"; + boite_dialogue_affichage_duree.open(); + } + } + onPressed: { + shipheart_clic(); + if (!timer_chrono.running) // On n'enclenche pas un appui long si le compteur tourne (il faut d'abord l'arrêter avant de le RAZ) + { + timer_appui_long.running = true; + valeur_timer_appui_long = 0; + flag_mouse_area_chrono_pressed = true; + } + } + onExited: { + timer_appui_long.running = false; + valeur_timer_appui_long = 0; + flag_mouse_area_chrono_pressed = false; + } + } + } + + //================================================== + // Minuteur : + Rectangle { + anchors.fill: parent + color: "transparent" + visible: model.type === shipheart_type_page_personnalisee_minuteur + + Image { + source: "/images/sablier.png" + sourceSize.height: 25 + anchors { + top: parent.top + topMargin: onglet_page_top_margin_texte_haut + horizontalCenter: parent.horizontalCenter + } + } + Text { + text: Math.trunc(compteur_minuteur / (60 * 60)).toString().padStart(2, '0') + ":" + Math.trunc((compteur_minuteur / 60) % 60).toString().padStart(2, '0') + ":" + Math.trunc(compteur_minuteur % 60).toString().padStart(2, '0') + anchors { + bottom: parent.bottom + bottomMargin: onglet_page_bottom_margin_texte_bas + horizontalCenter: parent.horizontalCenter + } + horizontalAlignment: Text.AlignHCenter + font.pixelSize: 18 + font.weight: Font.Bold + color: couleur_blanc_casse + visible: (compteur_minuteur !== 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: (mouse_area_minuteur.pressed) + && ((valeur_timer_appui_long / shipheart_mouse_press_and_hold_interval_tres_long) > 0.05) // Permet de ne pas commencer à afficher la barre défilante dans le cas d'un appui simple + } + + 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_minuteur + anchors.fill: parent + onClicked: { + shipheart_clic(); + if (etat_minuteur === 0) + { + boite_dialogue_minuteur.valeur_tumbler_heure = 0; + boite_dialogue_minuteur.valeur_tumbler_minute = 3; + boite_dialogue_minuteur.valeur_tumbler_seconde = 0 + boite_dialogue_minuteur.open(); + } + else + { + if (timer_minuteur.running) timer_minuteur.stop(); + else timer_minuteur.start(); + + timer_appui_long.running = false; + valeur_timer_appui_long = 0; + } + } + // Attention : la ligne suivante est nécessaire pour que dès que l'appui est supérieur au délai + // d'appui long (500ms en standard), le 'onClicked' ne soit PAS déclenché. Utile notamment lors + // d'un appui long "incomplet" qui ne RAZ pas le compteur mais qui ne relance pas non plus le comptage... + onPressAndHold: { + if (timer_minuteur.running) + { + boite_dialogue_affichage_duree.type = "minuteur"; + boite_dialogue_affichage_duree.open(); + } + } + onPressed: { + shipheart_clic(); + if (!timer_minuteur.running) // On n'enclenche pas un appui long si le compteur tourne (il faut d'abord l'arrêter avant de le RAZ) + { + timer_appui_long.running = true; + valeur_timer_appui_long = 0; + flag_mouse_area_minuteur_pressed = true; + } + } + onExited: { + timer_appui_long.running = false; + valeur_timer_appui_long = 0; + flag_mouse_area_minuteur_pressed = false; + } + } + } + + //================================================== + // Réveil : + Rectangle { + anchors.fill: parent + color: "transparent" + visible: model.type === shipheart_type_page_preconfiguree_reveil + + Image { + source: "/images/reveil.png" + sourceSize.height: 25 + anchors { + top: parent.top + topMargin: onglet_page_top_margin_texte_haut + horizontalCenter: parent.horizontalCenter + } + } + Text { + text: Fonctions_date_heure.nom_jour_semaine(reveils_next_jour) + " " + Fonctions.format_deux_digits(reveils_next_heure, '0') + ":" + Fonctions.format_deux_digits(reveils_next_minute, '0') + anchors { + bottom: parent.bottom + bottomMargin: onglet_page_bottom_margin_texte_bas + horizontalCenter: parent.horizontalCenter + } + horizontalAlignment: Text.AlignHCenter + font.pixelSize: 15 + color: couleur_blanc_casse + visible: (reveils_next_jour !== 0) + } + + MouseArea { + id: mouse_area_reveils + anchors.fill: parent + onClicked: { + shipheart_clic(); + boite_dialogue_reveil.open(); + } + } + } + + //================================================== + // Page personnalisée : + Rectangle { + anchors.fill: parent + color: "transparent" + visible: (model.type === shipheart_type_page_personnalisee_non_masquable) + || (model.type === shipheart_type_page_personnalisee_masquable) + + Text { + text: model.libelle + font.pixelSize: 15 + font.weight: Font.Bold + color: couleur_blanc_casse + anchors.fill: parent + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + wrapMode: Text.WordWrap +// elide: Text.ElideRight + } + + MouseArea { + anchors.fill: parent + onClicked: { + shipheart_clic(); + stackView.push("page_personnalisee.qml", {"id_page": model.id }) + } + } + + } + + //================================================== + // Toutes les pages : + Image { + source: (model.etat === 1) ? "/images/coin_bas_droite_orange.png" : "/images/coin_bas_droite_rouge.png" + sourceSize.height: 20 + anchors { + bottom: parent.bottom + right: parent.right + } + visible: model.etat !== 0 + } + + } + ScrollBar.vertical: ScrollBar {} + } // Fin de Gridview des onglets + + // Flèche de suite gauche : + Image { + anchors { + bottom: grille_onglets_pages.bottom + right: grille_onglets_pages.left + rightMargin: espace_bouton_suite + } + source: "/images/fleche_suite_gauche_sombre.png" + width: largeur_bouton_suite + height: grille_onglets_pages.height + opacity: 0.5 + visible: (!grille_onglets_pages.moving) // Permet de ne pas afficher la flèche pendant le mouvement (surtout génant à cause du lag généré par la fin du mouvement qui est assez lent). + && (grille_onglets_pages.index_base_en_cours > 0) + && flag_fleches_suite_onglets + } + + // Flèche de suite droite : + Image { + anchors { + bottom: grille_onglets_pages.bottom + left: grille_onglets_pages.right + leftMargin: espace_bouton_suite + } + source: "/images/fleche_suite_droite_sombre.png" + width: largeur_bouton_suite + height: grille_onglets_pages.height + opacity: 0.5 + visible: (!grille_onglets_pages.moving) // Permet de ne pas afficher la flèche pendant le mouvement (surtout génant à cause du lag généré par la fin du mouvement qui est assez lent). + && ((grille_onglets_pages.count - grille_onglets_pages.index_base_en_cours) > (modele_onglets_pages.count * (grille_onglets_pages.height / grille_onglets_pages.cellHeight))) // le calcul 'height/cellheight' donne le nombre de lignes de widget (généralement, 1 ou 2) + && flag_fleches_suite_onglets + } + } + + //................................................. + // Paramètres + //................................................. + Rectangle { + id: bandeau_bas_zone_parametres + + x: onglets_pages.x + onglets_pages.width // On ne rajoute pas le 'bandeau_bas_spacing' car les boutons dans la grille n'étant pas centrés, on ajouterait 2 espaces avant ce bouton + width: bandeau_bas_largeur_zone_parametres; + height: shipheart_hauteur_bandeau_bas + radius: shipheart_rayon_bouton + color: shipheart_couleur_fond_bouton + + Text { + id: texte_parametres + text: shipheart_code_pays + anchors { + top: parent.top + topMargin: onglet_page_top_margin_texte_haut + horizontalCenter: parent.horizontalCenter + } + font.pixelSize: 18 + font.weight: Font.Bold + color: couleur_gris_tres_pale + } + + Image { + id: image_parametres + source: "/images/icone_parametres.png" + sourceSize.height: 25 + anchors { + bottom: parent.bottom + bottomMargin: onglet_page_bottom_margin_texte_bas + horizontalCenter: parent.horizontalCenter + } + } + Image { + id: image_alarme_paramètres // Affichage du coin inférieur-droit en rouge si une erreur de paramètres est détectée + source: "/images/coin_bas_droite_rouge.png" + sourceSize.height: 20 + anchors { + bottom: parent.bottom + right: parent.right + } + visible: shipheart_defaut_config_k_bus + } + Image { + id: image_info_paramètres // Affichage du coin inférieur-droit en bleu si une nouvelle version est dispo + source: "/images/coin_bas_droite_bleu_koriolan.png" + sourceSize.height: 20 + anchors { + bottom: parent.bottom + right: parent.right + } + visible: !image_alarme_paramètres.visible && + ((shipheart_fichier_a_charger !== "") || (shipheart_fichier_a_valider !== "")) + } + + 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_parametres + anchors.fill: parent + onClicked: { + shipheart_clic(); + stackView.push("parametres.qml") + } + pressAndHoldInterval: shipheart_mouse_press_and_hold_interval_tres_long + onPressAndHold: { + stackView.pop(); + } + } + } + + } // Fin de bandeau bas + } // Fin de grille principale + + //------------------------------------------------------- + // Boite en travaux : + //------------------------------------------------------- + Shipheart_boite_dialogue { + id: boite_information_en_travaux + niveau: 0 + imageTitreSource: "/images/cone_chantier.png"; + message: qsTr("Cette page est actuellement en travaux.
Elle sera rendue disponible très rapidement à travers une mise à jour.

Merci de votre patience...

L'équipe ShipHeart") + } + + //------------------------------------------------------- + // Réseaux : + //------------------------------------------------------- + Shipheart_boite_dialogue { + id: boite_information_reseaux + niveau: 0 + imageTitreSource: "/images/satellite.png"; + } + + //------------------------------------------------------- + // Messages Users : + //------------------------------------------------------- + Shipheart_boite_dialogue { + id: boite_message_user + onClicked: { + acquittement_message_users(bouton); + } + } + + //------------------------------------------------------- + // Boite de chargement du minuteur : + //------------------------------------------------------- + Shipheart_boite_dialogue_minuteur { + id: boite_dialogue_minuteur + onClicked: { +//console.log("Le Bouton [" + bouton + "] est appuyé"); + if (bouton === shipheart_boite_dialogue_bouton_1) + { + compteur_minuteur = (heure * 60 * 60) + (minute * 60) + seconde + if (compteur_minuteur !== 0) // Si la valeur sélectionnée est nulle, on ne lancer rien.... + { + etat_minuteur = 1; + compteur_initial_minuteur = compteur_minuteur; + timer_minuteur.start(); + } + } + boite_dialogue_minuteur.close(); // Dans tous les cas... (notamment si ANNULER) + } + } + + //------------------------------------------------------- + // Boite de dialogues concernant les réveils : + //------------------------------------------------------- + Shipheart_boite_dialogue_reveils { + id: boite_dialogue_reveil + + onClicked: { +//console.log("Le Bouton [" + bouton + "] est appuyé"); + if (bouton === shipheart_boite_dialogue_bouton_1) + { + check_reveils(); + } + boite_dialogue_reveil.close(); // Tous le traitement est fait dans la boite de dialogue... + } + } + + //------------------------------------------------------- + // Boite d'affichage d'une durée : + // Utilisée pour chrono et minuteur + //------------------------------------------------------- + Shipheart_boite_dialogue_affichage_duree { + id: boite_dialogue_affichage_duree + + onClicked: { + boite_dialogue_affichage_duree.close(); + } + } + + + //=========================================================== + // 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: { + shipheart_clic(); + mise_en_veille(0); + } + } + + + //================================================================================================= + // Fonction : Traite les tâches à effectuer à l'ouverture de la page + //================================================================================================= + function init_page() + { + var req, res; + + + console.log("shipheart_type_installation = "+ shipheart_type_installation) + + // Paramètres dépendant du type d'installation : + switch (shipheart_type_installation) + { + //--------------------------------------------------------------------------- + case shipheart_type_installation_ecran_deporte_7_pouces: + nombre_colonnes_affichage_circuits = 1 + nombre_circuits_affiches_sur_une_colonne = 3 + break; + + //--------------------------------------------------------------------------- + case shipheart_type_installation_ecran_deporte_10_pouces: + nombre_colonnes_affichage_circuits = 2 + nombre_circuits_affiches_sur_une_colonne = 4 + break; + + //--------------------------------------------------------------------------- + case shipheart_type_installation_ecran_deporte_22_pouces: + nombre_colonnes_affichage_circuits = 3 + nombre_circuits_affiches_sur_une_colonne = 6 + break; + + //--------------------------------------------------------------------------- + default: // Dans ce cas, ce sont les valeurs par défaut qui sont conservées. + case shipheart_type_installation_shipbase: + break; + } + + console.log("Version en cours d'utilisation = " + AppInfo.version) + + // Mise à jour de la version de l'Application QT dans la BDD : + req = 'UPDATE TB_Systeme SET Valeur="' + AppInfo.version + '" WHERE Nom="Version_soft_application_qt" '; + bdd.requete_unique(req); + + // Récupération de la langue en cours d'utilisation : + req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Langue" '; + res = bdd.requete_unique(req); + shipheart_langue = Number(res[0]); + + // Et changement de langue si celle demandée n'est pas le FR (démarrage par défaut) : + shipheart_code_pays = Fonctions_localisation.code_pays(shipheart_langue); + shipheart_code_langue = Fonctions_localisation.code_langue(shipheart_langue); // Utilisé pour les 'toLocaleDateString' par exemple + backend.change_langue(shipheart_code_langue); + + // Récupération du fuseau horaire en cours : + req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Fuseau_horaire" '; + res = bdd.requete_unique(req); + shipheart_fuseau_horaire = Number(res[0]); + + // Récupération de l'indicateur d'heure d'été : + req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Heure_ete" '; + res = bdd.requete_unique(req); + shipheart_heure_ete = Number(res[0]); + + // Récupération de l'unité de volumes à utiliser : + req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Unite_volume" '; + res = bdd.requete_unique(req); + shipheart_unite_volume = Number(res[0]); + shipheart_unite_volume_symbole = Fonctions_localisation.symbole_unite_volume(shipheart_unite_volume); + + // Récupération de l'unité de températures à utiliser : + req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Unite_temperature" '; + res = bdd.requete_unique(req); + shipheart_unite_temperature = Number(res[0]); + shipheart_unite_temperature_symbole = Fonctions_localisation.symbole_unite_temperature(shipheart_unite_temperature); + + // Récupération de la période d'obsolescence des capteurs NMEA : + req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Periode_obsolescence_capteur_nmea" '; + res = bdd.requete_unique(req); + shipheart_periode_obsolescence_capteur_nmea = Number(res[0]); + + // Récupération du time-out de l'économiseur : +// req = 'SELECT Valeur FROM TB_Configuration WHERE Nom LIKE="Time_out_economiseur" '; // SDIR #328 + req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Time_out_economiseur" '; // SDIR #328 + res = bdd.requete_unique(req); + shipheart_time_out_economiseur = Number(res[0]); + + // Récupération du paramètres de bips audio : + req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Bips" '; + res = bdd.requete_unique(req); + shipheart_bips = res[0]; + + // Remise à Normal de la LED enface avant : + req = "UPDATE TB_Modules_config SET New_cde='" + shipheart_commande_module_etat_systeme + "/" + shipheart_commande_module_etat_systeme_normal + "' WHERE Adresse_k_bus=0 "; + bdd.requete_unique(req); + + /* // Récupération du nombre maxi de répétitions d'un message utilisateur : + req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Nb_maxi_reports_message_user" '; + res = bdd.requete_unique(req); + shipheart_message_users_max_nombre_reports = Number(res[0]); +*/ + reload_economiseur(); // Permet d'avoir une première tempo. Sinon, il faudrait attendre le premier clic pour que la tempo soit chargée... + mise_en_veille(0); // Par défaut, on affiche la page au démarrage... + shipheart_niveau_home = stackView.depth - 1; // Permet de stocker le niveau de la page dans la Stackview + } + + + //================================================================================================= + // Fonction : Met à jour les champs utilisé dans les différents affichages de la page. Elle n'est + // appelée que lorsque aucune interction n'est en cours sur l'écran (appui en cours, + // balayage, etc... + // Impact : Environ 20ms (chaque 1s) mesuré via QML Profiler et mesure de temps d'exec. le 01/02/2022 + //================================================================================================= + function mise_a_jour() + { + var req, res; + var nb; + var i; + var cde, adresse; + +//console.time('mise_a_jour_protegee') + + //----------------------------------------- + // Mise à jour des circuits, réservoirs et batteries : + mise_a_jour_circuits(); + mise_a_jour_onglets_circuits(); + mise_a_jour_reservoirs(); + mise_a_jour_onglets_reservoirs(); + mise_a_jour_batteries(); + mise_a_jour_onglets_batteries(); + mise_a_jour_capteurs(); + mise_a_jour_onglets_capteurs(); + + //----------------------------------------- + // Etat des connexions : +//shipheart_generation_shipbase = shipheart_generation_shipbase_v1; + if (shipheart_generation_shipbase < shipheart_generation_shipbase_v2) + { + //----------------------------------------- + // Etat GNSS : + req = 'SELECT Valeur FROM TB_Systeme WHERE Nom="Etat_gnss" '; + res = bdd.requete_unique(req); + switch(Number(res[0])) + { + default: + case 0: image_etat_connexion_1 = "/images/gnss_off.png"; break; + case 1: image_etat_connexion_1 = "/images/gnss_on.png"; break; + } + + //----------------------------------------- + // Etat 4G-LTE : + req = 'SELECT Valeur FROM TB_Systeme WHERE Nom="Etat_4g_lte" '; + res = bdd.requete_unique(req); + switch(Number(res[0])) + { + default: + case 0: image_etat_connexion_2 = "/images/4g_lte_off.png"; break; + case 1: image_etat_connexion_2 = "/images/4g_lte_on_1.png"; break; + case 2: image_etat_connexion_2 = "/images/4g_lte_on_2.png"; break; + case 3: image_etat_connexion_2 = "/images/4g_lte_on_3.png"; break; + case 4: image_etat_connexion_2 = "/images/4g_lte_on_4.png"; break; + } + } + else + { + //----------------------------------------- + // Etat GNSS : + req = 'SELECT Valeur FROM TB_Systeme WHERE Nom="Etat_gnss" '; + res = bdd.requete_unique(req); + switch(Number(res[0])) + { + default: + case 0: image_etat_connexion_1 = "/images/gnss_off.png"; break; + case 1: image_etat_connexion_1 = "/images/gnss_on.png"; break; + } + + //----------------------------------------- + // Etat Ethernet : + req = 'SELECT Valeur FROM TB_Systeme WHERE Nom="Adresse_ip_ethernet" '; + res = bdd.requete_unique(req); + if (res[0] === shipheart_adresse_ip_inconnue) image_etat_connexion_2 = "/images/ethernet_off.png"; + else image_etat_connexion_2 = "/images/ethernet_on.png"; + + //----------------------------------------- + // Etat Wifi Sta : + req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Wifi_sta_cde" '; + res = bdd.requete_unique(req); + cde = Number(res[0]); + + req = 'SELECT Valeur FROM TB_Systeme WHERE Nom="Adresse_ip_wifi_sta" '; + res = bdd.requete_unique(req); + adresse = res[0]; + + if ((adresse === shipheart_adresse_ip_inconnue) || (cde === 0)) image_etat_connexion_3 = "/images/wifi_sta_off.png"; + else image_etat_connexion_3 = "/images/wifi_sta_on.png"; + + //----------------------------------------- + // Etat Wifi Ap : + req = 'SELECT Valeur FROM TB_Systeme WHERE Nom="Adresse_ip_wifi_ap" '; + res = bdd.requete_unique(req); + adresse = res[0]; + + req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Wifi_ap_cde" '; + res = bdd.requete_unique(req); + cde = Number(res[0]); + + if ((adresse === shipheart_adresse_ip_inconnue) || (cde === 0)) image_etat_connexion_4 = "/images/wifi_ap_off.png"; + else image_etat_connexion_4 = "/images/wifi_ap_on.png"; + } + + //----------------------------------------- + // Etat config K-bus : + req = 'SELECT Valeur FROM TB_Systeme WHERE Nom="Defaut_config_k_bus" '; + res = bdd.requete_unique(req); + shipheart_defaut_config_k_bus = Number(res[0]); + + //----------------------------------------- + if (message_users_code === shipheart_message_users_code_aucun) lecture_messages_users(); // On ne lit d'éventuels nouveaux messages que si aucun n'est en cour + + //----------------------------------------- + // 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); + var suffixe_nom_jour; + + switch(shipheart_langue) + { + default: + case shipheart_langue_fr: + case shipheart_langue_es: + case shipheart_langue_pt: + case shipheart_langue_nl: + case shipheart_langue_it: + case shipheart_langue_lv: + case shipheart_langue_ca: + suffixe_nom_jour = " "; + break; + case shipheart_langue_en: + suffixe_nom_jour = ", "; + break; + case shipheart_langue_de: + suffixe_nom_jour = ", den "; + break; + } + + date_courante = Fonctions_date_heure.chaine_jour_semaine(date) + suffixe_nom_jour + Fonctions_date_heure.chaine_date_longue(date, shipheart_langue) + heure_courante = Fonctions_date_heure.chaine_heure(date); + +//console.timeEnd('mise_a_jour_protegee') + + } + + //================================================================================================= + // Fonction : + // - mise à jour de l'onglet en cours en vérifiant que l'ID en cours existe bien dans la table des familles, + // - vérifie que le modèle d'onglets a la même taille que la table des familles. + // - si Oui, mise à jour du nom et de l'état actif de chaque entrée du modèle et vérification que l'ordre du modèle égale celui de la table + // - Si Non (ou si l'ordre de la table n'est plus conforme au modèle), Raz du modèle est remplissage. + // - Création du modèle de circuits correspondant à l'onglet en cours + // NB : il n'est pas utile d'appeler la fonction 'mise_a_jour_circuits()' après car le modèle de circuits + // venant d'être créé, il est forcément à jour... + //================================================================================================= + function init_circuits() + { + var req, res; + var nb; + var i; + var actif; + + + // Mise à jour de l'onglet en cours : + req = 'SELECT COUNT(*) FROM TB_Familles WHERE Type_source=' + shipheart_type_source_circuits + ' AND Cle_primaire=' + id_groupe_circuits + ' '; + res = bdd.requete_unique(req); +//console.log("Requête = [ " + req + "; ]"); + if (Number(res[0]) !== 1) // Si l'ID en cours n'existe pas dans la BDD (à l'init notamment mais aussi si suppression de famille par exemple) + { + req = 'SELECT Cle_primaire FROM TB_Familles WHERE Type_source=' + shipheart_type_source_circuits + ' ORDER BY Priorite_affichage LIMIT 1'; // Choix de la première famille par ordre de priorité + res = bdd.requete_unique(req); +//console.log("Requête = [ " + req + "; ]"); + id_groupe_circuits = Number(res[0]); + } + + // Mise à jour du modèle d'onglets : + var flag_init_onglets_necessaire = false; + req = 'SELECT Cle_primaire, Nom FROM TB_Familles WHERE Type_source=' + shipheart_type_source_circuits + ' ORDER BY Priorite_affichage ' +//console.log("Requête = [" + req + "]"); + nb = bdd.requete(req); + + if (nb === modele_onglets_circuits.count) // Si on a supprimé ou ajouté des familles, on va devoir reconstruire le modèle d'onglets : + { + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + // On teste que l'ordre des familles n'a pas changé depuis la création du modèle : + if (Number(res[0]) !== modele_onglets_circuits.get(i).id) + { + flag_init_onglets_necessaire = true; // S'il a changé (ou si ajout/suppression de familles avec des clés différentes), on arrête et on demande une reconstruction complète du modèle. + break; + } + + // Détection du groupe en cours : + if (id_groupe_circuits === Number(res[0])) actif = true; + else actif = false; + + // Mise à jour du flag 'actif' pour chaque onglet : + modele_onglets_circuits.set(i, {"libelle": res[1], "actif": actif}); // On met à jour le nom au passage pour prendre en compte les éventuelles modifs de nom. + } + } + } + else flag_init_onglets_necessaire = true; + + // Création du modèle d'onglets si cela est nécessaire : + if (flag_init_onglets_necessaire) + { + modele_onglets_circuits.clear(); + + nb = bdd.requete(req); // La requete est toujours correcte mais le résultat a pu commncer a être utilisé : il faut donc la rééxécuter. + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + if (id_groupe_circuits === Number(res[0])) actif = true; + else actif = false; + + modele_onglets_circuits.append({"libelle": res[1], "id": Number(res[0]), "actif": actif, "etat": 0 }); + } + } + } + + // création du modèle des circuits de l'onglet en cours : + modele_circuits.clear(); + req = 'SELECT '; + req += ' Cle_primaire, '; + req += ' Etat_systeme, '; + req += ' Nom, '; + req += ' Etat_commande_carte, '; + req += ' Mode_commande, '; + req += ' Etat, '; + req += ' Consigne, '; + req += ' Old_consigne, '; + req += ' Mode_test, '; + req += ' Tension, '; + req += ' Intensite, '; + req += ' Frequence, '; + req += ' (SELECT Type FROM TB_Modules_config WHERE Adresse_k_bus=TB_Circuits.Adresse_module) AS type_circuit, '; + req += ' No_circuit, '; + req += ' (SELECT COUNT(*) FROM TB_Events WHERE Validite=1 AND Visibilite=1 AND (Action_circuits LIKE CONCAT(TB_Circuits.Cle_primaire,"/%") OR Action_circuits LIKE CONCAT("%;", TB_Circuits.Cle_primaire,"/%") ) ) AS nb_events, '; + req += ' Validation_cdes_events, '; + req += ' (SELECT COUNT(*) FROM TB_Events WHERE Validite=1 AND Type_source=' + shipheart_source_mesure_circuit + ' AND Alarme_source>0 AND Etat_test=1 AND ID_Source=TB_Circuits.Cle_primaire) AS Nb_alarmes'; + req += ' FROM TB_Circuits '; + req += ' WHERE Priorite_affichage_accueil>0 '; + req += ' AND ID_Famille=' + id_groupe_circuits + ' '; + req += ' ORDER BY Priorite_affichage_accueil, Cle_primaire'; +//console.log("Requête = [ " + req + "; ]"); + nb = bdd.requete(req); + + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + modele_circuits.append({ + "Cle_primaire": Number(res[0]), + "Etat_systeme": Number(res[1]), + "Nom": res[2], + "Etat_commande_carte": Number(res[3]), + "Mode_commande": Number(res[4]), + "Etat_circuit": Number(res[5]), + "Consigne": Number(res[6]), + "Old_consigne": Number(res[7]), + "Mode_test": Number(res[8]), + "Tension": Number(res[9]), + "Intensite": Number(res[10]), + "Frequence": Number(res[11]), + "Type_circuit": Number(res[12]), + "No_circuit": Number(res[13]), + "Validation_cdes_events": (Number(res[14]) === 0) ? -1 : Number(res[15]), + "Etat_events": Number(res[16]) }); + } + } + } + + //======================================================================================================= + // Fonction : Met à jour l'état de chaque onglet à partir de la synthès des circuits de l'onglet + //======================================================================================================= + function mise_a_jour_onglets_circuits() + { + var req, res; + var nb; + var i, j; + var etat_circuit; + + + for (i = 0; i < modele_onglets_circuits.count; i ++) + { + modele_onglets_circuits.set(i, {"etat": 0} ); // Valeur minimale par défaut + + // Détection d'alarmes provenant d'un évènement : + req = 'SELECT COUNT(*) '; + req += ' FROM TB_Events '; + req += ' WHERE Type_source=' + shipheart_source_mesure_circuit + ' '; + req += ' AND Validite=1 '; + req += ' AND Alarme_source>0 '; + req += ' AND Etat_test=1 '; + req += ' AND ID_Source IN (SELECT Cle_primaire FROM TB_Circuits WHERE ID_Famille=' + modele_onglets_circuits.get(i).id + ' )'; +//console.log("Requête = [" + req + "]"); + res = bdd.requete_unique(req); + + if (Number(res[0]) > 0) modele_onglets_circuits.set(i, {"etat": 1} ); // Coin orange + + + // Mise à jour de l'état de chaque onglet à partir de la synthèse des circuits de l'onglet : + req = 'SELECT Etat, Etat_commande_carte, Etat_systeme FROM TB_Circuits WHERE ID_Famille=' + modele_onglets_circuits.get(i).id + ' AND Priorite_affichage_accueil>0 '; +//console.log("Requête = [ " + req + "; ]"); + nb = bdd.requete(req); + for (j = 0; j < nb; j ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + if ((Number(res[2]) !== 0) // Si on a une ERREUR_SYSTEME_CONFIG ou ERREUR_SYSTEME_RESEAU sur ce circuit, on met l'onglet en rouge... + || (Number(res[0]) === shipheart_etat_circuit_limitation) + || (Number(res[0]) === shipheart_etat_circuit_protection) + || (Number(res[0]) === shipheart_etat_circuit_disjonte) + || (Number(res[0]) === shipheart_etat_circuit_absence_terre) + || (Number(res[0]) === shipheart_etat_circuit_absence_masse)) etat_circuit = 2; // Coin rouge + else if ((Number(res[1]) !== shipheart_etat_commande_module_ok) + || (Number(res[0]) !== shipheart_etat_circuit_ok)) etat_circuit = 1; // Coin orange + else etat_circuit = 0; + + if (etat_circuit > modele_onglets_circuits.get(i).etat) modele_onglets_circuits.set(i, {"etat": etat_circuit}); + } + } + } + } + + + //======================================================================================================= + // Fonction : Récupère l'état de tous les circuits valides dans la BDD et met à jour le modele_circuits + // Impact : Environ 10ms (chaque 1s) mesuré via QML Profiler et mesure de temps d'exec. le 01/02/2022 + //======================================================================================================= + function mise_a_jour_circuits() + { + var req, res; + var nb; + var i, j; + + req = 'SELECT '; + req += ' Cle_primaire, '; + req += ' Etat_systeme, '; + req += ' Nom, '; + req += ' Etat_commande_carte, '; + req += ' Mode_commande, '; + req += ' Etat, '; + req += ' Consigne, '; + req += ' Old_consigne, '; + req += ' Mode_test, '; + req += ' Tension, '; + req += ' Intensite, '; + req += ' Frequence, '; + req += ' (SELECT Type FROM TB_Modules_config WHERE Adresse_k_bus=TB_Circuits.Adresse_module) AS type_circuit, '; + req += ' No_circuit, '; + req += ' (SELECT COUNT(*) FROM TB_Events WHERE Validite=1 AND Visibilite=1 AND (Action_circuits LIKE CONCAT(TB_Circuits.Cle_primaire,"/%") OR Action_circuits LIKE CONCAT("%;", TB_Circuits.Cle_primaire,"/%") ) ) AS nb_events, '; + req += ' Validation_cdes_events, '; + req += ' (SELECT COUNT(*) FROM TB_Events WHERE Validite=1 AND Type_source=' + shipheart_source_mesure_circuit + ' AND Alarme_source>0 AND Etat_test=1 AND ID_Source=TB_Circuits.Cle_primaire) AS Nb_alarmes'; + req += ' FROM TB_Circuits '; + req += ' WHERE Priorite_affichage_accueil>0 '; + req += ' AND ID_Famille=' + id_groupe_circuits + ' '; + req += ' ORDER BY Priorite_affichage_accueil, Cle_primaire'; +//console.log("Requête = [ " + req + "; ]"); + nb = bdd.requete(req); + + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + for (j = 0; j < modele_circuits.count; j ++) + { + if (Number(res[0]) === modele_circuits.get(j).Cle_primaire) + { + modele_circuits.set(j, { + "Etat_systeme": Number(res[1]), + "Nom": res[2], + "Etat_commande_carte": Number(res[3]), + "Mode_commande": Number(res[4]), + "Etat_circuit": Number(res[5]), + "Consigne": Number(res[6]), + "Old_consigne": Number(res[7]), + "Mode_test": Number(res[8]), + "Tension": Number(res[9]), + "Intensite": Number(res[10]), + "Frequence": Number(res[11]), + "Type_circuit": Number(res[12]), + "No_circuit": Number(res[13]), + "Validation_cdes_events": (Number(res[14]) === 0) ? -1 : Number(res[15]), + "Etat_events": Number(res[16]) }); + break; // Si on a trouvé l'entrée du modèle correspondant au circuit en cours de traitement depuis la BDD, on sort de la boucle sur le modèle (mais on continue la boucle sur les résultats de la requete !) + } + } + } + } + } + + + //================================================================================================= + // Fonction : + // - mise à jour de l'onglet en cours en vérifiant que l'ID en cours existe bien dans la table des familles, + // - vérifie que le modèle d'onglets a la même taille que la table des familles. + // - si Oui, mise à jour du nom et de l'état actif de chaque entrée du modèle et vérification que l'ordre du modèle égale celui de la table + // - Si Non (ou si l'ordre de la table n'est plus conforme au modèle), Raz du modèle est remplissage. + // - Création du modèle de réservoirs correspondant à l'onglet en cours + // NB : il n'est pas utile d'appeler la fonction 'mise_a_jour_reservoirs()' après car le modèle de réservoirs + // venant d'être créé, il est forcément à jour... + //================================================================================================= + function init_reservoirs() + { + var req, res; + var nb; + var i; + var actif; + + + // Mise à jour de l'onglet en cours : + req = 'SELECT COUNT(*) FROM TB_Familles WHERE Cle_primaire=' + id_groupe_reservoirs + ' '; + res = bdd.requete_unique(req); + if (Number(res[0]) !== 1) // Si l'ID en cours n'existe pas dans la BDD (à l'init notamment mais aussi si suppression de famille par exemple) + { + req = 'SELECT Cle_primaire FROM TB_Familles WHERE Type_source=' + shipheart_type_source_reservoirs + ' ORDER BY Priorite_affichage LIMIT 1'; // Choix de la première famille par ordre de priorité + res = bdd.requete_unique(req); + id_groupe_reservoirs = Number(res[0]); + } + + // Mise à jour du modèle d'onglets : + var flag_init_onglets_necessaire = false; + req = 'SELECT Cle_primaire, Nom FROM TB_Familles WHERE Type_source=' + shipheart_type_source_reservoirs + ' ORDER BY Priorite_affichage '; +//console.log("Requête = [" + req + "]"); + nb = bdd.requete(req); + + if (nb === modele_onglets_reservoirs.count) // Si on a supprimé ou ajouté des familles, on va devoir reconstruire le modèle d'onglets : + { + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + // On teste que l'ordre des familles n'a pas changé depuis la création du modèle : + if (Number(res[0]) !== modele_onglets_reservoirs.get(i).id) + { + flag_init_onglets_necessaire = true; // S'il a changé (ou si ajout/suppression de familles avec des clés différentes), on arrête et on demande une reconstruction complète du modèle. + break; + } + + // Détection du groupe en cours : + if (id_groupe_reservoirs === Number(res[0])) actif = true; + else actif = false; + + // Mise à jour du flag 'actif' pour chaque onglet : + modele_onglets_reservoirs.set(i, {"libelle": res[1], "actif": actif}); // On met à jour le nom au passage pour prendre en compte les éventuelles modifs de nom. + } + } + } + else flag_init_onglets_necessaire = true; + + // Création du modèle d'onglets si cela est nécessaire : + if (flag_init_onglets_necessaire) + { + modele_onglets_reservoirs.clear(); + + nb = bdd.requete(req); // La requete est toujours correcte mais le résultat a pu commncer a être utilisé : il faut donc la rééxécuter. + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + if (id_groupe_reservoirs === Number(res[0])) actif = true; + else actif = false; + + modele_onglets_reservoirs.append({"libelle": res[1], "id": Number(res[0]), "actif": actif, "etat": 0}); + } + } + } + + // création du modèle des réservoirs de l'onglet en cours : + modele_reservoirs.clear(); + + req = 'SELECT Cle_primaire, '; + req += ' Nom, '; + req += ' Etat_systeme, '; + req += ' ID_Famille, '; + req += ' Niveau, '; + req += ' Capacite, '; + req += ' Logique, '; + req += ' (SELECT COUNT(*) FROM TB_Events WHERE Validite=1 AND Type_source=' + shipheart_source_mesure_reservoir + ' AND Alarme_source>0 AND Etat_test=1 AND ID_Source=TB_Reservoirs.Cle_primaire) AS Nb_alarmes, ' + req += ' Etat_entrees '; + req += ' FROM TB_Reservoirs '; + req += ' WHERE ID_Famille= ' + id_groupe_reservoirs + ' '; + req += ' 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_reservoirs.append({ + "Cle_primaire": Number(res[0]), + "Nom": res[1], + "Etat_systeme": Number(res[2]), + "ID_Famille": Number(res[3]), + "Niveau": Number(res[4]), + "Capacite": Number(res[5]), + "Logique": Number(res[6]), + "Etat": ( (Number(res[2]) < 0) // Etat_systeme = ERREUR_SYSTEME_CONFIG ou ERREUR_SYSTEME_RESEAU + || (Number(res[8]) > 0)) // Etat_entrees = 1 = Defaut ordre des sondes AUX + ? 2 + : ( Number(res[7]) > 0 // Au moins une alerte sur Event + ? 1 + : 0 ) }); + } + } + } + + //======================================================================================================= + // Fonction : Met à jour l'état de chaque onglet à partir de la synthès des réservoirs de l'onglet + //======================================================================================================= + function mise_a_jour_onglets_reservoirs() + { + var req, res; + var nb; + var i, j; + + + // Mise à jour de l'état de chaque onglet à partir de la synthèse des réservoirs de l'onglet : + // En pratique, seuls les réservoirs à électrodes plongées génèrent des Etats != 0.... + for (i = 0; i < modele_onglets_reservoirs.count; i ++) + { + modele_onglets_reservoirs.set(i, {"etat": 0}); + + // Détection d'alarmes provenant d'un évènement : + req = 'SELECT COUNT(*) '; + req += ' FROM TB_Events '; + req += ' WHERE Type_source=' + shipheart_source_mesure_reservoir + ' '; + req += ' AND Validite=1 '; + req += ' AND Alarme_source>0 '; + req += ' AND Etat_test=1 '; + req += ' AND ID_Source IN (SELECT Cle_primaire FROM TB_Reservoirs WHERE ID_Famille=' + modele_onglets_reservoirs.get(i).id + ' )'; +//console.log("Requête = [ " + req + "; ]"); + res = bdd.requete_unique(req); + + if (Number(res[0]) > 0) modele_onglets_reservoirs.set(i, {"etat": 1} ); // Coin orange + + + // Mise à jour de l'état de chaque onglet à partir de la synthèse des réservoirs de l'onglet : + req = 'SELECT Etat_entrees, Etat_systeme FROM TB_Reservoirs WHERE ID_Famille=' + modele_onglets_reservoirs.get(i).id + ' AND Priorite_affichage_accueil>0 '; +//console.log("Requête = [ " + req + "; ]"); + nb = bdd.requete(req); + for (j = 0; j < nb; j ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { +// if (Number(res[0]) > modele_onglets_reservoirs.get(i).etat) modele_onglets_reservoirs.set(i, {"etat": Number(res[0])}); // SDIR #285 + if ((Number(res[0]) > 0) // Si Défaut_capteur = 1 (ordre des sondes AUX inversées + || (Number(res[1]) !== 0) ) // Si ERREUR_SYSTEME_CONFIG ou ERREUR_SYSTEME_RESEAU + { + if (modele_onglets_reservoirs.get(i).etat < 2) modele_onglets_reservoirs.set(i, {"etat": 2}); // SDIR #285 + } + } + } + } + } + + + //=========================================================================================================== + // Fonction : Récupère l'état de tous les réservoirs valides dans la BDD et met à jour le modele_reservoirs + //=========================================================================================================== + function mise_a_jour_reservoirs() + { + var req, res; + var nb; + var i, j; + + req = 'SELECT Cle_primaire, '; + req += ' Nom, '; + req += ' Etat_systeme, '; + req += ' ID_Famille, '; + req += ' Niveau, '; + req += ' Capacite, '; + req += ' Logique, '; + req += ' (SELECT COUNT(*) FROM TB_Events WHERE Validite=1 AND Type_source=' + shipheart_source_mesure_reservoir + ' AND Alarme_source>0 AND Etat_test=1 AND ID_Source=TB_Reservoirs.Cle_primaire) AS Nb_alarmes, ' + req += ' Etat_entrees '; + req += ' FROM TB_Reservoirs '; + req += ' WHERE ID_Famille= ' + id_groupe_reservoirs + ' '; + req += ' 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) + { + for (j = 0; j < modele_reservoirs.count; j ++) + { + if (Number(res[0]) === modele_reservoirs.get(j).Cle_primaire) + { + modele_reservoirs.set(j, { + "Nom": res[1], + "Etat_systeme": Number(res[2]), + "ID_Famille": Number(res[3]), + "Niveau": Number(res[4]), + "Capacite": Number(res[5]), + "Logique": Number(res[6]), + "Etat": ( (Number(res[2]) < 0) // Etat_systeme = ERREUR_SYSTEME_CONFIG ou ERREUR_SYSTEME_RESEAU + || (Number(res[8]) > 0)) // Etat_entrees = 1 = Defaut ordre des sondes AUX + ? 2 + : ( Number(res[7]) > 0 // Au moins une alerte sur Event + ? 1 + : 0 ) }); + break; // Si on a trouvé l'entrée du modèle correspondant au réservoir en cours de traitement depuis la BDD, on sort de la boucle sur le modèle (mais on continue la boucle sur les résultats de la requete !) + } + } + } + } + } + + + //================================================================================================= + // Fonction : + // - mise à jour de l'onglet en cours en vérifiant que l'ID en cours existe bien dans la table des familles, + // - vérifie que le modèle d'onglets a la même taille que la table des familles. + // - si Oui, mise à jour du nom et de l'état actif de chaque entrée du modèle et vérification que l'ordre du modèle égale celui de la table + // - Si Non (ou si l'ordre de la table n'est plus conforme au modèle), Raz du modèle est remplissage. + // - Création du modèle de batteries correspondant à l'onglet en cours + // NB : il n'est pas utile d'appeler la fonction 'mise_a_jour_batteries()' après car le modèle de batteries + // venant d'être créé, il est forcément à jour... + //================================================================================================= + function init_batteries() + { + var req, res; + var nb; + var i; + var actif; + + // Mise à jour de l'onglet en cours : + req = 'SELECT COUNT(*) FROM TB_Familles WHERE Cle_primaire=' + id_groupe_batteries + ' '; + res = bdd.requete_unique(req); + if (Number(res[0]) !== 1) // Si l'ID en cours n'existe pas dans la BDD (à l'init notamment mais aussi si suppression de famille par exemple) + { + req = 'SELECT Cle_primaire FROM TB_Familles WHERE Type_source=' + shipheart_type_source_batteries + ' ORDER BY Priorite_affichage LIMIT 1'; // Choix de la première famille par ordre de priorité + res = bdd.requete_unique(req); + id_groupe_batteries = Number(res[0]); + } + + // Mise à jour du modèle d'onglets : + var flag_init_onglets_necessaire = false; + req = 'SELECT Cle_primaire, Nom FROM TB_Familles WHERE Type_source=' + shipheart_type_source_batteries + ' ORDER BY Priorite_affichage '; +//console.log("Requête = [" + req + "]"); + nb = bdd.requete(req); + + if (nb === modele_onglets_batteries.count) // Si on a supprimé ou ajouté des familles, on va devoir reconstruire le modèle d'onglets : + { + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + // On teste que l'ordre des familles n'a pas changé depuis la création du modèle : + if (Number(res[0]) !== modele_onglets_batteries.get(i).id) + { + flag_init_onglets_necessaire = true; // S'il a changé (ou si ajout/suppression de familles avec des clés différentes), on arrête et on demande une reconstruction complète du modèle. + break; + } + + // Détection du groupe en cours : + if (id_groupe_batteries === Number(res[0])) actif = true; + else actif = false; + + // Mise à jour du flag 'actif' pour chaque onglet : + modele_onglets_batteries.set(i, {"libelle": res[1], "actif": actif}); // On met à jour le nom au passage pour prendre en compte les éventuelles modifs de nom. + } + } + } + else flag_init_onglets_necessaire = true; + + // Création du modèle d'onglets si cela est nécessaire : + if (flag_init_onglets_necessaire) + { + modele_onglets_batteries.clear(); + + nb = bdd.requete(req); // La requete est toujours correcte mais le résultat a pu commncer a être utilisé : il faut donc la rééxécuter. + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + if (id_groupe_batteries === Number(res[0])) actif = true; + else actif = false; + + modele_onglets_batteries.append({"libelle": res[1], "id": Number(res[0]), "actif": actif, "etat": 0 }); + } + } + } + + // création du modèle des batteries de l'onglet en cours : + modele_batteries.clear(); + + req = 'SELECT Cle_primaire, '; + req += ' Etat_systeme, '; + req += ' Nom, '; + req += ' Type, '; + req += ' Soc, '; + req += ' Tension, '; + req += ' Tension_nominale, '; + req += ' (SELECT COUNT(*) FROM TB_Events WHERE Validite=1 AND Type_source=' + shipheart_source_mesure_batterie + ' AND Alarme_source>0 AND Etat_test=1 AND ID_Source=TB_Batteries.Cle_primaire) AS Nb_alarmes'; + req += ' FROM TB_Batteries '; + req += ' WHERE ID_Famille=' + id_groupe_batteries + ' '; + req += ' 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_batteries.append({ + "Cle_primaire": Number(res[0]), + "Etat_systeme": Number(res[1]), + "Nom": res[2], + "Type": res[3], + "Niveau": Number(res[4]), + "Tension": Number(res[5]), + "Tension_nominale": Number(res[6]), + "Etat": Number(res[7]) }); + } + } + } + + + //======================================================================================================= + // Fonction : Met à jour l'état de chaque onglet à partir de la synthès des batteries de l'onglet + //======================================================================================================= + function mise_a_jour_onglets_batteries() + { + var req, res; + var nb; + var i, j; + + // Détection d'alarmes sur les différents onglets : + for (i = 0; i < modele_onglets_batteries.count; i ++) + { + modele_onglets_batteries.set(i, {"etat": 0} ); + + // Détection d'alarmes provenant d'un évènement : + req = 'SELECT COUNT(*) '; + req += ' FROM TB_Events '; + req += ' WHERE Type_source=' + shipheart_source_mesure_batterie + ' '; + req += ' AND Validite=1 '; + req += ' AND Alarme_source>0 '; + req += ' AND Etat_test=1 '; + req += ' AND ID_Source IN (SELECT Cle_primaire FROM TB_Batteries WHERE ID_Famille=' + modele_onglets_batteries.get(i).id + ' )'; +//console.log("Requête = [" + req + "]"); + res = bdd.requete_unique(req); + + if (Number(res[0]) > 0) modele_onglets_batteries.set(i, {"etat": 1} ); // Coin orange + + + // Mise à jour de l'état de chaque onglet à partir de la synthèse des batteries de l'onglet : + req = 'SELECT Etat_systeme FROM TB_Batteries WHERE ID_Famille=' + modele_onglets_batteries.get(i).id + ' AND Priorite_affichage_accueil>0 '; +//console.log("Requête = [ " + req + "; ]"); + nb = bdd.requete(req); + for (j = 0; j < nb; j ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + if (Number(res[0]) !== 0) // Si ERREUR_SYSTEME_CONFIG ou ERREUR_SYSTEME_RESEAU + { + if (modele_onglets_batteries.get(i).etat < 2) modele_onglets_batteries.set(i, {"etat": 2}); // Coin rouge + } + } + } + } + } + + //========================================================================================================= + // Fonction : Récupère l'état de toutes les batteries valides dans la BDD et met à jour le modele_batteries + //========================================================================================================= + function mise_a_jour_batteries() + { + var req, res; + var nb; + var i, j; + + // Mise à jour des valeurs des batteries du groupe : + req = 'SELECT Cle_primaire, '; + req += ' Etat_systeme, '; + req += ' Nom, '; + req += ' Type, '; + req += ' Soc, '; + req += ' Tension, '; + req += ' Tension_nominale, '; + req += ' (SELECT COUNT(*) FROM TB_Events WHERE Validite=1 AND Type_source=' + shipheart_source_mesure_batterie + ' AND Alarme_source>0 AND Etat_test=1 AND ID_Source=TB_Batteries.Cle_primaire) AS Nb_alarmes'; + req += ' FROM TB_Batteries '; + req += ' WHERE ID_Famille=' + id_groupe_batteries + ' '; + req += ' 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) + { + for (j = 0; j < modele_batteries.count; j ++) + { + if (Number(res[0]) === modele_batteries.get(j).Cle_primaire) + { + modele_batteries.set(j, { + "Etat_systeme": Number(res[1]), + "Nom": res[2], + "Type": res[3], + "Niveau": Number(res[4]), + "Tension": Number(res[5]), + "Tension_nominale": Number(res[6]), + "Etat" : Number(res[7]) }); + break; // Si on a trouvé l'entrée du modèle correspondant au réservoir en cours de traitement depuis la BDD, on sort de la boucle sur le modèle (mais on continue la boucle sur les résultats de la requete !) + } + } + } + } + } + + + //================================================================================================= + // Fonction : + // - mise à jour de l'onglet en cours en vérifiant que l'ID en cours existe bien dans la table des familles, + // - vérifie que le modèle d'onglets a la même taille que la table des familles. + // - si Oui, mise à jour du nom et de l'état actif de chaque entrée du modèle et vérification que l'ordre du modèle égale celui de la table + // - Si Non (ou si l'ordre de la table n'est plus conforme au modèle), Raz du modèle est remplissage. + // - Création du modèle de capteurs correspondant à l'onglet en cours + // NB : il n'est pas utile d'appeler la fonction 'mise_a_jour_capteurs()' après car le modèle de capteurs + // venant d'être créé, il est forcément à jour... + //================================================================================================= + function init_capteurs() + { + var req, res; + var sous_res; + var nb; + var i; + var actif; + var nouvelle_unite + var symbole_unite + var type_unite; + var flag_obsolete; + + // Mise à jour de l'onglet en cours : + req = 'SELECT COUNT(*) FROM TB_Familles WHERE Cle_primaire=' + id_groupe_capteurs + ' '; + res = bdd.requete_unique(req); + if (Number(res[0]) !== 1) // Si l'ID en cours n'existe pas dans la BDD (à l'init notamment mais aussi si suppression de famille par exemple) + { + req = 'SELECT Cle_primaire FROM TB_Familles WHERE Type_source=' + shipheart_type_source_capteurs + ' ORDER BY Priorite_affichage LIMIT 1'; // Choix de la première famille par ordre de priorité + res = bdd.requete_unique(req); + id_groupe_capteurs = Number(res[0]); + } + + // Mise à jour du modèle d'onglets : + var flag_init_onglets_necessaire = false; + req = 'SELECT Cle_primaire, Nom FROM TB_Familles WHERE Type_source=' + shipheart_type_source_capteurs + ' ORDER BY Priorite_affichage '; +//console.log("Requête = [" + req + "]"); + nb = bdd.requete(req); + + if (nb === modele_onglets_capteurs.count) // Si on a supprimé ou ajouté des familles, on va devoir reconstruire le modèle d'onglets : + { + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + // On teste que l'ordre des familles n'a pas changé depuis la création du modèle : + if (Number(res[0]) !== modele_onglets_capteurs.get(i).id) + { + flag_init_onglets_necessaire = true; // S'il a changé (ou si ajout/suppression de familles avec des clés différentes), on arrête et on demande une reconstruction complète du modèle. + break; + } + + // Détection du groupe en cours : + if (id_groupe_capteurs === Number(res[0])) actif = true; + else actif = false; + + // Mise à jour du flag 'actif' pour chaque onglet : + modele_onglets_capteurs.set(i, {"libelle": res[1], "actif": actif}); // On met à jour le nom au passage pour prendre en compte les éventuelles modifs de nom. + } + } + } + else flag_init_onglets_necessaire = true; + + // Création du modèle d'onglets si cela est nécessaire : + if (flag_init_onglets_necessaire) + { + modele_onglets_capteurs.clear(); + + nb = bdd.requete(req); // La requete est toujours correcte mais le résultat a pu commncer a être utilisé : il faut donc la rééxécuter. + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + if (id_groupe_capteurs === Number(res[0])) actif = true; + else actif = false; + + modele_onglets_capteurs.append({"libelle": res[1], "id": Number(res[0]), "actif": actif, "etat": 0 }); + } + } + } + + + // création du modèle des capteurs de l'onglet en cours : + modele_capteurs.clear(); + + req = ' SELECT Cle_primaire, '; + req += ' Etat_systeme, '; + req += ' Nom, '; + req += ' Type_entrees, '; + req += ' Entrees, '; + req += ' ID_Variable, '; + req += ' Etat, '; + req += ' (SELECT COUNT(*) FROM TB_Events WHERE Validite=1 AND Type_source=' + shipheart_source_mesure_capteur + ' AND Alarme_source>0 AND Etat_test=1 AND ID_Source=TB_Capteurs.Cle_primaire) AS Nb_alarmes, ' + req += ' Valeur, '; + req += ' Precision_affichage_accueil, '; + req += ' Liste_valeurs_textes, '; + req += ' IF ( (Type_entrees=' + shipheart_capteur_type_entrees_nmea + '), '; + req += ' ( SELECT ( UNIX_TIMESTAMP() - UNIX_TIMESTAMP(Date_maj) ) '; + req += ' FROM TB_Nmea2000 WHERE '; + req += ' Pgn=SUBSTRING_INDEX(Entrees, \':\', 1) AND Field=SUBSTRING_INDEX(Entrees, \':\', -1) ), '; +// req += ' (UNIX_TIMESTAMP() - UNIX_TIMESTAMP(Date_maj)) )'; // SDIR #336 + req += ' 0 )'; // SDIR #336 + req += ' AS Age '; + req += ' FROM TB_Capteurs WHERE ID_Famille=' + id_groupe_capteurs + ' '; + req += ' AND Priorite_affichage_accueil>0 '; + req += ' ORDER BY Priorite_affichage_accueil, Nom'; +//console.log("Requête = [ " + req + "; ]"); + nb = bdd.requete(req); + + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + flag_obsolete = false; + + // 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="' + Number(res[5]) + '" '); + + // Traitement des conversions d'unités : + switch(Number(sous_res[1])) + { + 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( Number(res[8]), nouvelle_unite, "", Number(res[9]), type_unite); + switch(Number(res[3])) + { + //----------------------------------------------------------------- + case shipheart_capteur_type_entrees_aux: + case shipheart_capteur_type_entrees_calculee_booleen: + + // Traitement des listes : + var chaines_valeurs_textes = res[10].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 (Number(res[8]) === 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; + + //----------------------------------------------------------------- + case shipheart_capteur_type_entrees_nmea: + if (Number(res[11]) > shipheart_periode_obsolescence_capteur_nmea) flag_obsolete = true; + + break; + + //----------------------------------------------------------------- + default : + break; + } + + modele_capteurs.append({ + "Cle_primaire": Number(res[0]), + "Etat_systeme": Number(res[1]), + "Nom": res[2], + "Valeur": chaine_valeur +"", // Le ' + "" ' permet de s'assurer que c'est toujours une STRING, même quand c'est une valeur numérique (le modèle n'accepte pas d'avoir un coup des STRING, un coup des NUM...) + "Unite": symbole_unite, + "Obsolete": flag_obsolete, + "Etat": Number(res[7]), // Events + "Etat_capteur": Number(res[6]) }); // 'Etat' du capteur (entre 0 et 2) + } + } + } + + //======================================================================================================= + // Fonction : Met à jour l'état de chaque onglet à partir de la synthès des capteurs de l'onglet + //======================================================================================================= + function mise_a_jour_onglets_capteurs() + { + var req, res; + var nb; + var i, j; + + // Mise à jour de l'état de chaque onglet à partir de la synthèse des capteurs de l'onglet : + // En pratique, seuls les capteurs OW génèrent des Etats != 0.... + for (i = 0; i < modele_onglets_capteurs.count; i ++) + { + modele_onglets_capteurs.set(i, {"etat": 0} ); + + // Détection d'alarmes sur les différents onglets : + req = 'SELECT COUNT(*) '; + req += ' FROM TB_Events '; + req += ' WHERE Type_source=' + shipheart_source_mesure_capteur + ' '; + req += ' AND Validite=1 '; + req += ' AND Alarme_source>0 '; + req += ' AND Etat_test=1 '; + req += ' AND ID_Source IN (SELECT Cle_primaire FROM TB_Capteurs WHERE ID_Famille=' + modele_onglets_capteurs.get(i).id + ' )'; +//console.log("Requête = [" + req + "]"); + res = bdd.requete_unique(req); + + if (Number(res[0]) > 0) modele_onglets_capteurs.set(i, {"etat": 1} ); // Coin orange + + // Mise à jour de l'état de chaque onglet à partir de la synthèse des batteries de l'onglet : + req = ' SELECT Etat, '; + req += ' Etat_systeme, '; + req += ' IF ( (Type_entrees=' + shipheart_capteur_type_entrees_nmea + '), '; + req += ' ( SELECT ( UNIX_TIMESTAMP() - UNIX_TIMESTAMP(Date_maj) ) '; + req += ' FROM TB_Nmea2000 WHERE '; + req += ' Pgn=SUBSTRING_INDEX(Entrees, \':\', 1) AND Field=SUBSTRING_INDEX(Entrees, \':\', -1) ), '; +// req += ' (UNIX_TIMESTAMP() - UNIX_TIMESTAMP(Date_maj)) )'; // SDIR #336 + req += ' 0 )'; // SDIR #336 + req += ' AS Age '; + req += ' FROM TB_Capteurs '; + req += ' WHERE ID_Famille=' + modele_onglets_capteurs.get(i).id + ' '; + req += ' AND Priorite_affichage_accueil>0 '; +//console.log("Requête = [ " + req + "; ]"); + nb = bdd.requete(req); + for (j = 0; j < nb; j ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + // Obsolescence des capteurs NMEA : + if (Number(res[2]) > shipheart_periode_obsolescence_capteur_nmea) + { + if (modele_onglets_capteurs.get(i).etat < 1) modele_onglets_capteurs.set(i, {"etat": 1}); // Coin orange + } + + // Défaut capteur ou défaut système : + if ( (Number(res[0]) > 0) // Défaut de capteur + || (Number(res[1]) !== 0) ) // Si ERREUR_SYSTEME_CONFIG ou ERREUR_SYSTEME_RESEAU + { + if (modele_onglets_capteurs.get(i).etat < 2) modele_onglets_capteurs.set(i, {"etat": 2}); // Coin rouge + } + } + } + } + } + + //========================================================================================================= + // Fonction : Récupère l'état de tous les capteurs valides dans la BDD et met à jour le modele_capteurs + //========================================================================================================= + function mise_a_jour_capteurs() + { + var req, res; + var sous_res; + var nb; + var i, j; + var actif; + var nouvelle_unite + var symbole_unite + var type_unite; + var flag_obsolete; + + req = ' SELECT Cle_primaire, '; // Note : la requete est utilisée identique à la 'page_personnalisee.qml'@453 pour faciliter la recopie... Penser à porter les modifs là-bas aussi ! + req += ' Etat_systeme, '; + req += ' Nom, '; + req += ' Type_entrees, '; + req += ' Entrees, '; + req += ' ID_Variable, '; + req += ' Etat, '; + req += ' (SELECT COUNT(*) FROM TB_Events WHERE Validite=1 AND Type_source=' + shipheart_source_mesure_capteur + ' AND Alarme_source>0 AND Etat_test=1 AND ID_Source=TB_Capteurs.Cle_primaire) AS Nb_alarmes, ' + req += ' Valeur, '; + req += ' Precision_affichage_accueil, '; + req += ' Liste_valeurs_textes, '; + req += ' IF ( (Type_entrees=' + shipheart_capteur_type_entrees_nmea + '), '; + req += ' ( SELECT ( UNIX_TIMESTAMP() - UNIX_TIMESTAMP(Date_maj) ) '; + req += ' FROM TB_Nmea2000 WHERE '; + req += ' Pgn=SUBSTRING_INDEX(Entrees, \':\', 1) AND Field=SUBSTRING_INDEX(Entrees, \':\', -1) ), '; +// req += ' (UNIX_TIMESTAMP() - UNIX_TIMESTAMP(Date_maj)) )'; // SDIR #336 + req += ' 0 )'; // SDIR #336 + req += ' AS Age '; + req += ' FROM TB_Capteurs WHERE ID_Famille=' + id_groupe_capteurs + ' '; + req += ' AND Priorite_affichage_accueil>0 '; + req += ' ORDER BY Priorite_affichage_accueil, Nom'; +//console.log("Requête = [ " + req + "; ]"); + nb = bdd.requete(req); + + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + flag_obsolete = false; + + // 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="' + Number(res[5]) + '" '); + + // Traitement des conversions d'unités : + switch(Number(sous_res[1])) + { + 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( Number(res[8]), nouvelle_unite, "", Number(res[9]), type_unite); + switch(Number(res[3])) + { + //----------------------------------------------------------------- + case shipheart_capteur_type_entrees_aux: + case shipheart_capteur_type_entrees_calculee_booleen: + + // Traitement des listes : + var chaines_valeurs_textes = res[10].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 (Number(res[8]) === 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; + + //----------------------------------------------------------------- + case shipheart_capteur_type_entrees_nmea: + //console.log("Capteur " + res[2] + " : durée = " + Number(res[11]) + "s (maxi = " + shipheart_periode_obsolescence_capteur_nmea + ") ") + if (Number(res[11]) > shipheart_periode_obsolescence_capteur_nmea) flag_obsolete = true; + + break; + + //----------------------------------------------------------------- + default : + break; + } + + for (j = 0; j < modele_capteurs.count; j ++) + { + if (Number(res[0]) === modele_capteurs.get(j).Cle_primaire) + { + modele_capteurs.set(j, { + "Etat_systeme": Number(res[1]), + "Nom": res[2], + "Valeur": chaine_valeur +"", // Le ' + "" ' permet de s'assurer que c'est toujours une STRING, même quand c'est une valeur numérique (le modèle n'accepte pas d'avoir un coup des STRING, un coup des NUM...) + "Unite": symbole_unite, + "Obsolete": flag_obsolete, + "Etat": Number(res[7]), + "Etat_capteur": Number(res[6]) }); + break; // Si on a trouvé l'entrée du modèle correspondant au capteur en cours de traitement depuis la BDD, on sort de la boucle sur le modèle (mais on continue la boucle sur les résultats de la requete !) + } + } + } + } + } + + + //================================================================================================= + // Fonction : mise à jour du modèle des onglets de pages + //================================================================================================= + function init_pages() + { + var req, res; + var nb; + var i; + + modele_onglets_pages.clear(); + + req = 'SELECT Cle_primaire, Nom, type FROM TB_Pages WHERE Priorite_affichage>0 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) + { + modele_onglets_pages.append({ + "libelle": res[1], + "id": Number(res[0]), + "type": Number(res[2]), + "actif": false, + "etat": 0 }); + } + } + } + + + //========================================================================================================= + // Fonction : Récupère l'état des réseaux et formate le message à afficher dans la boite de dialogue + //========================================================================================================= + function maj_message_reseaux() + { + var req, res; + var nb; + var i; + var msg = ""; + var etat_gnss; + var siv; // Satellites in view + var adresse; + var cde; + var bssid; + var nom; + var canal; + var qualite; + + +// msg += ""; + msg += "
"; + msg += ""; + + //----------------------------------------------------------------------- + // GNSS : + req = 'SELECT Valeur FROM TB_Systeme WHERE Nom="Etat_gnss" '; + res = bdd.requete_unique(req); + etat_gnss = Number(res[0]); + + req = 'SELECT Valeur FROM TB_Capteurs WHERE Adresse_module=0 AND '; + req += ' Type_entrees=' + shipheart_capteur_type_entrees_predefinie + ' '; + req += ' AND Entrees=' + shipheart_capteur_predefini_siv + ' '; + res = bdd.requete_unique(req); + siv = Number(res[0]); + + msg += ""; + + msg += ""; + + msg += ""; + + msg += ""; + + msg += ""; + //----------------------------------------------------------------------- + + //----------------------------------------------------------------------- + msg += ""; + //----------------------------------------------------------------------- + + //----------------------------------------------------------------------- + // Ethernet : + req = 'SELECT Valeur FROM TB_Systeme WHERE Nom="Adresse_ip_ethernet" '; + res = bdd.requete_unique(req); + adresse = res[0]; + + msg += ""; + + msg += ""; + + msg += ""; + + msg += ""; + + msg += ""; + //----------------------------------------------------------------------- + + //----------------------------------------------------------------------- + msg += ""; + //----------------------------------------------------------------------- + + + //----------------------------------------------------------------------- + // Wifi STA : + req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Wifi_sta_cde" '; + res = bdd.requete_unique(req); + cde = Number(res[0]); + + req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="BSSID_Wifi_sta" '; + res = bdd.requete_unique(req); + bssid = res[0]; + + req = 'SELECT Valeur FROM TB_Systeme WHERE Nom="Adresse_ip_wifi_sta" '; + res = bdd.requete_unique(req); + adresse = res[0]; + + req = 'SELECT Nom, Canal, Qualite FROM TB_Wifi_sta WHERE Bssid="' + bssid + '" '; + res = bdd.requete_unique(req); + nom = res[0]; + canal = Number(res[1]); + qualite = Number(res[2]); + + msg += ""; + + msg += ""; + + msg += ""; + + msg += ""; + + msg += ""; + //----------------------------------------------------------------------- + + + //----------------------------------------------------------------------- + msg += ""; + //----------------------------------------------------------------------- + + + //----------------------------------------------------------------------- + // Wifi AP : + req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Wifi_ap_cde" '; + res = bdd.requete_unique(req); + cde = Number(res[0]); + + req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Wifi_ap_ssid" '; + res = bdd.requete_unique(req); + nom = res[0]; + + req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Wifi_ap_canal" '; + res = bdd.requete_unique(req); + canal = res[0]; + + req = 'SELECT Valeur FROM TB_Systeme WHERE Nom="Adresse_ip_wifi_ap" '; + res = bdd.requete_unique(req); + adresse = res[0]; + + msg += ""; + + msg += ""; + + msg += ""; + + msg += ""; + + msg += ""; + //----------------------------------------------------------------------- + + + msg += ""; + msg += "
"; + msg += "GNSS :"; + msg += ""; + if (etat_gnss === 0) msg += qsTr("Déconnecté"); + else msg += qsTr("Nombre de satellites visibles"); + msg += ""; + if (etat_gnss !== 0) msg += siv; + msg += "
"; + msg += "Ethernet :"; + msg += ""; + if (adresse === shipheart_adresse_ip_inconnue) + { + msg += qsTr("Déconnecté"); + } + else + { + msg += qsTr("Connecté"); + } + msg += ""; + msg += adresse; + msg += "
"; + msg += "Wifi (STAtion) :"; + msg += ""; + if (cde === 0) + { + msg += qsTr("OFF"); + } + else + { + if (adresse === shipheart_adresse_ip_inconnue) + { + msg += qsTr("ON") + "
"; // Si on est Connecté, on affiche pas le ON... + } + else + { + msg += qsTr("Connecté") + "
"; + } + msg += nom + "
"; + msg += ((canal < 20) ? "2.4GHz" : "5GHz") + " - Channel " + canal + "
"; + msg += qsTr("Niveau ") + qualite + " %"; + } + msg += "
"; + if (cde !== 0) // Si la commande est OFF, on n'affiche rien dans la colonne d'adresses + { + if (adresse === shipheart_adresse_ip_inconnue) msg += qsTr("Déconnecté"); + else msg += adresse; + } + msg += "
"; + msg += "Wifi (Access Point) :"; + msg += ""; + if (cde === 0) + { + msg += qsTr("OFF"); + } + else + { + if (adresse === shipheart_adresse_ip_inconnue) + { + msg += qsTr("ON") + "
"; // Si on est Connecté, on affiche pas le ON... + } + else + { + msg += qsTr("Actif") + "
"; + } + msg += nom + "
"; + msg += ((canal < 20) ? "2.4GHz" : "5GHz") + " - Channel " + canal + "
"; + } + msg += "
"; + if (cde !== 0) // Si la commande est OFF, on n'affiche rien dans la colonne d'adresses + { + if (adresse === shipheart_adresse_ip_inconnue) msg += qsTr("Inactif"); + else msg += adresse; + } + msg += "
"; + + return(msg); + } + + + //================================================================================================= + // Fonction : Vérifie si un message utilisateur valide existe dans la table TB_Messages_users. Si oui, + // la fonction appelle la boite de dialogue correspondant à ce message et attend une action + // de l'utilisateur en fonction du type de message. + //================================================================================================= + function lecture_messages_users() + { + var req, res; + var i, nb; + var flag_ouverture_boite_dialogue; + + req = 'SELECT Cle_primaire, Code, Parametres, Niveau FROM TB_Messages_users '; + req += ' WHERE Date_validite<=NOW() AND Nb_reports<' + shipheart_message_users_max_nombre_reports + ' '; + req += ' ORDER BY Niveau DESC, Cle_primaire DESC LIMIT 1'; + res = bdd.requete_unique(req); // L'utilisation de 'requete_unique' est possible puisqu'elle contient LIMIT 1. + + id_message_users = Number(res[0]); + message_users_code = Number(res[1]); + boite_message_user.niveau = Number(res[3]); + + boite_message_user.message = maj_texte_messages_users(message_users_code, res[2]); + + // Valeurs par défaut : + boite_message_user.boutonOk = true; // On est obligé de le mettre à jour après avant chaque appel car il a pû être mis à faux dans certains cas auparavant + boite_message_user.progressBarValid = false; // Même commentaire... + flag_ouverture_boite_dialogue = true; // Plus facile à coder... + + // Valeurs spécifiques au message en cours : + switch(message_users_code) + { + //----------------------------------------------------------------------------------------- + case shipheart_message_users_code_aucun: + flag_ouverture_boite_dialogue = false; + break; + + //----------------------------------------------------------------------------------------- + case shipheart_message_users_code_fin_minuteur: + boite_message_user.imageTitreSource = "/images/sablier.png" + break; + + //----------------------------------------------------------------------------------------- + case shipheart_message_users_code_reveil: + boite_message_user.imageTitreSource = "/images/reveil.png" + break; + + //----------------------------------------------------------------------------------------- + case shipheart_message_users_code_maj_en_cours: + boite_message_user.imageTitreSource = "/images/cycle.png" + boite_message_user.progressBarValid = true; + boite_message_user.progressBarValue = 0; + boite_message_user.boutonOk = false; + break; + + //----------------------------------------------------------------------------------------- + case shipheart_message_users_code_redemarrage: + boite_message_user.imageTitreSource = "/images/reset.png" + boite_message_user.boutonOk = false; + break; + + //----------------------------------------------------------------------------------------- + case shipheart_message_users_code_nouvelle_version_detectee: + boite_message_user.imageTitreSource = "/images/ampoule.png" + break; + + //----------------------------------------------------------------------------------------- + case shipheart_message_users_code_defaut_config_k_bus: + boite_message_user.imageTitreSource = "/images/attention.png" + break; + + //----------------------------------------------------------------------------------------- + case shipheart_message_users_code_declenchement_event: + boite_message_user.imageTitreSource = "/images/event.png" + break; + + //----------------------------------------------------------------------------------------- + default : + console.log("Message reçu inconnu (code = " + message_users_code + ")"); + flag_ouverture_boite_dialogue = false; + break; + } + + if (flag_ouverture_boite_dialogue) + { + mise_en_veille(0); // Si un message user arrive, on sort de veille (utile si on y était...) + boite_message_user.open(); + } + } + + + //================================================================================================= + // Fonction : Met à jour les paramètres du message user lorsqu'il est en cours d'affichage + //================================================================================================= + function maj_messages_users() + { + var req, res, nb; + var i; + + // Lecture de l'état actuel du message : + req = 'SELECT Parametres, Niveau FROM TB_Messages_users WHERE Cle_primaire='+ id_message_users + ' '; + nb = bdd.requete(req); + + // Mise à jour du message : + if (nb > 0) // Si le message existe toujours : + { + res = bdd.lecture_ligne(); // Lecture des données + boite_message_user.niveau = Number(res[1]); + boite_message_user.message = maj_texte_messages_users(message_users_code, res[0]); + boite_message_user.progressBarValue = maj_progressbar_message_users(message_users_code, res[0]); + } + else // Si le message a été supprimé (cas de l'appli, juste avant redémarrage) + { + message_users_code = shipheart_message_users_code_aucun; + boite_message_user.progressBarValid = false; // Dans le doute, pour que le prochain appel n'affiche pas la ProgressBar si elle n'est pas demandée... + boite_message_user.close(); + } + } + + + //================================================================================================= + // Fonction : Calcule le texte à afficher en fonction du code du message et de la valeur courante + // de ses paramètres. + //================================================================================================= + function maj_texte_messages_users(code, parametres) + { + var texte = ""; + var params; + var req, res; + + switch(code) + { + //----------------------------------------------------------------------------------------- + case shipheart_message_users_code_aucun: + break; + + //----------------------------------------------------------------------------------------- + case shipheart_message_users_code_fin_minuteur: + texte = qsTr("%1").arg(parametres); + break; + + //----------------------------------------------------------------------------------------- + case shipheart_message_users_code_reveil: + texte = qsTr("%1").arg(parametres); + break; + + //----------------------------------------------------------------------------------------- + case shipheart_message_users_code_maj_en_cours: // Valeur = 2 + params = parametres.split(';'); // Paramètres = 'no_module';'avancement_en_%' (no_module: -1=démarrage, 0-N=No_module en cours, -2=fin) + + switch (Number(params[0])) + { + //---------------------- + // Début de chargement : + case -1: + texte = qsTr("Démarrage"); + break; + + //---------------------------------- + // Chargement en cours d'un module : + default: + + // Récupération du type de carte à partir de son adresse reçue depuis l'Appli : + var libelle_module; + req = 'SELECT Type FROM TB_Modules_physiques WHERE Adresse_k_bus=' + Number(params[0]) + ' '; + res = bdd.requete_unique(req); + + switch(Number(res[0])) + { + case shipheart_type_module_shipbase: + libelle_module = qsTr("Firmware de ShipBase"); + break; + case shipheart_type_module_shippower812: + libelle_module = qsTr("Firmware du ShipPower812 à l'adresse %1").arg(Number(params[0])); + break; + case shipheart_type_module_shipBS: + libelle_module = qsTr("Firmware du ShipBS à l'adresse %1").arg(Number(params[0])); + break; + case shipheart_type_module_shippower4AC: + libelle_module = qsTr("Firmware du ShipPower4AC à l'adresse %1").arg(Number(params[0])); + break; + case shipheart_type_module_shippower8DC: + libelle_module = qsTr("Firmware du ShipPower8DC à l'adresse %1").arg(Number(params[0])); + break; + default: + libelle_module = qsTr("Firmware du module à l'adresse %1").arg(Number(params[0])); + break; + } + + // Génération du texte du message : + texte = libelle_module + "
"; +// if (Number(params[1]) === 0) texte += qsTr("Démarrage"); // SDIR #257 + + // Ajout de la seconde partie du texte, commune à tous les cas : + texte += qsTr("Merci de patienter et de ne rien débrancher
avant la fin de la mise à jour."); + break; + + //--------------------- + // Fin de chargement : + case -2: + boite_message_user.progressBarValid = false; // Suppression de la barre de progression + + texte = qsTr("Chargement des mises à jour effectué avec succès !

L'activation des nouvelles version est en cours sur tous les modules concernés.

Merci de patienter encore quelques secondes..."); + break; + } + break; + + //----------------------------------------------------------------------------------------- + case shipheart_message_users_code_redemarrage: + texte = qsTr("ShipHeart va redémarrer.

Cette opération va prendre quelques dizaines de secondes.
Merci de patienter..."); + break; + + //----------------------------------------------------------------------------------------- + case shipheart_message_users_code_nouvelle_version_detectee: + let versions = parametres.split(';'); // Séparation de l'ancienne et de la nouvelle version + texte = qsTr("Votre système ShipHeart est dorénavant équipé de la version

%1

(la version précédente était la %2)").arg(versions[1]).arg(versions[0]); + break; + + //----------------------------------------------------------------------------------------- + case shipheart_message_users_code_defaut_config_k_bus: + params = parametres.split(';'); // Séparation de 'adresse_k_bus du premier module Nok';'Type_module_physique à cette adresse (yc -1 pour type inconnu)';'Type module configuré' + + if (Number(params[1]) === shipheart_type_module_inconnu) // A priori, le réseau ext 'coupé' juste avant ADRESSE + { + var emplacement_1 = "" + req = 'SELECT Type, Emplacement FROM TB_Modules_config WHERE Adresse_k_bus=' + (Number(params[0]) - 1) + ' '; +//console.log("Requête = [" + req + "]"); + res = bdd.requete_unique(req); + var type_1 = Fonctions.nom_type_module(Number(res[0])); + if (typeof res[1] !== 'undefined') emplacement_1 = res[1]; + + + var emplacement_2 = "" + req = 'SELECT Type, Emplacement FROM TB_Modules_config WHERE Adresse_k_bus=' + Number(params[0]) + ' '; +//console.log("Requête = [" + req + "]"); + res = bdd.requete_unique(req); + var type_2 = Fonctions.nom_type_module(Number(params[2])); + if (typeof res[1] !== 'undefined') emplacement_2 = res[1]; + + texte = qsTr("Le nombre de modules détectés sur le réseau ShipHeart est insuffisant par rapport à la configuration du bateau.

Vérifiez les connexions entre le module %1 à la position @%2 %3 et le module %4 suivant%5

Vous pouvez visualiser l'état complet du réseau ShipHeart et les anomalies détectées dans le menu 'Réseau > ShipHeart' dans les Paramètres Avancés").arg(type_1).arg(Number(params[0]) - 1).arg(emplacement_1 === "" ? "" : "[" + emplacement_1 + "]").arg(type_2).arg(emplacement_2 === "" ? "." : " [" + emplacement_2 + "]"); + } + else + { + texte = qsTr("Le modules détecté en position @%1 est un %2. Cela ne correspond pas à la configuration actuelle du bateau (%3).

Cela peut provenir de l'ajout, de la suppression ou d'un déplacement de module.

Vous pouvez visualiser toutes les anomalies détectées et les corriger dans le menu 'Réseau > ShipHeart' dans les Paramètres Avancés").arg(Number(params[0])).arg(Fonctions.nom_type_module(Number(params[1]))).arg(Fonctions.nom_type_module(Number(params[2]))); + } + + break; + + + //----------------------------------------------------------------------------------------- + case shipheart_message_users_code_declenchement_event: + + req = 'SELECT Nom, Texte_message FROM TB_Events WHERE Cle_primaire=' + Number(parametres) + ' '; +//console.log("Requête = [" + req + "]"); + res = bdd.requete_unique(req); + + texte = qsTr("%1").arg(res[0]); + if (res[1] !== "") texte += "

" + res[1]; + + break; + + //----------------------------------------------------------------------------------------- + default : + texte = qsTr("Code inconnu"); + break; + } + return (texte); + } + + + //================================================================================================= + // Fonction : Calcule les paramètres de la barre d'avancement du message user. + //================================================================================================= + function maj_progressbar_message_users(code, parametres) + { + var valeur = 0; + var params; + + switch(code) + { + //----------------------------------------------------------------------------------------- + case shipheart_message_users_code_maj_en_cours: + params = parametres.split(';'); // Paramètres = 'no_module';'avancement_en_%' (no_module: -1=démarrage, 0-N=No_module en cours, -2=fin) + valeur = Number(params[1]) / 100 ; +//console.log("Nouvelle valeur de Progress Bar = " + valeur); + + break; + + //----------------------------------------------------------------------------------------- + case shipheart_message_users_code_aucun: + case shipheart_message_users_code_fin_minuteur: + case shipheart_message_users_code_reveil: + case shipheart_message_users_code_redemarrage: + case shipheart_message_users_code_nouvelle_version_detectee: + case shipheart_message_users_code_defaut_config_k_bus: + case shipheart_message_users_code_declenchement_event: + default : + + break; + } + + return(valeur); + } + + + //================================================================================================= + // Fonction : Appelée lorsque l'utilisateur à cliqué dans l'un des boutons de la boite de dialogue. + //================================================================================================= + function acquittement_message_users(retour) + { + var req, res; + var i, nb; + var duree_report; + + // Note : l'acquittement d'une boite de dialogue se fait en cliquant sur l'un de ses boutons. + // Ce clic génère un bip (cf 'Shipheart_boite_dialogue.qml' ==> 'shipheart_clic()' ==> 'emission_bip()') + // Ce bip annule la séquence sonore en cours. + // Lors de l'acquittement d'une message user, il n'est donc pas nécessaire de demander la fin d'une + // éventuelle boucle sonore car elle est, dans tous les cas arrêtée... + + switch(message_users_code) + { + //----------------------------------------------------------------------------------------- + case shipheart_message_users_code_aucun: + break; + + //----------------------------------------------------------------------------------------- + case shipheart_message_users_code_fin_minuteur: + case shipheart_message_users_code_reveil: + case shipheart_message_users_code_maj_en_cours: + case shipheart_message_users_code_redemarrage: + case shipheart_message_users_code_nouvelle_version_detectee: + case shipheart_message_users_code_defaut_config_k_bus: + case shipheart_message_users_code_declenchement_event: + switch(retour) + { + //...................................... + case shipheart_boite_dialogue_bouton_1: + // Suppression du message : + req = 'DELETE FROM TB_Messages_users WHERE Cle_primaire=' + id_message_users + ' '; +//console.log("Requête = [" + req + "]"); + bdd.requete_unique(req); + + // Dans le doute, remise à Normal l'état de la LED enface avant : + req = "UPDATE TB_Modules_config SET New_cde='" + shipheart_commande_module_etat_systeme + "/" + shipheart_commande_module_etat_systeme_normal + "' WHERE Adresse_k_bus=0 "; + bdd.requete_unique(req); + + break; + + //...................................... + default: + console.log("Valeur de retour de la boite de dialogue invalide [ " + retour + "]. Aucun traitement n'est effectué"); + break; + } + break; + + //----------------------------------------------------------------------------------------- + default: + console.log("Valeur de 'message_user_code' invalide [" + message_users_code + "]. La valeur est remise à AUCUN"); + break; + } + + message_users_code = shipheart_message_users_code_aucun; + } + + //================================================================================================= + // Fonction appelée lorsque le minuteur a décompté la totalité de sa temporisation + //================================================================================================= + function traitement_fin_minuteur() + { + var req, res; + var libelle_compteur_initial; + + etat_minuteur = 0; // Permet de remettre le minuteur en attente d'une prochaine commande + + libelle_compteur_initial = Math.trunc(compteur_initial_minuteur / (60 * 60)).toString().padStart(2, '0') + + ":" + Math.trunc((compteur_initial_minuteur / 60) % 60).toString().padStart(2, '0') + + ":" + Math.trunc(compteur_initial_minuteur % 60).toString().padStart(2, '0'); + + req = "INSERT INTO TB_Messages_users (Code, Parametres, Niveau) VALUES (" + shipheart_message_users_code_fin_minuteur + ", '" + libelle_compteur_initial + "', 1)"; + bdd.requete_unique(req); + + compteur_initial_minuteur = 0; // Pour prochaine utilisation + +// req = "UPDATE TB_Systeme SET Valeur='button-35.mp3/5/15/20' WHERE Nom='New_bip'"; // 20 x 1.5s = 30s +// req = "UPDATE TB_Systeme SET Valeur='button-32.mp3/2/50/6' WHERE Nom='New_bip'"; // 6 x 5.0s = 30s + req = "UPDATE TB_Systeme SET Valeur='beep-027.mp3/2/10/30' WHERE Nom='New_bip'"; // 30 x 1.0s = 30s +// req = "UPDATE TB_Systeme SET Valeur='beep-28.mp3/6/20/15' WHERE Nom='New_bip'"; // 20 x 1.5s = 30s + bdd.requete_unique(req); +//console.log("Requête = " + req) + synchro_bdd(shipheart_type_synchro_data); +//console.log("Requête = " + req) + + } + + //================================================================================================= + // Fonction appelée lorsqu'un réveil se déclenche + //================================================================================================= + function traitement_declenchement_reveil(jour_semaine, heure, minute) + { + var req; + + + req = 'INSERT INTO TB_Messages_users (Code, Parametres, Niveau) VALUES ('; + req += ' ' + shipheart_message_users_code_reveil + ', '; + req += ' "' + Fonctions_date_heure.nom_jour_semaine(jour_semaine) + "

" + Fonctions_date_heure.nom_heure(heure, minute) + '", '; + req += ' 1)'; +//console.log("Requête = " + req) + bdd.requete_unique(req); + + req = "UPDATE TB_Systeme SET Valeur='button-35.mp3/5/15/20' WHERE Nom='New_bip'"; // 20 x 1.5s = 30s +// req = "UPDATE TB_Systeme SET Valeur='button-32.mp3/2/50/6' WHERE Nom='New_bip'"; // 6 x 5.0s = 30s +// req = "UPDATE TB_Systeme SET Valeur='beep-027.mp3/2/10/30' WHERE Nom='New_bip'"; // 30 x 1.0s = 30s +// req = "UPDATE TB_Systeme SET Valeur='beep-28.mp3/6/20/15' WHERE Nom='New_bip'"; // 20 x 1.5s = 30s + bdd.requete_unique(req); +//console.log("Requête = " + req) + synchro_bdd(shipheart_type_synchro_data); +//console.log("Requête = " + req) + + } + + + //================================================================================================= + // Fonction de tâche de fond, appelée chaque seconde, quelle que soit la page affichée. + // Cette fonction étant toujours active, même quand la page n'est pas affichée, fait qu'il est prudent + // de ne pas trop la charger... + //================================================================================================= + function tache_de_fond() + { + + //---------------------------------------------------- + // Chaque seconde : + //---------------------------------------------------- + + //------------------------------------------------ + // Message de console toutes les secondes (debug) : + let date = new Date().toLocaleString(); + let msg = "[" + date + "] "; + msg += "Prof. stackView = " + stackView.depth; + msg += ", compt. économiseur = " + shipheart_compteur_economiseur; + msg += ", compt. TO niv. acces = " + shipheart_compteur_time_out_niveau_acces; + //msg += ", niv. acces en cours = " + shipheart_niveau_acces_en_cours; + //msg += ", TO niv. acces = " + shipheart_time_out_niveau_acces; + console.log(msg); + + + //---------------------------------------------------- + // Chaque minute (synchronisé sur un nombre défini de secondes) : + //---------------------------------------------------- + if (flag_init_tache_de_fond) // Exécuté une seule fois, au démarrage, pour ne pas avoir à attendre [0; 59s] avant de traiter les taches de fond... + { + tache_de_fond_30(); // Il est important que le traitement @30s soit fait AVANT celui @00 car il met à jour les heures solaires dont 'check_reveils()' a besoin. + tache_de_fond_00(); + flag_init_tache_de_fond = false; // Ce flag n'est utilisé qu'une fois au démarrage + } + else // Cas normal : + { + var now_systeme = new Date; + if (now_systeme.getSeconds() === 0) tache_de_fond_00(); + else if (now_systeme.getSeconds() === 30) tache_de_fond_30(); + } + } + + + //================================================================================================= + // Fonction appelée chaque minute par la tâche de fond, à xx minutes et 00 secondes. + //================================================================================================= + function tache_de_fond_00() + { + var req, res; + var commande; + +//console.log("Traitement de la tâche de fond 00") + + // Traitement des réveils : + check_reveils(); + // ATTENTION : appeler cette fonction AVANT la mise à jour de l'heure qui suit car celle-ci peut générer des écarts de 1 seconde + // et faire déclencher en double des réveils. En effet, le déclenchement de la minute ci-dessus donne par exemple 14:42:00 et + // le calcul dans 'check_reveils()' peut donner (après mise à jour ci-dessous) 14:41:59. Dans un tel cas, le réveil qui déclenche + // à 14:41 sera traité deux fois (à 14:41:00 et 14:41:59). + + // Fonction de mise à l'heure (pour ShipRs seulement) : SDIR #210 + if (shipheart_type_installation !== shipheart_type_installation_shipbase) + { + req = 'SELECT Date_maj FROM TB_Systeme WHERE Nom="Heart_beat" '; + res = bdd.requete_unique(req); + commande = 'sudo date -s "' + res[0] + '" '; + systeme.commande_shell(commande, ""); +//console.log("Commande shell : [" + commande + "]"); + } + } + + //================================================================================================= + // Fonction appelée chaque minute par la tâche de fond, à xx minutes et 30 secondes. + //================================================================================================= + function tache_de_fond_30() + { + var req, res; + var altitude = 0; + +//console.log("Traitement de la tâche de fond 30") + + //------------------------------------------------ + // Récupération de la position du bateau : + // Latitude : + req = 'SELECT Valeur, Precision_affichage_accueil FROM TB_Capteurs WHERE Adresse_module=0 AND '; + req += ' Type_entrees=' + shipheart_capteur_type_entrees_predefinie + ' '; + req += ' AND Entrees=' + shipheart_capteur_predefini_lat + ' '; + res = bdd.requete_unique(req); + shipheart_latitude = Number(res[0]); + + // Longitude : + req = 'SELECT Valeur, Precision_affichage_accueil FROM TB_Capteurs WHERE Adresse_module=0 AND '; + req += ' Type_entrees=' + shipheart_capteur_type_entrees_predefinie + ' '; + req += ' AND Entrees=' + shipheart_capteur_predefini_lon + ' '; + res = bdd.requete_unique(req); + shipheart_longitude = Number(res[0]); + + //------------------------------------------------ + // Mise à jour des heures solaires : + var sun_times = Suncalc.SunCalc.getTimes(Fonctions_date_heure.date_courante(null, shipheart_fuseau_horaire, shipheart_heure_ete), shipheart_latitude, shipheart_longitude, altitude); + + // Aube nautique : + shipheart_heure_aube_nautique = Fonctions_date_heure.conversion_heure_minutes_locales(sun_times.nauticalDawn.getHours(), sun_times.nauticalDawn.getMinutes(), shipheart_fuseau_horaire, shipheart_heure_ete) + req = 'UPDATE TB_Systeme SET Valeur="' + shipheart_heure_aube_nautique + '" WHERE Nom="Aube_nautique" '; +//console.log("Requête = [" + req + "]"); + bdd.requete_unique(req); + + // Lever_soleil : + shipheart_heure_lever_soleil = Fonctions_date_heure.conversion_heure_minutes_locales(sun_times.sunrise.getHours(), sun_times.sunrise.getMinutes(), shipheart_fuseau_horaire, shipheart_heure_ete) + req = 'UPDATE TB_Systeme SET Valeur="' + shipheart_heure_lever_soleil + '" WHERE Nom="Lever_soleil" '; +//console.log("Requête = [" + req + "]"); + bdd.requete_unique(req); + + // Zenith : + shipheart_heure_zenith = Fonctions_date_heure.conversion_heure_minutes_locales(sun_times.solarNoon.getHours(), sun_times.solarNoon.getMinutes(), shipheart_fuseau_horaire, shipheart_heure_ete) + req = 'UPDATE TB_Systeme SET Valeur="' + shipheart_heure_zenith + '" WHERE Nom="Zenith" '; +//console.log("Requête = [" + req + "]"); + bdd.requete_unique(req); + + // Coucher_soleil : + shipheart_heure_coucher_soleil = Fonctions_date_heure.conversion_heure_minutes_locales(sun_times.sunset.getHours(), sun_times.sunset.getMinutes(), shipheart_fuseau_horaire, shipheart_heure_ete) + req = 'UPDATE TB_Systeme SET Valeur="' + shipheart_heure_coucher_soleil + '" WHERE Nom="Coucher_soleil" '; +//console.log("Requête = [" + req + "]"); + bdd.requete_unique(req); + + // Crepuscule_nautique : + shipheart_heure_crepuscule_nautique = Fonctions_date_heure.conversion_heure_minutes_locales(sun_times.nauticalDusk.getHours(), sun_times.nauticalDusk.getMinutes(), shipheart_fuseau_horaire, shipheart_heure_ete) + req = 'UPDATE TB_Systeme SET Valeur="' + shipheart_heure_crepuscule_nautique + '" WHERE Nom="Crepuscule_nautique" '; +//console.log("Requête = [" + req + "]"); + bdd.requete_unique(req); + + //------------------------------------------------ + // Demande de reconnaissance réseau OW : + req = 'UPDATE TB_Systeme SET Valeur=1 WHERE Nom="Demande_decouverte_ow" '; +//console.log("req =" + req); + bdd.requete_unique(req); + } + + + //================================================================================================= + // Fonction appelée chaque minute par la tâche de fond. + // Charge la valeur de 'TB_Configuration.Reveils' et compare chacune de ses entrées avec l'heure en cours. + // Si une condition de match est trouvée, un message et un son dédié sont créés. + //================================================================================================= + function check_reveils() + { + var req, res; + var i; + var conditions; + var condition + var jour; + var heure; + var minute; + var validite; + + reveils_next_jour = 0; + + 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 !== "") + { + // Calcul des valeurs du moment dès lors qu'on a au moins une condition à analyser : + var now = Fonctions_date_heure.date_courante(null, shipheart_fuseau_horaire, shipheart_heure_ete); + var now_jour = now.getDay(); + if (now_jour === 0) now_jour = 7; + var now_heure = now.getHours(); + var now_minute = now.getMinutes(); + + // Découpage des conditions : + conditions = conditions_horaires.split(';'); + + // Bucle sur toutes les conditions : + for (i = 0; i < conditions.length; i ++) + { + // Découpage des 4 champs de la condition : + condition = conditions[i].split('/'); + + if (condition.length === 4) // Si le format de la condition n'est pas valide, on ne la traite pas... + { +//console.log("Now : "+now_jour+"/"+now_heure+"/"+now_minute+" - valeur en cours : "+Number(condition[0])+"/"+Number(condition[1])+"/"+Number(condition[2])+" et validite="+Number(condition[3])) + jour = Number(condition[0]); + heure = Number(condition[1]); + minute = Number(condition[2]); + validite = Number(condition[3]); + + if (validite !== 0) + { + // Adaptation aux heures spéciales : + if (heure > 23) + { + switch(heure) + { + case shipheart_heure_speciale_aube_nautique : + heure = Number(shipheart_heure_aube_nautique[0] + shipheart_heure_aube_nautique[1]); + minute = Number(shipheart_heure_aube_nautique[3] + shipheart_heure_aube_nautique[4]); + break; + + case shipheart_heure_speciale_lever_soleil : + heure = Number(shipheart_heure_lever_soleil[0] + shipheart_heure_lever_soleil[1]); + minute = Number(shipheart_heure_lever_soleil[3] + shipheart_heure_lever_soleil[4]); + break; + + case shipheart_heure_speciale_zenith : + heure = Number(shipheart_heure_zenith[0] + shipheart_heure_zenith[1]); + minute = Number(shipheart_heure_zenith[3] + shipheart_heure_zenith[4]); + break; + + case shipheart_heure_speciale_coucher_soleil : + heure = Number(shipheart_heure_coucher_soleil[0] + shipheart_heure_coucher_soleil[1]); + minute = Number(shipheart_heure_coucher_soleil[3] + shipheart_heure_coucher_soleil[4]); + break; + + case shipheart_heure_speciale_crepuscule_nautique : + heure = Number(shipheart_heure_crepuscule_nautique[0] + shipheart_heure_crepuscule_nautique[1]); + minute = Number(shipheart_heure_crepuscule_nautique[3] + shipheart_heure_crepuscule_nautique[4]); + break; + + case shipheart_heure_speciale_fin_nuit : + case shipheart_heure_speciale_aube : + case shipheart_heure_speciale_crepuscule : + case shipheart_heure_speciale_debut_nuit : + default: + break; // On garde l'heure existante, sachant qu'elle ne sera jamais déclenchée car > 23... + } + } + + // Calcul de la date du prochain déclenchement et de sa "distance" par rapport à maintenant : + var next = prochain_declenchement_condition(now_jour, now_heure, now_minute, jour, heure, minute); + +//console.log("Prochain déclenchement = "+next['jour']+"-"+next['heure']+":"+next['minute']) + + // Mise à jour du prochain déclenchement parmi toutes les conditions actuellement valides : + if ( (reveils_next_jour === 0) // Permet d'identifier qu'aucun NEXT n'a encore été enregistré... + || (next['distance'] < reveils_next_distance)) // ... ou la nouvelle condition se déclenchera avant le NEXT déjà enregistré + { + reveils_next_jour = next['jour']; + reveils_next_heure = next['heure']; + reveils_next_minute = next['minute']; + reveils_next_distance = next['distance']; + } + + // Test du déclenchement MAINTENANT : + if ((jour !== now_jour) && (jour !== 8)) continue; + if (heure !== now_heure) continue; + if (minute !== now_minute) continue; + + // Déclenchement réveil : + traitement_declenchement_reveil(jour, heure, minute); + break; // Inutile d'aller plus loin si on a décleché une fois + } + } + } + } + } + + + //================================================================================================= + // Fonction calculant la date (jour de la semaine, heure et minute) du prochain déclenchement d'une condition horaire. + // La fonction calcule également la "distance" (en minutes) entre maintenant et la date de déclenchement trouvée. + // Reçoit : le jour de la semaine, l'heure et les minutes de MAINTENANT et de la condition. + // Retour : le jour de la semaine, l'heure et minute du prochain déclenchement + la distance du déclenhement vs maintenant. + //================================================================================================= + function prochain_declenchement_condition(now_jour, now_heure, now_minute, jour, heure, minute) + { + var next_jour; + var next_heure; + var next_minute; + var distance; + + //------------------------------------------------------------------------ + // Détermination de la date du prochain déclenchement : + if (jour === 8) // Si c'est TOUS LES JOURS : + { + next_jour = now_jour; // Aujourd'hui par défaut + if ( (heure < now_heure) || // Sauf si l'heure est passée... + ((heure === now_heure) && (minute < now_minute)) ) // ... ou si on est sur l'heure en cours et les minutes sont passées : + { + if (++ next_jour > 7) next_jour = 1; // dans ce cas, on passe à Demain + } + } + else next_jour = jour; // Si c'est un jour de semaine particulier, on n'a pas le choix + + next_heure = heure; + next_minute = minute; + + //------------------------------------------------------------------------ + // Calcul de la distance entre le prochain déclenchement et MAINTENANT : + if (next_jour > now_jour) + { + distance = (60 - now_minute) // Minutes entre maintenant et fin de l'heure en cours + + ((24 - now_heure -1) * 60) // Heures entières entre fin de l'heure en cours et ce soir minuit + + ((next_jour - now_jour - 1) * (24*60)) // Jours entiers séparant les 2 jours + + (heure * 60) // Heures entre 0h du jour de déclenchement et l'heure entière de déclenchement + + (minute) // Minutes entre l'heure entière de déclenchement et le déclenchement + } + + else if (next_jour < now_jour) + { + distance = (60 - now_minute) // Minutes entre maintenant et fin de l'heure en cours + + ((24 - now_heure -1) * 60) // Heures entières entre fin de l'heure en cours et ce soir minuit + + ((7 - now_jour) * (24*60)) // Jours entiers entre ce soir minuit et dimanche soir minuit + + ((next_jour - 1) * (24*60)) // Jours entiers entre lundi 0h et minuit le jour précédent le déclenchement + + (heure * 60) // Heures entre 0h du jour de déclenchement et l'heure entière de déclenchement + + (minute) // Minutes entre l'heure entière de déclenchement et le déclenchement + } + + else // next_jour = now_jour + { + if (heure > now_heure) + { + distance = (60 - now_minute) // Minutes entre maintenant et fin de l'heure en cours + + ((heure - now_heure -1) * 60) // Heures entières entre fin de l'heure en cours et l'heure entière de déclenchement + + (minute) // Minutes entre l'heure entière de déclenchement et le déclenchement + } + + else if (heure < now_heure) + { + distance = (60 - now_minute) // Minutes entre maintenant et fin de l'heure en cours + + ((24 - now_heure -1) * 60) // Heures entières entre fin de l'heure en cours et ce soir minuit + + ((7 - now_jour) * (24*60)) // Jours entiers entre ce soir minuit et dimanche soir minuit + + ((next_jour - 1) * (24*60)) // Jours entiers entre lundi 0h et minuit le jour précédent le déclenchement + + (heure * 60) // Heures entre 0h du jour de déclenchement et l'heure entière de déclenchement + + (minute) // Minutes entre l'heure entière de déclenchement et le déclenchement + } + + else // heure = now_heure + { + if (minute > now_minute) + { + distance = (minute - now_minute) // Minutes entre maintenant et le déclenchement + } + else if (minute < now_minute) + { + distance = (60 - now_minute) // Minutes entre maintenant et fin de l'heure en cours + + ((24 - now_heure -1) * 60) // Heures entières entre fin de l'heure en cours et ce soir minuit + + ((7 - now_jour) * (24*60)) // Jours entiers entre ce soir minuit et dimanche soir minuit + + ((next_jour - 1) * (24*60)) // Jours entiers entre lundi 0h et minuit le jour précédent le déclenchement + + (heure * 60) // Heures entre 0h du jour de déclenchement et l'heure entière de déclenchement + + (minute) // Minutes entre l'heure entière de déclenchement et le déclenchement + } + else distance = 0; + } + } + + return( {"jour": next_jour, "heure": next_heure, "minute": next_minute, "distance": distance } ); + } + + + +} + + diff --git a/home_accueil.qml b/home_accueil.qml new file mode 100644 index 0000000..31f3f69 --- /dev/null +++ b/home_accueil.qml @@ -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"); + } + +} + diff --git a/home_attente.qml b/home_attente.qml new file mode 100644 index 0000000..d1eb63e --- /dev/null +++ b/home_attente.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, ""); + + } + + +} + + diff --git a/home_suncy.qml b/home_suncy.qml new file mode 100644 index 0000000..d64aaa3 --- /dev/null +++ b/home_suncy.qml @@ -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 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. + } + + + +} + diff --git a/images/4g_lte_off.png b/images/4g_lte_off.png new file mode 100755 index 0000000..01d9648 Binary files /dev/null and b/images/4g_lte_off.png differ diff --git a/images/4g_lte_on_1.png b/images/4g_lte_on_1.png new file mode 100755 index 0000000..d47051b Binary files /dev/null and b/images/4g_lte_on_1.png differ diff --git a/images/4g_lte_on_2.png b/images/4g_lte_on_2.png new file mode 100755 index 0000000..ae0aff0 Binary files /dev/null and b/images/4g_lte_on_2.png differ diff --git a/images/4g_lte_on_3.png b/images/4g_lte_on_3.png new file mode 100755 index 0000000..5126208 Binary files /dev/null and b/images/4g_lte_on_3.png differ diff --git a/images/4g_lte_on_4.png b/images/4g_lte_on_4.png new file mode 100755 index 0000000..30da103 Binary files /dev/null and b/images/4g_lte_on_4.png differ diff --git a/images/ak14.png b/images/ak14.png new file mode 100755 index 0000000..389e288 Binary files /dev/null and b/images/ak14.png differ diff --git a/images/ak5.png b/images/ak5.png new file mode 100755 index 0000000..f2fe322 Binary files /dev/null and b/images/ak5.png differ diff --git a/images/ampoule.png b/images/ampoule.png new file mode 100755 index 0000000..64a5de8 Binary files /dev/null and b/images/ampoule.png differ diff --git a/images/arrow-03-left.png b/images/arrow-03-left.png new file mode 100755 index 0000000..257d5c9 Binary files /dev/null and b/images/arrow-03-left.png differ diff --git a/images/attention.png b/images/attention.png new file mode 100755 index 0000000..5e1e8e8 Binary files /dev/null and b/images/attention.png differ diff --git a/images/backspace.png b/images/backspace.png new file mode 100755 index 0000000..3e3a18b Binary files /dev/null and b/images/backspace.png differ diff --git a/images/batterie.png b/images/batterie.png new file mode 100755 index 0000000..8e647da Binary files /dev/null and b/images/batterie.png differ diff --git a/images/batterie_12v.png b/images/batterie_12v.png new file mode 100755 index 0000000..63788fd Binary files /dev/null and b/images/batterie_12v.png differ diff --git a/images/batterie_24v.png b/images/batterie_24v.png new file mode 100755 index 0000000..c3ab950 Binary files /dev/null and b/images/batterie_24v.png differ diff --git a/images/batterie_moyen.png b/images/batterie_moyen.png new file mode 100755 index 0000000..6d738f2 Binary files /dev/null and b/images/batterie_moyen.png differ diff --git a/images/batterie_sombre.png b/images/batterie_sombre.png new file mode 100755 index 0000000..3aa80a9 Binary files /dev/null and b/images/batterie_sombre.png differ diff --git a/images/calendrier.png b/images/calendrier.png new file mode 100755 index 0000000..184fbbf Binary files /dev/null and b/images/calendrier.png differ diff --git a/images/chronometre.png b/images/chronometre.png new file mode 100755 index 0000000..c5a838f Binary files /dev/null and b/images/chronometre.png differ diff --git a/images/circuit_on.png b/images/circuit_on.png new file mode 100755 index 0000000..b9368cb Binary files /dev/null and b/images/circuit_on.png differ diff --git a/images/cloche.png b/images/cloche.png new file mode 100755 index 0000000..d63a669 Binary files /dev/null and b/images/cloche.png differ diff --git a/images/cloche_barree.png b/images/cloche_barree.png new file mode 100755 index 0000000..3ebd13e Binary files /dev/null and b/images/cloche_barree.png differ diff --git a/images/cloche_rouge.png b/images/cloche_rouge.png new file mode 100755 index 0000000..9488f88 Binary files /dev/null and b/images/cloche_rouge.png differ diff --git a/images/cloche_sombre.png b/images/cloche_sombre.png new file mode 100755 index 0000000..3dd2a60 Binary files /dev/null and b/images/cloche_sombre.png differ diff --git a/images/cloche_verte.png b/images/cloche_verte.png new file mode 100755 index 0000000..8721deb Binary files /dev/null and b/images/cloche_verte.png differ diff --git a/images/coin_bas_droite_bleu_koriolan.png b/images/coin_bas_droite_bleu_koriolan.png new file mode 100755 index 0000000..6a1e18e Binary files /dev/null and b/images/coin_bas_droite_bleu_koriolan.png differ diff --git a/images/coin_bas_droite_orange.png b/images/coin_bas_droite_orange.png new file mode 100755 index 0000000..ac9fd67 Binary files /dev/null and b/images/coin_bas_droite_orange.png differ diff --git a/images/coin_bas_droite_rouge.png b/images/coin_bas_droite_rouge.png new file mode 100755 index 0000000..2eba284 Binary files /dev/null and b/images/coin_bas_droite_rouge.png differ diff --git a/images/condition_horaire.pdn b/images/condition_horaire.pdn new file mode 100755 index 0000000..0355d56 Binary files /dev/null and b/images/condition_horaire.pdn differ diff --git a/images/condition_horaire.png b/images/condition_horaire.png new file mode 100755 index 0000000..484e8b1 Binary files /dev/null and b/images/condition_horaire.png differ diff --git a/images/cone_chantier.png b/images/cone_chantier.png new file mode 100755 index 0000000..c5088a4 Binary files /dev/null and b/images/cone_chantier.png differ diff --git a/images/cycle.png b/images/cycle.png new file mode 100755 index 0000000..87aaebb Binary files /dev/null and b/images/cycle.png differ diff --git a/images/cycle_100pc.png b/images/cycle_100pc.png new file mode 100755 index 0000000..fa87c01 Binary files /dev/null and b/images/cycle_100pc.png differ diff --git a/images/cycle_100pc_sombre.png b/images/cycle_100pc_sombre.png new file mode 100755 index 0000000..dad6bfd Binary files /dev/null and b/images/cycle_100pc_sombre.png differ diff --git a/images/cycle_clair.png b/images/cycle_clair.png new file mode 100755 index 0000000..609b2d9 Binary files /dev/null and b/images/cycle_clair.png differ diff --git a/images/cycle_sombre.png b/images/cycle_sombre.png new file mode 100755 index 0000000..3556aaa Binary files /dev/null and b/images/cycle_sombre.png differ diff --git a/images/double_fleche_gauche.png b/images/double_fleche_gauche.png new file mode 100755 index 0000000..a826842 Binary files /dev/null and b/images/double_fleche_gauche.png differ diff --git a/images/down.png b/images/down.png new file mode 100755 index 0000000..0660981 Binary files /dev/null and b/images/down.png differ diff --git a/images/enregistrer_OLD.png b/images/enregistrer_OLD.png new file mode 100755 index 0000000..861524c Binary files /dev/null and b/images/enregistrer_OLD.png differ diff --git a/images/ethernet_off.png b/images/ethernet_off.png new file mode 100755 index 0000000..e54a884 Binary files /dev/null and b/images/ethernet_off.png differ diff --git a/images/ethernet_off_old.png b/images/ethernet_off_old.png new file mode 100755 index 0000000..eb7bd1e Binary files /dev/null and b/images/ethernet_off_old.png differ diff --git a/images/ethernet_on.png b/images/ethernet_on.png new file mode 100755 index 0000000..7ba24e8 Binary files /dev/null and b/images/ethernet_on.png differ diff --git a/images/ethernet_on_old.png b/images/ethernet_on_old.png new file mode 100755 index 0000000..3cd2bc1 Binary files /dev/null and b/images/ethernet_on_old.png differ diff --git a/images/event.pdn b/images/event.pdn new file mode 100755 index 0000000..ac0dd00 Binary files /dev/null and b/images/event.pdn differ diff --git a/images/event.png b/images/event.png new file mode 100755 index 0000000..d538ec0 Binary files /dev/null and b/images/event.png differ diff --git a/images/factory_reset_actif.png b/images/factory_reset_actif.png new file mode 100755 index 0000000..9632879 Binary files /dev/null and b/images/factory_reset_actif.png differ diff --git a/images/factory_reset_sombre.png b/images/factory_reset_sombre.png new file mode 100755 index 0000000..4b21811 Binary files /dev/null and b/images/factory_reset_sombre.png differ diff --git a/images/faux.png b/images/faux.png new file mode 100755 index 0000000..ec02619 Binary files /dev/null and b/images/faux.png differ diff --git a/images/fibre_carbone.png b/images/fibre_carbone.png new file mode 100755 index 0000000..ad3431d Binary files /dev/null and b/images/fibre_carbone.png differ diff --git a/images/fleche_suite_bas.png b/images/fleche_suite_bas.png new file mode 100755 index 0000000..34664f6 Binary files /dev/null and b/images/fleche_suite_bas.png differ diff --git a/images/fleche_suite_droite.png b/images/fleche_suite_droite.png new file mode 100755 index 0000000..edcd0d4 Binary files /dev/null and b/images/fleche_suite_droite.png differ diff --git a/images/fleche_suite_droite_sombre.png b/images/fleche_suite_droite_sombre.png new file mode 100755 index 0000000..58b41bb Binary files /dev/null and b/images/fleche_suite_droite_sombre.png differ diff --git a/images/fleche_suite_gauche.png b/images/fleche_suite_gauche.png new file mode 100755 index 0000000..f76a0f3 Binary files /dev/null and b/images/fleche_suite_gauche.png differ diff --git a/images/fleche_suite_gauche_sombre.png b/images/fleche_suite_gauche_sombre.png new file mode 100755 index 0000000..8a4e7d3 Binary files /dev/null and b/images/fleche_suite_gauche_sombre.png differ diff --git a/images/fleche_suite_haut.png b/images/fleche_suite_haut.png new file mode 100755 index 0000000..4f8ce15 Binary files /dev/null and b/images/fleche_suite_haut.png differ diff --git a/images/fleche_tendance_haut_verte.png b/images/fleche_tendance_haut_verte.png new file mode 100755 index 0000000..275a802 Binary files /dev/null and b/images/fleche_tendance_haut_verte.png differ diff --git a/images/fonction_et_OLD.png b/images/fonction_et_OLD.png new file mode 100755 index 0000000..c4cfaeb Binary files /dev/null and b/images/fonction_et_OLD.png differ diff --git a/images/fonction_ou_OLD.png b/images/fonction_ou_OLD.png new file mode 100755 index 0000000..764df5e Binary files /dev/null and b/images/fonction_ou_OLD.png differ diff --git a/images/fond_2.jpg b/images/fond_2.jpg new file mode 100755 index 0000000..15b6b13 Binary files /dev/null and b/images/fond_2.jpg differ diff --git a/images/fond_3.jpg b/images/fond_3.jpg new file mode 100755 index 0000000..0afbcc6 Binary files /dev/null and b/images/fond_3.jpg differ diff --git a/images/gnss_off.png b/images/gnss_off.png new file mode 100755 index 0000000..331bde2 Binary files /dev/null and b/images/gnss_off.png differ diff --git a/images/gnss_on.png b/images/gnss_on.png new file mode 100755 index 0000000..b73dd30 Binary files /dev/null and b/images/gnss_on.png differ diff --git a/images/heure.png b/images/heure.png new file mode 100755 index 0000000..b75159a Binary files /dev/null and b/images/heure.png differ diff --git a/images/heure_minute.png b/images/heure_minute.png new file mode 100755 index 0000000..79ae6af Binary files /dev/null and b/images/heure_minute.png differ diff --git a/images/icone_auxiliaires.png b/images/icone_auxiliaires.png new file mode 100755 index 0000000..41532b8 Binary files /dev/null and b/images/icone_auxiliaires.png differ diff --git a/images/icone_barometre.png b/images/icone_barometre.png new file mode 100755 index 0000000..dc27082 Binary files /dev/null and b/images/icone_barometre.png differ diff --git a/images/icone_consommation_electrique.png b/images/icone_consommation_electrique.png new file mode 100755 index 0000000..4923bc6 Binary files /dev/null and b/images/icone_consommation_electrique.png differ diff --git a/images/icone_humidite.png b/images/icone_humidite.png new file mode 100755 index 0000000..299f86f Binary files /dev/null and b/images/icone_humidite.png differ diff --git a/images/icone_journal_de_bord.png b/images/icone_journal_de_bord.png new file mode 100755 index 0000000..04360cb Binary files /dev/null and b/images/icone_journal_de_bord.png differ diff --git a/images/icone_parametres.png b/images/icone_parametres.png new file mode 100755 index 0000000..1b181d4 Binary files /dev/null and b/images/icone_parametres.png differ diff --git a/images/icone_parametres_acces_autorise.png b/images/icone_parametres_acces_autorise.png new file mode 100755 index 0000000..3492de4 Binary files /dev/null and b/images/icone_parametres_acces_autorise.png differ diff --git a/images/icone_retour.png b/images/icone_retour.png new file mode 100755 index 0000000..2958364 Binary files /dev/null and b/images/icone_retour.png differ diff --git a/images/icone_retour_OLD.png b/images/icone_retour_OLD.png new file mode 100755 index 0000000..a5abf7d Binary files /dev/null and b/images/icone_retour_OLD.png differ diff --git a/images/icone_temperature.png b/images/icone_temperature.png new file mode 100755 index 0000000..f20d263 Binary files /dev/null and b/images/icone_temperature.png differ diff --git a/images/left.png b/images/left.png new file mode 100755 index 0000000..2b86a2a Binary files /dev/null and b/images/left.png differ diff --git a/images/logo_shipheart.png b/images/logo_shipheart.png new file mode 100755 index 0000000..51d0912 Binary files /dev/null and b/images/logo_shipheart.png differ diff --git a/images/logo_suncy_concept.png b/images/logo_suncy_concept.png new file mode 100755 index 0000000..b986f2e Binary files /dev/null and b/images/logo_suncy_concept.png differ diff --git a/images/lune_1.png b/images/lune_1.png new file mode 100755 index 0000000..f450280 Binary files /dev/null and b/images/lune_1.png differ diff --git a/images/lune_10.png b/images/lune_10.png new file mode 100755 index 0000000..bfbae73 Binary files /dev/null and b/images/lune_10.png differ diff --git a/images/lune_11.png b/images/lune_11.png new file mode 100755 index 0000000..c0fee65 Binary files /dev/null and b/images/lune_11.png differ diff --git a/images/lune_12.png b/images/lune_12.png new file mode 100755 index 0000000..d2e5ea2 Binary files /dev/null and b/images/lune_12.png differ diff --git a/images/lune_13.png b/images/lune_13.png new file mode 100755 index 0000000..f764c0a Binary files /dev/null and b/images/lune_13.png differ diff --git a/images/lune_14.png b/images/lune_14.png new file mode 100755 index 0000000..97bbd93 Binary files /dev/null and b/images/lune_14.png differ diff --git a/images/lune_15.png b/images/lune_15.png new file mode 100755 index 0000000..fa43ea5 Binary files /dev/null and b/images/lune_15.png differ diff --git a/images/lune_16.png b/images/lune_16.png new file mode 100755 index 0000000..fa43ea5 Binary files /dev/null and b/images/lune_16.png differ diff --git a/images/lune_2.png b/images/lune_2.png new file mode 100755 index 0000000..77ad83f Binary files /dev/null and b/images/lune_2.png differ diff --git a/images/lune_3.png b/images/lune_3.png new file mode 100755 index 0000000..79c845d Binary files /dev/null and b/images/lune_3.png differ diff --git a/images/lune_4.png b/images/lune_4.png new file mode 100755 index 0000000..c002267 Binary files /dev/null and b/images/lune_4.png differ diff --git a/images/lune_5.png b/images/lune_5.png new file mode 100755 index 0000000..f34f86f Binary files /dev/null and b/images/lune_5.png differ diff --git a/images/lune_6.png b/images/lune_6.png new file mode 100755 index 0000000..d4e27f9 Binary files /dev/null and b/images/lune_6.png differ diff --git a/images/lune_7.png b/images/lune_7.png new file mode 100755 index 0000000..6a3e52f Binary files /dev/null and b/images/lune_7.png differ diff --git a/images/lune_8.png b/images/lune_8.png new file mode 100755 index 0000000..58a6e1e Binary files /dev/null and b/images/lune_8.png differ diff --git a/images/lune_9.png b/images/lune_9.png new file mode 100755 index 0000000..c476aa2 Binary files /dev/null and b/images/lune_9.png differ diff --git a/images/minute.png b/images/minute.png new file mode 100755 index 0000000..410279f Binary files /dev/null and b/images/minute.png differ diff --git a/images/point_arc_en_ciel.png b/images/point_arc_en_ciel.png new file mode 100755 index 0000000..071afc0 Binary files /dev/null and b/images/point_arc_en_ciel.png differ diff --git a/images/point_blanc.png b/images/point_blanc.png new file mode 100755 index 0000000..3cc56d5 Binary files /dev/null and b/images/point_blanc.png differ diff --git a/images/point_bleu.png b/images/point_bleu.png new file mode 100755 index 0000000..94eb61d Binary files /dev/null and b/images/point_bleu.png differ diff --git a/images/point_jaune.png b/images/point_jaune.png new file mode 100755 index 0000000..a3072ec Binary files /dev/null and b/images/point_jaune.png differ diff --git a/images/point_orange.png b/images/point_orange.png new file mode 100755 index 0000000..6497a83 Binary files /dev/null and b/images/point_orange.png differ diff --git a/images/point_rouge.png b/images/point_rouge.png new file mode 100755 index 0000000..a13cacd Binary files /dev/null and b/images/point_rouge.png differ diff --git a/images/point_transparent.png b/images/point_transparent.png new file mode 100755 index 0000000..ebb945d Binary files /dev/null and b/images/point_transparent.png differ diff --git a/images/point_vert.png b/images/point_vert.png new file mode 100755 index 0000000..a6f0e68 Binary files /dev/null and b/images/point_vert.png differ diff --git a/images/reservoir.png b/images/reservoir.png new file mode 100755 index 0000000..29577c5 Binary files /dev/null and b/images/reservoir.png differ diff --git a/images/reservoir_eau.png b/images/reservoir_eau.png new file mode 100755 index 0000000..9d07ecf Binary files /dev/null and b/images/reservoir_eau.png differ diff --git a/images/reset.png b/images/reset.png new file mode 100755 index 0000000..b0fd6a0 Binary files /dev/null and b/images/reset.png differ diff --git a/images/reset_actif.png b/images/reset_actif.png new file mode 100755 index 0000000..c90f714 Binary files /dev/null and b/images/reset_actif.png differ diff --git a/images/reset_sombre.png b/images/reset_sombre.png new file mode 100755 index 0000000..01978d0 Binary files /dev/null and b/images/reset_sombre.png differ diff --git a/images/reveil.png b/images/reveil.png new file mode 100755 index 0000000..87eb85d Binary files /dev/null and b/images/reveil.png differ diff --git a/images/right.png b/images/right.png new file mode 100755 index 0000000..5d45d19 Binary files /dev/null and b/images/right.png differ diff --git a/images/right_sombre.png b/images/right_sombre.png new file mode 100755 index 0000000..253be02 Binary files /dev/null and b/images/right_sombre.png differ diff --git a/images/sablier.png b/images/sablier.png new file mode 100755 index 0000000..4a2cea6 Binary files /dev/null and b/images/sablier.png differ diff --git a/images/satellite.png b/images/satellite.png new file mode 100755 index 0000000..0568ae8 Binary files /dev/null and b/images/satellite.png differ diff --git a/images/shipbase.png b/images/shipbase.png new file mode 100755 index 0000000..a6fc621 Binary files /dev/null and b/images/shipbase.png differ diff --git a/images/shipbs.png b/images/shipbs.png new file mode 100755 index 0000000..92b3221 Binary files /dev/null and b/images/shipbs.png differ diff --git a/images/soh.png b/images/soh.png new file mode 100755 index 0000000..6968acd Binary files /dev/null and b/images/soh.png differ diff --git a/images/soh_sombre.png b/images/soh_sombre.png new file mode 100755 index 0000000..a5c1add Binary files /dev/null and b/images/soh_sombre.png differ diff --git a/images/sp4ac.png b/images/sp4ac.png new file mode 100755 index 0000000..9b93ecf Binary files /dev/null and b/images/sp4ac.png differ diff --git a/images/sp8dc.png b/images/sp8dc.png new file mode 100755 index 0000000..4b3b969 Binary files /dev/null and b/images/sp8dc.png differ diff --git a/images/tri.png b/images/tri.png new file mode 100755 index 0000000..34ad185 Binary files /dev/null and b/images/tri.png differ diff --git a/images/up.png b/images/up.png new file mode 100755 index 0000000..c37e529 Binary files /dev/null and b/images/up.png differ diff --git a/images/up_bleu.png b/images/up_bleu.png new file mode 100755 index 0000000..259b42d Binary files /dev/null and b/images/up_bleu.png differ diff --git a/images/vanne.png b/images/vanne.png new file mode 100755 index 0000000..66cc3f7 Binary files /dev/null and b/images/vanne.png differ diff --git a/images/vanne_fermee.png b/images/vanne_fermee.png new file mode 100755 index 0000000..e7adbb7 Binary files /dev/null and b/images/vanne_fermee.png differ diff --git a/images/vanne_ouverte.png b/images/vanne_ouverte.png new file mode 100755 index 0000000..8e6baee Binary files /dev/null and b/images/vanne_ouverte.png differ diff --git a/images/vanne_ouverte_2.png b/images/vanne_ouverte_2.png new file mode 100755 index 0000000..829b59f Binary files /dev/null and b/images/vanne_ouverte_2.png differ diff --git a/images/vrai.png b/images/vrai.png new file mode 100755 index 0000000..6bc6e9f Binary files /dev/null and b/images/vrai.png differ diff --git a/images/wifi_ap_off.png b/images/wifi_ap_off.png new file mode 100755 index 0000000..7773ade Binary files /dev/null and b/images/wifi_ap_off.png differ diff --git a/images/wifi_ap_on.png b/images/wifi_ap_on.png new file mode 100755 index 0000000..f3cc0ae Binary files /dev/null and b/images/wifi_ap_on.png differ diff --git a/images/wifi_sta_off.png b/images/wifi_sta_off.png new file mode 100755 index 0000000..e227b8b Binary files /dev/null and b/images/wifi_sta_off.png differ diff --git a/images/wifi_sta_on-koriolan-MS-7B98.png b/images/wifi_sta_on-koriolan-MS-7B98.png new file mode 100755 index 0000000..c42ef6e Binary files /dev/null and b/images/wifi_sta_on-koriolan-MS-7B98.png differ diff --git a/images/wifi_sta_on.png b/images/wifi_sta_on.png new file mode 100755 index 0000000..7677ee9 Binary files /dev/null and b/images/wifi_sta_on.png differ diff --git a/journal_de_bord.qml b/journal_de_bord.qml new file mode 100644 index 0000000..c4a9d89 --- /dev/null +++ b/journal_de_bord.qml @@ -0,0 +1,680 @@ +import QtQuick 2.12 +import QtQuick.Controls 2.12 +import QtQuick.Window 2.2 + +import qt.koriolan.shipheart 1.0 +import"fonctions_date_heure.js" as Fonctions_date_heure +import"fonctions_historique.js" as Fonctions_historique + + + +Shipheart_page { + id: page_journal_de_bord + + + // Mise en forme : + readonly property double pourcentage_largeur_colonne_gauche: 0.5 + readonly property double espace_colonnes_principales: 20 + readonly property double espace_colonnes_secondaires: 50 + readonly property double pourcentage_hauteur_ligne_haut: 1.0 // 0.7 + readonly property double pourcentage_hauteur_ligne_bas: (1 - pourcentage_hauteur_ligne_haut) + readonly property double espace_lignes_principales: 20 + + readonly property int nombre_types_affiches_sur_une_colonne: 10 + + readonly property int nombre_lignes_historique_visibles: 10 + readonly property int nombre_lignes_historique_par_page: 50 + + readonly property int periode_init_raffraichissement_journal: 1 // En ms + readonly property int periode_raffraichissement_journal: 1000 // En ms + + + // Affichage : + + // Historique + property string libelle_type_tous: qsTr("Tous") + property string libelle_type_batteries: qsTr("Batteries") + property string libelle_type_capteurs: qsTr("Capteurs") + property string libelle_type_circuits: qsTr("Circuits") + property string libelle_type_reservoirs: qsTr("Réservoirs") + property string libelle_type_systeme: qsTr("Système") + property string libelle_type_usb: qsTr("Ports USB") + + property string date_premiere_entree_historique: "" // Contient une chaine (format BDD) représentant la date/heure de l'entrée historique la plus ancienne. Permet de recharger de plus anciennes lors d'un MORE... + property string date_derniere_entree_historique: "" // Contient une chaine (format BDD) représentant la date/heure de l'entrée historique la plus récente. Permet de ne recharger que les nouvelles... + property int filtre_type: shipheart_historique_type_tous // -1=Tous, 0=Systeme, 1=Circuits, 2=Capteurs, 3=Réservoirs, 4=Batteries, 5=USB + property int filtre_id: 0 + property bool flag_choix_id: false // Si vrai, indique qu'un choix d'ID est possible. Su Faux, il n'y a pas de choix d'ID + property int index_type_en_cours: -1 + property int index_id_en_cours: -1 + property bool flag_journal_full: false // est positionné à vrai quand il n'y a plus d'enregistrements supplémentaires disponibles pour ce filtre + + + // Données dynamiques : + property var circuits: [] // Contient, après l'initialisation, le nom affecté à chaque clé primaire (utile pour afficher en clair l'ID dans l'historique) + property var capteurs: [] // Contient, après l'initialisation, le nom affecté à chaque clé primaire (utile pour afficher en clair l'ID dans l'historique) + property var reservoirs: [] // Contient, après l'initialisation, le nom affecté à chaque clé primaire (utile pour afficher en clair l'ID dans l'historique) + property var batteries: [] // Contient, après l'initialisation, le nom affecté à chaque clé primaire (utile pour afficher en clair l'ID dans l'historique) + + + // Modèles : + // Note : les modèles chargés dans 'main.qml' n'ont pas à être rechargés dans les pages suivantes + + + //=========================================================== + // Timer periode raffraichissement journal : + //=========================================================== + Timer { + id: timer_raffraichissement_journal + interval: periode_init_raffraichissement_journal + triggeredOnStart: false + running: true + repeat: true + onTriggered: { + if (interval == periode_init_raffraichissement_journal) { // Premier passage, 1ms après le premier chargement + interval = periode_raffraichissement_journal; + + init_page(); + } + else { +// mise_a_jour_filtres(); + mise_a_jour_journal("UPDATE"); + } + } + } + + + // Titre de la page : + Shipheart_titre_1 {titre:qsTr("Journal de bord"); hauteur: shipheart_hauteur_bandeau_haut} + + + //------------------------------------------------------- + // Ecran haut - gauche : Filtres + //------------------------------------------------------- + Rectangle { + id: zone_affichage_haut_gauche + x: 0 + y: shipheart_hauteur_bandeau_haut + espace_lignes_principales; + width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2); + height: (shipheart_hauteur_page - shipheart_hauteur_bandeau_haut - shipheart_hauteur_bandeau_bas - (((pourcentage_hauteur_ligne_bas > 0) ? 3 : 2) * espace_lignes_principales)) * pourcentage_hauteur_ligne_haut; + color: "transparent" + + //--------------------------------- + // Liste pour afficher les types : + //--------------------------------- + ListView { + id: liste_principale + + width: parent.width * 0.4 + 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_choix_type + delegate: Rectangle { + width:parent.width + height: ((liste_principale.height - ((nombre_types_affiches_sur_une_colonne - 1) * liste_principale.spacing)) / nombre_types_affiches_sur_une_colonne) + color: "transparent" + Rectangle { // c'est le bouton proprement dit... + height: parent.height + width:parent.width + color: (model.index === index_type_en_cours) ? shipheart_couleur_fond_bouton_actif : shipheart_couleur_fond_bouton + radius: shipheart_rayon_bouton + anchors.bottom: parent.bottom + Text { + anchors.fill: parent + horizontalAlignment: Qt.AlignLeft + verticalAlignment: Qt.AlignVCenter + leftPadding: 20 + text: model.libelle + color: couleur_blanc_casse + font.pixelSize: 18 + font.bold: ((index === 0) || (index === index_type_en_cours)) ? true : false + wrapMode: Label.Wrap + } + MouseArea{ + anchors.fill : parent + onClicked: { + shipheart_clic(); + mise_a_jour_filtres(model.index, index_id_en_cours); + } + } + } + } + ListModel { + id: modele_choix_type + } + + Label { + anchors.fill: parent + horizontalAlignment: Qt.AlignHCenter + verticalAlignment: Qt.AlignVCenter + visible: parent.count === 0 + text: qsTr("Aucun type n'est configuré...") + color: couleur_rouge_transparent + font.pixelSize: 15 + font.bold: true + wrapMode: Label.Wrap + } + } + + //------------------------------------------------------- + // Liste pour afficher les IDs correspondant aux types : + //------------------------------------------------------- + ListView { + id: liste_secondaire + + x: liste_principale.width + 10 + width: parent.width - x + height: liste_principale.height + spacing: 5 + snapMode: GridView.SnapToRow // L'arret de l'affichage se fera sur une rangée entière + model: modele_choix_id_circuits // Valeur par défaut mise à jour dynamiqueemnt ensuite + visible: flag_choix_id // On n'affiche ce choix que si le type en cours permet de choisir un ID spécifique + delegate: Rectangle { + width:parent.width + height: ((liste_secondaire.height - ((nombre_types_affiches_sur_une_colonne - 1) * liste_secondaire.spacing)) / nombre_types_affiches_sur_une_colonne) + color: "transparent" + Rectangle { // c'est le bouton proprement dit... + height: parent.height + width:parent.width + color: (model.index === index_id_en_cours) ? shipheart_couleur_fond_bouton_actif : shipheart_couleur_fond_bouton + radius: shipheart_rayon_bouton + anchors.bottom: parent.bottom + Text { + anchors.fill: parent + horizontalAlignment: Qt.AlignLeft + verticalAlignment: Qt.AlignVCenter + leftPadding: 20 + text: model.libelle + color: couleur_blanc_casse + font.pixelSize: 18 + font.bold: ((index === 0) || (index === index_id_en_cours)) ? true : false + wrapMode: Label.Wrap + } + MouseArea{ + anchors.fill : parent + onClicked: { + shipheart_clic(); + mise_a_jour_filtres(index_type_en_cours, model.index); + } + } + } + } + ListModel { + id: modele_choix_id_circuits + } + ListModel { + id: modele_choix_id_capteurs + } + ListModel { + id: modele_choix_id_reservoirs + } + ListModel { + id: modele_choix_id_batteries + } + } + } + + + //------------------------------------------------------- + // Ecran bas - gauche : + //------------------------------------------------------- + Rectangle { + id: zone_affichage_bas_gauche + x: 0 + y: shipheart_hauteur_bandeau_haut + zone_affichage_haut_gauche.height + (2 * espace_lignes_principales); + width: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) - (espace_colonnes_principales / 2); + height: (shipheart_hauteur_page - shipheart_hauteur_bandeau_haut - shipheart_hauteur_bandeau_bas - (3 * espace_lignes_principales)) * pourcentage_hauteur_ligne_bas + color: "transparent" + } + + + //------------------------------------------------------- + // Ecran haut - droite : Journal + //------------------------------------------------------- + Rectangle { + id: zone_affichage_haut_droite + x: (shipheart_largeur_page * pourcentage_largeur_colonne_gauche) + (espace_colonnes_principales / 2); + y: shipheart_hauteur_bandeau_haut + espace_lignes_principales; + width: (shipheart_largeur_page * (1 - pourcentage_largeur_colonne_gauche)) - (espace_colonnes_principales / 2); + height: zone_affichage_haut_gauche.height + zone_affichage_bas_gauche.height + (((pourcentage_hauteur_ligne_bas > 0) ? 1 : 0) * espace_lignes_principales); + color: "transparent" + + ListModel { + id: historique + } + + ListView { + id: liste_historique + anchors.fill: parent + model: historique + spacing: 5 + snapMode: GridView.SnapToRow // L'arret de l'affichage se fera sur une rangée entière + footerPositioning: ListView.InlineFooter // Positionne le footer à la fin des enregistrements (pratique pour le bouton MORE...) + delegate: Rectangle { + width:liste_historique.width + height: ((liste_historique.height - ((nombre_lignes_historique_visibles - 1) * liste_historique.spacing)) / nombre_lignes_historique_visibles) + color: shipheart_couleur_fond_bouton + radius: shipheart_rayon_bouton + Text { + id: no_ligne + width: parent.width * 0.07; + anchors.verticalCenter: parent.verticalCenter + horizontalAlignment: Text.AlignRight + text: index + 1 + font.pixelSize: 14 + font.bold: true + color: couleur_gris_moyen + } + Text { + id: date_ligne + x: no_ligne.width; + width: parent.width * 0.3; + anchors.verticalCenter: parent.verticalCenter + horizontalAlignment: Text.AlignHCenter + text: model.date_event + font.pixelSize: 14 + color: couleur_blanc_casse + } + Text { + id: texte_ligne + x: no_ligne.width + date_ligne.width; + width: parent.width - no_ligne.width - date_ligne.width; + anchors.verticalCenter: parent.verticalCenter + horizontalAlignment: Text.AlignJustify + text: model.texte_event + font.pixelSize: 14 + rightPadding: 10 + wrapMode: Text.Wrap + maximumLineCount: 2 + elide: Text.ElideRight + color: couleur_gris_moyen + } + MouseArea{ + anchors.fill : parent + onClicked: { + boite_information_journal.niveau = 0 + boite_information_journal.imageTitreSource = "/images/icone_journal_de_bord.png"; + boite_information_journal.message = qsTr("%1


%2").arg(Fonctions_date_heure.chaine_date_longue(Fonctions_date_heure.chaine_bdd_date_heure(model.date_event), shipheart_langue) + "

" + Fonctions_date_heure.chaine_heure(Fonctions_date_heure.chaine_bdd_date_heure(model.date_event))).arg(model.texte_event) + boite_information_journal.open(); + } + onPressed: shipheart_clic(); + } + } + 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_historique.height - ((nombre_lignes_historique_visibles - 1) * liste_historique.spacing)) / nombre_lignes_historique_visibles) + liste_historique.spacing + width:parent.width - 5 // Le '5' donne la marge droite + color: "transparent" + visible: !flag_journal_full + Rectangle { // c'est le bouton proprement dit... + height: ((liste_historique.height - ((nombre_lignes_historique_visibles - 1) * liste_historique.spacing)) / nombre_lignes_historique_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: { + mise_a_jour_journal("MORE"); + } + onPressed: shipheart_clic(); + } + } + } + Label { + anchors.fill: parent + horizontalAlignment: Qt.AlignHCenter + verticalAlignment: Qt.AlignVCenter + visible: parent.count === 0 + text: qsTr("Aucune entrée d'historique n'est disponible pour cette sélection...") + color: couleur_rouge_transparent + font.pixelSize: 15 + font.bold: true + wrapMode: Label.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: 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 + pressAndHoldInterval: shipheart_mouse_press_and_hold_interval_court + onClicked: { + shipheart_clic(); + stackView.pop(); + } + } + } + } + + //------------------------------------------------------- + // Boite de détails d'entrée de journal : + //------------------------------------------------------- + Shipheart_boite_dialogue { + id: boite_information_journal + } + + + //=========================================================== + // 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; + + // Mise à jour du modèle de choix de type : + // Simplement commenter les lignes non nécessaires .... + modele_choix_type.clear(); + modele_choix_type.append({"libelle": libelle_type_tous, "type": shipheart_historique_type_tous }); // Ajout du premier choix "Tous" + modele_choix_type.append({"libelle": libelle_type_circuits, "type": shipheart_historique_type_circuits }); + modele_choix_type.append({"libelle": libelle_type_reservoirs, "type": shipheart_historique_type_reservoirs }); + modele_choix_type.append({"libelle": libelle_type_batteries, "type": shipheart_historique_type_batteries }); + modele_choix_type.append({"libelle": libelle_type_capteurs, "type": shipheart_historique_type_capteurs }); + if (shipheart_niveau_acces_en_cours >= shipheart_niveau_acces_admin) + { + modele_choix_type.append({"libelle": libelle_type_systeme, "type": shipheart_historique_type_systeme }); + modele_choix_type.append({"libelle": libelle_type_usb, "type": shipheart_historique_type_usb }); + } + + // Mise à jour du modèle des Circuits : + modele_choix_id_circuits.clear(); + modele_choix_id_circuits.append({"libelle": qsTr("Tous"), "cle_primaire": 0 }); // Ajout du premier choix "Tous" + req = 'SELECT Cle_primaire, Nom FROM TB_Circuits '; + req += ' WHERE ID_Circuit_esclave>=0 '; // On écarte les circuits esclaves car il n'y a pas d'utilité à les faire apparaitre... + req += ' ORDER BY Priorite_affichage_accueil '; // On ne filtre volontairement sur aucune validité ou présence car le journal peut porter sur des éléments qui ne sont plus valables... +//console.log("Requête = " + req); + nb = bdd.requete(req); + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + modele_choix_id_circuits.append({"libelle": res[1], "cle_primaire": Number(res[0]) }); + circuits[res[0]] = res[1]; + } + } + + // Mise à jour du modèle des Capteurs : + modele_choix_id_capteurs.clear(); + modele_choix_id_capteurs.append({"libelle": qsTr("Tous"), "cle_primaire": 0 }); // Ajout du premier choix "Tous" + req = 'SELECT Cle_primaire, Nom FROM TB_Capteurs ORDER BY Nom '; // On ne filtre volontairement sur aucune validité ou présence car le journal peut porter sur des éléments qui ne sont plus valables... + nb = bdd.requete(req); + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + modele_choix_id_capteurs.append({"libelle": res[1], "cle_primaire": Number(res[0]) }); + capteurs[res[0]] = res[1]; + } + } + + // Mise à jour du modèle des Réservoirs : + modele_choix_id_reservoirs.clear(); + modele_choix_id_reservoirs.append({"libelle": qsTr("Tous"), "cle_primaire": 0 }); // Ajout du premier choix "Tous" + req = 'SELECT Cle_primaire, Nom FROM TB_Reservoirs ORDER BY Nom '; // On ne filtre volontairement sur aucune validité ou présence car le journal peut porter sur des éléments qui ne sont plus valables... + nb = bdd.requete(req); + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + modele_choix_id_reservoirs.append({"libelle": res[1], "cle_primaire": Number(res[0]) }); + reservoirs[res[0]] = res[1]; + } + } + + // Mise à jour du modèle des Batteries : + modele_choix_id_batteries.clear(); + modele_choix_id_batteries.append({"libelle": qsTr("Toutes"), "cle_primaire": 0 }); // Ajout du premier choix "Tous" + req = 'SELECT Cle_primaire, Nom FROM TB_Batteries ORDER BY Nom '; // On ne filtre volontairement sur aucune validité ou présence car le journal peut porter sur des éléments qui ne sont plus valables... + nb = bdd.requete(req); + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + modele_choix_id_batteries.append({"libelle": res[1], "cle_primaire": Number(res[0]) }); + batteries[res[0]] = res[1]; + } + } + + mise_a_jour_filtres(0, 0); // Cette mise à jour des filtres va générer une maj du journal + } + + + //============================================================================================================= + // Mise à jour de l'historique + // Note importante : tous les paramètres de recherche et de gestion sont en UTC ! La conversion en heure locale + // et heure Eté/Hiver est fait eau dernier moment, lors du remplissage du modèle. + //============================================================================================================= + function mise_a_jour_journal(mode) + { + var req, res; + var nb; + var i; + var table; + var liste_parametres = " Cle_primaire, Type, ID_Source, Valeur, Date, Complement"; + var sens; + var filtre= ""; + var nom_id; + +//console.time('maj_journal') + + if (filtre_id !== 0) filtre += " AND ID=" + filtre_id + " "; + + switch(mode) + { + case "INIT": + historique.clear(); // On remet à 0 le modèle lors d'un nouveau filtre + date_premiere_entree_historique = Fonctions_date_heure.chaine_date_heure_bdd(Fonctions_date_heure.date_courante(null, 0, 0)); + date_derniere_entree_historique = date_premiere_entree_historique; + sens = "DESC"; + break; + case "UPDATE": + filtre += ' AND Date>"' + date_derniere_entree_historique + '"'; // On ne récupère que les nouvelles entrées + sens = "ASC"; + break; + case "MORE": + filtre += ' AND Date<"' + date_premiere_entree_historique + '"'; // On ne récupère que les entrées plus ancienne que la plus vieille déjà récupérée + sens = "DESC"; + break; + default : + console.log("Fonction 'mise_a_jour_journal' appelée avec un type inconnu..."); + return; + } + + + + + + if (filtre_type !== shipheart_historique_type_tous) + { +// req = 'SELECT ' + liste_parametres + ', ' + filtre_type + ' FROM ' + table + ' WHERE ' + filtre + ' ORDER BY Date ' + sens + ' LIMIT ' + nombre_lignes_historique_par_page + ' '; + req = 'SELECT ' + liste_parametres + ' FROM TB_Historique WHERE Type_source=' + filtre_type + ' ' + filtre + ' ORDER BY Date ' + sens + ' LIMIT ' + nombre_lignes_historique_par_page + ' '; + +// !!!!! IL doit être possible de simplifier beaucoup le traitement maintenant que l'on a une seule table d'hostorique. !!! + + } + else + { + req = 'SELECT ' + liste_parametres + ' FROM TB_Historique WHERE ' + filtre + ' ORDER BY Date ' + sens + ' LIMIT ' + nombre_lignes_historique_par_page + ' '; + } + + + + + + +//console.log("Requête = " + req); + nb = bdd.requete(req); + + // Récupération des lignes d'historique : + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + switch(Number(res[6])) + { + case shipheart_historique_type_systeme: + nom_id = ""; + break; + case shipheart_historique_type_circuits: + nom_id = circuits[res[2]]; + break; + case shipheart_historique_type_capteurs: + nom_id = capteurs[res[2]]; + break; + case shipheart_historique_type_reservoirs: + nom_id = reservoirs[res[2]]; + break; + case shipheart_historique_type_batteries: + nom_id = batteries[res[2]]; + break; + case shipheart_historique_type_usb: + nom_id = ""; + break; + default: + nom_id = ""; + break; + } + + if ((mode === "INIT") || (mode === "MORE")) // Au démarrage et lorsqu'on ajoute des enregistrements, on le fait par ajout à la fin + { + historique.append( { "date_event": Fonctions_date_heure.chaine_date_heure_bdd(Fonctions_date_heure.date_courante(Fonctions_date_heure.chaine_bdd_date_heure(res[4]), shipheart_fuseau_horaire, shipheart_heure_ete)), + "texte_event": Fonctions_historique.historique_libelle(Number(res[6]), Number(res[1]), nom_id, Number(res[3]), res[5]) + }); + date_premiere_entree_historique = res[4]; + } + else // Si c'est un Update, on ajoute des évènement récents donc on le fait par INSERT (au début) : + { + historique.insert(0,{ "date_event": Fonctions_date_heure.chaine_date_heure_bdd(Fonctions_date_heure.date_courante(Fonctions_date_heure.chaine_bdd_date_heure(res[4]), shipheart_fuseau_horaire, shipheart_heure_ete)), + "texte_event": Fonctions_historique.historique_libelle(Number(res[6]), Number(res[1]), nom_id, Number(res[3]), res[5]) + }); + date_derniere_entree_historique = res[4]; + } + } + else break; // Ne devrait pas arriver.... + } +//console.log("mode = " + mode + " , nb = " + nb + " et date_première_entree = " + date_premiere_entree_historique + " et date_dernière_entrée = " + date_derniere_entree_historique + ". Nb lignes du modèle = " + historique.count); + + + // Traitement de l'affichage de l'historique après la mise à jour du modèle : + switch(mode) + { + case "INIT": + if (nb < nombre_lignes_historique_par_page) flag_journal_full = true; // Positionne le flag FULL lorsqu'on n'a pas récupéré autant d'enregistrements que demandé à l'INIT + else flag_journal_full = false; + liste_historique.positionViewAtBeginning(); // Positionne la liste au début lors d'une INIT + break; + case "UPDATE": + if (nb !== 0) liste_historique.positionViewAtBeginning(); // Positionne la liste au début si au moins une entrée a été ajoutée + break; + case "MORE": + if (nb < nombre_lignes_historique_par_page) flag_journal_full = true; // Positionne le flag FULL lorsqu'on n'a pas récupéré autant d'enregistrements que demandé sur un MORE + break; + } + + +//console.log("Nombre d'entrées de l'historique = " + historique.count + " premiere clé = " + cle_primaire_premiere_entree_historique + " et dernière clé = " + cle_primaire_derniere_entree_historique); // + " et req =" + req); + +//console.timeEnd('maj_journal') + } + + + //============================================================================================================= + // Mise à jour de liste de choix pour les filtres + //============================================================================================================= + function mise_a_jour_filtres(index_type, index_id) + { + var tableau; + + if (index_type_en_cours !== index_type) + { + index_type_en_cours = index_type + index_id_en_cours = 0 + filtre_type = modele_choix_type.get(index_type_en_cours).type; +//console.log("Tumbler choix type index =" + index_type_en_cours + " et valeur de filtre_type = " + filtre_type ) + + switch(filtre_type) + { + case shipheart_historique_type_tous : flag_choix_id = false; break; + case shipheart_historique_type_systeme: flag_choix_id = false; break; + case shipheart_historique_type_circuits: liste_secondaire.model= modele_choix_id_circuits; flag_choix_id = true; break; + case shipheart_historique_type_capteurs: liste_secondaire.model= modele_choix_id_capteurs; flag_choix_id = true; break; + case shipheart_historique_type_reservoirs: liste_secondaire.model= modele_choix_id_reservoirs; flag_choix_id = true; break; + case shipheart_historique_type_batteries: liste_secondaire.model= modele_choix_id_batteries; flag_choix_id = true; break; + case shipheart_historique_type_usb: flag_choix_id = false; break; + default: flag_choix_id = false; + } + + filtre_id = 0; + + mise_a_jour_journal("INIT"); + } + else if (index_id_en_cours !== index_id) + { + index_id_en_cours = index_id + filtre_id = liste_secondaire.model.get(index_id_en_cours).cle_primaire + mise_a_jour_journal("INIT"); + } + } +} diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..09ab7e9 --- /dev/null +++ b/main.cpp @@ -0,0 +1,184 @@ +#include +#include +#include +#include +#include +#include +#include // Pour usleep(), msleep() et sleep() + +#include "backend.h" +#include "bdd.h" +#include "shipheart.h" +#include "systeme.h" +#include "tb_mesures.h" +#include "_version.h" + + // Variables globales : +uint8_t etat_connexion_bdd; +QString TypeInstallation; +QString TailleEcran; +QString AdresseShipBase; +QTranslator translator; // En le déclarant ici, permet d'y accéder dans les fonctions de slot ('backend()' notamment...) + + +//=================================================================================================== +// Fonction : Connexion à la base de données +//=================================================================================================== +static void connectToDatabase() +{ +QString adresse_host; + + QSqlDatabase database = QSqlDatabase::database(); + if (!database.isValid()) { + database = QSqlDatabase::addDatabase("QMYSQL"); + if (!database.isValid()) + qFatal("Cannot add database: %s", qPrintable(database.lastError().text())); + } + + // Choix de l'adresse de la BDD : + switch (TypeInstallation.toInt()) // Renvoi 0 si la conversion échoue (ce qui est le cas si aucun paramètre n'est passé au démarrage, comme c'est le cas sur ShipBase) + { + default: + case 0: // Si on est sur ShipBase, on va se connecter sur 'localhost' + adresse_host = BDD_HOST_NAME; + break; + case 1: // Si on est sur un écran déporté, on va se connecter sur l'adresse de ShipBase reçue au lancement. + // SDIR #320 : + if (AdresseShipBase == "192.168.4.1") AdresseShipBase = "192.168.1.1"; + adresse_host = AdresseShipBase; + // Fin de SDIR #320 + break; + } + + database.setHostName(adresse_host); + database.setUserName(BDD_USER_NAME); + database.setPassword(BDD_USER_PWD); + database.setDatabaseName(BDD_BASE_NAME); + + int16_t nb_essais; + int16_t max_nb_essais = 20; + etat_connexion_bdd = 0; // Valeur par défaut (déconnecté) + + // En pratique, la tentative de connexion qui échoue dure environ 2s. Donc, avec une tempo de 1s d'attente, on fait uen tentative en 3s. + // Exemple : avec un max = 30, le passage à l'écran de défaut de connexion sur ShipRS se fait au bout de 1min 35s après le lancement de Qt. + for (nb_essais = 0; nb_essais < max_nb_essais; nb_essais ++) + { + if (!database.open()) + { + qDebug("Erreur : impossible de se connecter à la base de données [%s]", qPrintable(database.lastError().text())); + sleep(1); + } + else + { + etat_connexion_bdd = 1; + qDebug() << "Connection à la base de données à l'adresse " << adresse_host << ", après essai n° " << nb_essais; + break; + } + } +} + + +//=================================================================================================== +// Fonction : Fourni à QML des valeurs accessibles en C via un singleton intégré à +// "qt.koriolan.shipheart" (cf 'main' ci-dessous) +//=================================================================================================== +static QJSValue appVersionSingletonProvider(QQmlEngine *engine, QJSEngine *scriptEngine) +{ + Q_UNUSED(engine) + + QJSValue appInfo = scriptEngine->newObject(); + appInfo.setProperty("adresse_shipbase", AdresseShipBase); + appInfo.setProperty("etat_connexion_bdd", etat_connexion_bdd); + appInfo.setProperty("version", VERSION); // Fourni la version récupérée depuis le fichier .pro afin de la rendre disponible en QML + appInfo.setProperty("type_installation", TypeInstallation); + appInfo.setProperty("taille_ecran", TailleEcran); + return appInfo; +} + + + +//=================================================================================================== +// Fonction : Main +//=================================================================================================== +int main(int argc, char *argv[]) +{ + qputenv("QT_IM_MODULE", QByteArray("qtvirtualkeyboard")); + qputenv("QT_VIRTUALKEYBOARD_LAYOUT_PATH", ":/virtualkeyboard_layouts_koriolan/layouts"); // Ajout en V3.0.17 pour accéder aux layouts personnalisés + + #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + #endif + + //------------------------------------------------------------- + // Création de l'application : + QApplication app(argc, argv); + app.setOverrideCursor(Qt::BlankCursor); + + QApplication::setApplicationName("ShipHeart_Qt"); // Nom de l'appli si invoqué avec '-v' + QApplication::setApplicationVersion(VERSION); // Version de l'appli si invoqué avec '-v' + + //------------------------------------------------------------- + // Parser de ligne de commande : + QCommandLineParser parser; + parser.addHelpOption(); // Autorise l'invocation avec '-h' ou '--help' + parser.addVersionOption(); // Autorise l'invocation avec 'v' ou '--version' + + // An option with a value : + QCommandLineOption type_installation(QStringList() << "i" << "installation", + QApplication::translate("main", "Type d'installation :\n0 : ShipBase standard, \n1 : écran déporté"), + QApplication::translate("main", "valeur")); + parser.addOption(type_installation); + + QCommandLineOption adresse_shipbase(QStringList() << "a" << "adresse", + QApplication::translate("main", "Adresse IPv4 de ShipBase dans le cas d'une installation déportée"), + QApplication::translate("main", "xxx:xxx:xxx:xxx")); + parser.addOption(adresse_shipbase); + + QCommandLineOption taille_ecran(QStringList() << "t" << "taille", + QApplication::translate("main", "Taille de l'écran en pouces : \n7,\n10 (ShipBase standard),\n22"), + QApplication::translate("main", "valeur")); + parser.addOption(taille_ecran); + + // Process the actual command line arguments given by the user : + parser.process(app); + + TypeInstallation = parser.value(type_installation); + TailleEcran = parser.value(taille_ecran); + AdresseShipBase = parser.value(adresse_shipbase); + +qDebug() << "Type d'installation : " << TypeInstallation << ", adresse ShipBase : " << AdresseShipBase << ", taille d'écran : " << TailleEcran << " pouces"; + + // Fin du parser de commande. + //------------------------------------------------------------ + + + qmlRegisterType("qt.koriolan.shipheart", 1, 0, "Bdd"); + qmlRegisterType ("qt.koriolan.shipheart", 1, 0, "TbMesuresModel"); + qmlRegisterType("qt.koriolan.shipheart", 1, 0, "Systeme"); + qmlRegisterSingletonType("qt.koriolan.shipheart", 1, 0, "AppInfo", appVersionSingletonProvider); + + connectToDatabase(); + + auto engine = new QQmlApplicationEngine(&app); // Ce type de déclaration est un peu inhabituel mais solution trouvée pour remonter à cette variable depuis l'app (nécessaire pour gérer la mise à jour de la langue dans le backend) + engine->setObjectName("currentEngine"); + + const QUrl url(QStringLiteral("qrc:/main.qml")); + QObject::connect(engine, &QQmlApplicationEngine::objectCreated, + &app, [url](QObject *obj, const QUrl &objUrl) + { + if (!obj && url == objUrl) QCoreApplication::exit(-1); + }, Qt::QueuedConnection); + + Backend backend; + engine->rootContext()->setContextProperty("backend", &backend); + + engine->load(url); + + if (translator.load(":/shipheart_fr_FR.qm")) // Par défaut, on charge le fichier FR + { +// qDebug() << "Chargement de shipheart_fr_FR.qm par défaut"; + } + app.installTranslator(&translator); // ... et on l'installe (il sera éventuellement supprimé si la langue stockée dans la BDD est différente) + + return app.exec(); +} diff --git a/main.qml b/main.qml new file mode 100644 index 0000000..7ff6796 --- /dev/null +++ b/main.qml @@ -0,0 +1,1110 @@ +import QtQuick 2.12 +import QtQuick.Controls 2.12 +import QtQuick.VirtualKeyboard 2.4 +import QtQuick.VirtualKeyboard.Settings 2.2 + +import qt.koriolan.shipheart 1.0 + +ApplicationWindow { + id: root + + //=============================================================================================================================== + // Propriétés statiques : + //=============================================================================================================================== + + //----------------------------------------------------------------------------------- + // Générations de ShipBase : + readonly property int shipheart_generation_shipbase_inconnue: 0 + readonly property int shipheart_generation_shipbase_v1: 1 + readonly property int shipheart_generation_shipbase_v2: 2 + readonly property int shipheart_generation_shipbase_v3: 3 + + + //----------------------------------------------------------------------------------- + // Thèmes : + readonly property int shipheart_index_theme_nom: 0 + readonly property int shipheart_index_theme_fichier_fond_ecran: 1 + readonly property int shipheart_index_theme_couleur_fond_ecran: 2 + readonly property int shipheart_index_theme_couleur_fond_bouton: 3 + readonly property int shipheart_index_theme_couleur_fond_bouton_actif: 4 + readonly property int shipheart_index_theme_couleur_texte_titre_1: 5 + readonly property int shipheart_index_theme_couleur_texte_titre_2: 6 + readonly property int shipheart_index_theme_couleur_texte_titre_3: 7 + readonly property int shipheart_index_theme_couleur_fond_boite_dialogue_niveau_0: 8 + readonly property int shipheart_index_theme_couleur_fond_boite_dialogue_niveau_1: 9 + readonly property int shipheart_index_theme_couleur_fond_boite_dialogue_niveau_2: 10 + readonly property int shipheart_index_theme_couleur_texte_boite_dialogue_niveau_0: 11 + readonly property int shipheart_index_theme_couleur_texte_boite_dialogue_niveau_1: 12 + readonly property int shipheart_index_theme_couleur_texte_boite_dialogue_niveau_2: 13 + readonly property int shipheart_index_theme_couleur_texte_slider: 14 + readonly property int shipheart_index_theme_couleur_bordure_courbes: 15 + + + readonly property variant shipheart_config_themes: [ + //-------------------------------------------- + // Theme = 0: + [ + qsTr("Original"), // shipheart_index_theme_nom + "/images/fibre_carbone.png", // shipheart_index_theme_fichier_fond_ecran + "transparent", // shipheart_index_theme_couleur_fond_ecran + couleur_gris_tres_fonce_transparent, // shipheart_index_theme_couleur_fond_bouton + couleur_bleu_koriolan_transparent, // shipheart_index_theme_couleur_fond_bouton_actif + couleur_gris_fonce, // shipheart_index_theme_couleur_texte_titre_1 + couleur_bleu_koriolan, // shipheart_index_theme_couleur_texte_titre_2 + couleur_gris_pale, // shipheart_index_theme_couleur_texte_titre_3 + couleur_bleu_koriolan, // shipheart_index_theme_couleur_fond_boite_dialogue_niveau_0 + couleur_orange, // shipheart_index_theme_couleur_fond_boite_dialogue_niveau_1 + couleur_rouge, // shipheart_index_theme_couleur_fond_boite_dialogue_niveau_2 + couleur_blanc_casse, // shipheart_index_theme_couleur_texte_boite_dialogue_niveau_0 + couleur_blanc_casse, // shipheart_index_theme_couleur_texte_boite_dialogue_niveau_1 + couleur_blanc_casse, // shipheart_index_theme_couleur_texte_boite_dialogue_niveau_2 + couleur_bleu_koriolan, // shipheart_couleur_texte_slider + couleur_bleu_koriolan // shipheart_index_theme_couleur_bordure_courbes + ], + + //-------------------------------------------- + // Theme = 1: + [ + qsTr("Sombre"), + "", + couleur_noir, + couleur_gris_tres_fonce_transparent, // shipheart_index_theme_couleur_fond_bouton + couleur_bleu_koriolan_transparent, // shipheart_index_theme_couleur_fond_bouton_actif + couleur_gris_fonce, // shipheart_index_theme_couleur_texte_titre_1 + couleur_bleu_koriolan, // shipheart_index_theme_couleur_texte_titre_2 + couleur_gris_pale, // shipheart_index_theme_couleur_texte_titre_3 + couleur_bleu_koriolan, // shipheart_index_theme_couleur_fond_boite_dialogue_niveau_0 + couleur_orange, // shipheart_index_theme_couleur_fond_boite_dialogue_niveau_1 + couleur_rouge, // shipheart_index_theme_couleur_fond_boite_dialogue_niveau_2 + couleur_blanc_casse, // shipheart_index_theme_couleur_texte_boite_dialogue_niveau_0 + couleur_blanc_casse, // shipheart_index_theme_couleur_texte_boite_dialogue_niveau_1 + couleur_blanc_casse, // shipheart_index_theme_couleur_texte_boite_dialogue_niveau_2 + couleur_bleu_koriolan, // shipheart_couleur_texte_slider + couleur_bleu_koriolan // shipheart_index_theme_couleur_bordure_courbes + ], + + //-------------------------------------------- + // Theme = 2: + [ + qsTr("Métallique"), + "/images/fond_2.jpg", + "transparent", + couleur_gris_tres_fonce_transparent, // shipheart_index_theme_couleur_fond_bouton + couleur_bleu_koriolan_transparent, // shipheart_index_theme_couleur_fond_bouton_actif + couleur_gris_fonce, // shipheart_index_theme_couleur_texte_titre_1 + couleur_bleu_koriolan, // shipheart_index_theme_couleur_texte_titre_2 + couleur_gris_pale, // shipheart_index_theme_couleur_texte_titre_3 + couleur_bleu_koriolan, // shipheart_index_theme_couleur_fond_boite_dialogue_niveau_0 + couleur_orange, // shipheart_index_theme_couleur_fond_boite_dialogue_niveau_1 + couleur_rouge, // shipheart_index_theme_couleur_fond_boite_dialogue_niveau_2 + couleur_blanc_casse, // shipheart_index_theme_couleur_texte_boite_dialogue_niveau_0 + couleur_blanc_casse, // shipheart_index_theme_couleur_texte_boite_dialogue_niveau_1 + couleur_blanc_casse, // shipheart_index_theme_couleur_texte_boite_dialogue_niveau_2 + couleur_bleu_koriolan, // shipheart_couleur_texte_slider + couleur_bleu_koriolan // shipheart_index_theme_couleur_bordure_courbes + ], + + //-------------------------------------------- + // Theme = 3: + [ + qsTr("Triangles"), + "/images/fond_3.jpg", + "transparent", + couleur_gris_tres_fonce_transparent, // shipheart_index_theme_couleur_fond_bouton + couleur_bleu_koriolan_transparent, // shipheart_index_theme_couleur_fond_bouton_actif + couleur_gris_fonce, // shipheart_index_theme_couleur_texte_titre_1 + couleur_bleu_koriolan, // shipheart_index_theme_couleur_texte_titre_2 + couleur_gris_pale, // shipheart_index_theme_couleur_texte_titre_3 + couleur_bleu_koriolan, // shipheart_index_theme_couleur_fond_boite_dialogue_niveau_0 + couleur_orange, // shipheart_index_theme_couleur_fond_boite_dialogue_niveau_1 + couleur_rouge, // shipheart_index_theme_couleur_fond_boite_dialogue_niveau_2 + couleur_blanc_casse, // shipheart_index_theme_couleur_texte_boite_dialogue_niveau_0 + couleur_blanc_casse, // shipheart_index_theme_couleur_texte_boite_dialogue_niveau_1 + couleur_blanc_casse, // shipheart_index_theme_couleur_texte_boite_dialogue_niveau_2 + couleur_bleu_koriolan, // shipheart_couleur_texte_slider + couleur_bleu_koriolan // shipheart_index_theme_couleur_bordure_courbes + ], + + //-------------------------------------------- + // Theme = 4: + [ + qsTr("Sable"), + "", + couleur_noir, + couleur_gris_tres_fonce_transparent, // shipheart_index_theme_couleur_fond_bouton + couleur_sable_transparent, // shipheart_index_theme_couleur_fond_bouton_actif + couleur_sable_transparent, // shipheart_index_theme_couleur_texte_titre_1 + couleur_sable, // shipheart_index_theme_couleur_texte_titre_2 + couleur_sable_transparent, // shipheart_index_theme_couleur_texte_titre_3 + couleur_sable, // shipheart_index_theme_couleur_fond_boite_dialogue_niveau_0 + couleur_orange, // shipheart_index_theme_couleur_fond_boite_dialogue_niveau_1 + couleur_rouge, // shipheart_index_theme_couleur_fond_boite_dialogue_niveau_2 + couleur_blanc_casse, // shipheart_index_theme_couleur_texte_boite_dialogue_niveau_0 + couleur_blanc_casse, // shipheart_index_theme_couleur_texte_boite_dialogue_niveau_1 + couleur_blanc_casse, // shipheart_index_theme_couleur_texte_boite_dialogue_niveau_2 + couleur_sable, // shipheart_couleur_texte_slider + couleur_sable // shipheart_index_theme_couleur_bordure_courbes + ], + + //-------------------------------------------- + // Theme = 5: + [ + qsTr("Thème 5"), + "", + couleur_bleu_koriolan_transparent, + couleur_gris_tres_fonce_transparent, // shipheart_index_theme_couleur_fond_bouton + couleur_bleu_koriolan_transparent, // shipheart_index_theme_couleur_fond_bouton_actif + couleur_gris_fonce, // shipheart_index_theme_couleur_texte_titre_1 + couleur_bleu_koriolan, // shipheart_index_theme_couleur_texte_titre_2 + couleur_gris_pale, // shipheart_index_theme_couleur_texte_titre_3 + couleur_bleu_koriolan, // shipheart_index_theme_couleur_fond_boite_dialogue_niveau_0 + couleur_orange, // shipheart_index_theme_couleur_fond_boite_dialogue_niveau_1 + couleur_rouge, // shipheart_index_theme_couleur_fond_boite_dialogue_niveau_2 + couleur_blanc_casse, // shipheart_index_theme_couleur_texte_boite_dialogue_niveau_0 + couleur_blanc_casse, // shipheart_index_theme_couleur_texte_boite_dialogue_niveau_1 + couleur_blanc_casse, // shipheart_index_theme_couleur_texte_boite_dialogue_niveau_2 + couleur_bleu_koriolan, // shipheart_couleur_texte_slider + couleur_bleu_koriolan // shipheart_index_theme_couleur_bordure_courbes + ], + + //-------------------------------------------- + // Theme = 6: + [ + qsTr("Thème 6"), + "", + couleur_gris_pale, + couleur_gris_tres_fonce_transparent, // shipheart_index_theme_couleur_fond_bouton + couleur_sable_transparent, // shipheart_index_theme_couleur_fond_bouton_actif + couleur_gris_fonce, // shipheart_index_theme_couleur_texte_titre_1 + couleur_bleu_koriolan, // shipheart_index_theme_couleur_texte_titre_2 + couleur_gris_pale, // shipheart_index_theme_couleur_texte_titre_3 + couleur_bleu_koriolan, // shipheart_index_theme_couleur_fond_boite_dialogue_niveau_0 + couleur_orange, // shipheart_index_theme_couleur_fond_boite_dialogue_niveau_1 + couleur_rouge, // shipheart_index_theme_couleur_fond_boite_dialogue_niveau_2 + couleur_blanc_casse, // shipheart_index_theme_couleur_texte_boite_dialogue_niveau_0 + couleur_blanc_casse, // shipheart_index_theme_couleur_texte_boite_dialogue_niveau_1 + couleur_blanc_casse, // shipheart_index_theme_couleur_texte_boite_dialogue_niveau_2 + couleur_bleu_koriolan, // shipheart_couleur_texte_slider + couleur_bleu_koriolan // shipheart_index_theme_couleur_bordure_courbes + ], + + //-------------------------------------------- + // Theme = 7: + [ + qsTr("Thème 7"), + "", + "#2F076A", + couleur_gris_tres_fonce_transparent, // shipheart_index_theme_couleur_fond_bouton + couleur_bleu_koriolan_transparent, // shipheart_index_theme_couleur_fond_bouton_actif + couleur_gris_fonce, // shipheart_index_theme_couleur_texte_titre_1 + couleur_bleu_koriolan, // shipheart_index_theme_couleur_texte_titre_2 + couleur_gris_pale, // shipheart_index_theme_couleur_texte_titre_3 + couleur_bleu_koriolan, // shipheart_index_theme_couleur_fond_boite_dialogue_niveau_0 + couleur_orange, // shipheart_index_theme_couleur_fond_boite_dialogue_niveau_1 + couleur_rouge, // shipheart_index_theme_couleur_fond_boite_dialogue_niveau_2 + couleur_blanc_casse, // shipheart_index_theme_couleur_texte_boite_dialogue_niveau_0 + couleur_blanc_casse, // shipheart_index_theme_couleur_texte_boite_dialogue_niveau_1 + couleur_blanc_casse, // shipheart_index_theme_couleur_texte_boite_dialogue_niveau_2 + couleur_bleu_koriolan, // shipheart_couleur_texte_slider + couleur_bleu_koriolan // shipheart_index_theme_couleur_bordure_courbes + ], + + //-------------------------------------------- + // Theme = 8: + [ + qsTr("Thème 8"), + "", + "#5B1297", + couleur_gris_tres_fonce_transparent, // shipheart_index_theme_couleur_fond_bouton + couleur_bleu_koriolan_transparent, // shipheart_index_theme_couleur_fond_bouton_actif + couleur_gris_fonce, // shipheart_index_theme_couleur_texte_titre_1 + couleur_bleu_koriolan, // shipheart_index_theme_couleur_texte_titre_2 + couleur_gris_pale, // shipheart_index_theme_couleur_texte_titre_3 + couleur_bleu_koriolan, // shipheart_index_theme_couleur_fond_boite_dialogue_niveau_0 + couleur_orange, // shipheart_index_theme_couleur_fond_boite_dialogue_niveau_1 + couleur_rouge, // shipheart_index_theme_couleur_fond_boite_dialogue_niveau_2 + couleur_blanc_casse, // shipheart_index_theme_couleur_texte_boite_dialogue_niveau_0 + couleur_blanc_casse, // shipheart_index_theme_couleur_texte_boite_dialogue_niveau_1 + couleur_blanc_casse, // shipheart_index_theme_couleur_texte_boite_dialogue_niveau_2 + couleur_bleu_koriolan, // shipheart_couleur_texte_slider + couleur_bleu_koriolan // shipheart_index_theme_couleur_bordure_courbes + ] + ]; + + + //----------------------------------------------------------------------------------- + // Type d'installation : + readonly property int shipheart_type_installation_shipbase : 0 + readonly property int shipheart_type_installation_ecran_deporte : 1 + + readonly property int shipheart_type_installation_ecran_deporte_7_pouces : 17 + readonly property int shipheart_type_installation_ecran_deporte_10_pouces : 110 + readonly property int shipheart_type_installation_ecran_deporte_22_pouces : 122 + + //----------------------------------------------------------------------------------- + // Spécificités clients : + readonly property int shipheart_specifique_client_tous : 0 + readonly property int shipheart_specifique_client_suncy : 1 + readonly property int shipheart_specifique_client_o_yachts : 2 + + //----------------------------------------------------------------------------------- + // Types de source : + readonly property int shipheart_type_source_inconnu : 0 + readonly property int shipheart_type_source_circuits : 1 + readonly property int shipheart_type_source_capteurs: 2 + readonly property int shipheart_type_source_reservoirs: 3 + readonly property int shipheart_type_source_batteries: 4 + readonly property int shipheart_type_source_modules: 5 + readonly property int shipheart_type_source_events: 6 + + //----------------------------------------------------------------------------------- + // Types de page : + readonly property int shipheart_type_page_inconnu : 0 + readonly property int shipheart_type_page_preconfiguree_ephemeride : 1 + readonly property int shipheart_type_page_preconfiguree_chronometre : 2 + readonly property int shipheart_type_page_personnalisee_minuteur : 3 + readonly property int shipheart_type_page_preconfiguree_reveil : 4 + readonly property int shipheart_type_page_personnalisee_non_masquable : 10 + readonly property int shipheart_type_page_personnalisee_masquable : 11 + + //----------------------------------------------------------------------------------- + // Paramètres d'une page personnalisée : + readonly property int shipheart_page_personnalisee_nb_max_points : 30 + + readonly property variant shipheart_page_personnalisee_type_point_icones : [ + //-------------------------------------------- + // Type_source = 0 = Système + [], + + //-------------------------------------------- + // Type_source = 1 = Circuits: + [ + "point_transparent.png", // Attention : rang #0 = icone utilisée pour circuit OFF... + "point_blanc.png", + "point_rouge.png", + "point_vert.png", + "point_bleu.png", + "point_jaune.png", + "point_orange.png", + "point_arc_en_ciel.png" + ], + + //-------------------------------------------- + // Type_source = 2 = Capteurs: + [ + "icone_barometre.png", + "icone_humidite.png", + "icone_consommation_electrique.png", + "icone_temperature.png", + "vanne.png", + "vanne_ouverte.png", + "vanne_fermee.png", + "satellite.png" + ], + + //-------------------------------------------- + // Type_source = 3 = Reservoirs: + [ + "reservoir.png", + "reservoir_eau.png" + ], + + //-------------------------------------------- + // Type_source = 4 = Batteries: + [ + "batterie_moyen.png" + ], + + //-------------------------------------------- + // Type_source = 5 = Modules: + [ + "shipbase.png", // Attention : dans l'ordre du 'Types de modules' ci-dessous ! + "sp8dc.png", // Par approximation, on met une image de 8DC... + "shipbs.png", + "sp4ac.png", + "sp8dc.png" + ], + ] + + //----------------------------------------------------------------------------------- + // Langues : + readonly property int shipheart_langue_fr: 0 + readonly property int shipheart_langue_en: 1 + readonly property int shipheart_langue_de: 2 + readonly property int shipheart_langue_es: 3 + readonly property int shipheart_langue_pt: 4 + readonly property int shipheart_langue_nl: 5 + readonly property int shipheart_langue_it: 6 + readonly property int shipheart_langue_lv: 7 + readonly property int shipheart_langue_ca: 8 + + //----------------------------------------------------------------------------------- + // Types unité : // Cf aussi 'fonctions.js' et 'shipheart.h' en cas de modifications/ajouts + readonly property int shipheart_type_unite_volume: 1 + readonly property int shipheart_type_unite_temperature: 2 + readonly property int shipheart_type_unite_latitude: 3 + readonly property int shipheart_type_unite_longitude: 4 + + // Unités volume : // Cf aussi 'fonctions.js' et 'shipheart.h' en cas de modifications/ajouts + readonly property int shipheart_unite_volume_litres: 0 + readonly property int shipheart_unite_volume_us_gallons: 1 + readonly property int shipheart_unite_volume_imp_gallons: 2 + + // Unités température : // Cf aussi 'fonctions.js' et 'shipheart.h' en cas de modifications/ajouts + readonly property int shipheart_unite_temperature_celsius: 0 + readonly property int shipheart_unite_temperature_fahrehneit: 1 + + //----------------------------------------------------------------------------------- + // Localisation des fichiers : + + readonly property string shipheart_repertoire_versions_a_charger: "/home/koriolan/shipheart/versions/a_charger" + readonly property string shipheart_repertoire_versions_a_valider: "/home/koriolan/shipheart/versions/a_valider" + readonly property string shipheart_repertoire_versions_current: "/home/koriolan/shipheart/versions/current" + readonly property string shipheart_repertoire_config: "/home/koriolan/shipheart/config" + readonly property string shipheart_repertoire_cle_usb: "/home/koriolan/cle_usb" + readonly property string shipheart_repertoire_tmp_usb: "/home/koriolan/shipheart/tmp/usb" + readonly property string shipheart_repertoire_sys_usb: "/sys/kernel/debug/usb" + readonly property string shipheart_repertoire_utils: "/home/koriolan/shipheart/utils" + + readonly property string shipheart_sous_repertoire_rapports: "/rapports" + readonly property string shipheart_sous_repertoire_images_accueil: "/images_accueil" + readonly property string shipheart_sous_repertoire_sauvegardes: "/sauvegardes" + readonly property string shipheart_sous_repertoire_images_silhouette: "/images_silhouette" + + readonly property string shipheart_nom_complet_fichier_shiprs_conf: "/home/koriolan/shipheart/versions/shiprs.conf" + + readonly property string shipheart_nom_fichier_image_accueil_par_defaut: "logo_shipheart.png" + readonly property string shipheart_nom_fichier_rapport_installation: "rapport_installation.php" + readonly property string shipheart_nom_fichier_sauvegarde: "sauvegarde.php" + readonly property string shipheart_nom_fichier_usb_devices: "devices" + readonly property string shipheart_nom_fichier_usb_lsblk: "resultat_lsblk" + readonly property string shipheart_nom_fichier_usb_ls: "resultat_ls" + + //----------------------------------------------------------------------------------- + // Modes de fonctionnement du menu 'config_fichiers' : + readonly property int shipheart_mode_config_fichiers_inconnu: 0 + readonly property int shipheart_mode_config_fichiers_image_accueil: 1 + readonly property int shipheart_mode_config_fichiers_silhouette: 2 + readonly property int shipheart_mode_config_fichiers_rapports: 3 + readonly property int shipheart_mode_config_fichiers_sauvegardes: 4 + + readonly property int shipheart_taille_maxi_image_accueil: (5 * 1000 * 1000) // En octets + readonly property int shipheart_taille_maxi_silhouette: (2 * 1000 * 1000) // En octets + readonly property int shipheart_taille_maxi_rapport: (50 * 1000 * 1000) // En octets + readonly property int shipheart_taille_maxi_sauvegarde: (50 * 1000 * 1000) // En octets + + + //----------------------------------------------------------------------------------- + // Gestion des fichiers de mise à jour : + readonly property int shipheart_demande_maj_soft_aucune: 0 // Valeur de repos + readonly property int shipheart_demande_maj_soft_validation: 1 // Validation du fichier dans A_VALIDER qui sera copié dans A_CHARGER + readonly property int shipheart_demande_maj_soft_chargement: 2 // Idem VALIDATION + demande de reset pour prise en compte immédiate + readonly property int shipheart_demande_maj_soft_annulation: -1 // Suppression du fichier présent dans A_VALIDER ou dans A_CHARGER (les 2 sont vidés) + + + //----------------------------------------------------------------------------------- + // Modules : + readonly property int shipheart_max_nombre_modules: (32+1) + + // Types de modules : // Cf aussi 'fonctions.js' en cas de modifications/ajouts + readonly property int shipheart_type_module_inconnu: -1 + readonly property int shipheart_type_module_shipbase: 0 + readonly property int shipheart_type_module_shippower812: 1 + readonly property int shipheart_type_module_shipBS: 2 + readonly property int shipheart_type_module_shippower4AC: 3 + readonly property int shipheart_type_module_shippower8DC: 4 + + // Etat commande d'une carte : + readonly property int shipheart_etat_commande_module_ok: 0 + readonly property int shipheart_etat_commande_module_undervoltage: 1 + readonly property int shipheart_etat_commande_module_test: 2 + + // Code commande d'une carte : + readonly property int shipheart_commande_module_localisation: 1 + readonly property int shipheart_commande_module_etat_systeme: 2 + + readonly property int shipheart_commande_module_etat_systeme_normal: 0 + readonly property int shipheart_commande_module_etat_systeme_alerte: 1 + readonly property int shipheart_commande_module_etat_systeme_alarme: 2 + + + //----------------------------------------------------------------------------------- + // Historique types : + readonly property int shipheart_historique_type_tous: -1 + readonly property int shipheart_historique_type_systeme: 0 + readonly property int shipheart_historique_type_circuits: 1 + readonly property int shipheart_historique_type_capteurs: 2 + readonly property int shipheart_historique_type_reservoirs: 3 + readonly property int shipheart_historique_type_batteries: 4 + readonly property int shipheart_historique_type_usb: 5 + readonly property int shipheart_historique_type_event: 6 + + //----------------------------------------------------------------------------------- + // Messages users : + readonly property int shipheart_message_users_code_aucun: 0 + readonly property int shipheart_message_users_code_fin_minuteur: 1 + readonly property int shipheart_message_users_code_reveil: 2 + readonly property int shipheart_message_users_code_maj_en_cours: 3 + readonly property int shipheart_message_users_code_redemarrage: 4 + readonly property int shipheart_message_users_code_nouvelle_version_detectee: 5 + readonly property int shipheart_message_users_code_defaut_config_k_bus: 6 + readonly property int shipheart_message_users_code_declenchement_event: 7 + + + //----------------------------------------------------------------------------------- + // Protection d'accès : + readonly property string code_koriolan: "87cf9a09f9889c4c9d2d9e30cfb6dfe6f238ef7f2db16cd5ea3ebfcd2c90b9b9" + + readonly property int shipheart_type_code_normal: 0 + readonly property int shipheart_type_code_admin: 1 + + readonly property int shipheart_niveau_acces_aucun: 0 + readonly property int shipheart_niveau_acces_user: 1 + readonly property int shipheart_niveau_acces_admin: 10 + readonly property int shipheart_niveau_acces_koriolan: 20 + + //----------------------------------------------------------------------------------- + // Types de synchro de BDD : + readonly property int shipheart_type_synchro_aucune : 0 + readonly property int shipheart_type_synchro_data : 1 + readonly property int shipheart_type_synchro_config : 2 + + //----------------------------------------------------------------------------------- + // Timings système : + readonly property int shipheart_periode_timer_home: 1000 + + //----------------------------------------------------------------------------------- + // Ports USB : + readonly property int shipheart_port_usb_aucun: -1 + readonly property int shipheart_port_usb_arriere: 0 // Connecteur USB-A à l'arrière + readonly property int shipheart_port_usb_spare: 1 // Sortie sur 4 broches à souder au pas de 2.54mm + readonly property int shipheart_port_usb_avant_bas: 2 // Connecteur USB-A à l'avant, en partie basse de la colonne des 3 ports en face avant + readonly property int shipheart_port_usb_touchpad: 3 // Connecteur pour cable plat sur carte Shipbase, vers l'écran Densitron. + + //----------------------------------------------------------------------------------- + // Entrées Auxiliaires : + readonly property int shipheart_entrees_aux_max_nombre: 32 + + //----------------------------------------------------------------------------------- + // Entrées Level Sensor : + readonly property int shipheart_entrees_level_sensor_max_nombre: 8 + + //----------------------------------------------------------------------------------- + // Entrées Volt : + readonly property int shipheart_entrees_volt_max_nombre: 4 + + //----------------------------------------------------------------------------------- + // Events : + readonly property int shipheart_max_nombre_events: 200 // Cf 'event.h' dans l'appli + readonly property int shipheart_max_nombre_conditions_horaires_par_event: 15 // Cf 'event.h' dans l'appli + readonly property int shipheart_max_nombre_action_circuits_par_event: 50 // Cf 'event.h' dans l'appli + + // Heures spéciales : + readonly property int shipheart_heure_speciale_fin_nuit: 24 // -18° de l'horizon + readonly property int shipheart_heure_speciale_aube_nautique: 25 // -12° de l'horizon + readonly property int shipheart_heure_speciale_aube: 26 // -6° de l'horizon + readonly property int shipheart_heure_speciale_lever_soleil: 27 // -0.833° de l'horizon + readonly property int shipheart_heure_speciale_zenith: 28 + readonly property int shipheart_heure_speciale_coucher_soleil: 29 // -0.833° de l'horizon + readonly property int shipheart_heure_speciale_crepuscule: 30 // -6° de l'horizon + readonly property int shipheart_heure_speciale_crepuscule_nautique: 31 // -12° de l'horizon + readonly property int shipheart_heure_speciale_debut_nuit: 32 // -18° de l'horizon + + //----------------------------------------------------------------------------------- + // Mesures : + // Type mesure : // Cf aussi 'fonctions.js' et 'shipheart.h' en cas de modifications/ajouts + readonly property int shipheart_source_mesure_circuit: 1 + readonly property int shipheart_source_mesure_capteur: 2 + readonly property int shipheart_source_mesure_reservoir: 3 + readonly property int shipheart_source_mesure_batterie: 4 + + // Modes enregistrement mesures : + readonly property int shipheart_mode_enregistrement_mesures_aucun: 0 + readonly property int shipheart_mode_enregistrement_mesures_periodique: 1 + readonly property int shipheart_mode_enregistrement_mesures_changement_etat: 2 + + //----------------------------------------------------------------------------------- + // Divers : + readonly property string shipheart_adresse_ip_inconnue: "inconnue" // Valeur identique à ADRESSE_IP_INCONNUE dans l'appli, dans 'systeme.h' + + + + //----------------------------------------------------------------------------------- + // Couleurs prédéfinies : + readonly property color couleur_bleu_koriolan: Qt.rgba((0/255), (118/255), (154/255), 1.0) + readonly property color couleur_bleu_koriolan_transparent: Qt.rgba((0/255), (118/255), (154/255), 0.4) + readonly property color couleur_bleu_koriolan_tres_transparent: Qt.rgba((0/255), (118/255), (154/255), 0.2) + readonly property color couleur_bleu_koriolan_tres_tres_transparent: Qt.rgba((0/255), (118/255), (154/255), 0.1) + readonly property color couleur_bleu_koriolan_clair: Qt.rgba((113/255), (187/255), (216/255), 1.0) + readonly property color couleur_bleu_koriolan_clair_transparent: Qt.rgba((113/255), (187/255), (216/255), 0.4) + readonly property color couleur_bleu_koriolan_clair_tres_transparent: Qt.rgba((113/255), (187/255), (216/255), 0.2) + readonly property color couleur_noir: Qt.rgba((0/255), (0/255), (0/255), 1.0) + readonly property color couleur_gris_tres_tres_fonce: Qt.rgba((10/255), (10/255), (10/255), 1.0) + readonly property color couleur_gris_tres_tres_fonce_transparent: Qt.rgba((10/255), (10/255), (10/255), 0.9) + readonly property color couleur_gris_tres_tres_fonce_tres_transparent: Qt.rgba((10/255), (10/255), (10/255), 0.2) + readonly property color couleur_gris_tres_fonce: Qt.rgba((60/255), (60/255), (60/255), 1.0) + readonly property color couleur_gris_tres_fonce_transparent: Qt.rgba((60/255), (60/255), (60/255), 0.5) + readonly property color couleur_gris_tres_fonce_tres_transparent: Qt.rgba((60/255), (60/255), (60/255), 0.2) + readonly property color couleur_gris_fonce: Qt.rgba((80/255), (80/255), (80/255), 1.0) + readonly property color couleur_gris_moyen: Qt.rgba((110/255), (110/255), (110/255), 1.0) + readonly property color couleur_gris_pale: Qt.rgba((130/255), (130/255), (130/255), 1.0) + readonly property color couleur_gris_tres_pale: Qt.rgba((150/255), (150/255), (150/255), 1.0) + readonly property color couleur_gris_tres_pale_transparent: Qt.rgba((150/255), (150/255), (150/255), 0.2) + readonly property color couleur_gris_tres_tres_pale: Qt.rgba((200/255), (200/255), (200/255), 1.0) + readonly property color couleur_blanc_casse: Qt.rgba((230/255), (230/255), (230/255), 1.0) + readonly property color couleur_blanc_casse_transparent: Qt.rgba((230/255), (230/255), (230/255), 0.5) + readonly property color couleur_blanc: Qt.rgba(1, 1, 1, 1.0) + readonly property color couleur_vert: Qt.rgba((177/255), (251/255), (23/255), 1.0) + readonly property color couleur_vert_transparent: Qt.rgba((177/255), (251/255), (23/255), 0.4) + readonly property color couleur_jaune: Qt.rgba((253/255), (240/255), (100/255), 1.0) + readonly property color couleur_jaune_transparent: Qt.rgba((253/255), (240/255), (100/255), 0.4) + readonly property color couleur_jaune_post_it: Qt.rgba((255/255), (195/255), (63/255), 1.0) + readonly property color couleur_jaune_post_it_transparent: Qt.rgba((255/255), (195/255), (63/255), 0.4) + readonly property color couleur_orange: Qt.rgba((255/255),(140/255), (0/255), 1.0) + readonly property color couleur_orange_transparent: Qt.rgba((255/255),(140/255), (0/255), 0.4) + readonly property color couleur_rouge: Qt.rgba((255/255), (30/255), (0/255), 1.0) + readonly property color couleur_rouge_transparent: Qt.rgba((255/255), (30/255), (0/255), 0.4) + readonly property color couleur_green_yellow: Qt.rgba((173/255), (255/255), (47/255), 1.0) + readonly property color couleur_green_yellow_transparent: Qt.rgba((173/255), (255/255), (47/255), 0.4) + readonly property color couleur_sable: Qt.rgba((205/255), (154/255), (124/255), 1.0) + readonly property color couleur_sable_transparent: Qt.rgba((205/255), (154/255), (124/255), 0.4) + readonly property color couleur_sable_tres_transparent: Qt.rgba((205/255), (154/255), (124/255), 0.2) + + + + // Boutons : + readonly property int shipheart_rayon_bouton: 6 + readonly property int shipheart_grand_rayon_bouton: 12 + readonly property int shipheart_rayon_zoom: 20 + + readonly property int shipheart_mouse_press_and_hold_interval_tres_court: 5 // Utilisé comme léger filtrage + readonly property int shipheart_mouse_press_and_hold_interval_court: 250 // Utilisé comme léger filtrage + readonly property int shipheart_mouse_press_and_hold_interval_long: 1000 // Utilisé pour les commandes 'sensibles', comme la comm + readonly property int shipheart_mouse_press_and_hold_interval_tres_long: 2000 // Utilisé pour valider par appui maintenu sur un "bouton défilant" + + // Mise en page : + readonly property double bandeau_bas_spacing: 0.004 // pourcentage de la largeur de page utilisé pour séparer les boutons dans le bandeau bas. + + // Formulaires : + readonly property int shipheart_formulaire_ligne_separation_haute: 1 + readonly property int shipheart_formulaire_ligne_separation_basse: 2 + readonly property int shipheart_formulaire_ligne_separation_haute_basse: 3 + + readonly property int shipheart_formulaire_ligne_separation_force_faible: 1 + readonly property int shipheart_formulaire_ligne_separation_force_moyenne: 2 + readonly property int shipheart_formulaire_ligne_separation_force_elevee: 3 + + readonly property string shipheart_font_saisie_textarea: "Noto Mono" // "Sans Serif" [Default], "URW Gothic L", "Nimbus Mono L" + readonly property string shipheart_font_saisie_textfield: "Noto Mono" + + readonly property color shipheart_formulaire_couleur_texte_par_defaut: couleur_blanc_casse + readonly property color shipheart_formulaire_couleur_texte_en_erreur: couleur_rouge + + // Boutons validation boite de dialogue : + readonly property int shipheart_boite_dialogue_bouton_1: 1 // Souvent Ok + readonly property int shipheart_boite_dialogue_bouton_2: 2 // Souvent Annuler + readonly property int shipheart_boite_dialogue_bouton_3: 3 // Souvent Plus Tard ou Supprimer + readonly property int shipheart_boite_dialogue_bouton_4: 4 // Souvent Bouton Sécurisé + + // Protection : + readonly property int protection_mode_access_parametres_avances: 1 + readonly property int protection_mode_verrouillage: 2 + readonly property int protection_mode_deverrouillage: 3 + + // Courbes : + readonly property color courbes_couleur_fond: couleur_bleu_koriolan_tres_transparent // Couleur intérieure des AreaSeries + readonly property color courbes_couleur_shades_fond: couleur_gris_tres_tres_fonce_tres_transparent // Couleur des bandes verticales du fond (celles qui ne sont pas purement transparentes). + readonly property int courbes_epaisseur_bordure: 4 // Epaisseur de la courbe elle-même + readonly property int courbe_etalonnage_max_points: 12 // Max nb de points d'étalonnage (utilisé dans'config_valeur_niveau.qml' pour les batteries et les réservoirs) + + // Caractères spéciaux : + readonly property int unicode_fleche_droite: 0x2192 // Utilisation du type 'String.fromCharCode(unicode_fleche_droite)' + readonly property int unicode_fleche_demi_epaisse_continue_droite: 0x279E + readonly property int unicode_fleche_demi_epaisse_discontinue_droite: 0x279F + readonly property int unicode_fleche_epaisse_discontinue_droite: 0x27A0 + readonly property int unicode_fleche_epaisse_continue_droite: 0x27A1 + readonly property int unicode_omega: 0x2126 // Symbole des Ohms + + //----------------------------------------------------------------------------------- + // Batteries : + // Type d'entrées batteries : + readonly property int shipheart_batteries_type_entrees_volt: 3 + readonly property int shipheart_batteries_type_entrees_predefinie: 5 + readonly property int shipheart_batteries_type_entrees_ibs: 6 + + // Types de variables : + readonly property string shipheart_batterie_temperature: "Batt_temperature" + readonly property string shipheart_batterie_tension: "Batt_tension" + readonly property string shipheart_batterie_courant_differentiel: "Batt_courant_differentiel" + readonly property string shipheart_batterie_courant_charge: "Batt_courant_charge" + readonly property string shipheart_batterie_courant_decharge: "Batt_courant_decharge" + readonly property string shipheart_batterie_soh: "Batt_soh" + readonly property string shipheart_batterie_soc: "Batt_soc" + readonly property string shipheart_batterie_autonomie: "Batt_autonomie" + readonly property string shipheart_batterie_puissance: "Batt_puissance" + readonly property string shipheart_batterie_energie: "Batt_energie" + + // Commande de batterie : + readonly property int shipheart_batteries_commande_reserve: 0 + readonly property int shipheart_batteries_commande_forcage_pleine_charge: 1 + readonly property int shipheart_batteries_commande_reset_soh: 2 + readonly property int shipheart_batteries_commande_reset_compteurs: 3 + + // Type de batterie : + readonly property int shipheart_batteries_type_indefini: 0 + readonly property int shipheart_batteries_type_plomb_acide_liquide: 1 + readonly property int shipheart_batteries_type_plomb_agm_vrla: 2 + readonly property int shipheart_batteries_type_plomb_gel: 3 + readonly property int shipheart_batteries_type_plomb_carbone: 4 + readonly property int shipheart_batteries_type_lihium: 10 + + + //----------------------------------------------------------------------------------- + // Capteurs : + readonly property int shipheart_capteur_max_nombre_entrees_aux: 4 // Vérifier cohérence avec MAX_NOMBRE_ENTREES_PAR_CAPTEUR dans 'capteurs.h' de l'Appli. + + // Type d'entrées capteurs : + readonly property int shipheart_capteur_type_entrees_aux: 1 + readonly property int shipheart_capteur_type_entrees_level_sensor: 2 + readonly property int shipheart_capteur_type_entrees_volt: 3 + readonly property int shipheart_capteur_type_entrees_ow: 4 + readonly property int shipheart_capteur_type_entrees_predefinie: 5 + readonly property int shipheart_capteur_type_entrees_ibs: 6 + readonly property int shipheart_capteur_type_entrees_nmea: 7 + readonly property int shipheart_capteur_type_entrees_can: 8 + readonly property int shipheart_capteur_type_entrees_calculee_booleen: 20 + readonly property int shipheart_capteur_type_entrees_calculee_numerique: 21 + + // Modes des capteurs : + readonly property int shipheart_capteur_mode_entrees_aux_normal: 0 + readonly property int shipheart_capteur_mode_entrees_aux_inverse: 1 + + readonly property int shipheart_capteur_mode_entrees_level_sensor_non_defini: 0 + readonly property int shipheart_capteur_mode_entrees_level_sensor_0_10v: 1 + readonly property int shipheart_capteur_mode_entrees_level_sensor_500r: 2 + readonly property int shipheart_capteur_mode_entrees_level_sensor_4_20ma: 3 + readonly property int shipheart_capteur_mode_entrees_level_sensor_defaut_isolement_masse: 5 + readonly property int shipheart_capteur_mode_entrees_level_sensor_defaut_isolement_v_plus: 6 + readonly property int shipheart_capteur_mode_entrees_level_sensor_defaut_isolement_complet: 7 + + // Etat capteurs : + readonly property int shipheart_capteur_etat_normal: 0 + readonly property int shipheart_capteur_etat_alerte: 1 + readonly property int shipheart_capteur_etat_alarme: 2 + + // Capteurs prédéfinis : + readonly property int shipheart_capteur_predefini_aucun: 0 + readonly property int shipheart_capteur_predefini_pat: 1 + readonly property int shipheart_capteur_predefini_hum: 2 + readonly property int shipheart_capteur_predefini_temp: 3 + readonly property int shipheart_capteur_predefini_lat: 4 + readonly property int shipheart_capteur_predefini_lon: 5 + readonly property int shipheart_capteur_predefini_in_v: 6 + readonly property int shipheart_capteur_predefini_in_i: 7 + readonly property int shipheart_capteur_predefini_usb_i: 8 + readonly property int shipheart_capteur_predefini_edm: 9 + readonly property int shipheart_capteur_predefini_acc_xyz: 10 + readonly property int shipheart_capteur_predefini_acc_x: 11 + readonly property int shipheart_capteur_predefini_acc_y: 12 + readonly property int shipheart_capteur_predefini_acc_z: 13 + readonly property int shipheart_capteur_predefini_alt: 14 + readonly property int shipheart_capteur_predefini_sog: 15 + readonly property int shipheart_capteur_predefini_cog: 16 + readonly property int shipheart_capteur_predefini_siv: 17 + readonly property int shipheart_capteur_predefini_hpa: 18 + readonly property int shipheart_capteur_predefini_vpa: 19 + readonly property int shipheart_capteur_predefini_rsrp: 20 + readonly property int shipheart_capteur_predefini_rssi: 21 + readonly property int shipheart_capteur_predefini_sinr: 22 + + // Types de variables : + readonly property string shipheart_capteur_sans_unite: "Capt_sans_unite" + readonly property string shipheart_capteur_tension_v: "Capt_tension_v" + readonly property string shipheart_capteur_tension_mv: "Capt_tension_mv" + readonly property string shipheart_capteur_courant_a: "Capt_courant_a" + readonly property string shipheart_capteur_courant_ma: "Capt_courant_ma" + readonly property string shipheart_capteur_puissance_w: "Capt_puissance_w" + readonly property string shipheart_capteur_puissance_va: "Capt_puissance_va" + readonly property string shipheart_capteur_puissance_db: "Capt_puissance_db" + readonly property string shipheart_capteur_frequence: "Capt_frequence" + readonly property string shipheart_capteur_resistance: "Capt_resistance" + readonly property string shipheart_capteur_temperature: "Capt_temperature" + readonly property string shipheart_capteur_pression_atm: "Capt_pression_atm" + readonly property string shipheart_capteur_humidite: "Capt_humidite" + readonly property string shipheart_capteur_acceleration: "Capt_acceleration" + readonly property string shipheart_capteur_position: "Capt_position" + readonly property string shipheart_capteur_pourcentage: "Capt_pourcentage" + readonly property string shipheart_capteur_distance_m: "Capt_distance_m" + readonly property string shipheart_capteur_distance_km: "Capt_distance_km" + readonly property string shipheart_capteur_distance_nq: "Capt_distance_nq" + readonly property string shipheart_capteur_vitesse_kts: "Capt_vitesse_kts" + readonly property string shipheart_capteur_vitesse_kmh: "Capt_vitesse_kmh" + readonly property string shipheart_capteur_angle_degres: "Capt_angle_degres" + readonly property string shipheart_capteur_latitude: "Capt_latitude" + readonly property string shipheart_capteur_longitude: "Capt_longitude" + readonly property string shipheart_capteur_volume: "Capt_volume" + + // Capteurs calculés : + readonly property int shipheart_max_nombre_conditions_par_capteur: 50 // Cf 'capteurs.h' dans l'appli + + // Opération de condition : + readonly property int shipheart_operation_condition_non_definie: 0 + readonly property int shipheart_operation_condition_ou: 1 + readonly property int shipheart_operation_condition_et: 2 + readonly property int shipheart_operation_condition_ou_exclusif: 3 + readonly property int shipheart_operation_condition_plus: 10 + readonly property int shipheart_operation_condition_moins: 11 + readonly property int shipheart_operation_condition_multiplie: 12 + readonly property int shipheart_operation_condition_divise: 13 + + // Type de condition : + readonly property int shipheart_type_condition_normale: 0 + readonly property int shipheart_type_condition_debut_groupe_ou: shipheart_operation_condition_ou + readonly property int shipheart_type_condition_debut_groupe_et: shipheart_operation_condition_et + readonly property int shipheart_type_condition_debut_groupe_ou_exclusif: shipheart_operation_condition_ou_exclusif + readonly property int shipheart_type_condition_debut_groupe_plus: shipheart_operation_condition_plus + readonly property int shipheart_type_condition_debut_groupe_moins: shipheart_operation_condition_moins + readonly property int shipheart_type_condition_debut_groupe_multiplie: shipheart_operation_condition_multiplie + readonly property int shipheart_type_condition_debut_groupe_divise: shipheart_operation_condition_divise + // NB : il existe les même valeurs en négatif pour fermer le groupe correspondant. + + // Tests : + readonly property int shipheart_test_non_defini: 0 + readonly property int shipheart_test_strictement_inferieur: 1 + readonly property int shipheart_test_inferieur_ou_egal: 2 + readonly property int shipheart_test_egal: 3 + readonly property int shipheart_test_superieur_ou_egal: 4 + readonly property int shipheart_test_strictement_superieur: 5 + + + //----------------------------------------------------------------------------------- + // Circuits : + + // Max : + readonly property int shipheart_max_circuits_par_module_shipbase: 3 + readonly property int shipheart_max_circuits_par_module_sp812: 8 + readonly property int shipheart_max_circuits_par_module_sp8dc: 8 + readonly property int shipheart_max_circuits_par_module_sp8xx: 8 // Valeur commune aux SP812 et aux SP8DC + readonly property int shipheart_max_circuits_par_module_sp4ac: 4 + + readonly property double shipheart_max_courant_masses_sp8dc: 25.0 // En A (le max 'technique' est 25.5 car transféré en uint_8 vers les SP8DC + + readonly property double shipheart_plancher_intensite_circuit_shipbase: 0.05 // En dessous de cette valeur, l'intensité ne sera pas affichée + readonly property double shipheart_plancher_intensite_circuit_sp8xx: 0.05 // En dessous de cette valeur, l'intensité ne sera pas affichée + readonly property double shipheart_plancher_intensite_circuit_sp4ac: 0.5 // En dessous de cette valeur, l'intensité ne sera pas affichée + + // Mode commande des circuits : + readonly property int shipheart_mode_commande_circuit_tor: 0 + readonly property int shipheart_mode_commande_circuit_soft_tor: 1 + readonly property int shipheart_mode_commande_circuit_soft_variable: 2 + + // Etat des circuits : + readonly property int shipheart_etat_circuit_ok: 0 + readonly property int shipheart_etat_circuit_limitation: 1 + readonly property int shipheart_etat_circuit_protection: 2 + readonly property int shipheart_etat_circuit_disjonte: 3 + readonly property int shipheart_etat_circuit_cc_batterie: 4 + readonly property int shipheart_etat_circuit_deleste: 5 + readonly property int shipheart_etat_circuit_undervoltage: 6 + readonly property int shipheart_etat_circuit_inversion_phase_neutre: 7 + readonly property int shipheart_etat_circuit_absence_terre: 8 + readonly property int shipheart_etat_circuit_absence_masse: 9 + readonly property int shipheart_etat_circuit_inconnu: 99 + + // Types de variables : + readonly property string shipheart_circuit_consigne: "Circ_consigne" + readonly property string shipheart_circuit_tension: "Circ_tension" + readonly property string shipheart_circuit_courant: "Circ_courant" + readonly property string shipheart_circuit_frequence: "Circ_frequence" + readonly property string shipheart_circuit_puissance: "Circ_puissance" + readonly property string shipheart_circuit_energie: "Circ_energie" + readonly property string shipheart_circuit_tension_secteur: "Circ_tension_secteur" + + + //----------------------------------------------------------------------------------- + // Réservoirs : + readonly property int shipheart_reservoir_max_nombre_entrees_aux: 12 + + // Type d'entrées réservoir : + readonly property int shipheart_reservoir_type_entrees_aux: 1 + readonly property int shipheart_reservoir_type_entrees_level_sensor: 2 + + // Mode entrées réservoir : + readonly property int shipheart_reservoir_mode_entrees_aux_normal: 0 + readonly property int shipheart_reservoir_mode_entrees_aux_inverse: 1 + + readonly property int shipheart_reservoir_mode_entrees_level_sensor_0_10v: 1 + readonly property int shipheart_reservoir_mode_entrees_level_sensor_500r: 2 + readonly property int shipheart_reservoir_mode_entrees_level_sensor_4_20ma: 3 + + // Type_sonde réservoir : + readonly property int shipheart_reservoir_mode_entrees_level_sensor_500r_0_500r: 0 + readonly property int shipheart_reservoir_mode_entrees_level_sensor_500r_0_190r: 1 + readonly property int shipheart_reservoir_mode_entrees_level_sensor_500r_240_30r: 2 + + // Types de variables : + readonly property string shipheart_reservoir_niveau: "Res_niveau" + + + + //=============================================================================================================================== + // Propriétés dynamiques : + //=============================================================================================================================== + property int shipheart_type_installation: shipheart_type_installation_shipbase + property var shipheart_specifique_client // Tableau mis à jour avec 'TB_Configuration.Specifique_client' dans 'main.qml' via l'appel à 'init_shipheart_specifique_client()' dans initialItem de StackView ci-dessous + property string shipheart_code_client: "" // Chaine contenant le code client 'TB_Configuration.Code_client' + + // Thèmes d'affichage : + property string shipheart_fichier_image_accueil: "" // Fichier dans '/docs/image_accueil' à utiliser sur la page d'accueil (ou "" pour l'image par défaut) + property int shipheart_theme: 0 // N° du thème à utiliser. Mis à jour au démarrage à partir de TB_Configuration.Theme. + property string shipheart_theme_fichier_fond_ecran: "" // Le nom du fichier à utiliser comme fond d'écran + property string shipheart_theme_couleur_fond_ecran: couleur_noir // Le nom (cf plus haut) de la couleur à utiliser en fond d'écran (ne fonctionne que si 'shipheart_theme_fichier_fond_ecran' est vide) + property color shipheart_couleur_fond_bouton: couleur_gris_tres_fonce_transparent + property color shipheart_couleur_fond_bouton_actif: couleur_bleu_koriolan_transparent + property color shipheart_couleur_texte_titre_1: couleur_gris_fonce + property color shipheart_couleur_texte_titre_2: couleur_bleu_koriolan + property color shipheart_couleur_texte_titre_3: couleur_gris_pale + property color shipheart_couleur_fond_boite_dialogue_niveau_0: couleur_bleu_koriolan + property color shipheart_couleur_fond_boite_dialogue_niveau_1: couleur_orange + property color shipheart_couleur_fond_boite_dialogue_niveau_2: couleur_rouge + property color shipheart_couleur_texte_boite_dialogue_niveau_0: couleur_blanc_casse + property color shipheart_couleur_texte_boite_dialogue_niveau_1: couleur_blanc_casse + property color shipheart_couleur_texte_boite_dialogue_niveau_2: couleur_blanc_casse + property color shipheart_couleur_texte_slider: couleur_bleu_koriolan + property color shipheart_couleur_bordure_courbes: couleur_bleu_koriolan // Couleur de la courbe elle-même + + + + property int shipheart_generation_shipbase: shipheart_generation_shipbase_inconnue + property int shipheart_defaut_config_k_bus: 0 // 0=normal, 1=défaut de config K-Bus vs modules réellement présents (mis à jour par Home en fonction du flag provenant de l'Appli) + property int shipheart_fuseau_horaire: 0 // UTC par défaut + property int shipheart_heure_ete: 0 // 0= hiver, 1= été + property int shipheart_langue: 0 // Français par défaut + property string shipheart_code_pays: "FR" // Français par défaut + property string shipheart_code_langue: "fr_FR" // Français par défaut + property int shipheart_unite_temperature: shipheart_unite_temperature_celsius // °C par défaut + property string shipheart_unite_temperature_symbole: "°C" + property int shipheart_unite_volume: shipheart_unite_volume_litres // Litres par défaut + property string shipheart_unite_volume_symbole: "l" + property int shipheart_time_out_economiseur: 0 // Image de TB_Configuration.Time_out_economiseur + property string shipheart_bips: "" // Image de TB_Configuration.Bips. + + property double shipheart_latitude: 0 + property double shipheart_longitude: 0 + property string shipheart_heure_aube_nautique: "--:--" + property string shipheart_heure_lever_soleil: "--:--" + property string shipheart_heure_zenith: "--:--" + property string shipheart_heure_coucher_soleil: "--:--" + property string shipheart_heure_crepuscule_nautique: "--:--" + + property string shipheart_fichier_a_valider: ""; + property string shipheart_fichier_a_charger: ""; + property int shipheart_nb_fichiers_a_charger: 0; + + property int max_taille_code_pattern: 10 // Nb maxi de chiffres saisissable d'un code (attention : différent de Min_taille_code et Max_taille code de TB_Configuration). D'ailleurs, cette valeur est ajustée à Max_taille_code + 2 dans 'parametres.qml' et dans les pages spécifiques qui traitent la saisie de codes d'accès (ex : home_suncy.qml). + property int shipheart_compteur_economiseur: 30 // Valeur décrémentée chaque seconde et réarmée à chaque interaction d'un utilisateur (valeur mise à jour avec 'TB_Configuration.Time_out_economiseur' à chaque 'reload_economiseur()' dans 'Shipheart_page.qml') + property bool shipheart_flag_nettoyage_ecran_en_cours: false // Permet de passer l'info que le nettoyage est en cours (et, par exemple, bloquer l'économiseur d'écran) + property bool shipheart_flag_blocage_compteurs_pendant_config: false // Permet de bloquer le compteur pendant qu'on est en config + property int shipheart_compteur_time_out_niveau_acces: 0 // Contient le temps restant, en secondes, de la validité de l'accés en cours + property int shipheart_time_out_niveau_acces: 120 + property int shipheart_niveau_acces_en_cours: shipheart_niveau_acces_aucun // 0=aucun accès valide, 1=accès user validé, 10=accès admin validé, 20=accès Koriolan validé + property int shipheart_message_users_max_nombre_reports: 3 // Valeur mise à jour avec 'TB_Configuration.Nb_maxi_reports_message_user' lors de l'init de 'home.qml' + property int shipheart_periode_obsolescence_capteur_nmea: 600 // En secondes + + property int shipheart_niveau_home: 0 // Contient le niveau dans la StackView de la page 'home.qml' (dépend si des pages spécifique au client sont disposées avant). Permet de revenir directement à la page 'home.qml' depuis certaines pages + + property double shipheart_test_vitesse_test_ecran: 1500 + property int nombre_lignes_matrice_test: 8 + property int nombre_colonnes_matrice_test: 10 + + property bool flag_economiseur_actif: false + + // Dimensions (mises à jour dans 'home_attente.qml' selon la valeur de 'shipheart_type_installation' : + property int shipheart_largeur_page + property int shipheart_hauteur_page + property int shipheart_hauteur_bandeau_haut + property int shipheart_hauteur_titre_2 + property int shipheart_hauteur_bandeau_bas + property int shipheart_hauteur_clavier + + + // Modèles : + property Bdd bdd : Bdd{} + property Systeme systeme : Systeme{} + property TbMesuresModel tbmesuresModel : TbMesuresModel{} + + // Signals : + + + + width: shipheart_largeur_page + height: shipheart_hauteur_page + color: shipheart_theme_couleur_fond_ecran + visible: true + property int duree_animation_pages: 400 // En ms + + + //=========================================================== + // Connexion BDD : + // La connexion MySql a un time-out (par défaut de 8h apparemment). La page Home faisant des mises à jour chaque secondes, il n'y a + // aucun soucis de déclenchement. + // Par contre, les mises à jour de Home étant désactivées lorsqu'on navigue sur les pages de niveau inférieur, si on reste sur + // une telle page pendant plusieurs heures, le time-out se déclenche. Par exemple, si on reste sur une page de configuration + // pensant une nuit, il est probable qu'on se trouve dans ce cas... + // Dans ce cas, seul une réinit de l'appli QT permet de redémarrer puisque la connexion à la BDD est fait dans main.cpp. + // Plutôt que d'allonger le time-out (il ne semble pas possible de le mettre à infini), il est ajouté ce timer qui fait une requête + // toutes les heures, même lorsque Home n'est pas la page active. + //=========================================================== + Timer { + id: timer_maintient_connexion_bdd + interval: 60 * 60 * 1000 // Toutes les heures = 60 minutes x 60 secondes x 1000ms + running: true + repeat: true + onTriggered: { + let req = 'SELECT Valeur FROM TB_Systeme WHERE Nom="Heart_beat" '; + let res = bdd.requete_unique(req); + console.log("Déclenchement du timer de maintient de la connexion avec la BDD") + } + } + + + //============================================================== + // Pile de pages : + //============================================================== + StackView { + id: stackView + width: root.width + height: root.height + Component.onCompleted: { + var result = stackView.push(Qt.resolvedUrl("qrc:/home_attente.qml")) // Cela permet d'avoir une page "propre" plutot qu'une page toute blanche en attendant que l'accès à la BDD soit possible et permette de déterminer la home page à charger. +// console.log("Résultat du push : " + result) + } + + pushEnter: Transition { // Nouvelle page, lors d'un PUSH + PropertyAnimation { + property: "x" + from: shipheart_largeur_page // Part du bord droit... + to:0 // ... jusqu'au bord gauche (la page "entre" par la gauche) + duration: duree_animation_pages + easing.type: Easing.OutQuad; + } + } + pushExit: Transition { // Ancienne page, lors d'un PUSH + PropertyAnimation { + property: "x" + from: 0 // Part du bord gauche, là où elle était affichée... + to: -shipheart_largeur_page // ... et sort par la gauche, jusqu'à ce qu'elle disparaisse complètement à gauche. + duration: duree_animation_pages + easing.type: Easing.OutQuad; + } + } + popEnter: Transition { // Nouvelle page, lors d'un POP + PropertyAnimation { + property: "x" + from: -shipheart_largeur_page // Part de complètement hors du cadre, à gauche... + to: 0 // ... jusqu'à ce que son bord gauche soit aligné avec le bord gauche de l'écran. + duration: duree_animation_pages + easing.type: Easing.OutQuad; + } + } + popExit: Transition { // Ancienne page lors d'un POP. + PropertyAnimation { + property: "x" + from: 0 // Part du bord gauche... + to: shipheart_largeur_page // ... jusqu'au bord droit de l'écran (sort par la droite). + duration: duree_animation_pages + easing.type: Easing.OutQuad; + } + } + } + + + + + + //============================================================== + // Clavier : + //============================================================== + InputPanel { + id: clavier + z: 99 + x: 0 + y: root.height + width: root.width + + states: State { + name: "visible" + when: clavier.active + PropertyChanges { + target: clavier + y: root.height - clavier.height + } + } + transitions: Transition { + from: "" + to: "visible" + reversible: true + ParallelAnimation { + NumberAnimation { + properties: "y" + duration: 250 + easing.type: Easing.InOutQuad + } + } + } + Component.onCompleted: { + console.log("locales available: " + VirtualKeyboardSettings.availableLocales) + console.log("Locale before changing it: " + VirtualKeyboardSettings.locale) + VirtualKeyboardSettings.locale = "fr_FR"; + console.log("Locale after changing it: " + VirtualKeyboardSettings.locale) +// VirtualKeyboardSettings.styleName = "retro" + + // Les fichiers de layout spécifiques à Koriolan sont dans le répertoire /virtualkeyboard_layouts_koriolan et renseigné en ressource de qrc. + // La procédure a été trouvée ici : https://forum.qt.io/topic/93279/how-to-custom-qml-virtual-keyboard/2 + + // Note : les fichiers relatifs au clavier sont situés dans /home/koriolan/qt/raspi/qt-everywhere-src-5.12.5/qtvirtualkeyboard/src/virtualkeyboard + // En particulier, les fichiers de DEFAULT ou RETRO sont dans /home/koriolan/qt/raspi/qt-everywhere-src-5.12.5/qtvirtualkeyboard/src/virtualkeyboard/content/styles + } + } + + + + //--------------------------------------------------------------------------------------------------------------------------------------- + // Les fonctions ci-dessous sont accessibles depuis n'importe quelle page (puisque appelée, directement ou indirectement par cell-ci). + //--------------------------------------------------------------------------------------------------------------------------------------- + + + //============================================================================================================= + // Demande de synchro de la BDD + //============================================================================================================= + function synchro_bdd(type_synchro) + { + switch (type_synchro) + { + case shipheart_type_synchro_aucune: + break; + case shipheart_type_synchro_data: + bdd.requete_unique('UPDATE TB_Systeme SET Valeur=1 WHERE Nom="Synchro" '); + break; + case shipheart_type_synchro_config: + bdd.requete_unique('UPDATE TB_Systeme SET Valeur=2 WHERE Nom="Synchro" '); + break; + default: + console.log("/!\\ Le paramètre de synchro de BDD reçu n'est pas valide [" + type_synchro + "]") + break; + } + } + + //============================================================================================================= + // Rebooter via l'Appli (permet un reboot "ordonné") : + //============================================================================================================= + function rebooter() + { + + console.log("!!! Commande de REBOOT reçue !!!"); + bdd.requete_unique('UPDATE TB_Systeme SET Valeur="Reboot" WHERE Nom="Demande_reboot" '); + + stackView.pop(stackView.get(shipheart_niveau_home)); // Retour à la page 'home.qml' car on va reseter et il faut pouvoir afficher le message user + } + +} diff --git a/page_personnalisee.qml b/page_personnalisee.qml new file mode 100644 index 0000000..7fa0fc0 --- /dev/null +++ b/page_personnalisee.qml @@ -0,0 +1,981 @@ +//======================================================================================================================================================================== +// PAGE_PERSONNALISEE.QML +// Ce fichier traite l'affichage d'une page personnalisée. La page utilise les données de TB_Pages correspondant à 'id_page'. +// Elle affiche notamment : +// - l'image de fond à partir des champs Fichiers, Opacité, Taille, Offset_x et Offset-y. +// - Tous les points listés dans le champ Points et en fonction de leur paramètre 'type_point' +// - l'état actuel de chaque point en fonction de l'état de l'équipement qu'ils représentent +// - un mousearea pour les circuits qui se comporte comme le bouton On/Off de la Home Page. +// La page est appelée depuis la page HOME, en cliquant sur la page, dans les onglets de page +//======================================================================================================================================================================== + +import QtQuick 2.12 +import QtQuick.Controls 2.12 + +import qt.koriolan.shipheart 1.0 +import"fonctions.js" as Fonctions + + + + +Shipheart_page { + id: page_page_personnalisee + + + // Mis en forme : + 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 periode_init_raffraichissement_parametres: 20 // En ms ATtention : The Timer type is synchronized with the animation timer. Since the animation timer is usually set to 60fps, the resolution of Timer will be at best 16ms. + readonly property int periode_raffraichissement_parametres: 1000 // En ms + + readonly property int periode_base_affichage_nom: 10 // En ms + readonly property int periode_affichage_nom: 150 // En x 'periode_base_affichage_nom' + readonly property int tempo_avant_fadding_affichage_nom: 50 // En x 'periode_base_affichage_nom' + + + // Données : + property bool flag_init: true // Permet de bloquer certains affichage tant que l'init n'est pas terminée + + 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_affichage_nom_en_cours: -1 + property int compteur_affichage_nom_en_cours: 0 + property bool appui_sur_point_en_cours: false + property int point_en_cours_details: -1 + + + // 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 + { + if (!appui_sur_point_en_cours) mise_a_jour(); // Evite une maj pendant que l'on est en appui long + } + } + } + + //=========================================================== + // Timer temporisation affichage nom : + //=========================================================== + Timer { + id: timer_tempo_affichage_nom + interval: periode_base_affichage_nom + triggeredOnStart: false + running: false + repeat: true + onTriggered: { + if (point_en_cours_details === -1) // On garde le nom affiché si on est sur ses détails + { + if (-- compteur_affichage_nom_en_cours <= 0) + { + index_affichage_nom_en_cours = -1; + timer_tempo_affichage_nom.stop(); + } + } + } + } + + //=========================================================== + // 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:nom_page; hauteur: shipheart_hauteur_bandeau_haut} + + + //------------------------------------------------------- + // Ecran principal : + //------------------------------------------------------- + Rectangle { + id: zone_affichage_droite + + x: 0 + y: shipheart_hauteur_bandeau_haut; + width: shipheart_largeur_page + height: affichage_hauteur_utile + color: "transparent" +border.color: couleur_gris_moyen + + ListModel { + id: modele_liste_points + } + + //========================== + // 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 + + 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 + + x: (image_silhouette.visible) ? + (model.x * image_silhouette.paintedWidth) + (zone_affichage_droite.width / 2) - (point.width / 2) : + (model.x * zone_affichage_droite.width) + (zone_affichage_droite.width / 2) - (point.width / 2) + y: (image_silhouette.visible) ? + (model.y * image_silhouette.paintedHeight) + (zone_affichage_droite.height / 2) - (point.height / 2) : + (model.y * zone_affichage_droite.height) + (zone_affichage_droite.height / 2) - (point.height / 2) + + radius: model.taille_point / 2 + width: model.taille_point + height: width + color: "transparent" + + //----------------------------------------------------- + // Icone : + + // Remplissage de l'icone : + Rectangle { + anchors { + horizontalCenter: icone_point.horizontalCenter + bottom: icone_point.bottom + } + width: icone_point.width * 0.9 + height: icone_point.height * (model.remplissage / 100) + opacity: 0.7 + color: (model.type_remplissage === 3) ? + couleur_gris_pale : // Eaux noires/grises + (model.type_remplissage === 4) ? + couleur_orange : // Carburant + couleur_bleu_koriolan // Eau douce (et autres...) + visible: (model.remplissage !== -1) + } + Image { + id: icone_point + source: model.icone + sourceSize.height: model.taille_point + anchors { + horizontalCenter: parent.horizontalCenter + verticalCenter: parent.verticalCenter + } + } + /* ColorOverlay { + anchors.fill: icone_point + source: icone_point + color: couleur_green_yellow + } +*/ + Glow { + anchors.fill: icone_point + radius: 30 + samples: 61 +// spread: 0.9 + color: couleur_blanc + source: icone_point + visible: model.halo + } + + //----------------------------------------------------- + // Nom : + Text { + id: libelle_nom + anchors.bottom: parent.top + anchors.horizontalCenter: parent.horizontalCenter + text: model.nom + font.pixelSize: 15 + font.weight: Font.Bold + color: couleur_blanc_casse + opacity: (compteur_affichage_nom_en_cours > tempo_avant_fadding_affichage_nom) // Si on est > 500ms, on reste à 100% d'opacité + ? 1.0 + : (compteur_affichage_nom_en_cours / tempo_avant_fadding_affichage_nom) // Si on est <= 500ms, on réduit linéairement l'opacité jusqu'à 0 + visible: (index_affichage_nom_en_cours === index) // On dévalide carément l'affichage du nom puisque la valeur de repos est -1 (pas obligatoire mais plus propre) + } + + //----------------------------------------------------- + // Valeur_1 : + Text { + id: libelle_valeur_1 + anchors.top: parent.bottom + anchors.horizontalCenter: parent.horizontalCenter + text: model.valeur_1 + font.pixelSize: 15 + font.weight: Font.Bold + color: couleur_blanc_casse + visible: (model.valeur_1 !== "") + } + //----------------------------------------------------- + // Valeur_2 : + Text { + id: libelle_valeur_2 + anchors.top: libelle_valeur_1.bottom + anchors.horizontalCenter: parent.horizontalCenter + text: model.valeur_2 + font.pixelSize: 15 +// font.weight: Font.Bold + color: couleur_blanc_casse + visible: (model.valeur_2 !== "") + } + //----------------------------------------------------- + // Détails du point : + Rectangle { + anchors.fill: libelle_details_point + opacity: 0.2 + radius: shipheart_rayon_bouton + color: couleur_gris_moyen + visible: libelle_details_point.visible && (model.details !== "") + } + Rectangle { + id: libelle_details_point + anchors { + left: (model.x <= 0) ? libelle_nom.right : undefined + right: (model.x > 0) ? libelle_nom.left : undefined + top: (model.y < 0) ? libelle_valeur_1.bottom : undefined + bottom: (model.y >= 0) ? libelle_nom.top : undefined + } + width: details_point.contentWidth + 20 + height: details_point.contentHeight + 20 + +// opacity: 0.4 + color: "transparent" + visible: (point_en_cours_details === index) + + MouseArea { + id: dragArea + anchors.fill: parent + drag.target: parent + drag.axis: Drag.XAndYAxis + onPressed: { + libelle_details_point.anchors.left = undefined + libelle_details_point.anchors.right = undefined + libelle_details_point.anchors.top = undefined + libelle_details_point.anchors.bottom = undefined + } + } + + Text { + id: details_point + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + text: (point_en_cours_details >= 0) ? model.details : "" + font.pixelSize: 15 + // font.weight: Font.Bold + color: couleur_blanc_casse + } + } + + //----------------------------------------------------- + // Picto d'alerte : + Image { + id: picto_alerte + source: "/images/ak14.png" + sourceSize.height: 20; + anchors { + left: icone_point.right + leftMargin: -10 + bottom: icone_point.bottom + } + visible: (model.alarme > 0) + } + + //----------------------------------------------------- + MouseArea { + id: mousearea_point + width: 100 + height: 100 + anchors { + horizontalCenter: parent.horizontalCenter + verticalCenter: parent.verticalCenter + } + onPressed: { + shipheart_clic(); + + appui_sur_point_en_cours = true; + index_affichage_nom_en_cours = index; + compteur_affichage_nom_en_cours = periode_affichage_nom; + timer_tempo_affichage_nom.start(); + + if (model.type_source !== shipheart_type_source_modules) point_en_cours_details = -1; // Dans le doute, on dévalide les détails d'un module s'il y en a un en cours + } + pressAndHoldInterval: shipheart_mouse_press_and_hold_interval_long; + onPressAndHold: { + if (model.type_source === shipheart_type_source_circuits) + { + shipheart_clic(); // On enlève aussi le son si on n'est pas sur un circuit (sinon, on a le 'clic' mais aucun effet...) + toggle_consigne_circuit(model.id_source, index); + } + else if (model.type_source === shipheart_type_source_modules) + { + if (point_en_cours_details >= 0) + { + if (point_en_cours_details === index) point_en_cours_details = -1; + else point_en_cours_details = index; + } + else point_en_cours_details = index; + } + } + onDoubleClicked: { + shipheart_clic(); + + switch(model.type_source) + { + //------------------------------------------------------ + case shipheart_type_source_circuits: + stackView.push("circuit.qml", {"id_circuit": model.id_source }) + break; + + //------------------------------------------------------ + case shipheart_type_source_reservoirs: + stackView.push("reservoir.qml", {"id_reservoir": model.id_source }) + break; + + //------------------------------------------------------ + case shipheart_type_source_batteries: + stackView.push("batterie.qml", {"id_batterie": model.id_source }) + break; + + //------------------------------------------------------ + case shipheart_type_source_capteurs: + stackView.push("capteur.qml", {"id_capteur": model.id_source }) + break; + } + } + onReleased: { + timer_raffraichissement_parametres.restart(); // Permet de réarmer le timer et éviter qu'il ne se déclenche juste après le retrait du doigt (et risquer que la prise en compte de l'action sur circuit n'ait pas été complèemnt traité). + appui_sur_point_en_cours = false; + } + } + } + } + } + + //------------------------------------------------------- + // Bandeau bas : + //------------------------------------------------------- + Row { + x: 0 + y: shipheart_hauteur_page - shipheart_hauteur_bandeau_bas; + width: shipheart_largeur_page; + height: shipheart_hauteur_bandeau_bas; + + //................................................. + // 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); + } + } + + //============================================================================================================= + // Init de la page + //============================================================================================================= + function init_page() + { + var req, res; + var i; + +//console.log("Id de la page = " + id_page); + + //==================================================================== + // Recherche des infos de la page : + req = 'SELECT Nom, '; + 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("Requête = [" + req + "]") + res = bdd.requete_unique(req); + + // Récupération des données : + i = 0; + 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 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... + + //==================================================================== + // Première mise à jour : + mise_a_jour(); + + //==================================================================== + // Libération du flag : + flag_init = false; + } + + //============================================================================================================= + // Met à jour 'modele_liste_points' 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 nom; + var icone; + var halo; + var type_remplissage + + // RAZ des courbes : + nb_points = 0; + modele_liste_points.clear(); + + 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 le modèle : + 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++]); + halo = false; // Par défaut + type_remplissage = 0; // Par défaut + + // Recherche des infos de l'équipement : + switch(type_source) + { + //------------------------------------------------------ + case shipheart_type_source_circuits: + req = ' SELECT Nom, Consigne, Etat_commande_carte, Etat, Mode_test FROM TB_Circuits WHERE Cle_primaire=' + id_source + ' '; +//console.log("req = [ " + req + "; ]"); + res = bdd.requete_unique(req); + nom = res[0]; + + // Calcul de l'icone à utiliser : + if (Number(res[1]) > 0) + { + icone = "/images/" + shipheart_page_personnalisee_type_point_icones[type_source][type_point]; + halo = true; + } + else icone = "/images/" + shipheart_page_personnalisee_type_point_icones[type_source][0]; + + break; + + //------------------------------------------------------ + case shipheart_type_source_reservoirs: + req = ' SELECT Nom, ID_Famille FROM TB_Reservoirs WHERE Cle_primaire=' + id_source + ' '; + res = bdd.requete_unique(req); + nom = res[0]; + type_remplissage = Number(res[1]); + + // Calcul de l'icone à utiliser : + icone = "/images/" + shipheart_page_personnalisee_type_point_icones[type_source][type_point]; + + break; + + //------------------------------------------------------ + case shipheart_type_source_batteries: + req = ' SELECT Nom FROM TB_Batteries WHERE Cle_primaire=' + id_source + ' '; + res = bdd.requete_unique(req); + nom = res[0]; + + // Calcul de l'icone à utiliser : + icone = "/images/" + shipheart_page_personnalisee_type_point_icones[type_source][type_point]; + + break; + + //------------------------------------------------------ + case shipheart_type_source_capteurs: + req = ' SELECT Nom FROM TB_Capteurs WHERE Cle_primaire=' + id_source + ' '; + res = bdd.requete_unique(req); + nom = res[0]; + + // Calcul de l'icone à utiliser : + icone = "/images/" + shipheart_page_personnalisee_type_point_icones[type_source][type_point]; + + break; + + //------------------------------------------------------ + case shipheart_type_source_modules: + req = ' SELECT Type FROM TB_Modules_config WHERE Adresse_k_bus=' + id_source + ' '; + res = bdd.requete_unique(req); + nom = Fonctions.nom_type_module(Number(res[0])); + + // Calcul de l'icone à utiliser : + icone = "/images/" + shipheart_page_personnalisee_type_point_icones[type_source][type_point]; + + break; + } + + modele_liste_points.append({ + "validite": validite, + "type_source": type_source, + "id_source": id_source, + "x": x, + "y": y, + "type_point": type_point, + "taille_point": taille_point, + "nom": nom, + "icone": icone, + "halo": halo, + "valeur_1": "", + "valeur_2": "", + "details": "", + "remplissage": -1, + "type_remplissage": type_remplissage, + "alarme": false }); + } + } + + + //============================================================================================================= + // Mise à jour des valeurs courantes de tous les points + //============================================================================================================= + function mise_a_jour() + { + var req, res; + var sous_req, sous_res; + var nb; + var i, j; + + for (i = 0; i < modele_liste_points.count; i ++) + { + switch(modele_liste_points.get(i).type_source) + { + //------------------------------------------------------ + case shipheart_type_source_circuits: + req = 'SELECT Cle_primaire, '; // Note : la requete est gardée identique à celle de 'home.qml'@1905 pour faciliter la recopie... + req += ' Etat_systeme, '; + req += ' Nom, '; + req += ' Etat_commande_carte, '; + req += ' Mode_commande, '; + req += ' Etat, '; + req += ' Consigne, '; + req += ' Old_consigne, '; + req += ' Mode_test, '; + req += ' Tension, '; + req += ' Intensite, '; + req += ' Frequence, '; + req += ' (SELECT Type FROM TB_Modules_config WHERE Adresse_k_bus=TB_Circuits.Adresse_module) AS type_circuit, '; + req += ' No_circuit, '; + req += ' (SELECT COUNT(*) FROM TB_Events WHERE Validite=1 AND Visibilite=1 AND (Action_circuits LIKE CONCAT(TB_Circuits.Cle_primaire,"/%") OR Action_circuits LIKE CONCAT("%;", TB_Circuits.Cle_primaire,"/%") ) ) AS nb_events, '; + req += ' Validation_cdes_events, '; + req += ' (SELECT COUNT(*) FROM TB_Events WHERE Validite=1 AND Type_source=' + shipheart_source_mesure_circuit + ' AND Alarme_source>0 AND Etat_test=1 AND ID_Source=TB_Circuits.Cle_primaire) AS Nb_alarmes'; + req += ' FROM TB_Circuits WHERE Cle_primaire=' + modele_liste_points.get(i).id_source + ' '; +//console.log("Requête = [" + req + "]"); + res = bdd.requete_unique(req); + + // Calcul de l'icone à utiliser : + var icone; + var halo = false; + if (Number(res[6]) > 0) + { + icone = "/images/" + shipheart_page_personnalisee_type_point_icones[shipheart_type_source_circuits][modele_liste_points.get(i).type_point]; + halo = true; + } + else icone = "/images/" + shipheart_page_personnalisee_type_point_icones[shipheart_type_source_circuits][0]; + + modele_liste_points.set(i, { + "etat_systeme": Number(res[1]), + "nom": res[2], + "valeur_1": "", + "valeur_2": "", + "remplissage": -1, + "icone": icone, + "halo": halo, + "alarme": ( (Number(res[3]) !== shipheart_etat_commande_module_ok) + || (Number(res[5]) !== shipheart_etat_circuit_ok) + || (Number(res[16]) > 0) ) }); + break; + + //------------------------------------------------------ + case shipheart_type_source_reservoirs: + req = 'SELECT Cle_primaire, '; // Note : la requete est gardée identique à celle de 'home.qml'@2140 pour faciliter la recopie... + req += ' Nom, '; + req += ' Etat_systeme, '; + req += ' ID_Famille, '; + req += ' Niveau, '; + req += ' Capacite, '; + req += ' Logique, '; + req += ' (SELECT COUNT(*) FROM TB_Events WHERE Validite=1 AND Type_source=' + shipheart_source_mesure_reservoir + ' AND Alarme_source>0 AND Etat_test=1 AND ID_Source=TB_Reservoirs.Cle_primaire) AS Nb_alarmes, ' + req += ' Etat_entrees '; + req += ' FROM TB_Reservoirs WHERE Cle_primaire=' + modele_liste_points.get(i).id_source + ' '; +//console.log("Requête = [" + req + "]"); + res = bdd.requete_unique(req); + + modele_liste_points.set(i, { + "etat_systeme": Number(res[2]), + "nom": res[1], + "valeur_1": Fonctions.conversion_volume(((Number(res[4]) / 100) * Number(res[5])), shipheart_unite_volume, shipheart_unite_volume_symbole, 0), + "valeur_2": Number(res[4]).toFixed(0) + " %", // Niveau en % + "remplissage": Number(res[4]), + "alarme": ((Number(res[7]) !== shipheart_capteur_etat_normal) || (Number(res[8]) !== 0)) }); + break; + + //------------------------------------------------------ + case shipheart_type_source_batteries: + req = 'SELECT Cle_primaire, '; // Note : la requete est gardée identique à celle de 'home.qml'@2330 pour faciliter la recopie... + req += ' Etat_systeme, '; + req += ' Nom, '; + req += ' Type, '; + req += ' Soc, '; + req += ' Tension, '; + req += ' Tension_nominale, '; + req += ' (SELECT COUNT(*) FROM TB_Events WHERE Validite=1 AND Type_source=' + shipheart_type_source_batteries + ' AND Alarme_source>0 AND Etat_test=1 AND ID_Source=TB_Batteries.Cle_primaire) AS Nb_alarmes'; + req += ' FROM TB_Batteries WHERE Cle_primaire=' + modele_liste_points.get(i).id_source + ' '; +//console.log("Requête = [" + req + "]"); + res = bdd.requete_unique(req); + + modele_liste_points.set(i, { + "etat_systeme": Number(res[1]), + "nom": res[2], + "valeur_1": Number(res[4]).toFixed(0) + " %", // Niveau + "valeur_2": Number(res[5]).toFixed(1) + " V", + "remplissage": -1, + "alarme": (Number(res[7]) > 0) }); + break; + + //------------------------------------------------------ + case shipheart_type_source_capteurs: + req = ' SELECT Cle_primaire, '; // Note : la requete est gardée identique à celle de 'home.qml'@2630 pour faciliter la recopie... + req += ' Etat_systeme, '; + req += ' Nom, '; + req += ' Type_entrees, '; + req += ' Entrees, '; + req += ' ID_Variable, '; + req += ' Etat, '; + req += ' (SELECT COUNT(*) FROM TB_Events WHERE Validite=1 AND Type_source=' + shipheart_type_source_capteurs + ' AND Alarme_source>0 AND Etat_test=1 AND ID_Source=TB_Capteurs.Cle_primaire) AS Nb_alarmes, ' + req += ' Valeur, '; + req += ' Precision_affichage_accueil, '; + req += ' Liste_valeurs_textes '; + req += ' FROM TB_Capteurs WHERE Cle_primaire=' + modele_liste_points.get(i).id_source + ' '; +//console.log("Requête = [" + req + "]"); + res = bdd.requete_unique(req); + + // 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="' + Number(res[5]) + '" '); + + // Traitement des conversions d'unités : + var nouvelle_unite; + var symbole_unite; + var type_unite; + switch(Number(sous_res[1])) + { + 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( Number(res[8]), nouvelle_unite, "", Number(res[9]), type_unite); + switch(Number(res[3])) + { + //----------------------------------------------------------------- + case shipheart_capteur_type_entrees_aux: + case shipheart_capteur_type_entrees_calculee_booleen: + + // Traitement des listes : + var chaines_valeurs_textes = res[10].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 (Number(res[8]) === 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; + } + + modele_liste_points.set(i, { + "etat_systeme": Number(res[1]), + "nom": res[2], + "valeur_1": chaine_valeur + " " + symbole_unite, + "valeur_2": "", + "remplissage": -1, + "alarme": ((Number(res[6]) !== shipheart_capteur_etat_normal) || (Number(res[7]) !== 0)) }); + break; + + //------------------------------------------------------ + case shipheart_type_source_modules: + req = 'SELECT Adresse_k_bus, '; + req += ' Etat_systeme, '; + req += ' Mode_test, '; + req += ' Tension_etat, '; + req += ' Type '; + req += ' FROM TB_Modules_config WHERE Adresse_k_bus=' + modele_liste_points.get(i).id_source + ' '; +//console.log("Requête = [" + req + "]"); + res = bdd.requete_unique(req); + + modele_liste_points.set(i, { + "etat_systeme": Number(res[1]), + "valeur_1": (Number(res[0]) === 0) ? "" : "@" + res[0], + "alarme": ( (Number(res[2]) > 0) || (Number(res[3]) > 0) ) }); + + //================================================== + // Mise à jour de l'usage du module : + var nb_elements; + var type_carte; + var usage = ""; + var nom_circuits = []; + var nom_batterie; + + type_carte = Number(res[4]); + + switch(type_carte) + { + //----------------------------------- + case shipheart_type_module_shippower812: + case shipheart_type_module_shippower4AC: + case shipheart_type_module_shippower8DC: + + // Init du nom des circuits affectés au module : + if ((type_carte === shipheart_type_module_shippower812) || (type_carte === shipheart_type_module_shippower8DC)) nb_elements = shipheart_max_circuits_par_module_sp8xx; + else nb_elements = shipheart_max_circuits_par_module_sp4ac; + for (j = 0; j < nb_elements; j ++) nom_circuits.push(qsTr("--- Circuit non affecté ---")); + + // Recherche des circuits affectés à ce n° de carte : + req = 'SELECT No_circuit, Nom, ID_Circuit_esclave FROM TB_Circuits WHERE Adresse_module=' + modele_liste_points.get(i).id_source + ' ORDER BY No_circuit '; +//console.log("req =" + req); + nb = bdd.requete(req); + + for (j = 0; j < nb; j ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + nom_circuits[Number(res[0])] = res[1]; + if (Number(res[2]) < 0) nom_circuits[Number(res[0])] += " " + qsTr("[renfort]") + ""; + } + else break; + } + + // Création du texte d'utilisation des circuits : + for (j = 0; j < nb_elements; j ++) + { + if (j !== 0) usage += "
"; + usage += (j + 1) + " - " + nom_circuits[j]; + } + + break; + + //----------------------------------- + case shipheart_type_module_shipBS: + + // Recherche des circuits affectés à ce n° de carte : + req = 'SELECT Nom FROM TB_Batteries WHERE Type_entrees=' + shipheart_batteries_type_entrees_ibs + ' AND Adresse_module=' + modele_liste_points.get(i).id_source + ' '; + //console.log("req =" + req); + nb = bdd.requete(req); + + usage = ""; + for (j = 0; j < nb; j ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + usage = res[0]; + } + else break; + } + + if (usage === "") usage = qsTr("--- Aucune batterie affectée ---"); + + break; + + //----------------------------------- + default: + break; + } + + if (usage != "") modele_liste_points.set(i, {"details": usage }); + + break; + } + } + } + + + //============================================================================================================= + // Toggle de la valeur de consigne d'un circuit + //============================================================================================================= + function toggle_consigne_circuit(id_source, index) + { + var req, res; + var i; + var new_consigne; + + // Recherche de l'état actuel du circuity : + req = ' SELECT Consigne, Old_consigne FROM TB_Circuits WHERE Cle_primaire=' + id_source + ' '; +//console.log("req = [ " + req + "; ]"); + res = bdd.requete_unique(req); + + // Détermination du nouvel état et mise à jour du modèle : + if (Number(res[0]) === 0) // Le circuit était Off : + { + if (Number(res[1]) === 0) new_consigne = 100; // Si OLD = 0, on passe la consigne à 100% + else new_consigne = Number(res[1]); // Sinon, on applique OLD à NEW + + // Mise à jour immédiate du modèle pour que l'affichage réagisse immédiatement sur tous les points correspondant à ce circuit : + for (i = 0; i < modele_liste_points.count; i ++) + { + if ( (modele_liste_points.get(i).type_source === shipheart_type_source_circuits) + && (modele_liste_points.get(i).id_source === id_source) ) + { + modele_liste_points.setProperty(i , "icone", "/images/" + shipheart_page_personnalisee_type_point_icones[shipheart_type_source_circuits][modele_liste_points.get(i).type_point]); + modele_liste_points.setProperty(i , "halo", true); + } + } + } + else + { + new_consigne = 0; // Le circuit était On : + + for (i = 0; i < modele_liste_points.count; i ++) + { + if ( (modele_liste_points.get(i).type_source === shipheart_type_source_circuits) + && (modele_liste_points.get(i).id_source === id_source) ) + { + modele_liste_points.setProperty(i , "icone", "/images/" + shipheart_page_personnalisee_type_point_icones[shipheart_type_source_circuits][0]); + modele_liste_points.setProperty(i , "halo", false); + } + } + } + + // Mise à jour dans la BDD : + req = "UPDATE TB_Circuits SET New_consigne=" + new_consigne + " WHERE Cle_primaire='" + id_source + "'"; +//console.log("Requête = [" + req + "]"); + bdd.requete_unique(req); + + synchro_bdd(shipheart_type_synchro_data); + } +} diff --git a/parametres.qml b/parametres.qml new file mode 100644 index 0000000..e0d3c6b --- /dev/null +++ b/parametres.qml @@ -0,0 +1,1302 @@ +import QtQuick 2.12 +import QtQuick.Controls 2.12 + +import qt.koriolan.shipheart 1.0 +import"fonctions_localisation.js" as Fonctions_localisation + + + +Shipheart_page { + id: page_parametres + + + // Mis en forme : + readonly property double pourcentage_largeur_colonne_1: 0.25 + readonly property double pourcentage_largeur_colonne_2: 0.25 + readonly property double pourcentage_largeur_colonne_3: 0.25 + readonly property double pourcentage_largeur_colonne_4: (1 - pourcentage_largeur_colonne_1 - pourcentage_largeur_colonne_2 - pourcentage_largeur_colonne_3) + readonly property int espace_colonnes_principales: 10 + readonly property double pourcentage_hauteur_ligne_haut: 0.4 + readonly property double pourcentage_hauteur_ligne_milieu: 0.4 + readonly property int espace_lignes_principales: 10 + readonly property double affichage_hauteur_utile: shipheart_hauteur_page - shipheart_hauteur_bandeau_haut - shipheart_hauteur_bandeau_bas - (3 * espace_lignes_principales) + + readonly property double pourcentage_bandeau_bas_largeur_zone_retour: 0.93 + readonly property double pourcentage_bandeau_bas_largeur_zone_parametres_avances: (1 - pourcentage_bandeau_bas_largeur_zone_retour) + + readonly property int langues_nombre_colonnes_affichage: 1 + readonly property int langues_nombre_lignes_affichage: 7 + + readonly property int temperatures_nombre_colonnes_affichage: 1 + readonly property int temperatures_nombre_lignes_affichage: 3 + + readonly property int volumes_nombre_colonnes_affichage: 1 + readonly property int volumes_nombre_lignes_affichage: 3 + + readonly property int affichage_nombre_colonnes_affichage: 1 + readonly property int affichage_nombre_lignes_affichage: 3 + + readonly property int date_heure_nombre_colonnes_affichage: 1 + readonly property int date_heure_nombre_lignes_affichage: 3 + + + + readonly property int periode_init_raffraichissement_parametres: 1 // En ms + readonly property int periode_raffraichissement_parametres: 1000 // En ms + + + // Affichage : + property int niveau_page: 0 + property bool bouton_bandeau_bas_zone_retour_actif: false + property bool bouton_bandeau_bas_zone_parametres_actif: false + + + + // Données : + property var table_backlight: [0, 13.75, 26.30, 37.85, 48.54, 58.50, 67.81, 76.55, 84.80, 92.60, 100.00] // Les valeurs correspondent à 0, 10%, 20%,... 90%, 100% + property var table_volume: [0, 30, 48, 60, 70, 79, 86, 91, 95, 98, 100] // Les valeurs correspondent à 0, 10%, 20%,... 90%, 100% + + // 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 + { + mise_a_jour_periodique(); + } + } + } + + // Titre de la page : + Shipheart_titre_1 {titre:qsTr("Paramètres"); hauteur: shipheart_hauteur_bandeau_haut} + + //------------------------------------------------------- + // Ecran Colonne 1 : + //------------------------------------------------------- + Rectangle { + id: zone_affichage_colonne_1 + x: 0 + y: shipheart_hauteur_bandeau_haut; + width: (shipheart_largeur_page * pourcentage_largeur_colonne_1) - (espace_colonnes_principales / 2); + height: affichage_hauteur_utile * (pourcentage_hauteur_ligne_haut + pourcentage_hauteur_ligne_milieu) + espace_lignes_principales; + color: "transparent" + + // Titre du paragrapahe : + Shipheart_titre_2 {titre:qsTr("Langue"); hauteur: shipheart_hauteur_titre_2} + + GridView { + id: grid_langues + x: 0 + y: shipheart_hauteur_titre_2 + width: parent.width + height: parent.height - shipheart_hauteur_titre_2; + cellWidth: parent.width / langues_nombre_colonnes_affichage; + cellHeight: height / langues_nombre_lignes_affichage; + 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_langues + + delegate: Item { + Rectangle { + x: 5 + width:grid_langues.cellWidth - 10 + height:grid_langues.cellHeight - 10 + color: actif ? shipheart_couleur_fond_bouton_actif : shipheart_couleur_fond_bouton + opacity: 0.5 + radius: shipheart_rayon_bouton + Text { + text: 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: actif ? Font.Bold : Font.Normal + color: couleur_blanc_casse + } + + MouseArea { + anchors.fill: parent + onClicked: { + shipheart_clic(); + mise_a_jour_langue(index); + } + } + } + } + ListModel { + id: modele_langues + } + } + } + + //------------------------------------------------------- + // Ecran Colonne 2 - Haut : + //------------------------------------------------------- + Rectangle { + id: zone_affichage_colonne_2_haut + x: (shipheart_largeur_page * pourcentage_largeur_colonne_1) + (espace_colonnes_principales / 2); + y: shipheart_hauteur_bandeau_haut; + width: (shipheart_largeur_page * pourcentage_largeur_colonne_2) - (espace_colonnes_principales / 2); + height: affichage_hauteur_utile * pourcentage_hauteur_ligne_haut; + color: "transparent" + + + // Titre du paragrapahe : + Shipheart_titre_2 {titre:qsTr("Températures")} + + GridView { + id: grid_temperatures + x: 0 + y: shipheart_hauteur_titre_2 + width: parent.width + height: parent.height - shipheart_hauteur_titre_2; + cellWidth: parent.width / temperatures_nombre_colonnes_affichage; + cellHeight: height / temperatures_nombre_lignes_affichage; + 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_temperatures + + delegate: Item { + Rectangle { + x: 5 + width:grid_temperatures.cellWidth - 10 + height:grid_temperatures.cellHeight - 10 + color: actif ? shipheart_couleur_fond_bouton_actif : shipheart_couleur_fond_bouton + opacity: 0.5 + radius: shipheart_rayon_bouton + Text { + text: 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: actif ? Font.Bold : Font.Normal + color: couleur_blanc_casse + } + + MouseArea { + anchors.fill: parent + onClicked: { + shipheart_clic(); + mise_a_jour_temperatures(index); + } + } + } + } + ListModel { + id: modele_temperatures + } + } + } + + //------------------------------------------------------- + // Ecran Colonne 2 - Bas : + //------------------------------------------------------- + Rectangle { + id: zone_affichage_colonne_2_bas + + x: (shipheart_largeur_page * pourcentage_largeur_colonne_1) + (espace_colonnes_principales / 2); + y: shipheart_hauteur_bandeau_haut + zone_affichage_colonne_2_haut.height + espace_lignes_principales; + width: (shipheart_largeur_page * pourcentage_largeur_colonne_2) - (espace_colonnes_principales / 2); + height: affichage_hauteur_utile * pourcentage_hauteur_ligne_milieu; + color: "transparent" + + // Titre du paragrapahe : + Shipheart_titre_2 {titre:qsTr("Volumes")} + + GridView { + id: grid_volumes + x: 0 + y: shipheart_hauteur_titre_2 + width: parent.width + height: parent.height - shipheart_hauteur_titre_2; + cellWidth: parent.width / volumes_nombre_colonnes_affichage; + cellHeight: height / volumes_nombre_lignes_affichage; + 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_volumes + + delegate: Item { + Rectangle { + x: 5 + width:grid_volumes.cellWidth - 10 + height:grid_volumes.cellHeight - 10 + color: actif ? shipheart_couleur_fond_bouton_actif : shipheart_couleur_fond_bouton + opacity: 0.5 + radius: shipheart_rayon_bouton + Text { + text: 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: actif ? Font.Bold : Font.Normal + color: couleur_blanc_casse + } + + MouseArea { + anchors.fill: parent + onClicked: { + shipheart_clic(); + mise_a_jour_volumes(index); + } + } + } + } + ListModel { + id: modele_volumes + } + } + } + + //------------------------------------------------------- + // Ecran Colonne 3 - Haut : + //------------------------------------------------------- + Rectangle { + id: zone_affichage_colonne_3_haut + + x: (shipheart_largeur_page * (pourcentage_largeur_colonne_1 + pourcentage_largeur_colonne_2)) + (espace_colonnes_principales / 2); + y: shipheart_hauteur_bandeau_haut; + width: (shipheart_largeur_page * pourcentage_largeur_colonne_3) - (espace_colonnes_principales / 2); + height: affichage_hauteur_utile * pourcentage_hauteur_ligne_haut; + color: "transparent" + visible: (shipheart_type_installation === shipheart_type_installation_shipbase) + + // Titre du paragrapahe : + Shipheart_titre_2 {titre:qsTr("Affichage"); hauteur: shipheart_hauteur_titre_2} + + GridView { + id: grid_affichage + x: 0 + y: shipheart_hauteur_titre_2 + width: parent.width + height: parent.height - shipheart_hauteur_titre_2; + cellWidth: parent.width / affichage_nombre_colonnes_affichage; + cellHeight: height / affichage_nombre_lignes_affichage; + 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_affichage + + delegate: Item { + Rectangle { + x: 5 + width:grid_affichage.cellWidth - 10 + height:grid_affichage.cellHeight - 10 + color: actif ? shipheart_couleur_fond_bouton_actif : shipheart_couleur_fond_bouton + opacity: 0.5 + radius: shipheart_rayon_bouton + Text { + text: actif ? texte_actif : texte_inactif + 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: actif ? Font.Bold : Font.Normal + color: couleur_blanc_casse + } + + MouseArea { + anchors.fill: parent + onClicked: { + shipheart_clic(); + mise_a_jour_affichage(model.index); + } + } + } + } + ListModel { + id: modele_affichage + } + } + } + + //------------------------------------------------------- + // Ecran Colonne 3 - Bas : + //------------------------------------------------------- + Rectangle { + id: zone_affichage_colonne_3_bas + + x: (shipheart_largeur_page * (pourcentage_largeur_colonne_1 + pourcentage_largeur_colonne_2)) + (espace_colonnes_principales / 2); + y: shipheart_hauteur_bandeau_haut + zone_affichage_colonne_3_haut.height + espace_lignes_principales; + width: (shipheart_largeur_page * pourcentage_largeur_colonne_3) - (espace_colonnes_principales / 2); + height: affichage_hauteur_utile * pourcentage_hauteur_ligne_milieu; + color: "transparent" + + // Titre du paragrapahe : + Shipheart_titre_2 {titre:qsTr("Date et heure")} + + GridView { + id: grid_date_heure + x: 0 + y: shipheart_hauteur_titre_2 + width: parent.width + height: parent.height - shipheart_hauteur_titre_2; + cellWidth: parent.width / date_heure_nombre_colonnes_affichage; + cellHeight: height / date_heure_nombre_lignes_affichage; + 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_date_heure + + delegate: Item { + Rectangle { + x: 5 + width:grid_date_heure.cellWidth - 10 + height:grid_date_heure.cellHeight - 10 + color: actif ? shipheart_couleur_fond_bouton_actif : shipheart_couleur_fond_bouton + opacity: 0.5 + radius: shipheart_rayon_bouton + Text { + text: actif ? texte_actif : texte_inactif + 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: actif ? Font.Bold : Font.Normal + color: couleur_blanc_casse + } + + MouseArea { + anchors.fill: parent + onClicked: { + shipheart_clic(); + mise_a_jour_date_heure(model.index); + } + } + } + } + ListModel { + id: modele_date_heure + } + } + } + + + //------------------------------------------------------- + // Ecran Colonne 4 : + //------------------------------------------------------- + Rectangle { + id: zone_affichage_colonne_4 + + x: (shipheart_largeur_page * (pourcentage_largeur_colonne_1 + pourcentage_largeur_colonne_2 + pourcentage_largeur_colonne_3)) + (espace_colonnes_principales / 2); + y: shipheart_hauteur_bandeau_haut; + width: (shipheart_largeur_page * pourcentage_largeur_colonne_4) - (espace_colonnes_principales / 2); + height: affichage_hauteur_utile * (pourcentage_hauteur_ligne_haut + pourcentage_hauteur_ligne_milieu) + espace_lignes_principales; + + color: "transparent" + + // Titre du paragrapahe : + Shipheart_titre_2 {titre:qsTr("Protection"); hauteur: shipheart_hauteur_titre_2; visible: (modele_parametres_4.count > 0) ? true : false} + + GridView { + id: grid_parametres_4 + x: 0 + y: shipheart_hauteur_titre_2 + width: parent.width + height: parent.height - shipheart_hauteur_titre_2; + cellWidth: parent.width / langues_nombre_colonnes_affichage; + cellHeight: height / langues_nombre_lignes_affichage; + 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_parametres_4 + + delegate: Item { + Rectangle { + x: 5 + width:grid_affichage.cellWidth - 10 + height:grid_affichage.cellHeight - 10 + color: actif ? shipheart_couleur_fond_bouton_actif : shipheart_couleur_fond_bouton + opacity: 0.5 + radius: shipheart_rayon_bouton + Text { + text: actif ? texte_actif : texte_inactif + 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: actif ? Font.Bold : Font.Normal + color: couleur_blanc_casse + } + + MouseArea { + anchors.fill: parent + onClicked: { + shipheart_clic(); +//A supprimer probablement changer_validation_economiseur(); + mise_a_jour_parametre_4(nom); + } + } + } + } + ListModel { + id: modele_parametres_4 + } + } + } + + + //------------------------------------------------------- + // Ecran bas - Gauche : + //------------------------------------------------------- + Rectangle { + id: zone_affichage_bas_gauche + x: 0; + y: shipheart_hauteur_bandeau_haut + zone_affichage_colonne_1.height + espace_lignes_principales; + width: (shipheart_largeur_page * (pourcentage_largeur_colonne_1 + pourcentage_largeur_colonne_2)) - (espace_colonnes_principales / 2) + height: affichage_hauteur_utile * (1 - pourcentage_hauteur_ligne_haut - pourcentage_hauteur_ligne_milieu) + 5; // +5 pour compenser margin-top du bandeau bas + color: "transparent" + visible: (shipheart_type_installation === shipheart_type_installation_shipbase) + + // Titre du paragraphe : + Shipheart_titre_2 {titre:qsTr("Son")} + + Slider { + id: slider_volume + + y: shipheart_hauteur_titre_2 + width: parent.width * 0.9 + height: (parent.height - shipheart_hauteur_titre_2) * 0.8 + padding: 0 + anchors { + horizontalCenter: parent.horizontalCenter + } + from: 0 + value: 25 + to: 100 + stepSize:1 // Permet de n'avoir que des valeurs en %, sans décimales (il est probable que cela accélère le traitement mais pas vérifié...) + + background: Rectangle { + x: parent.leftPadding + y: 0 + width: parent.width + height: parent.height + radius: shipheart_rayon_bouton + color: shipheart_couleur_fond_bouton + + Rectangle { + width: slider_volume.visualPosition * parent.width + height: parent.height + color: shipheart_couleur_fond_bouton_actif + radius: shipheart_rayon_bouton + Behavior on width { + NumberAnimation { + properties:"width" + duration: 350 + easing.type: Easing.OutQuad + } + } + + Text { // Affichage de la valeur dans la barre lorsque le circuit est ON : + text: slider_volume.value.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: 18 + font.weight: Font.Bold + color: shipheart_couleur_texte_slider + visible: (slider_volume.value === 0) ? false : true + } + } + } + + handle: Rectangle { + x: parent.leftPadding + (parent.visualPosition * (parent.availableWidth - width)) + y: (parent.availableHeight / 2) - (height / 2) + implicitWidth: 80 // Le bouton n'étant pas visible + implicitHeight: parent.height + color: couleur_rouge_transparent + visible: (slider_volume.value === 0) ? true : false + + Text { // Affichage de la valeur dans le bouton lorsque le circuit est OFF : + text: "Off" + 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: 18 + font.weight: Font.Bold + color: couleur_rouge + visible: (slider_volume.value === 0) ? true : false + } + } + onMoved: { +// shipheart_clic(); // SDIR #145 + reload_economiseur(); // SDIR #145 Permet de réarmer l'économiseur mais par démettre de bip qui viendrait perturber les bips de réglage de niveau sonore. + if (!timer_time_out_volume.running) + { + timer_time_out_volume.running = true + + var req + req = 'UPDATE TB_Configuration SET Valeur="' + consigne_volume(slider_volume.value) + '" WHERE Nom="Consigne_volume" ' + bdd.requete_unique(req); + synchro_bdd(shipheart_type_synchro_data); +//console.log("ON MOVED : Nouvelle valeur de Volume = " + slider_volume.value + "% et la requête est : " + req) + } + } + Timer { // Timer qui permet de brider les envoi de mise à jour dans la BDD + id: timer_time_out_volume + interval: 400 + triggeredOnStart: false + running: false + repeat: false + onTriggered: { // Permet d'être sûr que la dernière position est bien enregistrée dans la BDD, même si l'arrêt s'est produit pendant que le timer tournait + var req + req = 'UPDATE TB_Configuration SET Valeur="' + consigne_volume(slider_volume.value) + '" WHERE Nom="Consigne_volume" ' + bdd.requete_unique(req); + synchro_bdd(shipheart_type_synchro_data); +//console.log("TIMER : Nouvelle valeur de Volume = " + slider_volume.value + "% et la requête est : " + req) + } + } + } + } + + //------------------------------------------------------- + // Ecran bas - Droite : + //------------------------------------------------------- + Rectangle { + id: zone_affichage_bas_droite + x: zone_affichage_bas_gauche.width + (espace_colonnes_principales / 2) + y: shipheart_hauteur_bandeau_haut + zone_affichage_colonne_1.height + espace_lignes_principales; + width: (shipheart_largeur_page * (pourcentage_largeur_colonne_3 + pourcentage_largeur_colonne_4)) - (espace_colonnes_principales / 2) + height: affichage_hauteur_utile * (1 - pourcentage_hauteur_ligne_haut - pourcentage_hauteur_ligne_milieu) + 5; // +5 pour compenser margin-top du bandeau bas + color: "transparent" + visible: (shipheart_type_installation === shipheart_type_installation_shipbase) + + // Titre du paragraphe : + Shipheart_titre_2 {titre:qsTr("Luminosité")} + + Slider { + id: slider_backlight + + y: shipheart_hauteur_titre_2 + width: parent.width * 0.9 + height: (parent.height - shipheart_hauteur_titre_2) * 0.8 + padding: 0 + anchors { + horizontalCenter: parent.horizontalCenter + } + from: 20 + value: 25 + to: 100 + stepSize:1 // Permet de n'avoir que des valeurs en %, sans décimales (il est probable que cela accélère le traitement mais pas vérifié...) + + background: Rectangle { + x: parent.leftPadding + y: 0 + width: parent.width + height: parent.height + radius: shipheart_rayon_bouton + color: shipheart_couleur_fond_bouton + + Rectangle { + width: slider_backlight.visualPosition * parent.width + height: parent.height + color: shipheart_couleur_fond_bouton_actif + radius: shipheart_rayon_bouton + Behavior on width { + NumberAnimation { + properties:"width" + duration: 350 + easing.type: Easing.OutQuad + } + } + + Text { // Affichage de la valeur dans la barre + text: slider_backlight.value.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: 18 + font.weight: Font.Bold + color: shipheart_couleur_texte_slider + } + } + } + + handle: Rectangle { + x: parent.leftPadding + (parent.visualPosition * (parent.availableWidth - width)) + y: (parent.availableHeight / 2) - (height / 2) + implicitWidth: 80 // Le bouton n'étant pas visible + implicitHeight: parent.height + color: "transparent" + visible: false + } + onMoved: { + shipheart_clic(); + if (!timer_time_out_backlight.running) + { + timer_time_out_backlight.running = true + + var req + req = 'UPDATE TB_Configuration SET Valeur="' + consigne_backlight(slider_backlight.value) + '" WHERE Nom="Consigne_backlight" ' + bdd.requete_unique(req); + synchro_bdd(shipheart_type_synchro_data); +console.log("ON MOVED : Nouvelle valeur de backlight = " + value + " et la requête est : " + req) + } + } + Timer { // Timer qui permet de brider les envoi de mise à jour dans la BDD + id: timer_time_out_backlight + interval: 400 + triggeredOnStart: false + running: false + repeat: false + onTriggered: { // Permet d'être sûr que la dernière position est bien enregistrée dans la BDD, même si l'arrêt s'est produit pendant que le timer tournait + var req + req = 'UPDATE TB_Configuration SET Valeur="' + consigne_backlight(slider_backlight.value) + '" WHERE Nom="Consigne_backlight" ' + bdd.requete_unique(req); + req = 'UPDATE TB_Configuration SET Valeur="' + consigne_backlight(slider_backlight.value) + '" WHERE Nom="Consigne_leds" ' + bdd.requete_unique(req); + synchro_bdd(shipheart_type_synchro_data); +//console.log("TIMER : Nouvelle valeur de backlight = " + slider_backlight.value + " et la requête est : " + req) + } + } + } + } + + + //------------------------------------------------------- + // Bandeau bas : + //------------------------------------------------------- + Row { + x: 0 + y: shipheart_hauteur_page - shipheart_hauteur_bandeau_bas; + width: shipheart_largeur_page; + height: shipheart_hauteur_bandeau_bas; + spacing: bandeau_bas_spacing * shipheart_largeur_page; + topPadding: 5 + bottomPadding:5 + + + //................................................. + // Bouton retour + //................................................. + Rectangle { + id: bandeau_bas_zone_retour + width: parent.width * 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 + + 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() + } + } + } + + //................................................. + // Paramètres avancés + //................................................. + Rectangle { + id: bandeau_bas_zone_parametres_avances + width: parent.width * pourcentage_bandeau_bas_largeur_zone_parametres_avances - (parent.spacing / 2) + height: shipheart_hauteur_bandeau_bas - parent.topPadding - parent.bottomPadding; //- (bandeau_bas_marge_verticale * 2); + radius: shipheart_rayon_bouton + color: shipheart_couleur_fond_bouton + + Rectangle { // Barre diminuant selon l'évolution du compteur de time-out d'accès + width: (shipheart_compteur_time_out_niveau_acces / shipheart_time_out_niveau_acces) * parent.width + height: parent.height + color: couleur_green_yellow_transparent + opacity: 0.5 + radius: shipheart_rayon_bouton + visible: (shipheart_time_out_niveau_acces > 0) && (shipheart_compteur_time_out_niveau_acces > 0) + } + + /* ChartView { + anchors { + horizontalCenter: parent.horizontalCenter + verticalCenter: parent.verticalCenter + } + width: parent.width * 1.1 + height: parent.height * 1.1 + legend.visible: false + antialiasing: true + backgroundColor: "transparent" + margins.bottom: 0 + margins.top: 0 + margins.left: 0 + margins.right: 0 + visible: (shipheart_time_out_niveau_acces > 0) && (shipheart_compteur_time_out_niveau_acces > 0) + PieSeries { + size: 1.0 + holeSize: 0.9 + startAngle: 0 + endAngle: visible ? (shipheart_compteur_time_out_niveau_acces * 360) / shipheart_time_out_niveau_acces : 0 + + PieSlice { + value: 2 + color: couleur_green_yellow + } + } + } +*/ + + Image { + id: image_parametres + source: (shipheart_compteur_time_out_niveau_acces === 0) && (shipheart_time_out_niveau_acces !== -1) ? "/images/icone_parametres.png" : "/images/icone_parametres_acces_autorise.png" + sourceSize.height: 25 + anchors { + verticalCenter: parent.verticalCenter + horizontalCenter: parent.horizontalCenter + } + } + + Image { + id: image_alarme_paramètres // Affichage du coin inférieur-droit en rouge si une erreur de paramètres est détectée + source: "/images/coin_bas_droite_rouge.png" + sourceSize.height: 20 + anchors { + bottom: parent.bottom + right: parent.right + } + visible: shipheart_defaut_config_k_bus + } + Image { + id: image_info_paramètres // Affichage du coin inférieur-droit en bleu si une nouvelle version est dispo + source: "/images/coin_bas_droite_bleu_koriolan.png" + sourceSize.height: 20 + anchors { + bottom: parent.bottom + right: parent.right + } + visible: !image_alarme_paramètres.visible && + ((shipheart_fichier_a_charger !== "") || (shipheart_fichier_a_valider !== "")) + } + +/* Text { // Affichage de la valeur dans la barre + text: (shipheart_compteur_time_out_niveau_acces > 59) ? (Math.trunc(shipheart_compteur_time_out_niveau_acces / 60) + " min " + (shipheart_compteur_time_out_niveau_acces % 60) + " s") : (shipheart_compteur_time_out_niveau_acces + " s") + anchors.fill: parent // Permet que le texte occupe tout l'espace du parent (et que le centrage vertical qui suit fonctionne...) +// bottomPadding: 5 + verticalAlignment: Text.AlignBottom + horizontalAlignment: Text.AlignHCenter + font.pixelSize: 10 + color: couleur_gris_tres_pale + visible: (shipheart_compteur_time_out_niveau_acces === 0) || (shipheart_time_out_niveau_acces === -1) ? false : 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. + id: mouse_area_bandeau_bas_zone_parametres + anchors.fill: parent + pressAndHoldInterval: shipheart_mouse_press_and_hold_interval_long + onClicked: { + shipheart_clic(); + +console.log("shipheart_compteur_time_out_niveau_acces = " + shipheart_compteur_time_out_niveau_acces + ", shipheart_time_out_niveau_acces = " + shipheart_time_out_niveau_acces + " et shipheart_niveau_acces_en_cours = " + shipheart_niveau_acces_en_cours) + + if (shipheart_time_out_niveau_acces === -1) // Cas où il n'y a aucune protection : + { +console.log("L'accès est validé sans entrer de code car 'time_out_access' = -1"); + shipheart_compteur_time_out_niveau_acces = 0; // ... le compteur est laissé à 0 car inutile, + shipheart_niveau_acces_en_cours = shipheart_niveau_acces_user; // ... et on donne un accès USER (si on veut accéder en Admin ou Koriolan, il faut d'abord revalider un contrôle d'accès) + } + + if(shipheart_niveau_acces_en_cours > shipheart_niveau_acces_aucun) stackView.push("parametres_avances.qml") + else stackView.push("protection.qml", {"protection_mode": protection_mode_access_parametres_avances}) + } + onPressAndHold: { + shipheart_compteur_time_out_niveau_acces = 0; // Dans le cas d'un appui long, on dévalide l'autorisation d'accès en cours... + shipheart_niveau_acces_en_cours = shipheart_niveau_acces_aucun; + } + } + } + } + + //------------------------------------------------------- + // Nettoyage de l'écran : + //------------------------------------------------------- + Shipheart_boite_dialogue_nettoyage_ecran { + id: boite_dialogue_nettoyage_ecran + onOpened: { + shipheart_flag_nettoyage_ecran_en_cours = true; + } + onClosed: { + shipheart_flag_nettoyage_ecran_en_cours = false; + } + } + + //=========================================================== + // 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 i; + + mise_en_veille(0); + niveau_page = stackView.depth - 1; // Permet de stocker le niveau de la page dans la Stackview + + //--------------------------------------------- + // Init des différentes modèles : + //--------------------------------------------- + init_modeles(); + + //--------------------------------------------- + // Init des paramètres d'accès : + //--------------------------------------------- + req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Time_out_acces" '; + res = bdd.requete_unique(req); + shipheart_time_out_niveau_acces = Number(res[0]); + + } + + //============================================================================================================= + // Init des modèles + //============================================================================================================= + function init_modeles() + { + var req, res; + var i; + + + //--------------------------------------------- + // Init des langues : + // NB : la valeur de 'shipheart_langue' a été initialisée dans 'home.qml' avec la valeur actuelle de TB_Configuration.Langue + //--------------------------------------------- + modele_langues.clear(); // RAZ des valeurs existantes + + for (i = 0; i < Fonctions_localisation.nb_langues(); i ++) + { + modele_langues.append({"nom": Fonctions_localisation.nom_langue(i), "code_langue": Fonctions_localisation.code_langue(i), "actif": (shipheart_langue === i)}); + } + + //--------------------------------------------- + // Init des températures : + // NB : la valeur de 'shipheart_unite_temperature' a été initialisée dans 'home.qml' avec la valeur actuelle de TB_Configuration.Unite_temperature + //--------------------------------------------- + modele_temperatures.clear(); // RAZ des valeurs existantes + + for (i = 0; i < Fonctions_localisation.nb_unites_temperature(); i ++) + { + modele_temperatures.append({"nom": Fonctions_localisation.nom_unite_temperature(i), "symbole": Fonctions_localisation.symbole_unite_temperature(i), "actif": (shipheart_unite_temperature === i)}); + } + + //--------------------------------------------- + // Init des volumes : + // NB : la valeur de 'shipheart_unite_volume' a été initialisée dans 'home.qml' avec la valeur actuelle de TB_Configuration.Unite_volume + //--------------------------------------------- + modele_volumes.clear(); // RAZ des valeurs existantes + + for (i = 0; i < Fonctions_localisation.nb_unites_volume(); i ++) + { + modele_volumes.append({"nom": Fonctions_localisation.nom_unite_volume(i), "symbole": Fonctions_localisation.symbole_unite_volume(i), "actif": (shipheart_unite_volume === i)}); + } + + + //--------------------------------------------------- + // Init des paramètres des la 3ième colonne - haut : + //--------------------------------------------------- + modele_affichage.clear(); + modele_affichage.append({"nom": "Validation_economiseur", "texte_actif": qsTr("Economiseur d'écran : désactivé"), "texte_inactif": qsTr("Economiseur d'écran : normal"), "actif": !get_validation_economiseur()}); + modele_affichage.append({"nom": "Validation_leds", "texte_actif": qsTr("Flash LEDs : désactivé"), "texte_inactif": qsTr("Flash LEDs : normal"), "actif": !get_validation_leds()}); + modele_affichage.append({"nom": "Nettoyage_ecran", "texte_actif": qsTr("Nettoyage de l'écran"), "texte_inactif": qsTr("Nettoyage de l'écran"), "actif": false}); + + //------------------------------------------------- + // Init des paramètres des la 3ième colonne - bas : + //------------------------------------------------- + modele_date_heure.clear(); + modele_date_heure.append({"nom": "Heure_ete", "texte_actif": qsTr("Heure d'été"), "texte_inactif": qsTr("Heure d'hiver"), "actif": (shipheart_heure_ete === 0 ? false : true)}); + + + //--------------------------------------------- + // Init des paramètres des la 4ième colonne : + //--------------------------------------------- + modele_parametres_4.clear(); + if (Number(shipheart_specifique_client[0]) === shipheart_specifique_client_suncy) modele_parametres_4.append({"nom": "retour_home_suncy", "texte_actif": qsTr("Verrouiller le bateau"), "texte_inactif": qsTr("Verrouiller le bateau"), "actif": false}); + + mise_a_jour_slider_backlight(); + mise_a_jour_slider_volume(); + } + + //============================================================================================================= + // Mise à jour périodique + //============================================================================================================= + function mise_a_jour_periodique() + { + var req, res; + + //----------------------------------------- + // Etat config K-bus : + req = 'SELECT Valeur FROM TB_Systeme WHERE Nom="Defaut_config_k_bus" '; + res = bdd.requete_unique(req); + shipheart_defaut_config_k_bus = Number(res[0]); + } + + //============================================================================================================= + // Mise à jour de la langue + //============================================================================================================= + function mise_a_jour_langue(rang) + { + var i; + var req; + + + // Recherche dans le modèle de l'entrée correspondant à l'entrée sélectionnée : + for (i = 0; i < modele_langues.count; i ++) + { + if (i === rang) modele_langues.setProperty(i, "actif", true); // Passage de l'entrée en actif (pour visu) + else modele_langues.setProperty(i, "actif", false); // Passage de toutes les autres entrées à inactif (pour visu) + } + + // Mise à jour de la langue en cours dans TB_Configuration : + req = 'UPDATE TB_Configuration SET Valeur="' + rang + '" WHERE Nom="Langue" ' + bdd.requete_unique(req); + + shipheart_langue = rang; + shipheart_code_pays = Fonctions_localisation.code_pays(shipheart_langue); + shipheart_code_langue = Fonctions_localisation.code_langue(shipheart_langue); + +console.log("==================> AVANT") + backend.change_langue(shipheart_code_langue); +console.log("==================> APRES") + + init_modeles(); // Permet que les modèles d'affichage de la page soient mis à jour avec la nouvelle langue... + } + + //============================================================================================================= + // Mise à jour de l'unité de température + //============================================================================================================= + function mise_a_jour_temperatures(rang) + { + var i; + var req; + + // Recherche dans le modèle de l'entrée correspondant à l'entrée sélectionnée : + for (i = 0; i < modele_temperatures.count; i ++) + { + if (i === rang) modele_temperatures.setProperty(i, "actif", true); // Passage de l'entrée en actif (pour visu) + else modele_temperatures.setProperty(i, "actif", false); // Passage de toutes les autres entrées à inactif (pour visu) + } + + shipheart_unite_temperature = rang; + shipheart_unite_temperature_symbole = modele_temperatures.get(rang).symbole; + + // Mise à jour de l'unité de température en cours dans TB_Configuration : + req = 'UPDATE TB_Configuration SET Valeur="' + rang + '" WHERE Nom="Unite_temperature" ' + //console.log("Requête = [" + req + "]"); + bdd.requete_unique(req); + } + + + //============================================================================================================= + // Mise à jour de l'unité de volumes + //============================================================================================================= + function mise_a_jour_volumes(rang) + { + var i; + var req; + + // Recherche dans le modèle de l'entrée correspondant à l'entrée sélectionnée : + for (i = 0; i < modele_volumes.count; i ++) + { + if (i === rang) modele_volumes.setProperty(i, "actif", true); // Passage de l'entrée en actif (pour visu) + else modele_volumes.setProperty(i, "actif", false); // Passage de toutes les autres entrées à inactif (pour visu) + } + + shipheart_unite_volume = rang; + shipheart_unite_volume_symbole = modele_volumes.get(rang).symbole; + + // Mise à jour de l'unité de volumes en cours dans TB_Configuration : + req = 'UPDATE TB_Configuration SET Valeur="' + rang + '" WHERE Nom="Unite_volume" ' + bdd.requete_unique(req); + } + + //============================================================================================================= + // Mise à jour des paramètrs de la 3ième colonne - haut + //============================================================================================================= + function mise_a_jour_affichage(index) + { + var i; + var nb; + + // Mise à jour du paramètre ayant été touché dans la BDD : + if (modele_affichage.get(index).nom === "Validation_economiseur") changer_validation_economiseur(); + else if (modele_affichage.get(index).nom === "Validation_leds") changer_validation_leds(); + else if (modele_affichage.get(index).nom === "Nettoyage_ecran") boite_dialogue_nettoyage_ecran.open(); + + // Mise à jour de l'état de chaque paramètres : + nb = modele_affichage.count; + + for (i = 0; i < nb; i ++) + { + if (modele_affichage.get(i).nom === "Validation_economiseur") modele_affichage.setProperty(i, "actif", !get_validation_economiseur()); + else if (modele_affichage.get(i).nom === "Validation_leds") modele_affichage.setProperty(i, "actif", !get_validation_leds()); + } + } + + //============================================================================================================= + // Mise à jour des paramètrs de la 3ième colonne - bas + //============================================================================================================= + function mise_a_jour_date_heure(index) + { + var i; + var nb; + + + // Mise à jour du paramètre ayant été touché dans la BDD : + if (modele_date_heure.get(index).nom === "Heure_ete") + { + if (shipheart_heure_ete === 0) mise_a_jour_heure_ete(1); + else mise_a_jour_heure_ete(0); + } + + // Mise à jour de l'état de chaque paramètres : + nb = modele_date_heure.count; + + for (i = 0; i < nb; i ++) + { + if (modele_date_heure.get(i).nom === "Heure_ete") modele_date_heure.setProperty(i, "actif", (shipheart_heure_ete === 0 ? false : true)); + } + } + + //============================================================================================================= + // Mise à jour des paramètres de la 4ième colonne + //============================================================================================================= + function mise_a_jour_parametre_4(nom) + { + var res; + var nb; + var i; + + nb = modele_parametres_4.count; + + for (i = 0; i < nb; i ++) + { + switch (modele_parametres_4.get(i).nom) + { + //-------------------------------------- + case "retour_home_suncy": + + // Désactivation 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=0 WHERE Cle_primaire='" + Number(parametre[1]) + "' ") + break; // Inutile d'aller plus loin... + } + } + + // Coupure de tous les circuits par défaut : + // bdd.requete_unique('UPDATE TB_Circuits SET New_consigne=0 '); + + + stackView.pop(null); // retour directement à la page "home_attente.qml" qui va se charger de trouver la Home Page à utiliser et va la charger. + + break; + + default: + break; + + } + } + } + + + //============================================================================================================= + // Mise à jour du slider du backlight + //============================================================================================================= + function mise_a_jour_slider_backlight() + { + var res; + +//var i; +//for (i = 0; i < 11; i ++) +//{ +// console.log("Table Backlight " + Number(i) + " = " + Number(table_backlight[i])); +//} + + // Récupération de la valeur actuelle du backlight : + var consigne; + var rang; + res = bdd.requete_unique('SELECT Valeur FROM TB_Configuration WHERE Nom="Consigne_backlight" '); + consigne = Number(res[0]); + + if (consigne < 0) rang = -1; + else if (consigne < table_backlight[1]) rang = 0; + else if (consigne < table_backlight[2]) rang = 1; + else if (consigne < table_backlight[3]) rang = 2; + else if (consigne < table_backlight[4]) rang = 3; + else if (consigne < table_backlight[5]) rang = 4; + else if (consigne < table_backlight[6]) rang = 5; + else if (consigne < table_backlight[7]) rang = 6; + else if (consigne < table_backlight[8]) rang = 7; + else if (consigne < table_backlight[9]) rang = 8; + else if (consigne < table_backlight[10]) rang = 9; + else if (consigne < table_backlight[11]) rang = 10; + else rang = 11; + + if (rang < 0) slider_backlight.value = 0; + else if (rang > 10) slider_backlight.value = 100; + else slider_backlight.value = (10 * (rang + 1)) - (10 * (table_backlight[rang + 1] - consigne) / (table_backlight[rang + 1] - table_backlight[rang])); + } + + //============================================================================================================= + // Calcul de la consigne du backlight en fonction de la position du slider + //============================================================================================================= + function consigne_backlight(pc) + { + var i; + var a, b; + var val; + + if (pc <= 0) return (0); + if (pc >= 100) return (100); + + i = Math.trunc(pc / 10); + +//console.log("Conversion Backlight : PC=" + Number(pc) + " i=" + Number(i) + " et valeur de retour =" + (((table_backlight[i+1] - table_backlight[i]) * (pc % 10) / 10) + table_backlight[i])); + return ((table_backlight[i+1] - table_backlight[i]) * (pc % 10) / 10) + table_backlight[i]; + } + + //================================================================================================= + // Fonction : Retourne l'état actuel de la consigne des LEDs + //================================================================================================= + function get_validation_leds() + { + var req, res; + + req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Validation_leds" '; + res = bdd.requete_unique(req); + + return(Number(res[0])); + } + + //================================================================================================= + // Fonction : Change l'état de la validation des LEDs + //================================================================================================= + function changer_validation_leds() + { + var req, res; + var new_val; + + req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Validation_leds" '; + 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="Validation_leds" '); + } + + //================================================================================================= + // Fonction : Mise à jour de la valeur d'heure d'été dans TB_Configuration + //================================================================================================= + function mise_a_jour_heure_ete(heure_ete) + { + var req, res; + var new_val; + + if ((heure_ete === 0) || (heure_ete === 1)) shipheart_heure_ete = heure_ete; + else shipheat_heure_ete = 0; + + req = 'UPDATE TB_Configuration '; + req += ' SET Valeur="' + shipheart_heure_ete + '" '; + req += ' WHERE Nom="Heure_ete" '; +//console.log("Requête = " + req) + bdd.requete_unique(req); + } + + //============================================================================================================= + // Mise à jour du slider du volume + //============================================================================================================= + function mise_a_jour_slider_volume() + { + var res; + +//var i; +//for (i = 0; i < 11; i ++) +//{ +// console.log("Table Volume " + Number(i) + " = " + Number(table_volume[i])); +//} + + // Récupération de la valeur actuelle du Volume : + var consigne; + var rang; + res = bdd.requete_unique('SELECT Valeur FROM TB_Configuration WHERE Nom="Consigne_volume" '); + consigne = Number(res[0]); + + if (consigne < 0) rang = -1; + else if (consigne < table_volume[1]) rang = 0; + else if (consigne < table_volume[2]) rang = 1; + else if (consigne < table_volume[3]) rang = 2; + else if (consigne < table_volume[4]) rang = 3; + else if (consigne < table_volume[5]) rang = 4; + else if (consigne < table_volume[6]) rang = 5; + else if (consigne < table_volume[7]) rang = 6; + else if (consigne < table_volume[8]) rang = 7; + else if (consigne < table_volume[9]) rang = 8; + else if (consigne < table_volume[10]) rang = 9; + else if (consigne < table_volume[11]) rang = 10; + else rang = 11; + + if (rang < 0) slider_volume.value = 0; + else if (rang > 10) slider_volume.value = 100; + else slider_volume.value = (10 * (rang + 1)) - (10 * (table_volume[rang + 1] - consigne) / (table_volume[rang + 1] - table_volume[rang])); + } + + //============================================================================================================= + // Calcul de la consigne du Volume en fonction de la position du slider + //============================================================================================================= + function consigne_volume(pc) + { + var i; + var a, b; + var val; + + if (pc <= 0) return (0); + if (pc >= 100) return (100); + + i = Math.trunc(pc / 10); + +//console.log("Conversion Volume : PC=" + Number(pc) + " i=" + Number(i) + " et valeur de retour =" + (((table_volume[i+1] - table_volume[i]) * (pc % 10) / 10) + table_volume[i])); + return ((table_volume[i+1] - table_volume[i]) * (pc % 10) / 10) + table_volume[i]; + } + +} diff --git a/parametres_avances.qml b/parametres_avances.qml new file mode 100644 index 0000000..a55d7e7 --- /dev/null +++ b/parametres_avances.qml @@ -0,0 +1,672 @@ +import QtQuick 2.12 +import QtQuick.Controls 2.12 + +import qt.koriolan.shipheart 1.0 + + + +Shipheart_page { + id: page_parametres_avances + + + // Mis en forme : + readonly property int menu_nombre_colonnes: 4 + readonly property int menu_espace_colonnes: 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: 0.86 + + readonly property int nombre_menus_affiches_sur_une_colonne: 8 + + readonly property int periode_init_raffraichissement_parametres: 1 // En ms + readonly property int periode_raffraichissement_parametres: 1000 // En ms + readonly property int step_timer_reset: 10 // en ms + + + + // Affichage : + property int niveau_page: 0 + property bool bouton_bandeau_bas_zone_retour_actif: false + property bool flag_nouvelle_version: false // Permet de mémoriser et donc détecter un changement + + + // Données : + property int valeur_timer_reset: 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(); + } + + if (stackView.depth === (niveau_page + 1)) // Désactive le raffraichissement quand la page n'est pas activée dans la pile + { + mise_a_jour_periodique(); + } + } + } + + //=========================================================== + // Timer pour gérer l'appui long du reboot : + //=========================================================== + Timer { + id: timer_reset + interval: step_timer_reset + triggeredOnStart: false + repeat: true + onTriggered: { + if (valeur_timer_reset < shipheart_mouse_press_and_hold_interval_tres_long) valeur_timer_reset+= step_timer_reset; + else // Le fait de ne pas utilise le OnPressandHold permet d'être sûr que le reset se fait au même moment que la fin du comptage (sinon, on peut avoir de petits décalages) + { + timer_reset.running = false; + valeur_timer_reset = 0; + + shipheart_clic(); + + boite_validation_securisee.niveau = 2; + boite_validation_securisee.boutonOk = false + boite_validation_securisee.boutonAnnuler = true + boite_validation_securisee.boutonSecurise = true + boite_validation_securisee.boutonSecuriseTexte = qsTr("Confirmer"); + boite_validation_securisee.imageTitreSource = "/images/attention.png"; + boite_validation_securisee.message = qsTr("Redémarrage

Si vous confirmez, ShipHeart va redémarrer.
Pendant ce redémarrage (environ une minute), votre système ShipHeart ne sera pas accessible ! ") + boite_validation_securisee.alignementMessage = Text.AlignHCenter + boite_validation_securisee.affichageAscenseur = true; + boite_validation_securisee.open(); + } + } + } + + + //=========================================================== + // Actions avant l'affichage proprement dit : + //=========================================================== + StackView.onActivating: { // Permet que lors du retour sur la page, un traitement soit fait avant l'affichage proprement dit + init_page(); + } + + //=========================================================== + // Titre de la page : + //=========================================================== + Shipheart_titre_1 {titre:qsTr("Paramètres avancés"); hauteur: shipheart_hauteur_bandeau_haut} + + //------------------------------------------------------- + // Ecran Principal Gauche : + //------------------------------------------------------- + Rectangle { + id: zone_affichage_gauche + x: (0 * shipheart_largeur_page / menu_nombre_colonnes) + (menu_espace_colonnes / 2) + y: shipheart_hauteur_bandeau_haut + width: (shipheart_largeur_page / menu_nombre_colonnes) - menu_espace_colonnes + height: affichage_hauteur_utile + color: "transparent" + + + Shipheart_titre_2 {titre:qsTr("Votre installation"); hauteur: shipheart_hauteur_bandeau_haut} + + ListView { + id: liste_menu_gauche + + y : shipheart_hauteur_bandeau_haut + width: parent.width + height: parent.height - shipheart_hauteur_bandeau_haut + 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: liste_menu_gauche.width + height: (shipheart_niveau_acces_en_cours >= niveau_mini) ? (liste_menu_gauche.height / nombre_menus_affiches_sur_une_colonne) : 0 + color: "transparent" + visible: (shipheart_niveau_acces_en_cours >= niveau_mini) ? true : false + Rectangle { + width: parent.width + height: parent.height -10 + color: (libelle !== "") ? shipheart_couleur_fond_bouton : "transparent" + radius: shipheart_rayon_bouton + + //-------------------------------------------------------------------- + // 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 à gaiche (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: 10 + color: "transparent" + + Image { + source: "/images/" + model.icone + sourceSize.height: parent.height * 0.6 + sourceSize.width: parent.width + anchors { + verticalCenter: parent.verticalCenter + horizontalCenter: parent.horizontalCenter + } + visible: (model.icone !== "") + } + } + + //-------------------------------------------------------------------- + // Libellé du bouton : + Text { + anchors { + verticalCenter: parent.verticalCenter + horizontalCenter: parent.horizontalCenter + } + font.pixelSize: 20 + text: libelle; + color: couleur_blanc_casse + visible: (libelle !== "") ? true : false + } + + //-------------------------------------------------------------------- + // Triangle rouge en bas à droite : + Image { + source: alarme + sourceSize.height: 20 + anchors { + bottom: parent.bottom + right: parent.right + } + visible: alarme !== "" + } + + //-------------------------------------------------------------------- + // Zone de clic du bouton : + MouseArea { + anchors.fill: parent + visible: (libelle !== "") ? true : false + onClicked: { + shipheart_clic(); + if (page_cible !== "") + { + stackView.push(page_cible, param_cible); + } + else boite_information_en_travaux.open(); + } + } + } + } + ScrollBar.vertical: ScrollBar {} + } + } + + + //------------------------------------------------------- + // Ecran Principal Milieu Gauche : + //------------------------------------------------------- + Rectangle { + id: zone_affichage_milieu_gauche + x: (1 * shipheart_largeur_page / menu_nombre_colonnes) + (menu_espace_colonnes / 2) + y: shipheart_hauteur_bandeau_haut + width: (shipheart_largeur_page / menu_nombre_colonnes) - menu_espace_colonnes + height: affichage_hauteur_utile + color: "transparent" + + + Shipheart_titre_2 {titre:qsTr("Vos paramètres"); hauteur: shipheart_hauteur_bandeau_haut} + + ListView { + id: liste_menu_milieu_gauche + + y : shipheart_hauteur_bandeau_haut + width: parent.width + height: parent.height - shipheart_hauteur_bandeau_haut + 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: liste_menu_milieu_gauche.width + height: (shipheart_niveau_acces_en_cours >= niveau_mini) ? (liste_menu_milieu_gauche.height / nombre_menus_affiches_sur_une_colonne) : 0 + color: "transparent" + visible: (shipheart_niveau_acces_en_cours >= niveau_mini) ? true : false + Rectangle { + width: parent.width + height: parent.height -10 + color: (libelle !== "") ? shipheart_couleur_fond_bouton : "transparent" + radius: shipheart_rayon_bouton + Text { + anchors { + verticalCenter: parent.verticalCenter + horizontalCenter: parent.horizontalCenter + } + font.pixelSize: 20 + text: libelle; + color: couleur_blanc_casse + visible: (libelle !== "") ? true : false + } + MouseArea { + anchors.fill: parent + visible: (libelle !== "") ? true : false + onClicked: { + shipheart_clic(); + if (page_cible !== "") + { + stackView.push(page_cible, param_cible); + } + else boite_information_en_travaux.open(); + } + } + Image { + source: alarme + sourceSize.height: 20 + anchors { + bottom: parent.bottom + right: parent.right + } + visible: alarme !== "" + } + } + } + ScrollBar.vertical: ScrollBar {} + } + } + + + //------------------------------------------------------- + // Ecran Principal Milieu Droite : + //------------------------------------------------------- + Rectangle { + id: zone_affichage_milieu_droite + x: (2 * shipheart_largeur_page / menu_nombre_colonnes) + (menu_espace_colonnes / 2) + y: shipheart_hauteur_bandeau_haut + width: (shipheart_largeur_page / menu_nombre_colonnes) - menu_espace_colonnes + height: affichage_hauteur_utile + color: "transparent" + + + Shipheart_titre_2 {titre:qsTr("Réseaux"); hauteur: shipheart_hauteur_bandeau_haut} + + ListView { + id: liste_menu_milieu_droite + + y : shipheart_hauteur_bandeau_haut + width: parent.width + height: parent.height - shipheart_hauteur_bandeau_haut + 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: liste_menu_milieu_droite.width + height: (shipheart_niveau_acces_en_cours >= niveau_mini) ? (liste_menu_milieu_droite.height / nombre_menus_affiches_sur_une_colonne) : 0 + color: "transparent" + visible: (shipheart_niveau_acces_en_cours >= niveau_mini) ? true : false + Rectangle { + width: parent.width + height: parent.height -10 + color: shipheart_couleur_fond_bouton + radius: shipheart_rayon_bouton + Text { + anchors { + verticalCenter: parent.verticalCenter + horizontalCenter: parent.horizontalCenter + } + font.pixelSize: 20 + text: libelle; + color: couleur_blanc_casse + visible: (libelle !== "") ? true : false + } + MouseArea { + anchors.fill: parent + onClicked: { + shipheart_clic(); + if (page_cible !== "") + { + stackView.push(page_cible, param_cible); + } + else boite_information_en_travaux.open(); + } + } + Image { + source: alarme + sourceSize.height: 20 + anchors { + bottom: parent.bottom + right: parent.right + } + visible: alarme !== "" + } + } + } + ScrollBar.vertical: ScrollBar {} + } + } + + + //------------------------------------------------------- + // Ecran Principal Droite : + //------------------------------------------------------- + Rectangle { + id: zone_affichage_droite + x: (3 * shipheart_largeur_page / menu_nombre_colonnes) + (menu_espace_colonnes / 2) + y: shipheart_hauteur_bandeau_haut + width: (shipheart_largeur_page / menu_nombre_colonnes) - menu_espace_colonnes + height: affichage_hauteur_utile + color: "transparent" + + + Shipheart_titre_2 {titre:qsTr("Système"); hauteur: shipheart_hauteur_bandeau_haut} + + ListView { + id: liste_menu_droite + + y : shipheart_hauteur_bandeau_haut + width: parent.width + height: parent.height - shipheart_hauteur_bandeau_haut + 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: liste_menu_droite.width + height: (shipheart_niveau_acces_en_cours >= niveau_mini) ? (liste_menu_droite.height / nombre_menus_affiches_sur_une_colonne) : 0 + color: "transparent" + visible: (shipheart_niveau_acces_en_cours >= niveau_mini) ? true : false + Rectangle { + width: parent.width + height: parent.height -10 + color: shipheart_couleur_fond_bouton + radius: shipheart_rayon_bouton + Text { + anchors { + verticalCenter: parent.verticalCenter + horizontalCenter: parent.horizontalCenter + } + font.pixelSize: 20 + text: libelle; + color: couleur_blanc_casse + visible: (libelle !== "") ? true : false + } + MouseArea { + anchors.fill: parent + onClicked: { + shipheart_clic(); + + if (page_cible !== "") + { + stackView.push(page_cible, param_cible); + } + else boite_information_en_travaux.open(); + } + } + Image { + source: alarme + sourceSize.height: 20 + anchors { + bottom: parent.bottom + right: parent.right + } + visible: alarme !== "" + } + } + } + ScrollBar.vertical: ScrollBar {} + } + } + + + + + //------------------------------------------------------- + // 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_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 Reset : + //................................................. + Rectangle { + id: bandeau_bas_zone_bouton_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_generation_shipbase >= shipheart_generation_shipbase_v2) && + (shipheart_type_installation === shipheart_type_installation_shipbase) + Rectangle { // Barre grandissante pour montrer durée d'appui vs tempo nécessaire : + width: (valeur_timer_reset / shipheart_mouse_press_and_hold_interval_tres_long) * parent.width + height: parent.height + color: couleur_rouge_transparent + radius: shipheart_rayon_bouton + visible: mousearea_reset.pressed + } + Image { + source: mousearea_reset.pressed ? "/images/reset_actif.png" : "/images/reset_sombre.png" + sourceSize.height: 30 + anchors { + verticalCenter: parent.verticalCenter + horizontalCenter: parent.horizontalCenter + } + } + MouseArea { + id: mousearea_reset + anchors.fill: parent + onPressed: { // Déclenché lors de l'appui inital + valeur_timer_reset = 0; + timer_reset.running = true; + } + onClicked: { // Déclenché si l'appui n'a pas été suffisement long pour avoir un Press&Hold : + timer_reset.running = false; + valeur_timer_reset = 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_reset.running = false; + valeur_timer_reset = 0; + } + } + } + } + + + //------------------------------------------------------- + // Boite en travaux : + //------------------------------------------------------- + Shipheart_boite_dialogue { + id: boite_information_en_travaux + niveau: 0 + imageTitreSource: "/images/cone_chantier.png"; + message: qsTr("Cette page est actuellement en travaux.
Elle sera rendue disponible très rapidement à travers une mise à jour.

Merci de votre patience...

L'équipe ShipHeart") + } + + + //------------------------------------------------------- + // 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 : + rebooter(); + break; + + case shipheart_boite_dialogue_bouton_2: // Annuler : on revient sur la page pour que l'on puisse enregistrer. + break; + + default: + } + boite_validation_securisee.close(); + } + } + + //=========================================================== + // 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() + { + + mise_en_veille(0); + niveau_page = stackView.depth - 1; // Permet de stocker le niveau de la page dans la Stackview + + shipheart_flag_blocage_compteurs_pendant_config = true; // Blocage du comptage pendant tout le temps où on est en config (SDIR #187) + + //----------------------------------------- + // Nouvelle version : + if ((shipheart_fichier_a_charger !== "") || (shipheart_fichier_a_valider !== "")) flag_nouvelle_version = true; + else flag_nouvelle_version = false; + + //------------------------------------- + // Menu de gauche : + //------------------------------------- + liste_menu_gauche.model.clear(); + liste_menu_gauche.model.append({ libelle: qsTr("Circuits"), page_cible: "config_circuits.qml", param_cible: {}, icone: "icone_consommation_electrique.png", niveau_mini: 0, alarme: "" }); + liste_menu_gauche.model.append({ libelle: qsTr("Réservoirs"), page_cible: "config_reservoirs.qml", param_cible: {}, icone: "reservoir_eau.png", niveau_mini: 0, alarme: "" }); + liste_menu_gauche.model.append({ libelle: qsTr("Batteries"), page_cible: "config_batteries.qml", param_cible: {}, icone: "batterie_moyen.png", niveau_mini: 0, alarme: "" }); + liste_menu_gauche.model.append({ libelle: qsTr("Capteurs"), page_cible: "config_capteurs.qml", param_cible: {}, icone: "icone_auxiliaires.png", niveau_mini: 0, alarme: "" }); + liste_menu_gauche.model.append({ libelle: qsTr("Evènements"), page_cible: "config_events.qml", param_cible: {}, icone: "event.png", niveau_mini: 0, alarme: "" }); +//liste_menu_gauche.model.append({ libelle: qsTr("TEST"), page_cible: "test_batterie.qml", param_cible: {}, niveau_mini: 0 }); +//liste_menu_gauche.model.append({ libelle: qsTr("TEST"), page_cible: "test_tri_liste.qml", param_cible: {}, niveau_mini: 0 }); + + //------------------------------------- + // Menu de milieu gauche : + //------------------------------------- + liste_menu_milieu_gauche.model.clear(); + liste_menu_milieu_gauche.model.append({ libelle: qsTr("Affichage"), page_cible: "config_affichage.qml", param_cible: {}, niveau_mini: 0, alarme: "" }); + liste_menu_milieu_gauche.model.append({ libelle: qsTr("Image d'accueil"), page_cible: "config_fichiers.qml", param_cible: {"mode_config_fichiers": shipheart_mode_config_fichiers_image_accueil}, niveau_mini: 0, alarme: "" }); + liste_menu_milieu_gauche.model.append({ libelle: qsTr("Pages personnalisées"), page_cible: "config_pages.qml", param_cible: {}, niveau_mini: 0, alarme: "" }); + liste_menu_milieu_gauche.model.append({ libelle: qsTr("Audio"), page_cible: "config_audio.qml", param_cible: {}, niveau_mini: 0, alarme: "" }); +// liste_menu_milieu_gauche.model.append({ libelle: qsTr("Evènements"), page_cible: "config_events.qml", param_cible: {}, niveau_mini: 0, alarme: "" }); + + + //------------------------------------- + // Menu du milieu droite : + //------------------------------------- + liste_menu_milieu_droite.model.clear(); + liste_menu_milieu_droite.model.append({ libelle: qsTr("ShipHeart"), page_cible: "config_reseau_k_bus.qml", param_cible: {}, niveau_mini: 0, alarme: (shipheart_defaut_config_k_bus !== 0) ? "/images/coin_bas_droite_rouge.png" : ""}); + liste_menu_milieu_droite.model.append({ libelle: qsTr("Ethernet & Wifi"), page_cible: "config_reseau_ethernet_wifi.qml", param_cible: {}, niveau_mini: 0, alarme: "" }); +// liste_menu_milieu.model.append({ libelle: qsTr("Wifi"), page_cible: "config_reseau_wifi.qml", param_cible: {}, niveau_mini: 0, alarme: "" }); + liste_menu_milieu_droite.model.append({ libelle: qsTr("One Wire"), page_cible: "config_reseau_one_wire.qml", param_cible: {}, niveau_mini: 0, alarme: "" }); + liste_menu_milieu_droite.model.append({ libelle: qsTr("NMEA 2000"), page_cible: "config_reseau_nmea.qml", param_cible: {}, niveau_mini: 0, alarme: "" }); + liste_menu_milieu_droite.model.append({ libelle: qsTr("J1939"), page_cible: "", param_cible: {}, niveau_mini: 0, alarme: "" }); + liste_menu_milieu_droite.model.append({ libelle: qsTr("DMX"), page_cible: "", param_cible: {}, niveau_mini: 0, alarme: "" }); + + //------------------------------------- + // Menu de droite : + //------------------------------------- + liste_menu_droite.model.clear(); + liste_menu_droite.model.append({ libelle: qsTr("Accès au paramètres"), page_cible: "config_acces_parametres.qml", param_cible: {}, niveau_mini: 0, alarme: "" }); + liste_menu_droite.model.append({ libelle: qsTr("Ship2net"), page_cible: "config_ship2net.qml", param_cible: {}, niveau_mini: 0, alarme: "" }); + liste_menu_droite.model.append({ libelle: qsTr("Journal de bord"), page_cible: "journal_de_bord.qml", param_cible: {}, niveau_mini: 0, alarme: "" }); + // liste_menu_droite.model.append({ libelle: qsTr("Protection"), page_cible: "", param_cible: {}, niveau_mini: 0, alarme: "" }); + if (shipheart_type_installation !== shipheart_type_installation_shipbase) + { + liste_menu_droite.model.append({ libelle: qsTr("Configuration ShipRS"), page_cible: "config_shiprs.qml", param_cible: {}, niveau_mini: 0, alarme: "" }); + } + liste_menu_droite.model.append({ libelle: qsTr("Installation"), page_cible: "config_fichiers.qml", param_cible: {"mode_config_fichiers": shipheart_mode_config_fichiers_rapports}, niveau_mini: 0, alarme: "" }); + liste_menu_droite.model.append({ libelle: qsTr("Sauvegardes"), page_cible: "config_fichiers.qml", param_cible: {"mode_config_fichiers": shipheart_mode_config_fichiers_sauvegardes}, niveau_mini: 0, alarme: "" }); + liste_menu_droite.model.append({ libelle: qsTr("Version"), page_cible: "config_version.qml", param_cible: {}, niveau_mini: 0, alarme: flag_nouvelle_version ? "/images/coin_bas_droite_bleu_koriolan.png" : "" }); + + switch(Number(shipheart_specifique_client[0])) + { + case shipheart_specifique_client_suncy: // Suncy Concept + liste_menu_droite.model.append({libelle: qsTr("Spécifique Suncy"), page_cible: "config_specifique_client_suncy.qml", param_cible: {}, niveau_mini: 0, alarme: "" }); + break; + default: break; + } + + liste_menu_droite.model.append({ libelle: qsTr("Accès réservé Koriolan"), page_cible: "config_koriolan.qml", param_cible: {}, niveau_mini: 10, alarme: "" }); + } + + //============================================================================================================= + // Mise à jour périodique + //============================================================================================================= + function mise_a_jour_periodique() + { + var req, res; + + //----------------------------------------- + // Etat config K-bus : + req = 'SELECT Valeur FROM TB_Systeme WHERE Nom="Defaut_config_k_bus" '; + res = bdd.requete_unique(req); + if (shipheart_defaut_config_k_bus !== Number(res[0])) + { + shipheart_defaut_config_k_bus = Number(res[0]); + init_page(); // Permet de mettre à jour le champ 'alarme' de tous les boutons... Un peu brut mais efficace. + } + + //----------------------------------------- + // Nouvelle version : + if ((shipheart_fichier_a_charger !== "") || (shipheart_fichier_a_valider !== "")) // Nouvelle version présente : + { + if (!flag_nouvelle_version) // Etat précédent = pas de nouvelle version + { + flag_nouvelle_version = true; + init_page(); // Permet de mettre à jour le champ 'alarme' de tous les boutons... Un peu brut mais efficace. + } + } + else // Nouvelle version absente : + { + if (flag_nouvelle_version) // Etat précédent = nouvelle version présente + { + flag_nouvelle_version = false; + init_page(); // Permet de mettre à jour le champ 'alarme' de tous les boutons... Un peu brut mais efficace. + } + } + } + +} + diff --git a/protection.qml b/protection.qml new file mode 100644 index 0000000..c80127d --- /dev/null +++ b/protection.qml @@ -0,0 +1,443 @@ +import QtQuick 2.12 + +import qt.koriolan.shipheart 1.0 + + + +Shipheart_page { + id: page_protection + + + // 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 int niveau_page: 0 + property bool bouton_bandeau_bas_zone_retour_actif: false + property int protection_mode: 0 + + + // Données : + property string code: "" + property string code_admin: "" + 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 type_code: shipheart_type_code_normal + + // 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 + { + mise_a_jour_periodique(); + } + } + } + + // Titre de la page : + Shipheart_titre_1 {titre:qsTr("Accès protégé"); 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); + type_code = shipheart_type_code_normal; // Par défaut, si on clique sur Backspace, on retourne en mode normal + break; + case "clear": + code_saisi = ""; + type_code = shipheart_type_code_normal; // Par défaut, si on clique sur Clear, on retourne en mode normal + break; + default: + code_saisi += libelle; + break; + } + if (check_code() === 0) deverrouillage(); + mise_a_jour_pattern(); + } + onPressAndHold: { + if (libelle === "0") // Appui long sur le '0' pour passer en accès administrateur + { + if (type_code === shipheart_type_code_normal) type_code = shipheart_type_code_admin; + else type_code = shipheart_type_code_normal; + } + } + } + } + } + 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" + + Text { + id: texte_protection_mode_access_parametres_avances + anchors { + verticalCenter: parent.verticalCenter + horizontalCenter: parent.horizontalCenter + } + padding: 20 + font.pixelSize: 20 + horizontalAlignment: Text.AlignHCenter + text: qsTr("L'accès aux paramètres avancés est protégé.\nMerci d'entrer le code de déverrouillage pour y accéder...") + color: couleur_blanc_casse + visible: (protection_mode === protection_mode_access_parametres_avances) ? true : false + } + + Text { + id: texte_protection_mode_access_parametres_avances_admin + anchors { + top: texte_protection_mode_access_parametres_avances.bottom + horizontalCenter: parent.horizontalCenter + } + padding: 20 + font.pixelSize: 20 + horizontalAlignment: Text.AlignHCenter + text: qsTr("Mode administrateur validé
Entrer votre code dédié") + color: couleur_bleu_koriolan + visible: (protection_mode === protection_mode_access_parametres_avances) ? ((type_code === shipheart_type_code_admin) ? true : false) : false + } + + } + + + //------------------------------------------------------- + // 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 + } + } + + Image { + id: image_alarme_paramètres // Affichage du coin inférieur-droit en rouge si une erreur de paramètres est détectée + source: "/images/coin_bas_droite_rouge.png" + sourceSize.height: 20 + anchors { + bottom: parent.bottom + right: parent.right + } + visible: shipheart_defaut_config_k_bus + } + + Image { + id: image_info_paramètres // Affichage du coin inférieur-droit en bleu si une nouvelle version est dispo + source: "/images/coin_bas_droite_bleu_koriolan.png" + sourceSize.height: 20 + anchors { + bottom: parent.bottom + right: parent.right + } + visible: !image_alarme_paramètres.visible && + ((shipheart_fichier_a_charger !== "") || (shipheart_fichier_a_valider !== "")) + } + + 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); + } + } + + + //============================================================================================================= + // Init de la page + //============================================================================================================= + function init_page() + { + var req, res; + +//console.log("Mode actuel : " + protection_mode); + + mise_en_veille(0); + niveau_page = stackView.depth - 1; // Permet de stocker le niveau de la page dans la Stackview + + req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Code" '; + res = bdd.requete_unique(req); + code = res[0]; + + req = 'SELECT Valeur FROM TB_Configuration WHERE Nom="Code_admin" '; + res = bdd.requete_unique(req); + code_admin = 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 req, res; + +//console.log("Le code est valide. La page est déverrouillée....") + code_saisi = ""; + switch(protection_mode) + { + case protection_mode_access_parametres_avances: + if (shipheart_time_out_niveau_acces === 0) shipheart_niveau_acces_en_cours = shipheart_niveau_acces_aucun; + else if (shipheart_time_out_niveau_acces === -1)shipheart_compteur_time_out_niveau_acces = 0; + shipheart_compteur_time_out_niveau_acces = shipheart_time_out_niveau_acces; + stackView.push("parametres_avances.qml"); + + break; + + case protection_mode_verrouillage: break; + case protection_mode_deverrouillage: break; + default: ; + } + } + + //============================================================================================================= + // 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 user est [" + code + "]"); +//console.debug("Le hash du code admin est [" + code_admin + "]"); +//console.debug("Le hash du code Koriolan est [" + code_koriolan + "]"); + + switch(type_code) + { + case shipheart_type_code_normal: + default : + if (code.localeCompare(code_saisi_encrypte) === 0) + { + shipheart_niveau_acces_en_cours = shipheart_niveau_acces_user; // Vérification du code saisi vs code user +//console.debug("Code User validé"); + return (0); + } + break; + + case shipheart_type_code_admin: + if (code_admin.localeCompare(code_saisi_encrypte) === 0) + { + shipheart_niveau_acces_en_cours = shipheart_niveau_acces_admin; // Vérification du code saisi vs code administrateur +//console.debug("Code Admin validé"); + return (0); + } + else if (code_koriolan.localeCompare(code_saisi_encrypte) === 0) + { + shipheart_niveau_acces_en_cours = shipheart_niveau_acces_koriolan; // Vérification du code saisi vs code Koriolan +//console.debug("Code Koriolan validé"); + return (0); + } + break; + } + + return(-1); // Autres cas.... + } + + + //============================================================================================================= + // 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 + + main.qml + home.qml + ephemeride.qml + capteur.qml + qtquickcontrols2.conf + images/fibre_carbone.png + Shipheart_page.qml + Shipheart_bouton_circuit.qml + Shipheart_titre_1.qml + images/ak14.png + images/icone_consommation_electrique.png + Shipheart_bouton_reservoir.qml + Shipheart_bouton_batterie.qml + images/logo_shipheart.png + images/icone_auxiliaires.png + images/icone_barometre.png + images/icone_humidite.png + images/icone_journal_de_bord.png + images/icone_retour.png + images/icone_temperature.png + images/icone_parametres.png + fonctions.js + parametres.qml + Shipheart_titre_2.qml + suncalc.js + images/lune_1.png + images/lune_2.png + images/lune_3.png + images/lune_4.png + images/lune_5.png + images/lune_6.png + images/lune_7.png + images/lune_8.png + images/lune_9.png + images/lune_10.png + images/lune_11.png + images/lune_12.png + images/lune_13.png + images/lune_14.png + images/lune_15.png + images/lune_16.png + circuit.qml + images/ak5.png + fonctions_date_heure.js + fonctions_historique.js + reservoir.qml + fonctions_couleurs.js + batterie.qml + journal_de_bord.qml + protection.qml + images/backspace.png + images/double_fleche_gauche.png + parametres_avances.qml + images/tri.png + config_circuit.qml + Shipheart_formulaire_textfield.qml + Shipheart_formulaire_combobox.qml + images/up.png + images/down.png + Shipheart_formulaire_label.qml + Shipheart_formulaire_ligne_separation.qml + Shipheart_boite_dialogue.qml + images/4g_lte_off.png + images/4g_lte_on_1.png + images/4g_lte_on_2.png + images/4g_lte_on_3.png + images/4g_lte_on_4.png + images/gnss_off.png + images/gnss_on.png + config_reservoirs.qml + config_reservoir.qml + Shipheart_boite_dialogue_entrees_aux.qml + Shipheart_boite_dialogue_entrees_level_sensor.qml + config_batteries.qml + config_batterie.qml + config_affichage.qml + home_suncy.qml + images/logo_suncy_concept.png + Shipheart_busy_indicator.qml + config_capteurs.qml + config_ordre_elements.qml + images/icone_parametres_acces_autorise.png + config_acces_parametres.qml + Shipheart_boite_dialogue_nettoyage_ecran.qml + config_valeurs_niveaux.qml + images/coin_bas_droite_rouge.png + fonctions_batteries.js + config_specifique_client_suncy.qml + Shipheart_formulaire_checkbox.qml + config_version.qml + config_ship2net.qml + Shipheart_formulaire_valeur_fixe.qml + config_koriolan.qml + home_attente.qml + images/coin_bas_droite_orange.png + images/coin_bas_droite_bleu_koriolan.png + config_groupe_elements.qml + etalonnage_capteur.qml + test_batterie.qml + images/fleche_tendance_haut_verte.png + fonctions_reservoirs.js + etalonnage_carte.qml + config_audio.qml + images/wifi_ap_off.png + images/wifi_ap_on.png + images/wifi_sta_off.png + images/wifi_sta_on.png + images/ethernet_off.png + images/ethernet_on.png + config_shiprs.qml + config_reseau_k_bus.qml + test_tri_liste.qml + config_module_modification.qml + Shipheart_formulaire_textarea.qml + shipheart_test_liste_fonts.qml + Shipheart_formulaire_bouton.qml + Shipheart_formulaire_unite.qml + images/cloche_sombre.png + images/circuit_on.png + images/cycle_100pc.png + images/soh.png + images/cycle_100pc_sombre.png + images/cycle_sombre.png + images/soh_sombre.png + images/batterie.png + images/batterie_sombre.png + images/batterie_12v.png + images/batterie_24v.png + fonctions_circuits.js + images/fleche_suite_droite.png + images/fleche_suite_gauche.png + images/reset_actif.png + images/left.png + images/right.png + config_capteur_calcule_booleen_condition.qml + images/reservoir.png + images/batterie_moyen.png + shipheart_test_config.qml + shipheart_test_screen.qml + shipheart_test_touchpad.qml + shipheart_test_backlight.qml + shipheart_test_home.qml + config_capteur.qml + config_module.qml + config_reseau_ethernet_wifi.qml + config_reseau_wifi_ap.qml + config_reseau_wifi_sta.qml + config_reseau_wifi_sta_liste.qml + config_reseau_one_wire.qml + fonctions_localisation.js + config_reseau_one_wire_modification.qml + config_events.qml + config_event.qml + Shipheart_boite_dialogue_action_circuit.qml + Shipheart_titre_3.qml + images/right_sombre.png + images/fleche_suite_droite_sombre.png + images/fleche_suite_gauche_sombre.png + Shipheart_boite_dialogue_condition_horaire.qml + config_capteur_calcule_booleen.qml + images/reservoir_eau.png + images/faux.png + images/vrai.png + virtualkeyboard_layouts_koriolan/layouts/ar_AR/dialpad.fallback + virtualkeyboard_layouts_koriolan/layouts/ar_AR/digits.qml + virtualkeyboard_layouts_koriolan/layouts/ar_AR/handwriting.qml + virtualkeyboard_layouts_koriolan/layouts/ar_AR/main.qml + virtualkeyboard_layouts_koriolan/layouts/ar_AR/numbers.qml + virtualkeyboard_layouts_koriolan/layouts/ar_AR/symbols.qml + virtualkeyboard_layouts_koriolan/layouts/bg_BG/dialpad.fallback + virtualkeyboard_layouts_koriolan/layouts/bg_BG/digits.fallback + virtualkeyboard_layouts_koriolan/layouts/bg_BG/handwriting.qml + virtualkeyboard_layouts_koriolan/layouts/bg_BG/main.qml + virtualkeyboard_layouts_koriolan/layouts/bg_BG/numbers.fallback + virtualkeyboard_layouts_koriolan/layouts/bg_BG/symbols.fallback + virtualkeyboard_layouts_koriolan/layouts/cs_CZ/dialpad.fallback + virtualkeyboard_layouts_koriolan/layouts/cs_CZ/digits.fallback + virtualkeyboard_layouts_koriolan/layouts/cs_CZ/handwriting.qml + virtualkeyboard_layouts_koriolan/layouts/cs_CZ/main.qml + virtualkeyboard_layouts_koriolan/layouts/cs_CZ/numbers.fallback + virtualkeyboard_layouts_koriolan/layouts/cs_CZ/symbols.fallback + virtualkeyboard_layouts_koriolan/layouts/da_DK/dialpad.fallback + virtualkeyboard_layouts_koriolan/layouts/da_DK/digits.fallback + virtualkeyboard_layouts_koriolan/layouts/da_DK/handwriting.fallback + virtualkeyboard_layouts_koriolan/layouts/da_DK/main.qml + virtualkeyboard_layouts_koriolan/layouts/da_DK/numbers.fallback + virtualkeyboard_layouts_koriolan/layouts/da_DK/symbols.fallback + virtualkeyboard_layouts_koriolan/layouts/de_DE/dialpad.fallback + virtualkeyboard_layouts_koriolan/layouts/de_DE/digits.fallback + virtualkeyboard_layouts_koriolan/layouts/de_DE/handwriting.fallback + virtualkeyboard_layouts_koriolan/layouts/de_DE/main.qml + virtualkeyboard_layouts_koriolan/layouts/de_DE/numbers.fallback + virtualkeyboard_layouts_koriolan/layouts/de_DE/symbols.fallback + virtualkeyboard_layouts_koriolan/layouts/el_GR/dialpad.fallback + virtualkeyboard_layouts_koriolan/layouts/el_GR/digits.fallback + virtualkeyboard_layouts_koriolan/layouts/el_GR/handwriting.qml + virtualkeyboard_layouts_koriolan/layouts/el_GR/main.qml + virtualkeyboard_layouts_koriolan/layouts/el_GR/numbers.fallback + virtualkeyboard_layouts_koriolan/layouts/el_GR/symbols.fallback + virtualkeyboard_layouts_koriolan/layouts/en_GB/dialpad.fallback + virtualkeyboard_layouts_koriolan/layouts/en_GB/digits.fallback + virtualkeyboard_layouts_koriolan/layouts/en_GB/handwriting.fallback + virtualkeyboard_layouts_koriolan/layouts/en_GB/main.fallback + virtualkeyboard_layouts_koriolan/layouts/en_GB/numbers.fallback + virtualkeyboard_layouts_koriolan/layouts/en_GB/symbols.fallback + virtualkeyboard_layouts_koriolan/layouts/en_US/dialpad.fallback + virtualkeyboard_layouts_koriolan/layouts/en_US/digits.fallback + virtualkeyboard_layouts_koriolan/layouts/en_US/handwriting.fallback + virtualkeyboard_layouts_koriolan/layouts/en_US/main.fallback + virtualkeyboard_layouts_koriolan/layouts/en_US/numbers.fallback + virtualkeyboard_layouts_koriolan/layouts/en_US/symbols.fallback + virtualkeyboard_layouts_koriolan/layouts/es_ES/dialpad.fallback + virtualkeyboard_layouts_koriolan/layouts/es_ES/digits.fallback + virtualkeyboard_layouts_koriolan/layouts/es_ES/handwriting.qml + virtualkeyboard_layouts_koriolan/layouts/es_ES/main.qml + virtualkeyboard_layouts_koriolan/layouts/es_ES/numbers.fallback + virtualkeyboard_layouts_koriolan/layouts/es_ES/symbols.qml + virtualkeyboard_layouts_koriolan/layouts/es_MX/dialpad.fallback + virtualkeyboard_layouts_koriolan/layouts/es_MX/digits.fallback + virtualkeyboard_layouts_koriolan/layouts/es_MX/handwriting.qml + virtualkeyboard_layouts_koriolan/layouts/es_MX/main.qml + virtualkeyboard_layouts_koriolan/layouts/es_MX/numbers.fallback + virtualkeyboard_layouts_koriolan/layouts/es_MX/symbols.qml + virtualkeyboard_layouts_koriolan/layouts/et_EE/dialpad.fallback + virtualkeyboard_layouts_koriolan/layouts/et_EE/digits.fallback + virtualkeyboard_layouts_koriolan/layouts/et_EE/handwriting.fallback + virtualkeyboard_layouts_koriolan/layouts/et_EE/main.qml + virtualkeyboard_layouts_koriolan/layouts/et_EE/numbers.fallback + virtualkeyboard_layouts_koriolan/layouts/et_EE/symbols.fallback + virtualkeyboard_layouts_koriolan/layouts/fa_FA/dialpad.fallback + virtualkeyboard_layouts_koriolan/layouts/fa_FA/digits.qml + virtualkeyboard_layouts_koriolan/layouts/fa_FA/handwriting.qml + virtualkeyboard_layouts_koriolan/layouts/fa_FA/main.qml + virtualkeyboard_layouts_koriolan/layouts/fa_FA/numbers.qml + virtualkeyboard_layouts_koriolan/layouts/fa_FA/symbols.qml + virtualkeyboard_layouts_koriolan/layouts/fallback/dialpad.qml + virtualkeyboard_layouts_koriolan/layouts/fallback/digits.qml + virtualkeyboard_layouts_koriolan/layouts/fallback/handwriting.qml + virtualkeyboard_layouts_koriolan/layouts/fallback/main.qml + virtualkeyboard_layouts_koriolan/layouts/fallback/numbers.qml + virtualkeyboard_layouts_koriolan/layouts/fallback/symbols.qml + virtualkeyboard_layouts_koriolan/layouts/fi_FI/dialpad.fallback + virtualkeyboard_layouts_koriolan/layouts/fi_FI/digits.fallback + virtualkeyboard_layouts_koriolan/layouts/fi_FI/handwriting.fallback + virtualkeyboard_layouts_koriolan/layouts/fi_FI/main.qml + virtualkeyboard_layouts_koriolan/layouts/fi_FI/numbers.fallback + virtualkeyboard_layouts_koriolan/layouts/fi_FI/symbols.fallback + virtualkeyboard_layouts_koriolan/layouts/fr_CA/dialpad.fallback + virtualkeyboard_layouts_koriolan/layouts/fr_CA/digits.fallback + virtualkeyboard_layouts_koriolan/layouts/fr_CA/handwriting.fallback + virtualkeyboard_layouts_koriolan/layouts/fr_CA/main.qml + virtualkeyboard_layouts_koriolan/layouts/fr_CA/numbers.fallback + virtualkeyboard_layouts_koriolan/layouts/fr_CA/symbols.fallback + virtualkeyboard_layouts_koriolan/layouts/fr_FR/dialpad.fallback + virtualkeyboard_layouts_koriolan/layouts/fr_FR/digits.fallback + virtualkeyboard_layouts_koriolan/layouts/fr_FR/handwriting.fallback + virtualkeyboard_layouts_koriolan/layouts/fr_FR/main.qml + virtualkeyboard_layouts_koriolan/layouts/fr_FR/numbers.fallback + virtualkeyboard_layouts_koriolan/layouts/fr_FR/symbols.fallback + virtualkeyboard_layouts_koriolan/layouts/he_IL/dialpad.fallback + virtualkeyboard_layouts_koriolan/layouts/he_IL/digits.fallback + virtualkeyboard_layouts_koriolan/layouts/he_IL/handwriting.qml + virtualkeyboard_layouts_koriolan/layouts/he_IL/main.qml + virtualkeyboard_layouts_koriolan/layouts/he_IL/numbers.fallback + virtualkeyboard_layouts_koriolan/layouts/he_IL/symbols.qml + virtualkeyboard_layouts_koriolan/layouts/hi_IN/dialpad.fallback + virtualkeyboard_layouts_koriolan/layouts/hi_IN/digits.fallback + virtualkeyboard_layouts_koriolan/layouts/hi_IN/handwriting.qml + virtualkeyboard_layouts_koriolan/layouts/hi_IN/main.qml + virtualkeyboard_layouts_koriolan/layouts/hi_IN/numbers.fallback + virtualkeyboard_layouts_koriolan/layouts/hi_IN/symbols.qml + virtualkeyboard_layouts_koriolan/layouts/hr_HR/dialpad.fallback + virtualkeyboard_layouts_koriolan/layouts/hr_HR/digits.fallback + virtualkeyboard_layouts_koriolan/layouts/hr_HR/handwriting.qml + virtualkeyboard_layouts_koriolan/layouts/hr_HR/main.qml + virtualkeyboard_layouts_koriolan/layouts/hr_HR/numbers.fallback + virtualkeyboard_layouts_koriolan/layouts/hr_HR/symbols.fallback + virtualkeyboard_layouts_koriolan/layouts/hu_HU/dialpad.fallback + virtualkeyboard_layouts_koriolan/layouts/hu_HU/digits.fallback + virtualkeyboard_layouts_koriolan/layouts/hu_HU/handwriting.qml + virtualkeyboard_layouts_koriolan/layouts/hu_HU/main.qml + virtualkeyboard_layouts_koriolan/layouts/hu_HU/numbers.fallback + virtualkeyboard_layouts_koriolan/layouts/hu_HU/symbols.fallback + virtualkeyboard_layouts_koriolan/layouts/id_ID/dialpad.fallback + virtualkeyboard_layouts_koriolan/layouts/id_ID/digits.fallback + virtualkeyboard_layouts_koriolan/layouts/id_ID/handwriting.fallback + virtualkeyboard_layouts_koriolan/layouts/id_ID/main.fallback + virtualkeyboard_layouts_koriolan/layouts/id_ID/numbers.fallback + virtualkeyboard_layouts_koriolan/layouts/id_ID/symbols.fallback + virtualkeyboard_layouts_koriolan/layouts/it_IT/dialpad.fallback + virtualkeyboard_layouts_koriolan/layouts/it_IT/digits.fallback + virtualkeyboard_layouts_koriolan/layouts/it_IT/handwriting.fallback + virtualkeyboard_layouts_koriolan/layouts/it_IT/main.qml + virtualkeyboard_layouts_koriolan/layouts/it_IT/numbers.fallback + virtualkeyboard_layouts_koriolan/layouts/it_IT/symbols.fallback + virtualkeyboard_layouts_koriolan/layouts/ja_JP/dialpad.fallback + virtualkeyboard_layouts_koriolan/layouts/ja_JP/digits.fallback + virtualkeyboard_layouts_koriolan/layouts/ja_JP/handwriting.qml + virtualkeyboard_layouts_koriolan/layouts/ja_JP/main.qml + virtualkeyboard_layouts_koriolan/layouts/ja_JP/numbers.fallback + virtualkeyboard_layouts_koriolan/layouts/ja_JP/symbols.qml + virtualkeyboard_layouts_koriolan/layouts/ko_KR/dialpad.fallback + virtualkeyboard_layouts_koriolan/layouts/ko_KR/digits.fallback + virtualkeyboard_layouts_koriolan/layouts/ko_KR/handwriting.qml + virtualkeyboard_layouts_koriolan/layouts/ko_KR/main.qml + virtualkeyboard_layouts_koriolan/layouts/ko_KR/numbers.fallback + virtualkeyboard_layouts_koriolan/layouts/ko_KR/symbols.qml + virtualkeyboard_layouts_koriolan/layouts/ms_MY/dialpad.fallback + virtualkeyboard_layouts_koriolan/layouts/ms_MY/digits.fallback + virtualkeyboard_layouts_koriolan/layouts/ms_MY/handwriting.fallback + virtualkeyboard_layouts_koriolan/layouts/ms_MY/main.fallback + virtualkeyboard_layouts_koriolan/layouts/ms_MY/numbers.fallback + virtualkeyboard_layouts_koriolan/layouts/ms_MY/symbols.fallback + virtualkeyboard_layouts_koriolan/layouts/nb_NO/dialpad.fallback + virtualkeyboard_layouts_koriolan/layouts/nb_NO/digits.fallback + virtualkeyboard_layouts_koriolan/layouts/nb_NO/handwriting.fallback + virtualkeyboard_layouts_koriolan/layouts/nb_NO/main.qml + virtualkeyboard_layouts_koriolan/layouts/nb_NO/numbers.fallback + virtualkeyboard_layouts_koriolan/layouts/nb_NO/symbols.fallback + virtualkeyboard_layouts_koriolan/layouts/nl_NL/dialpad.fallback + virtualkeyboard_layouts_koriolan/layouts/nl_NL/digits.fallback + virtualkeyboard_layouts_koriolan/layouts/nl_NL/handwriting.fallback + virtualkeyboard_layouts_koriolan/layouts/nl_NL/main.fallback + virtualkeyboard_layouts_koriolan/layouts/nl_NL/numbers.fallback + virtualkeyboard_layouts_koriolan/layouts/nl_NL/symbols.fallback + virtualkeyboard_layouts_koriolan/layouts/pl_PL/dialpad.fallback + virtualkeyboard_layouts_koriolan/layouts/pl_PL/digits.fallback + virtualkeyboard_layouts_koriolan/layouts/pl_PL/handwriting.fallback + virtualkeyboard_layouts_koriolan/layouts/pl_PL/main.qml + virtualkeyboard_layouts_koriolan/layouts/pl_PL/numbers.fallback + virtualkeyboard_layouts_koriolan/layouts/pl_PL/symbols.fallback + virtualkeyboard_layouts_koriolan/layouts/pt_BR/dialpad.fallback + virtualkeyboard_layouts_koriolan/layouts/pt_BR/digits.fallback + virtualkeyboard_layouts_koriolan/layouts/pt_BR/handwriting.fallback + virtualkeyboard_layouts_koriolan/layouts/pt_BR/main.qml + virtualkeyboard_layouts_koriolan/layouts/pt_BR/numbers.fallback + virtualkeyboard_layouts_koriolan/layouts/pt_BR/symbols.fallback + virtualkeyboard_layouts_koriolan/layouts/pt_PT/dialpad.fallback + virtualkeyboard_layouts_koriolan/layouts/pt_PT/digits.fallback + virtualkeyboard_layouts_koriolan/layouts/pt_PT/handwriting.fallback + virtualkeyboard_layouts_koriolan/layouts/pt_PT/main.qml + virtualkeyboard_layouts_koriolan/layouts/pt_PT/numbers.fallback + virtualkeyboard_layouts_koriolan/layouts/pt_PT/symbols.fallback + virtualkeyboard_layouts_koriolan/layouts/ro_RO/dialpad.fallback + virtualkeyboard_layouts_koriolan/layouts/ro_RO/digits.fallback + virtualkeyboard_layouts_koriolan/layouts/ro_RO/handwriting.qml + virtualkeyboard_layouts_koriolan/layouts/ro_RO/main.qml + virtualkeyboard_layouts_koriolan/layouts/ro_RO/numbers.fallback + virtualkeyboard_layouts_koriolan/layouts/ro_RO/symbols.fallback + virtualkeyboard_layouts_koriolan/layouts/ru_RU/dialpad.fallback + virtualkeyboard_layouts_koriolan/layouts/ru_RU/digits.fallback + virtualkeyboard_layouts_koriolan/layouts/ru_RU/handwriting.fallback + virtualkeyboard_layouts_koriolan/layouts/ru_RU/main.qml + virtualkeyboard_layouts_koriolan/layouts/ru_RU/numbers.fallback + virtualkeyboard_layouts_koriolan/layouts/ru_RU/symbols.fallback + virtualkeyboard_layouts_koriolan/layouts/sk_SK/dialpad.fallback + virtualkeyboard_layouts_koriolan/layouts/sk_SK/digits.fallback + virtualkeyboard_layouts_koriolan/layouts/sk_SK/handwriting.fallback + virtualkeyboard_layouts_koriolan/layouts/sk_SK/main.qml + virtualkeyboard_layouts_koriolan/layouts/sk_SK/numbers.fallback + virtualkeyboard_layouts_koriolan/layouts/sk_SK/symbols.fallback + virtualkeyboard_layouts_koriolan/layouts/sl_SI/dialpad.fallback + virtualkeyboard_layouts_koriolan/layouts/sl_SI/digits.fallback + virtualkeyboard_layouts_koriolan/layouts/sl_SI/handwriting.fallback + virtualkeyboard_layouts_koriolan/layouts/sl_SI/main.qml + virtualkeyboard_layouts_koriolan/layouts/sl_SI/numbers.fallback + virtualkeyboard_layouts_koriolan/layouts/sl_SI/symbols.fallback + virtualkeyboard_layouts_koriolan/layouts/sq_AL/dialpad.fallback + virtualkeyboard_layouts_koriolan/layouts/sq_AL/digits.fallback + virtualkeyboard_layouts_koriolan/layouts/sq_AL/handwriting.fallback + virtualkeyboard_layouts_koriolan/layouts/sq_AL/main.qml + virtualkeyboard_layouts_koriolan/layouts/sq_AL/numbers.fallback + virtualkeyboard_layouts_koriolan/layouts/sq_AL/symbols.fallback + virtualkeyboard_layouts_koriolan/layouts/sr_SP/dialpad.fallback + virtualkeyboard_layouts_koriolan/layouts/sr_SP/digits.fallback + virtualkeyboard_layouts_koriolan/layouts/sr_SP/handwriting.qml + virtualkeyboard_layouts_koriolan/layouts/sr_SP/main.qml + virtualkeyboard_layouts_koriolan/layouts/sr_SP/numbers.fallback + virtualkeyboard_layouts_koriolan/layouts/sr_SP/symbols.fallback + virtualkeyboard_layouts_koriolan/layouts/sv_SE/dialpad.fallback + virtualkeyboard_layouts_koriolan/layouts/sv_SE/digits.fallback + virtualkeyboard_layouts_koriolan/layouts/sv_SE/handwriting.fallback + virtualkeyboard_layouts_koriolan/layouts/sv_SE/main.qml + virtualkeyboard_layouts_koriolan/layouts/sv_SE/numbers.fallback + virtualkeyboard_layouts_koriolan/layouts/sv_SE/symbols.fallback + virtualkeyboard_layouts_koriolan/layouts/th_TH/dialpad.fallback + virtualkeyboard_layouts_koriolan/layouts/th_TH/digits.fallback + virtualkeyboard_layouts_koriolan/layouts/th_TH/handwriting.fallback + virtualkeyboard_layouts_koriolan/layouts/th_TH/handwriting.qml + virtualkeyboard_layouts_koriolan/layouts/th_TH/main.qml + virtualkeyboard_layouts_koriolan/layouts/th_TH/numbers.fallback + virtualkeyboard_layouts_koriolan/layouts/th_TH/symbols.qml + virtualkeyboard_layouts_koriolan/layouts/tr_TR/dialpad.fallback + virtualkeyboard_layouts_koriolan/layouts/tr_TR/digits.fallback + virtualkeyboard_layouts_koriolan/layouts/tr_TR/handwriting.fallback + virtualkeyboard_layouts_koriolan/layouts/tr_TR/main.qml + virtualkeyboard_layouts_koriolan/layouts/tr_TR/numbers.fallback + virtualkeyboard_layouts_koriolan/layouts/tr_TR/symbols.fallback + virtualkeyboard_layouts_koriolan/layouts/uk_UA/dialpad.fallback + virtualkeyboard_layouts_koriolan/layouts/uk_UA/digits.fallback + virtualkeyboard_layouts_koriolan/layouts/uk_UA/handwriting.fallback + virtualkeyboard_layouts_koriolan/layouts/uk_UA/main.qml + virtualkeyboard_layouts_koriolan/layouts/uk_UA/numbers.fallback + virtualkeyboard_layouts_koriolan/layouts/uk_UA/symbols.fallback + virtualkeyboard_layouts_koriolan/layouts/vi_VN/dialpad.fallback + virtualkeyboard_layouts_koriolan/layouts/vi_VN/digits.fallback + virtualkeyboard_layouts_koriolan/layouts/vi_VN/handwriting.fallback + virtualkeyboard_layouts_koriolan/layouts/vi_VN/main.qml + virtualkeyboard_layouts_koriolan/layouts/vi_VN/numbers.fallback + virtualkeyboard_layouts_koriolan/layouts/vi_VN/symbols.qml + virtualkeyboard_layouts_koriolan/layouts/zh_CN/dialpad.fallback + virtualkeyboard_layouts_koriolan/layouts/zh_CN/digits.fallback + virtualkeyboard_layouts_koriolan/layouts/zh_CN/handwriting.qml + virtualkeyboard_layouts_koriolan/layouts/zh_CN/main.qml + virtualkeyboard_layouts_koriolan/layouts/zh_CN/numbers.fallback + virtualkeyboard_layouts_koriolan/layouts/zh_CN/symbols.qml + virtualkeyboard_layouts_koriolan/layouts/zh_TW/dialpad.fallback + virtualkeyboard_layouts_koriolan/layouts/zh_TW/digits.fallback + virtualkeyboard_layouts_koriolan/layouts/zh_TW/handwriting.qml + virtualkeyboard_layouts_koriolan/layouts/zh_TW/main.qml + virtualkeyboard_layouts_koriolan/layouts/zh_TW/numbers.fallback + virtualkeyboard_layouts_koriolan/layouts/zh_TW/symbols.qml + home_accueil.qml + images/up_bleu.png + config_installateur.qml + Shipheart_bouton_capteur.qml + images/chronometre.png + images/sablier.png + images/reveil.png + Shipheart_boite_dialogue_minuteur.qml + Shipheart_boite_dialogue_affichage_duree.qml + Shipheart_boite_dialogue_reveils.qml + images/cloche_verte.png + images/cloche_barree.png + images/cloche_rouge.png + Shipheart_boite_dialogue_liste_alarmes.qml + images/ampoule.png + images/attention.png + images/cone_chantier.png + images/satellite.png + images/cycle_clair.png + images/cycle.png + images/event.png + images/reset_sombre.png + images/reset.png + images/calendrier.png + images/heure.png + images/minute.png + images/condition_horaire.png + images/cloche.png + images/fond_2.jpg + images/fond_3.jpg + Shipheart_boite_dialogue_validation_securisee.qml + config_pages.qml + config_page.qml + config_page_edition.qml + config_page_point.qml + page_personnalisee.qml + images/point_arc_en_ciel.png + images/point_blanc.png + images/point_bleu.png + images/point_jaune.png + images/point_orange.png + images/point_rouge.png + images/point_transparent.png + images/point_vert.png + Shipheart_formulaire_combobox_icones.qml + images/fleche_suite_haut.png + images/fleche_suite_bas.png + config_reseau_nmea.qml + images/sp8dc.png + images/shipbase.png + images/shipbs.png + images/sp4ac.png + images/vanne_ouverte.png + images/vanne_fermee.png + images/vanne.png + config_module_physique.qml + config_module_creation.qml + config_circuits.qml + config_fichiers.qml + images/factory_reset_actif.png + images/factory_reset_sombre.png + + diff --git a/qt_shipheart_phrase_book.qph b/qt_shipheart_phrase_book.qph new file mode 100755 index 0000000..ff4d4d5 --- /dev/null +++ b/qt_shipheart_phrase_book.qph @@ -0,0 +1,3 @@ + + + diff --git a/qtquickcontrols2.conf b/qtquickcontrols2.conf new file mode 100755 index 0000000..aaf6461 --- /dev/null +++ b/qtquickcontrols2.conf @@ -0,0 +1,10 @@ +; This file can be edited to change the style of the application +; Read "Qt Quick Controls 2 Configuration File" for details: +; https://doc.qt.io/qt/qtquickcontrols2-configuration.html + +#[Controls] +#Style=Material + +#[Material] +#Theme=Dark +#Accent=Red diff --git a/reservoir.qml b/reservoir.qml new file mode 100644 index 0000000..65390af --- /dev/null +++ b/reservoir.qml @@ -0,0 +1,982 @@ +//======================================================================================================================================================================== +// RESERVOIR.QML +// Ce fichier traite l'affichage des détails d'un réservoir. La page affiche notamment : +// - le niveau actuel sous forme graphique (avec référence aux seuils haut et bas) +// - la contenance actuelle (dans l'unit en cours) et son niveau relatif +// - la liste des derniers événements, +// - la courbe historique de niveau +// La page est appelée depuis la page HOME, en cliquant sur la zone d'information du réservoir. +//======================================================================================================================================================================== + +import QtQuick 2.12 +import QtQuick.Controls 2.12 +import QtQuick.Layouts 1.12 +import QtCharts 2.3 + +import qt.koriolan.shipheart 1.0 +import"fonctions.js" as Fonctions +import"fonctions_date_heure.js" as Fonctions_date_heure + + +Shipheart_page { + id: page_reservoir + + + // Mis en forme : + readonly property double affichage_hauteur_utile: shipheart_hauteur_page - shipheart_hauteur_bandeau_haut - shipheart_hauteur_bandeau_bas - (2 * espace_lignes_principales) + readonly property double pourcentage_hauteur_ligne_haut: 0.6 + readonly property double pourcentage_hauteur_ligne_erreur: 0.3 // Part de 'pourcentage_hauteur_ligne_haut' + readonly property double espace_lignes_principales: 20 + + + readonly property double pourcentage_largeur_colonne_gauche: 0.5 + readonly property double pourcentage_largeur_graphique: 0.85 + readonly property double espace_colonnes_principales: 20 + readonly property double espace_colonnes_secondaires: 50 + + + + + readonly property int nombre_lignes_historique_visibles: 8 + readonly property int nombre_lignes_historique_par_page: 30 + + readonly property double nb_boutons_periode: 4 + + readonly property int periode_init_raffraichissement_parametres: 20 // En ms ATtention : The Timer type is synchronized with the animation timer. Since the animation timer is usually set to 60fps, the resolution of Timer will be at best 16ms. + readonly property int periode_raffraichissement_parametres: 1000 // En ms + readonly property int periode_init_raffraichissement_graphiques: 20 // En ms + readonly property int periode_raffraichissement_graphiques: (15 * 1000) // en ms + + + // Affichage : + property bool courbe_flag_vide: false // Flag indiquant s'il y a des données à afficher ou pas + property int courbe_nombre_principal_graduations_axe_x: 13 + property int courbe_nombre_zoom_1_graduations_axe_x: 8 + property int courbe_nombre_graduations_axe_y: 5 + property string courbe_format_principal_axe_x: "HH:mm" // exemple : "yyyy-MM-dd HH:mm:ss" + property string courbe_format_zoom_1_axe_x: "HH:mm" // exemple : "yyyy-MM-dd HH:mm:ss" + + property int periode_analyse: 0 + + property bool flag_zoom_en_cours: false + property real zoomx_en_cours: 1 + + property date xMin_date + property date xMax_date + property real yMin_valeur: 0 + property real yMax_valeur: 1 + property int precision_affichage_axe_y_courbe: 1 + property string symbole_unite: "--" + + + // Historique : + property string date_premiere_entree_historique: "" // Contient une chaine (format BDD) représentant la date/heure de l'entrée historique la plus ancienne. Permet de recharger de plus anciennes lors d'un MORE... + property string date_derniere_entree_historique: "" // Contient une chaine (format BDD) représentant la date/heure de l'entrée historique la plus récente. Permet de ne recharger que les nouvelles... + property bool flag_journal_full: false // est positionné à vrai quand il n'y a plus d'enregistrements supplémentaires disponibles pour ce filtre + + + // Données : + property bool flag_init: true // Permet de bloquer certains affichage tant que l'init n'est pas terminée + + property int id_reservoir: 0 + property int id_variable: 0 + property int etat_systeme: 0 + property int etat: 0 + property string nom_reservoir: "---" + property double niveau: 0 + property double niveau_seuil_bas: 75 + property double niveau_seuil_haut: 25 + property int capacite: 0 + property int id_famille: 1 // Eau par défaut + property int precision_affichage_mesures: 0 + property int type_periode_graphique: 1 + + property string texte_alerte: "" + property int nb_events: -1 // -1: aucun event n'est lié à ce capteur, 0: au moins 1 event est lié à ce capteur mais aucun n'a Etat_test>0, 1: au moins un event lié et au moins un Etat_test=1 + + // 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 du circuit : + //=========================================================== + 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; + busy_indicator.running = true; + init_page(); + } + else + { + mise_a_jour_valeurs_instantanees(); + } + } + } + //=========================================================== + // Timer periode raffraichissement graphiques : + //=========================================================== + Timer { + id: timer_raffraichissement_graphiques + interval: periode_raffraichissement_graphiques + triggeredOnStart: false + running: true + repeat: true + onTriggered: { + if (interval === periode_init_raffraichissement_graphiques) interval = periode_raffraichissement_graphiques; + + if (!flag_init) // La gestion du premier calcul des courbes est géré directement par 'init()' car le séquençage des 2 timers au démarrage n'est pas garanti !! + { + if (!flag_zoom_en_cours) // On ne met pas à jour les courbes si on est en train de zoomer + { + mise_a_jour_courbes(); + } + } + } + } + + + // Titre de la page : + Shipheart_titre_1 {titre:nom_reservoir; 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; + color: "transparent" + visible: (etat_systeme === 0) + + //------------------------------------------------------- + // Valeur si unité : + Rectangle { + anchors.fill: parent + color: "transparent" + visible: (symbole_unite !== "") + + Text { + id: valeur_actuelle + anchors { + verticalCenter: parent.verticalCenter + verticalCenterOffset: -80 + horizontalCenter: parent.horizontalCenter + horizontalCenterOffset: -20 + } + text: Fonctions.conversion_volume((capacite * niveau / 100), shipheart_unite_volume, "", precision_affichage_mesures); + font.family: "Montserrat" + font.pixelSize: 120 + font.weight: Font.Bold +// color: (nb_events > 0) ? couleur_rouge : couleur_blanc_casse + color: couleur_blanc_casse + } + + //------------------------------------------------------- + // Unite : + Text { + anchors { + baseline: valeur_actuelle.baseline + left: valeur_actuelle.right + leftMargin: 10 + } + text: shipheart_unite_volume_symbole + font.pixelSize: 20 + color: couleur_blanc_casse + } + + //------------------------------------------------------- + // Valeur en % de remplissage : + Text { + id: valeur_relative + anchors { + verticalCenter: parent.verticalCenter + verticalCenterOffset: 50 + horizontalCenter: parent.horizontalCenter + horizontalCenterOffset: -10 + } + text: qsTr("[ %1 % ]").arg(niveau.toFixed(0)) + font.family: "Montserrat" + font.pixelSize: 50 + color: couleur_blanc_casse + } + } + + //----------------------------------- + // Alarmes : + Rectangle { + id: zone_alarmes + width: parent.width + height: 50 + color: shipheart_couleur_fond_bouton + radius: shipheart_rayon_bouton + anchors { + left: parent.left + bottom: parent.bottom + } + visible: nb_events >= 0 + + Image { + source: (nb_events === 0) ? "/images/cloche_sombre.png" : "/images/cloche_rouge.png" + sourceSize.height: 20 + anchors { + verticalCenter: zone_alarmes.verticalCenter + horizontalCenter: zone_alarmes.horizontalCenter + } + } + + //----------------------------------- + // Zone de clics dédiée aux alarmes : + MouseArea{ + anchors.fill: zone_alarmes + + onClicked: { + shipheart_clic(); + boite_dialogue_liste_alarmes.open(); + } + } + } + + Component.onCompleted: { + mise_a_jour_valeurs_instantanees(); + } + } + + + + //------------------------------------------------------- + // Ecran haut - droite : + //------------------------------------------------------- + Rectangle { + id: zone_affichage_haut_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 * pourcentage_hauteur_ligne_haut * pourcentage_hauteur_ligne_erreur) - (espace_lignes_principales / 2) + color: "transparent" + border.width: 3 + border.color: couleur_rouge + radius: shipheart_rayon_bouton + visible: (etat_systeme === 0) && (texte_alerte !== "") + + Image { + id: picto_alerte + source: "/images/ak14.png" + sourceSize.height: 30; + 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. + 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: texte_alerte; + anchors { + left: picto_alerte.right + verticalCenter: parent.verticalCenter + } + font.pixelSize: 16 + color: couleur_blanc_casse + } + } + + + //------------------------------------------------------- + // Ecran milieu - droite : + //------------------------------------------------------- + Rectangle { + id: zone_affichage_milieu_droite + x: zone_affichage_haut_droite.x + y: zone_affichage_haut_droite.y + zone_affichage_haut_droite.height + espace_lignes_principales + width: zone_affichage_haut_droite.width + height: (affichage_hauteur_utile * pourcentage_hauteur_ligne_haut * (1 - pourcentage_hauteur_ligne_erreur)) - (espace_lignes_principales / 2) + color: "transparent" + visible: (etat_systeme === 0) + + + Rectangle { + id: visuel_niveau + width: parent.width * 0.6 + height: parent.height + color: "transparent" + border.width: 3 + border.color: couleur_gris_moyen + radius: 30 + anchors { + horizontalCenter: parent.horizontalCenter + } + Rectangle { + width: parent.width - (2 * parent.border.width) + height: (parent.height - (2 * parent.border.width)) * niveau / 100 + radius: 2 + color: couleur_bleu_koriolan_transparent + anchors { + bottom: parent.bottom + bottomMargin: parent.border.width + horizontalCenter: parent.horizontalCenter + } + } + + Rectangle { // Rectangle permettant de centrer tout le texte de capacité (valeur et unité) + width: texte_capacite_reservoir.paintedWidth + texte_unite_capacite_reservoir.paintedWidth + texte_unite_capacite_reservoir.anchors.leftMargin + height: texte_capacite_reservoir.paintedHeight + anchors { + verticalCenter: parent.verticalCenter + horizontalCenter: parent.horizontalCenter + } + color: "transparent" + Text { + id: texte_capacite_reservoir + text: Fonctions.conversion_volume(capacite, shipheart_unite_volume, "", 0); + font.pixelSize: 50 + font.bold: true + color: couleur_gris_tres_pale_transparent + } + Text { + id: texte_unite_capacite_reservoir + text: shipheart_unite_volume_symbole + anchors { + left: texte_capacite_reservoir.right + leftMargin: 20 + baseline: texte_capacite_reservoir.baseline + } + font.pixelSize: 20 + font.bold: true + color: couleur_gris_tres_pale_transparent + } + } + +/* Rectangle { // Ligne de niveau haut + width: parent.width * 0.9 + height: 1 + anchors { + bottom: parent.bottom + bottomMargin: (parent.height - (2 * parent.border.width)) * niveau_seuil_haut / 100 + horizontalCenter: parent.horizontalCenter + } + color: couleur_vert_transparent + } + Rectangle { // Ligne de niveau bas + width: parent.width * 0.9 + height: 1 + anchors { + bottom: parent.bottom + bottomMargin: (parent.height - (2 * parent.border.width)) * niveau_seuil_bas / 100 + horizontalCenter: parent.horizontalCenter + } + color: couleur_rouge_transparent + } +*/ + } + } + + + //------------------------------------------------------- + // Ecran bas : + //------------------------------------------------------- + Rectangle { + id: zone_affichage_bas + x: 0 + y: zone_affichage_haut_gauche.y + zone_affichage_haut_gauche.height + espace_lignes_principales; + width: shipheart_largeur_page; + height: affichage_hauteur_utile * (1 - pourcentage_hauteur_ligne_haut) + color: "transparent" + visible: (etat_systeme === 0) + + + //======================== + // Graphique : + ChartView { + id: graphique + antialiasing: true + anchors { + top: parent.top; + left:parent.left; + bottom:parent.bottom; + margins: -15 // Un peu compliqué mais permet, avec la ligne suivante, ... + } + margins { right: 0; bottom: 0; left: 5; top: 0 } // ... d'annuler les marges. + width: parent.width * pourcentage_largeur_graphique; + backgroundColor: "transparent" + // animationDuration: 10000 + // animationOptions: ChartView.SeriesAnimations + legend {visible: false } + visible: (id_variable !== 0) + + DateTimeAxis { + id: axisX + format: (zoomx_en_cours > 0.5) ? courbe_format_principal_axe_x : courbe_format_zoom_1_axe_x + min: xMin_date + max: xMax_date + tickCount: (zoomx_en_cours > 0.5) ? courbe_nombre_principal_graduations_axe_x : courbe_nombre_zoom_1_graduations_axe_x + //labelsColor: (!flag_zoom_en_cours) ? couleur_blanc_casse : couleur_green_yellow + labelsColor: couleur_blanc_casse + labelsFont: Qt.font({pointSize: 10}) + color: couleur_gris_moyen + shadesColor: courbes_couleur_shades_fond + shadesVisible: true + gridVisible: false + // gridLineColor: "green" + } + ValueAxis { + id: axisY1 + min: yMin_valeur + max: yMax_valeur + tickCount: courbe_nombre_graduations_axe_y + labelFormat: "%." + precision_affichage_axe_y_courbe + "f" +// labelsColor: (!flag_zoom_en_cours) ? couleur_blanc_casse : couleur_green_yellow + labelsColor: couleur_blanc_casse + labelsFont:Qt.font({pointSize: 10}) + color: couleur_gris_moyen + // shadesColor: courbes_couleur_shades_fond + shadesVisible: false + gridVisible: true + gridLineColor: couleur_gris_tres_fonce + titleText: "" + symbole_unite + "" + titleFont { + pointSize: 20 + bold: true + } + } + LineSeries { // Utilisé si on veut renforcer la courbe mais sans avoir tout le tour de l'area renfocée (qui se fait dans AreaSeries pour le coup) + id: courbe_principale + name: "Courbe principale" + axisX: axisX + axisY: axisY1 + capStyle: Qt.RoundCap + style: Qt.SolidLine + width: courbes_epaisseur_bordure + color: shipheart_couleur_bordure_courbes + } + Text { + id: texte_courbe_vide + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + text: qsTr("Aucune donnée n'est disponible pour cette période") + font.pixelSize: 20 + font.weight: Font.Bold + color: "red" + visible: courbe_flag_vide ? true : false; + } + + //--------------------------------- + // Rectangle de sélection de zoom : + Rectangle { + id: rectangle_zoom + x: pinch_area.zoom_x + y: pinch_area.zoom_y + width: pinch_area.zoom_w + height: pinch_area.zoom_h + radius: shipheart_rayon_zoom + + color: couleur_bleu_koriolan_tres_transparent + } + + //--------------------------------- + // Zone de pinch : + PinchArea{ + id: pinch_area + + // Propriété de la eone de zoom pendant toute la phase de sélection : + property real zoom_x: 0 + property real zoom_y: 0 + property real zoom_w: 0 + property real zoom_h: 0 + + anchors.fill: parent // Calé sur 'graphique'. + // Attention : la zone de traçage à l'intérieur de 'graphique' est 'graphique.plotArea'. + // Toutes les coordonnées sont données dans 'graphique' mais on limite à l'usage les coordonnées intérieures à 'graphique.plotArea'. + + //----------------------------------------------- + // Mis à jour en cours de déplacement du pinch : + onPinchUpdated: { + + if ((pinch.point1.x !== pinch.point2.x) || // Il arrive, en fin de pinch, que les 2 points renvoyés soient les mêmes... + (pinch.point1.y !== pinch.point2.y)) // ... Il faut éviter de les traiter sous peine de ramener W et H à 0. + { + // Récupération des données en s'affranchissant de la position des 2 points : + zoom_x = Math.min(pinch.point1.x, pinch.point2.x) + zoom_y = Math.min(pinch.point1.y, pinch.point2.y) + zoom_w = Math.abs(pinch.point1.x - pinch.point2.x) + zoom_h = Math.abs(pinch.point1.y - pinch.point2.y) + + // Limitation de 'x' et 'w' à la largeur de la zone de traçage : + if (zoom_x < graphique.plotArea.x) zoom_x = graphique.plotArea.x; + if (zoom_x > (graphique.plotArea.x + graphique.plotArea.width)) zoom_x = graphique.plotArea.x + graphique.plotArea.width + if ((zoom_x + zoom_w) > (graphique.plotArea.x + graphique.plotArea.width)) zoom_w = (graphique.plotArea.x + graphique.plotArea.width) - zoom_x; + + // Limitation de 'y' et 'h' à la hauteur de la zone de traçage : + if (zoom_y < graphique.plotArea.y) zoom_y = graphique.plotArea.y; + if (zoom_y > (graphique.plotArea.y + graphique.plotArea.height)) zoom_y = graphique.plotArea.y + graphique.plotArea.height + if ((zoom_y + zoom_h) > (graphique.plotArea.y + graphique.plotArea.height)) zoom_h = (graphique.plotArea.y + graphique.plotArea.height) - zoom_y; + } + } + + //------------------------- + // Valeur de fin du pinch : + onPinchFinished: { + // Préparation du zoom sur le rectangle sélectionné : + var r = Qt.rect(zoom_x, zoom_y, zoom_w, zoom_h); + graphique.zoomIn(r); + flag_zoom_en_cours = true; + + zoomx_en_cours *= (zoom_w / graphique.plotArea.width); + + // Effacement du rectangle : + zoom_x = 0 + zoom_y = 0 + zoom_w = 0 + zoom_h = 0 + } + + // Déplacement de la courbe : + MouseArea{ + anchors.fill: parent + drag.target: dragTarget + drag.axis: Drag.XAndYAxis + onClicked: { + shipheart_clic(); + if (!flag_zoom_en_cours) // Si le zoom est en cours, il ne faut PAS lancer le raffraichissement...! + { + busy_indicator.running = true; + timer_raffraichissement_graphiques.interval = periode_init_raffraichissement_graphiques; // Cela permet de lancer le "busy_indicator' avant de faire la mise à jour de la courbe + } + } + onPressAndHold: { + raz_zoom(); + } + } + Item { + id: dragTarget + property real oldX : x // Permet de mémoriser la dernière position d'arrivée + property real oldY : y + + property real cumulX : 0 // Permet de revenir à un déclage nul lorsque nécessaire + property real cumulY : 0 + + onXChanged: { + graphique.scrollLeft( x - oldX ); + cumulX -= (x - oldX); // Le signe '-' permettra ensuite de revenir à le position de départ + oldX = x; + } + + onYChanged: { + graphique.scrollUp( y - oldY ); + cumulY -= (y - oldY); // Le signe '-' permettra ensuite de revenir à le position de départ + oldY = y; + } + } + } + } + + //======================== + // Busy Indicator : + Shipheart_busy_indicator { + id: busy_indicator + } + + //======================== + // Boutons de pếriode : + ColumnLayout { + spacing: 10 + anchors { + top: parent.top; + right:parent.right; + rightMargin: 5; + bottom:parent.bottom; + } + width: (parent.width * (1 - pourcentage_largeur_graphique)) - anchors.rightMargin; + + ListModel { + id: modele_periodes_graphique + } + + Repeater { + model: modele_periodes_graphique + + Rectangle { + color: "transparent" + Layout.preferredWidth: parent.width; + Layout.preferredHeight: (parent.height / nb_boutons_periode) - parent.spacing; + + Text { + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + text: model.libelle + font.pixelSize: 18 + font.weight: (model.index === periode_analyse) ? Font.Bold : Font.Normal + color: couleur_blanc_casse + } + 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 + onClicked: { + shipheart_clic(); + raz_zoom(); // Au-delà de la fonctionnalité, c'est obligatoire sinon, le raffraichissement des la courbe est bloqué au niveau du timer + periode_analyse = model.index; + busy_indicator.running = true; + timer_raffraichissement_graphiques.interval = periode_init_raffraichissement_graphiques; // Cela permet de lancer le "busy_indicator' avant de faire la mise à jour de la courbe + } + } + // Fond du bouton : + Rectangle { // Permet d'avoir un fond et de pouvoir régler son opacité sans changer celle des textes au-dessus + width: parent.width + height: parent.height + color: (model.index === periode_analyse) ? (flag_zoom_en_cours ? couleur_green_yellow_transparent : shipheart_couleur_fond_bouton_actif) : shipheart_couleur_fond_bouton; + opacity: 0.5 + radius: shipheart_rayon_bouton + } + } + } + } + } + + + //------------------------------------------------------- + // Message d'erreur si réservoir Absent + // (le module sur lequel le réservoir est configuré n'est pas physiquement présent) + //------------------------------------------------------- + Rectangle { + id: zone_message_absence + x: 0 + y: shipheart_hauteur_bandeau_haut + espace_lignes_principales + width: shipheart_largeur_page + height: shipheart_hauteur_page - shipheart_hauteur_bandeau_haut - shipheart_hauteur_bandeau_bas - espace_lignes_principales + color: "transparent" + visible: (etat_systeme !== 0) + + Rectangle { // Rectangle entouré de rouge + anchors.verticalCenter: parent.verticalCenter + anchors.verticalCenterOffset: -50 + anchors.horizontalCenter: parent.horizontalCenter + width: parent.width + height: parent.height / 2 + radius: shipheart_rayon_bouton + border.width: 3 + border.color: couleur_rouge + color: couleur_rouge_transparent + + Image { // Pictogramme DANGER + anchors.verticalCenter: parent.verticalCenter + anchors.verticalCenterOffset: -100 + anchors.horizontalCenter: parent.horizontalCenter + source: "/images/ak14.png" + sourceSize.height: 70; + } + + Text { // Texte d'info + anchors.verticalCenter: parent.verticalCenter + anchors.verticalCenterOffset: 50 + anchors.horizontalCenter: parent.horizontalCenter + width: parent.width + height : parent.height / 2 + horizontalAlignment: Qt.AlignCenter + verticalAlignment: Qt.AlignVCenter + padding: 50 + text: qsTr("Le module assurant la supervision de ce réservoir n'est pas accessible !

Si des ajouts/suppression/déplacements de modules ont eu lieu récemment, mettez à jour la configuration correspondant dans le menu MODULES de PARAMETRES AVANCES.

Dans le cas où aucune modification n'a été effectuée récemment, vérifier les connexions de tous les modules.") + color: couleur_blanc_casse + font.pixelSize: 18 + wrapMode: Label.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: 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() + } + } + } + } + + + //------------------------------------------------------- + // Boite d'affichage de la liste des alarmes : + //------------------------------------------------------- + Shipheart_boite_dialogue_liste_alarmes { + id: boite_dialogue_liste_alarmes + + titre: nom_reservoir + type_source: shipheart_source_mesure_reservoir + id_source: id_reservoir + id_variable: page_reservoir.id_variable + titre_widget: qsTr("Niveau") + unite: "%" + } + + //=========================================================== + // 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; + + + //==================================================================== + // Init du nom des périodes du graphique : + modele_periodes_graphique.append({ "libelle": Fonctions_date_heure.nom_periode_analyse(0), "actif": true }); + modele_periodes_graphique.append({ "libelle": Fonctions_date_heure.nom_periode_analyse(1), "actif": true }); + modele_periodes_graphique.append({ "libelle": Fonctions_date_heure.nom_periode_analyse(2), "actif": true }); + modele_periodes_graphique.append({ "libelle": Fonctions_date_heure.nom_periode_analyse(3), "actif": true }); + + + //==================================================================== + // Recherche de ID_Variable : + req = ' SELECT Cle_primaire, Unite FROM TB_Variables WHERE Code="' + shipheart_reservoir_niveau + '" '; + res = bdd.requete_unique(req); + id_variable = Number(res[0]); + symbole_unite = res[1]; + + //==================================================================== + // Première mise à jour : + mise_a_jour_valeurs_instantanees(); + mise_a_jour_courbes(); + + //==================================================================== + // Libération du flag : + flag_init = false; + } + + + + + //============================================================================================================= + // Mise à jour de la valeur instantanée + //============================================================================================================= + function mise_a_jour_valeurs_instantanees() + { + var req, res; + var nb; + var i; + var type_entrees; + var etat; + + //==================================================================== + // Valeur numérique instantanée : + req = 'SELECT Niveau, '; + req += ' Capacite, '; + req += ' ID_Famille, '; + req += ' Etat_systeme, '; + req += ' Type_entrees, '; + req += ' Etat_entrees '; + req += ' FROM TB_Reservoirs '; + req += ' WHERE Cle_primaire="' + id_reservoir + '" '; + res = bdd.requete_unique(req); + niveau = Number(res[0]); + capacite = Number(res[1]); + id_famille = Number(res[2]); + etat_systeme = Number(res[3]); + type_entrees = Number(res[4]); + etat = Number(res[5]); + +//console.log("Niveau = " + niveau); + + switch(shipheart_unite_volume) + { + case shipheart_unite_volume_litres: precision_affichage_mesures = 0; break; + case shipheart_unite_volume_us_gallons: precision_affichage_mesures = 1; break; + case shipheart_unite_volume_imp_gallons: precision_affichage_mesures = 1; break; + default : precision_affichage_mesures = 1; break; + } + + // Message d'alerte : + if ((type_entrees === shipheart_reservoir_type_entrees_aux) && (etat !== shipheart_capteur_etat_normal)) + { + texte_alerte = qsTr("La valeur lue sur les electrodes plongées de ce réservoir est incohérente.
Vérifier l'ordre de cablage des électrodes sur les entrées auxiliaires à l'arrière de ShipBase. ") + } + else texte_alerte = ""; + + + // Recherche des events liés à ce capteur et leur valeur : + nb_events = -1; + + req = 'SELECT Etat_test '; + req += ' FROM TB_Events '; + req += ' WHERE Alarme_source>0 '; + req += ' AND Type_source=' + shipheart_source_mesure_reservoir + ' '; + req += ' AND ID_Source=' + id_reservoir + ' '; +//console.log("Requête = [ " + req + "; ]"); + nb = bdd.requete(req); + for (i = 0; i < nb; i ++) + { + res = bdd.lecture_ligne(); + if (!res.isEmpty) + { + if (nb_events < Number(res[0])) nb_events = Number(res[0]); + } + } + // En sortant, on a donc nb_events=-1 si aucun event lié, 0 si au moins un event lié mais tous leurs Etat_test=0, et 1 si au moins un event et au moins un a Etat_test=1. + } + + + //============================================================================================================= + // Mise à jour des données des courbes + //============================================================================================================= + function mise_a_jour_courbes() + { + var req, res; + var nb; + var courbe_principale_duree; + var date_debut, date_fin; + var delta_x, delta_y; + var min, max; + var mini_maxi; + var gradient; + var id_sb_in_i, id_sb_usb_i; + +//console.time('mise_a_jour_courbes') + + // Paramètres de la courbe dépendant de la période d'analyse : + switch(periode_analyse) + { + default: + case 0: // 1 heure + courbe_nombre_principal_graduations_axe_x = 7 // Nombre de bandes verticales + 1 + courbe_nombre_zoom_1_graduations_axe_x = 7 // Utilisé lorsque le taux de zoom passe en-dessous de 0.5 + courbe_format_principal_axe_x = "HH:mm" // exemple : "yyyy-MM-dd HH:mm:ss" + courbe_format_zoom_1_axe_x = "HH:mm" // Utilisé lorsque le taux de zoom passe en-dessous de 0.5 + break; + + case 1: // 24 heures + courbe_nombre_principal_graduations_axe_x = 13 // Nombre de bandes verticales + 1 + courbe_nombre_zoom_1_graduations_axe_x = 13 // Utilisé lorsque le taux de zoom passe en-dessous de 0.5 + courbe_format_principal_axe_x = "HH:mm" // exemple : "yyyy-MM-dd HH:mm:ss" + courbe_format_zoom_1_axe_x = "HH:mm" // Utilisé lorsque le taux de zoom passe en-dessous de 0.5 + break; + + case 2: // 7 jours + courbe_nombre_principal_graduations_axe_x = 8 // Nombre de bandes verticales + 1 + courbe_nombre_zoom_1_graduations_axe_x = 8 // Utilisé lorsque le taux de zoom passe en-dessous de 0.5 + courbe_format_principal_axe_x = "dd/MM HH:mm" // exemple : "yyyy-MM-dd HH:mm:ss" + courbe_format_zoom_1_axe_x = "HH:mm" // Utilisé lorsque le taux de zoom passe en-dessous de 0.5 + break; + + case 3: // 30 jours + courbe_nombre_principal_graduations_axe_x = 31 // Nombre de bandes verticales + 1 + courbe_nombre_zoom_1_graduations_axe_x = 13 // Utilisé lorsque le taux de zoom passe en-dessous de 0.5 + courbe_format_principal_axe_x = "dd" // exemple : "yyyy-MM-dd HH:mm:ss" + courbe_format_zoom_1_axe_x = "HH:mm" // Utilisé lorsque le taux de zoom passe en-dessous de 0.5 + break; + } + + + // Dates et durée : + courbe_principale_duree = Fonctions_date_heure.duree_periode_analyse(periode_analyse); // En secondes + date_fin = new Date(); // En UTC + date_debut = Fonctions_date_heure.date_add_secondes(date_fin, -(courbe_principale_duree)); // En UTC +//console.log("Date de début initiale UTC = " + date_debut + " et date de fin UTC = " + date_fin) + + // Mise à jour des données de la courbe principale : + res = tbmesuresModel.maj_data(graphique.series("Courbe principale"), "TB_Mesures_reservoirs", id_reservoir, id_variable, date_debut, date_fin, 1, 1, (shipheart_fuseau_horaire + shipheart_heure_ete), 0, 0); + + + //----------------------------------------------------------------------------------------------------- + // Cas où aucune donnée n'est disponible sur la période : + if (Number(res[0]) === 0) + { + courbe_flag_vide = true; // Permet d'afficher le texte "Aucune donnée disponible..." sur la zone graphique + } + //----------------------------------------------------------------------------------------------------- + // Cas où des données sont disponibles sur la période (cas normal donc...) : + else + { + courbe_flag_vide = false; + + xMin_date = new Date(Number(res[1])); // Nécessaire pour la Min de l'axe X (NB : les dates retournées par 'maj_data' sont en heure locale) + xMax_date = new Date(Number(res[3])); // Nécessaire pour la Max de l'axe X (NB : les dates retournées par 'maj_data' sont en heure locale) + // var mini_maxi = Fonctions.ajustement_mini_maxi(Number(res[6]), Number(res[8]), courbe_principale_nombre_graduations_axe_y); + // yMin_valeur = mini_maxi.mini // Nécessaire pour le Min de l'axe Y + // yMax_valeur = mini_maxi.maxi // Nécessaire pour le Max de l'axe Y + yMin_valeur = 0 + yMax_valeur = 100.4 // Le '.4' permet de libérer l'espace de l'épaisseur du trait haut quand on est à 100%... +// precision_affichage_axe_y_courbe = Fonctions.precision_affichage_mini_maxi(Number(res[6]), Number(res[8]), courbe_principale_nombre_graduations_axe_y); + precision_affichage_axe_y_courbe = 0 +//console.log("Min val=" + Number(res[6]) + " et mini=" + yMin_valeur + " - Max val=" + Number(res[8]) + " et maxi=" + yMax_valeur); + +console.timeEnd('mise_a_jour_courbes') + } + busy_indicator.running = false; // Arrêt du tourniquet s'il est en marche + } + + + //============================================================================================================= + // RAZ du zoom + //============================================================================================================= + function raz_zoom() + { + + graphique.zoomReset(); // RAZ du zoom proprement dit + graphique.scrollLeft(dragTarget.cumulX); // RAZ du déplacement horizontal par annulation du cumul + graphique.scrollUp(dragTarget.cumulY); // RAZ du déplacement vertical par annulation du cumul + + dragTarget.cumulX = 0; // RAZ du cumul après retour à la position d'origine + dragTarget.cumulY = 0; + + flag_zoom_en_cours = false; + zoomx_en_cours = 1; + } + + +} diff --git a/shipheart.h b/shipheart.h new file mode 100755 index 0000000..589e97a --- /dev/null +++ b/shipheart.h @@ -0,0 +1,44 @@ +#ifndef SHIPHEART_H +#define SHIPHEART_H + +#include // Nécessaire pour les fonctions du type 'numeric_limits' qui donnent les valeurs maxi en fonction du type. Exemple : std::numeric_limits::max(); +#include + + + +// Type mesure : +#define SOURCE_MESURE_CIRCUIT 1 +#define SOURCE_MESURE_CAPTEUR 2 +#define SOURCE_MESURE_RESERVOIR 3 +#define SOURCE_MESURE_BATTERIE 4 + +// Type unité : +#define UNITE_VOLUME 1 +#define UNITE_TEMPERATURE 2 +#define UNITE_LATITUDE 3 // A priori, pas utilisé dans la partie C++ +#define UNITE_LONGITUDE 4 // A priori, pas utilisé dans la partie C++ + +// Unités de type Volume : +#define UNITE_VOLUME_LITRES 0 +#define UNITE_VOLUME_US_GALLONS 1 +#define UNITE_VOLUME_IMP_GALLONS 2 + +// Unités de type Température : +#define UNITE_TEMPERATURE_CELSIUS 0 +#define UNITE_TEMPERATURE_FAHRENHEIT 1 + + + + +#define FORMAT_DATE_HEURE_BDD "yyyy-MM-dd hh:mm:ss" + + +// Base de données : +//#define BDD_HOST_NAME "192.168.1.195" +#define BDD_HOST_NAME "localhost" +#define BDD_USER_NAME "koriolan" +#define BDD_USER_PWD "Mp7Hgf12bV9zm" +#define BDD_BASE_NAME "shipheart" + + +#endif // SHIPHEART_H diff --git a/shipheart.pro b/shipheart.pro new file mode 100755 index 0000000..6c48c7f --- /dev/null +++ b/shipheart.pro @@ -0,0 +1,354 @@ +QT += quick virtualkeyboard +QT += qml sql quickcontrols2 charts + +CONFIG += c++11 + +TEMPLATE = app + +# Suppression du fichier 'main.o' pour forcer la recompilation de 'main.c'. +# Cela permet que main.c prenne en compte la nouvelle valeur de VERSION... +exists($${OUT_PWD}/main.o) { + system(rm $${OUT_PWD}/main.o) +} + +# Suppression du fichier 'Makefile' pour forcer sa regénération. +# Sinon, le fichier est considéré comme inchangé et la date n'est pas recalculée. +# NB : la suppression comme le .o ci-dessus ne fonctionne pas... La source de la solution est : https://stackoverflow.com/questions/12873437/force-qtcreator-to-run-qmake-when-building +qmakeforce.target = dummy +qmakeforce.commands = rm -f Makefile ##to force rerun of qmake +qmakeforce.depends = FORCE +PRE_TARGETDEPS += $$qmakeforce.target +QMAKE_EXTRA_TARGETS += qmakeforce + +# Calcul de la version : +VERSION = $$system(date +%y%m%d_%H%M%S) + +message($$VERSION) + +# Define rendu disponible en C++ : +DEFINES += VERSION="\\\"$$VERSION\\\"" + +TARGET = shipheart_qt + +# Copie du fichier exécutable (en post_link) vers le fichier avec la version en extension : +QMAKE_POST_LINK += $$quote(cp $${TARGET} /home/koriolan/SharePoint_Koriolan_Documents/Technique/Projets_Qt/koriolan/shipheart/versions/shipheart_qt_$${VERSION}) +#QMAKE_POST_LINK += $$quote(cp /home/koriolan/qt/koriolan/build-shipheart-ShipHeart-Release/shipheart_qt /home/koriolan/SharePoint_Koriolan_Documents/Technique/Projets_Qt/koriolan/shipheart/versions/shipheart_qt_$${VERSION}) $$escape_expand(\n\t) + + +# You can make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +SOURCES += \ + backend.cpp \ + bdd.cpp \ + main.cpp \ + systeme.cpp \ + tb_mesures.cpp + +RESOURCES += qml.qrc \ + traductions.qrc + +# Pour ajouter une langue, ajouter le nom du fichier ci-dessous puis lancer 'lupdate' (qui va créér le fichier .ts). +# Il faut ensuite traiter le fichier .ts avec 'qlinguist' et enregistrer les modifs. +# Puis publier l'ensemble via 'lrelease' +# Enfin, il faut aller dans le répertoire "traductions.qrc" et faire et sélectionner le fichier .qm correspondant à la langue créée. +# Relancer la compilation/chargement et la nouvelle langue doit être visible... +# NB : le code s'appuie sur 'fonctions_localisation.js' et le champ 'code_langue' dans le tableau 'langues'. Il faut s'assurer que la langue à créer existe +# bien dans ce tableau et que son nom correspond à ce code langue ! +TRANSLATIONS += \ + 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 + +# Additional import path used to resolve QML modules in Qt Creator's code model +QML_IMPORT_PATH = + +# Additional import path used to resolve QML modules just for Qt Quick Designer +QML_DESIGNER_IMPORT_PATH = + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +# Pour indiquer où le chargement sur la cible doit se faire : +# target.path = /home/koriolan/projets/qt +target.path = /home/koriolan/shipheart/versions/current + +HEADERS += \ + _version.h \ + backend.h \ + bdd.h \ + shipheart.h \ + systeme.h \ + tb_mesures.h + +DISTFILES += \ + shipheart_lv_LV.ts \ + virtualkeyboard_layouts_koriolan/layouts/ar_AR/dialpad.fallback \ + virtualkeyboard_layouts_koriolan/layouts/ar_AR/digits.qml \ + virtualkeyboard_layouts_koriolan/layouts/ar_AR/handwriting.qml \ + virtualkeyboard_layouts_koriolan/layouts/ar_AR/main.qml \ + virtualkeyboard_layouts_koriolan/layouts/ar_AR/numbers.qml \ + virtualkeyboard_layouts_koriolan/layouts/ar_AR/symbols.qml \ + virtualkeyboard_layouts_koriolan/layouts/bg_BG/dialpad.fallback \ + virtualkeyboard_layouts_koriolan/layouts/bg_BG/digits.fallback \ + virtualkeyboard_layouts_koriolan/layouts/bg_BG/handwriting.qml \ + virtualkeyboard_layouts_koriolan/layouts/bg_BG/main.qml \ + virtualkeyboard_layouts_koriolan/layouts/bg_BG/numbers.fallback \ + virtualkeyboard_layouts_koriolan/layouts/bg_BG/symbols.fallback \ + virtualkeyboard_layouts_koriolan/layouts/cs_CZ/dialpad.fallback \ + virtualkeyboard_layouts_koriolan/layouts/cs_CZ/digits.fallback \ + virtualkeyboard_layouts_koriolan/layouts/cs_CZ/handwriting.qml \ + virtualkeyboard_layouts_koriolan/layouts/cs_CZ/main.qml \ + virtualkeyboard_layouts_koriolan/layouts/cs_CZ/numbers.fallback \ + virtualkeyboard_layouts_koriolan/layouts/cs_CZ/symbols.fallback \ + virtualkeyboard_layouts_koriolan/layouts/da_DK/dialpad.fallback \ + virtualkeyboard_layouts_koriolan/layouts/da_DK/digits.fallback \ + virtualkeyboard_layouts_koriolan/layouts/da_DK/handwriting.fallback \ + virtualkeyboard_layouts_koriolan/layouts/da_DK/main.qml \ + virtualkeyboard_layouts_koriolan/layouts/da_DK/numbers.fallback \ + virtualkeyboard_layouts_koriolan/layouts/da_DK/symbols.fallback \ + virtualkeyboard_layouts_koriolan/layouts/de_DE/dialpad.fallback \ + virtualkeyboard_layouts_koriolan/layouts/de_DE/digits.fallback \ + virtualkeyboard_layouts_koriolan/layouts/de_DE/handwriting.fallback \ + virtualkeyboard_layouts_koriolan/layouts/de_DE/main.qml \ + virtualkeyboard_layouts_koriolan/layouts/de_DE/numbers.fallback \ + virtualkeyboard_layouts_koriolan/layouts/de_DE/symbols.fallback \ + virtualkeyboard_layouts_koriolan/layouts/el_GR/dialpad.fallback \ + virtualkeyboard_layouts_koriolan/layouts/el_GR/digits.fallback \ + virtualkeyboard_layouts_koriolan/layouts/el_GR/handwriting.qml \ + virtualkeyboard_layouts_koriolan/layouts/el_GR/main.qml \ + virtualkeyboard_layouts_koriolan/layouts/el_GR/numbers.fallback \ + virtualkeyboard_layouts_koriolan/layouts/el_GR/symbols.fallback \ + virtualkeyboard_layouts_koriolan/layouts/en_GB/dialpad.fallback \ + virtualkeyboard_layouts_koriolan/layouts/en_GB/digits.fallback \ + virtualkeyboard_layouts_koriolan/layouts/en_GB/handwriting.fallback \ + virtualkeyboard_layouts_koriolan/layouts/en_GB/main.fallback \ + virtualkeyboard_layouts_koriolan/layouts/en_GB/numbers.fallback \ + virtualkeyboard_layouts_koriolan/layouts/en_GB/symbols.fallback \ + virtualkeyboard_layouts_koriolan/layouts/en_US/dialpad.fallback \ + virtualkeyboard_layouts_koriolan/layouts/en_US/digits.fallback \ + virtualkeyboard_layouts_koriolan/layouts/en_US/handwriting.fallback \ + virtualkeyboard_layouts_koriolan/layouts/en_US/main.fallback \ + virtualkeyboard_layouts_koriolan/layouts/en_US/numbers.fallback \ + virtualkeyboard_layouts_koriolan/layouts/en_US/symbols.fallback \ + virtualkeyboard_layouts_koriolan/layouts/es_ES/dialpad.fallback \ + virtualkeyboard_layouts_koriolan/layouts/es_ES/digits.fallback \ + virtualkeyboard_layouts_koriolan/layouts/es_ES/handwriting.qml \ + virtualkeyboard_layouts_koriolan/layouts/es_ES/main.qml \ + virtualkeyboard_layouts_koriolan/layouts/es_ES/numbers.fallback \ + virtualkeyboard_layouts_koriolan/layouts/es_ES/symbols.qml \ + virtualkeyboard_layouts_koriolan/layouts/es_MX/dialpad.fallback \ + virtualkeyboard_layouts_koriolan/layouts/es_MX/digits.fallback \ + virtualkeyboard_layouts_koriolan/layouts/es_MX/handwriting.qml \ + virtualkeyboard_layouts_koriolan/layouts/es_MX/main.qml \ + virtualkeyboard_layouts_koriolan/layouts/es_MX/numbers.fallback \ + virtualkeyboard_layouts_koriolan/layouts/es_MX/symbols.qml \ + virtualkeyboard_layouts_koriolan/layouts/et_EE/dialpad.fallback \ + virtualkeyboard_layouts_koriolan/layouts/et_EE/digits.fallback \ + virtualkeyboard_layouts_koriolan/layouts/et_EE/handwriting.fallback \ + virtualkeyboard_layouts_koriolan/layouts/et_EE/main.qml \ + virtualkeyboard_layouts_koriolan/layouts/et_EE/numbers.fallback \ + virtualkeyboard_layouts_koriolan/layouts/et_EE/symbols.fallback \ + virtualkeyboard_layouts_koriolan/layouts/fa_FA/dialpad.fallback \ + virtualkeyboard_layouts_koriolan/layouts/fa_FA/digits.qml \ + virtualkeyboard_layouts_koriolan/layouts/fa_FA/handwriting.qml \ + virtualkeyboard_layouts_koriolan/layouts/fa_FA/main.qml \ + virtualkeyboard_layouts_koriolan/layouts/fa_FA/numbers.qml \ + virtualkeyboard_layouts_koriolan/layouts/fa_FA/symbols.qml \ + virtualkeyboard_layouts_koriolan/layouts/fallback/dialpad.qml \ + virtualkeyboard_layouts_koriolan/layouts/fallback/digits.qml \ + virtualkeyboard_layouts_koriolan/layouts/fallback/handwriting.qml \ + virtualkeyboard_layouts_koriolan/layouts/fallback/main.qml \ + virtualkeyboard_layouts_koriolan/layouts/fallback/numbers.qml \ + virtualkeyboard_layouts_koriolan/layouts/fallback/symbols.qml \ + virtualkeyboard_layouts_koriolan/layouts/fi_FI/dialpad.fallback \ + virtualkeyboard_layouts_koriolan/layouts/fi_FI/digits.fallback \ + virtualkeyboard_layouts_koriolan/layouts/fi_FI/handwriting.fallback \ + virtualkeyboard_layouts_koriolan/layouts/fi_FI/main.qml \ + virtualkeyboard_layouts_koriolan/layouts/fi_FI/numbers.fallback \ + virtualkeyboard_layouts_koriolan/layouts/fi_FI/symbols.fallback \ + virtualkeyboard_layouts_koriolan/layouts/fr_CA/dialpad.fallback \ + virtualkeyboard_layouts_koriolan/layouts/fr_CA/digits.fallback \ + virtualkeyboard_layouts_koriolan/layouts/fr_CA/handwriting.fallback \ + virtualkeyboard_layouts_koriolan/layouts/fr_CA/main.qml \ + virtualkeyboard_layouts_koriolan/layouts/fr_CA/numbers.fallback \ + virtualkeyboard_layouts_koriolan/layouts/fr_CA/symbols.fallback \ + virtualkeyboard_layouts_koriolan/layouts/fr_FR/dialpad.fallback \ + virtualkeyboard_layouts_koriolan/layouts/fr_FR/digits.fallback \ + virtualkeyboard_layouts_koriolan/layouts/fr_FR/handwriting.fallback \ + virtualkeyboard_layouts_koriolan/layouts/fr_FR/main.qml \ + virtualkeyboard_layouts_koriolan/layouts/fr_FR/numbers.fallback \ + virtualkeyboard_layouts_koriolan/layouts/fr_FR/symbols.fallback \ + virtualkeyboard_layouts_koriolan/layouts/he_IL/dialpad.fallback \ + virtualkeyboard_layouts_koriolan/layouts/he_IL/digits.fallback \ + virtualkeyboard_layouts_koriolan/layouts/he_IL/handwriting.qml \ + virtualkeyboard_layouts_koriolan/layouts/he_IL/main.qml \ + virtualkeyboard_layouts_koriolan/layouts/he_IL/numbers.fallback \ + virtualkeyboard_layouts_koriolan/layouts/he_IL/symbols.qml \ + virtualkeyboard_layouts_koriolan/layouts/hi_IN/dialpad.fallback \ + virtualkeyboard_layouts_koriolan/layouts/hi_IN/digits.fallback \ + virtualkeyboard_layouts_koriolan/layouts/hi_IN/handwriting.qml \ + virtualkeyboard_layouts_koriolan/layouts/hi_IN/main.qml \ + virtualkeyboard_layouts_koriolan/layouts/hi_IN/numbers.fallback \ + virtualkeyboard_layouts_koriolan/layouts/hi_IN/symbols.qml \ + virtualkeyboard_layouts_koriolan/layouts/hr_HR/dialpad.fallback \ + virtualkeyboard_layouts_koriolan/layouts/hr_HR/digits.fallback \ + virtualkeyboard_layouts_koriolan/layouts/hr_HR/handwriting.qml \ + virtualkeyboard_layouts_koriolan/layouts/hr_HR/main.qml \ + virtualkeyboard_layouts_koriolan/layouts/hr_HR/numbers.fallback \ + virtualkeyboard_layouts_koriolan/layouts/hr_HR/symbols.fallback \ + virtualkeyboard_layouts_koriolan/layouts/hu_HU/dialpad.fallback \ + virtualkeyboard_layouts_koriolan/layouts/hu_HU/digits.fallback \ + virtualkeyboard_layouts_koriolan/layouts/hu_HU/handwriting.qml \ + virtualkeyboard_layouts_koriolan/layouts/hu_HU/main.qml \ + virtualkeyboard_layouts_koriolan/layouts/hu_HU/numbers.fallback \ + virtualkeyboard_layouts_koriolan/layouts/hu_HU/symbols.fallback \ + virtualkeyboard_layouts_koriolan/layouts/id_ID/dialpad.fallback \ + virtualkeyboard_layouts_koriolan/layouts/id_ID/digits.fallback \ + virtualkeyboard_layouts_koriolan/layouts/id_ID/handwriting.fallback \ + virtualkeyboard_layouts_koriolan/layouts/id_ID/main.fallback \ + virtualkeyboard_layouts_koriolan/layouts/id_ID/numbers.fallback \ + virtualkeyboard_layouts_koriolan/layouts/id_ID/symbols.fallback \ + virtualkeyboard_layouts_koriolan/layouts/it_IT/dialpad.fallback \ + virtualkeyboard_layouts_koriolan/layouts/it_IT/digits.fallback \ + virtualkeyboard_layouts_koriolan/layouts/it_IT/handwriting.fallback \ + virtualkeyboard_layouts_koriolan/layouts/it_IT/main.qml \ + virtualkeyboard_layouts_koriolan/layouts/it_IT/numbers.fallback \ + virtualkeyboard_layouts_koriolan/layouts/it_IT/symbols.fallback \ + virtualkeyboard_layouts_koriolan/layouts/ja_JP/dialpad.fallback \ + virtualkeyboard_layouts_koriolan/layouts/ja_JP/digits.fallback \ + virtualkeyboard_layouts_koriolan/layouts/ja_JP/handwriting.qml \ + virtualkeyboard_layouts_koriolan/layouts/ja_JP/main.qml \ + virtualkeyboard_layouts_koriolan/layouts/ja_JP/numbers.fallback \ + virtualkeyboard_layouts_koriolan/layouts/ja_JP/symbols.qml \ + virtualkeyboard_layouts_koriolan/layouts/ko_KR/dialpad.fallback \ + virtualkeyboard_layouts_koriolan/layouts/ko_KR/digits.fallback \ + virtualkeyboard_layouts_koriolan/layouts/ko_KR/handwriting.qml \ + virtualkeyboard_layouts_koriolan/layouts/ko_KR/main.qml \ + virtualkeyboard_layouts_koriolan/layouts/ko_KR/numbers.fallback \ + virtualkeyboard_layouts_koriolan/layouts/ko_KR/symbols.qml \ + virtualkeyboard_layouts_koriolan/layouts/ms_MY/dialpad.fallback \ + virtualkeyboard_layouts_koriolan/layouts/ms_MY/digits.fallback \ + virtualkeyboard_layouts_koriolan/layouts/ms_MY/handwriting.fallback \ + virtualkeyboard_layouts_koriolan/layouts/ms_MY/main.fallback \ + virtualkeyboard_layouts_koriolan/layouts/ms_MY/numbers.fallback \ + virtualkeyboard_layouts_koriolan/layouts/ms_MY/symbols.fallback \ + virtualkeyboard_layouts_koriolan/layouts/nb_NO/dialpad.fallback \ + virtualkeyboard_layouts_koriolan/layouts/nb_NO/digits.fallback \ + virtualkeyboard_layouts_koriolan/layouts/nb_NO/handwriting.fallback \ + virtualkeyboard_layouts_koriolan/layouts/nb_NO/main.qml \ + virtualkeyboard_layouts_koriolan/layouts/nb_NO/numbers.fallback \ + virtualkeyboard_layouts_koriolan/layouts/nb_NO/symbols.fallback \ + virtualkeyboard_layouts_koriolan/layouts/nl_NL/dialpad.fallback \ + virtualkeyboard_layouts_koriolan/layouts/nl_NL/digits.fallback \ + virtualkeyboard_layouts_koriolan/layouts/nl_NL/handwriting.fallback \ + virtualkeyboard_layouts_koriolan/layouts/nl_NL/main.fallback \ + virtualkeyboard_layouts_koriolan/layouts/nl_NL/numbers.fallback \ + virtualkeyboard_layouts_koriolan/layouts/nl_NL/symbols.fallback \ + virtualkeyboard_layouts_koriolan/layouts/pl_PL/dialpad.fallback \ + virtualkeyboard_layouts_koriolan/layouts/pl_PL/digits.fallback \ + virtualkeyboard_layouts_koriolan/layouts/pl_PL/handwriting.fallback \ + virtualkeyboard_layouts_koriolan/layouts/pl_PL/main.qml \ + virtualkeyboard_layouts_koriolan/layouts/pl_PL/numbers.fallback \ + virtualkeyboard_layouts_koriolan/layouts/pl_PL/symbols.fallback \ + virtualkeyboard_layouts_koriolan/layouts/pt_BR/dialpad.fallback \ + virtualkeyboard_layouts_koriolan/layouts/pt_BR/digits.fallback \ + virtualkeyboard_layouts_koriolan/layouts/pt_BR/handwriting.fallback \ + virtualkeyboard_layouts_koriolan/layouts/pt_BR/main.qml \ + virtualkeyboard_layouts_koriolan/layouts/pt_BR/numbers.fallback \ + virtualkeyboard_layouts_koriolan/layouts/pt_BR/symbols.fallback \ + virtualkeyboard_layouts_koriolan/layouts/pt_PT/dialpad.fallback \ + virtualkeyboard_layouts_koriolan/layouts/pt_PT/digits.fallback \ + virtualkeyboard_layouts_koriolan/layouts/pt_PT/handwriting.fallback \ + virtualkeyboard_layouts_koriolan/layouts/pt_PT/main.qml \ + virtualkeyboard_layouts_koriolan/layouts/pt_PT/numbers.fallback \ + virtualkeyboard_layouts_koriolan/layouts/pt_PT/symbols.fallback \ + virtualkeyboard_layouts_koriolan/layouts/ro_RO/dialpad.fallback \ + virtualkeyboard_layouts_koriolan/layouts/ro_RO/digits.fallback \ + virtualkeyboard_layouts_koriolan/layouts/ro_RO/handwriting.qml \ + virtualkeyboard_layouts_koriolan/layouts/ro_RO/main.qml \ + virtualkeyboard_layouts_koriolan/layouts/ro_RO/numbers.fallback \ + virtualkeyboard_layouts_koriolan/layouts/ro_RO/symbols.fallback \ + virtualkeyboard_layouts_koriolan/layouts/ru_RU/dialpad.fallback \ + virtualkeyboard_layouts_koriolan/layouts/ru_RU/digits.fallback \ + virtualkeyboard_layouts_koriolan/layouts/ru_RU/handwriting.fallback \ + virtualkeyboard_layouts_koriolan/layouts/ru_RU/main.qml \ + virtualkeyboard_layouts_koriolan/layouts/ru_RU/numbers.fallback \ + virtualkeyboard_layouts_koriolan/layouts/ru_RU/symbols.fallback \ + virtualkeyboard_layouts_koriolan/layouts/sk_SK/dialpad.fallback \ + virtualkeyboard_layouts_koriolan/layouts/sk_SK/digits.fallback \ + virtualkeyboard_layouts_koriolan/layouts/sk_SK/handwriting.fallback \ + virtualkeyboard_layouts_koriolan/layouts/sk_SK/main.qml \ + virtualkeyboard_layouts_koriolan/layouts/sk_SK/numbers.fallback \ + virtualkeyboard_layouts_koriolan/layouts/sk_SK/symbols.fallback \ + virtualkeyboard_layouts_koriolan/layouts/sl_SI/dialpad.fallback \ + virtualkeyboard_layouts_koriolan/layouts/sl_SI/digits.fallback \ + virtualkeyboard_layouts_koriolan/layouts/sl_SI/handwriting.fallback \ + virtualkeyboard_layouts_koriolan/layouts/sl_SI/main.qml \ + virtualkeyboard_layouts_koriolan/layouts/sl_SI/numbers.fallback \ + virtualkeyboard_layouts_koriolan/layouts/sl_SI/symbols.fallback \ + virtualkeyboard_layouts_koriolan/layouts/sq_AL/dialpad.fallback \ + virtualkeyboard_layouts_koriolan/layouts/sq_AL/digits.fallback \ + virtualkeyboard_layouts_koriolan/layouts/sq_AL/handwriting.fallback \ + virtualkeyboard_layouts_koriolan/layouts/sq_AL/main.qml \ + virtualkeyboard_layouts_koriolan/layouts/sq_AL/numbers.fallback \ + virtualkeyboard_layouts_koriolan/layouts/sq_AL/symbols.fallback \ + virtualkeyboard_layouts_koriolan/layouts/sr_SP/dialpad.fallback \ + virtualkeyboard_layouts_koriolan/layouts/sr_SP/digits.fallback \ + virtualkeyboard_layouts_koriolan/layouts/sr_SP/handwriting.qml \ + virtualkeyboard_layouts_koriolan/layouts/sr_SP/main.qml \ + virtualkeyboard_layouts_koriolan/layouts/sr_SP/numbers.fallback \ + virtualkeyboard_layouts_koriolan/layouts/sr_SP/symbols.fallback \ + virtualkeyboard_layouts_koriolan/layouts/sv_SE/dialpad.fallback \ + virtualkeyboard_layouts_koriolan/layouts/sv_SE/digits.fallback \ + virtualkeyboard_layouts_koriolan/layouts/sv_SE/handwriting.fallback \ + virtualkeyboard_layouts_koriolan/layouts/sv_SE/main.qml \ + virtualkeyboard_layouts_koriolan/layouts/sv_SE/numbers.fallback \ + virtualkeyboard_layouts_koriolan/layouts/sv_SE/symbols.fallback \ + virtualkeyboard_layouts_koriolan/layouts/th_TH/dialpad.fallback \ + virtualkeyboard_layouts_koriolan/layouts/th_TH/digits.fallback \ + virtualkeyboard_layouts_koriolan/layouts/th_TH/handwriting.fallback \ + virtualkeyboard_layouts_koriolan/layouts/th_TH/handwriting.qml \ + virtualkeyboard_layouts_koriolan/layouts/th_TH/main.qml \ + virtualkeyboard_layouts_koriolan/layouts/th_TH/numbers.fallback \ + virtualkeyboard_layouts_koriolan/layouts/th_TH/symbols.qml \ + virtualkeyboard_layouts_koriolan/layouts/tr_TR/dialpad.fallback \ + virtualkeyboard_layouts_koriolan/layouts/tr_TR/digits.fallback \ + virtualkeyboard_layouts_koriolan/layouts/tr_TR/handwriting.fallback \ + virtualkeyboard_layouts_koriolan/layouts/tr_TR/main.qml \ + virtualkeyboard_layouts_koriolan/layouts/tr_TR/numbers.fallback \ + virtualkeyboard_layouts_koriolan/layouts/tr_TR/symbols.fallback \ + virtualkeyboard_layouts_koriolan/layouts/uk_UA/dialpad.fallback \ + virtualkeyboard_layouts_koriolan/layouts/uk_UA/digits.fallback \ + virtualkeyboard_layouts_koriolan/layouts/uk_UA/handwriting.fallback \ + virtualkeyboard_layouts_koriolan/layouts/uk_UA/main.qml \ + virtualkeyboard_layouts_koriolan/layouts/uk_UA/numbers.fallback \ + virtualkeyboard_layouts_koriolan/layouts/uk_UA/symbols.fallback \ + virtualkeyboard_layouts_koriolan/layouts/vi_VN/dialpad.fallback \ + virtualkeyboard_layouts_koriolan/layouts/vi_VN/digits.fallback \ + virtualkeyboard_layouts_koriolan/layouts/vi_VN/handwriting.fallback \ + virtualkeyboard_layouts_koriolan/layouts/vi_VN/main.qml \ + virtualkeyboard_layouts_koriolan/layouts/vi_VN/numbers.fallback \ + virtualkeyboard_layouts_koriolan/layouts/vi_VN/symbols.qml \ + virtualkeyboard_layouts_koriolan/layouts/zh_CN/dialpad.fallback \ + virtualkeyboard_layouts_koriolan/layouts/zh_CN/digits.fallback \ + virtualkeyboard_layouts_koriolan/layouts/zh_CN/handwriting.qml \ + virtualkeyboard_layouts_koriolan/layouts/zh_CN/main.qml \ + virtualkeyboard_layouts_koriolan/layouts/zh_CN/numbers.fallback \ + virtualkeyboard_layouts_koriolan/layouts/zh_CN/symbols.qml \ + virtualkeyboard_layouts_koriolan/layouts/zh_TW/dialpad.fallback \ + virtualkeyboard_layouts_koriolan/layouts/zh_TW/digits.fallback \ + virtualkeyboard_layouts_koriolan/layouts/zh_TW/handwriting.qml \ + virtualkeyboard_layouts_koriolan/layouts/zh_TW/main.qml \ + virtualkeyboard_layouts_koriolan/layouts/zh_TW/numbers.fallback \ + virtualkeyboard_layouts_koriolan/layouts/zh_TW/symbols.qml + diff --git a/shipheart.pro-koriolan-MS-7B98-safeBackup-0001.user b/shipheart.pro-koriolan-MS-7B98-safeBackup-0001.user new file mode 100755 index 0000000..93a02a0 --- /dev/null +++ b/shipheart.pro-koriolan-MS-7B98-safeBackup-0001.user @@ -0,0 +1,561 @@ + + + + + + EnvironmentId + {5b3dea33-5bbe-4cdf-a144-b777c9e3122e} + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + false + true + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + UTF-8 + false + 4 + false + 80 + true + true + 1 + false + true + false + 0 + true + true + 0 + 8 + true + false + 1 + true + true + true + *.md, *.MD, Makefile + false + true + true + + + + ProjectExplorer.Project.PluginSettings + + + true + false + true + true + true + true + + + 0 + true + + false + Builtin.Questionable + + true + true + Builtin.DefaultTidyAndClazy + 4 + + + + true + + + + + ProjectExplorer.Project.Target.0 + + GenericLinuxOsType + ShipHeart + ShipHeart + {a206e9a6-616e-4362-9a28-a1446ae1ee0c} + 1 + 0 + 0 + + 0 + /home/koriolan/qt/koriolan/build-shipheart-ShipHeart-Debug + /home/koriolan/qt/koriolan/build-shipheart-ShipHeart-Debug + + + true + QtProjectManager.QMakeBuildStep + false + + + + true + Qt4ProjectManager.MakeStep + + 2 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + true + Qt4ProjectManager.MakeStep + clean + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + Debug + Qt4ProjectManager.Qt4BuildConfiguration + 2 + 0 + + + /home/koriolan/qt/koriolan/build-shipheart-ShipHeart-Release + /home/koriolan/qt/koriolan/build-shipheart-ShipHeart-Release + + + true + QtProjectManager.QMakeBuildStep + false + + + + true + Qt4ProjectManager.MakeStep + + 2 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + true + Qt4ProjectManager.MakeStep + clean + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + Release + Qt4ProjectManager.Qt4BuildConfiguration + 0 + 1 + 0 + + + 0 + /home/koriolan/qt/koriolan/build-shipheart-ShipHeart-Profile + /home/koriolan/qt/koriolan/build-shipheart-ShipHeart-Profile + + + true + QtProjectManager.QMakeBuildStep + false + + + + true + Qt4ProjectManager.MakeStep + + 2 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + true + Qt4ProjectManager.MakeStep + clean + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + Profile + Qt4ProjectManager.Qt4BuildConfiguration + 0 + 0 + 0 + 0 + + 3 + + + + true + RemoteLinux.KillAppStep + + + + + + + + + true + RemoteLinux.DirectUploadStep + + /home/koriolan/qt/koriolan/build-shipheart-ShipHeart-Release/shipheart_qt + /home/koriolan/qt/koriolan/build-shipheart-ShipHeart-Release/shipheart_qt + /home/koriolan/qt/koriolan/build-shipheart-ShipHeart-Release/shipheart_qt + /home/koriolan/qt/koriolan/build-shipheart-ShipHeart-Release/shipheart + /home/koriolan/qt/koriolan/build-shipheart-ShipHeart-Release/shipheart_qt.bin + /home/koriolan/qt/koriolan/build-shipheart-ShipHeart-Release/shipheart_qt + /home/koriolan/qt/koriolan/build-shipheart-ShipHeart-Release/shipheart_qt + /home/koriolan/qt/koriolan/build-shipheart-ShipHeart-Release/shipheart_qt + /home/koriolan/qt/koriolan/build-shipheart-ShipHeart-Release/shipheart_qt + /home/koriolan/qt/koriolan/build-shipheart-ShipHeart-Release/shipheart_qt + /home/koriolan/qt/koriolan/build-shipheart-ShipHeart-Release/shipheart_qt + /home/koriolan/qt/koriolan/build-shipheart-ShipHeart-Release/shipheart + /home/koriolan/qt/koriolan/build-shipheart-ShipHeart-Release/Shipheart_Qt.bin + + + 192.168.1.31 + 192.168.1.30 + 192.168.1.195 + 192.168.1.52 + 192.168.1.30 + 192.168.1.12 + 192.168.1.30 + 192.168.1.30 + 192.168.1.32 + 192.168.1.197 + 192.168.1.5 + 192.168.1.52 + 192.168.1.30 + + + /home/koriolan/shipheart/versions/current + /home/pi/projets/qt + /home/koriolan/shipheart/versions/current + /home/pi + /home/pi/projets/qt + /home/koriolan/shipheart/versions/current + /home/pi/shipheart/versions/current + /home/koriolan/shipheart/versions/current + /home/koriolan/shipheart/versions/current + /home/koriolan/shipheart/versions/current + /home/koriolan/shipheart/versions/current + /home/pi/projets/qt + /home/pi/projets/qt + + + /home/koriolan/qt/raspi/sysroot + /home/koriolan/qt/raspi/sysroot + /home/koriolan/qt/raspi/sysroot + /home/koriolan/qt/raspi/sysroot + /home/koriolan/qt/raspi/sysroot + /home/koriolan/qt/raspi/sysroot + /home/koriolan/qt/raspi/sysroot + /home/koriolan/qt/raspi/sysroot + /home/koriolan/qt/raspi/sysroot + /home/koriolan/qt/raspi/sysroot + /home/koriolan/qt/raspi/sysroot + /home/koriolan/qt/raspi/sysroot + /home/koriolan/qt/raspi/sysroot + + + 2025-07-10T17:23:43.446 + 2021-06-16T10:01:30.498 + 2023-07-07T09:03:30.239 + 2021-02-11T17:19:57.456 + 2021-05-11T16:16:58.187 + 2024-05-30T11:53:17.091 + 2021-07-22T15:47:04.936 + 2022-08-08T12:23:15.358 + 2024-03-25T11:41:08.358 + 2023-03-28T18:52:40.648 + 2023-06-17T10:26:48.546 + 2021-03-09T19:33:16.796 + 2021-05-11T16:11:27.863 + + + 2025-07-10T17:24:37.000 + 2021-06-16T10:01:40.000 + 2023-07-07T09:03:32.000 + 2021-02-11T17:19:58.000 + 2021-05-11T16:17:01.000 + 2024-05-30T11:53:20.000 + 2021-07-22T15:47:08.000 + 2022-08-08T12:23:19.000 + 2024-03-25T11:41:09.000 + 2023-03-28T18:52:42.000 + 2023-06-17T10:26:55.000 + 2021-03-09T19:33:19.000 + 2021-05-11T16:11:30.000 + + + 2 + Deploy + Deploy + ProjectExplorer.BuildSteps.Deploy + + 1 + + false + DeployToGenericLinux + + 1 + + true + true + true + + 1 + + shipheart (on %{Device:Name}) + RemoteLinuxRunConfiguration:/home/koriolan/SharePoint_Koriolan_Documents/Technique/Projets_Qt/koriolan/shipheart/shipheart.pro + /home/koriolan/SharePoint_Koriolan_Documents/Technique/Projets_Qt/koriolan/shipheart/shipheart.pro + 1 + false + true + false + true + :0 + + 1 + + + + ProjectExplorer.Project.Target.1 + + GenericLinuxOsType + ShipHeart V2 - Test + ShipHeart V2 - Test + {78724f45-faee-4be3-83bc-2b00146f2d14} + 1 + 0 + 0 + + 0 + /home/koriolan/Dropbox/Koriolan/Technique/Projets_Qt/koriolan/build-shipheart-ShipHeart_sur_CM4-Debug + /home/koriolan/Dropbox/Koriolan/Technique/Projets_Qt/koriolan/build-shipheart-ShipHeart_sur_CM4-Debug + + + true + QtProjectManager.QMakeBuildStep + false + + + + true + Qt4ProjectManager.MakeStep + + 2 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + true + Qt4ProjectManager.MakeStep + clean + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + Debug + Qt4ProjectManager.Qt4BuildConfiguration + 2 + + + /home/koriolan/Dropbox/Koriolan/Technique/Projets_Qt/koriolan/build-shipheart-ShipHeart_sur_CM4-Release + /home/koriolan/Dropbox/Koriolan/Technique/Projets_Qt/koriolan/build-shipheart-ShipHeart_sur_CM4-Release + + + true + QtProjectManager.QMakeBuildStep + false + + + + true + Qt4ProjectManager.MakeStep + + 2 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + true + Qt4ProjectManager.MakeStep + clean + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + Release + Qt4ProjectManager.Qt4BuildConfiguration + 0 + 0 + + + 0 + /home/koriolan/Dropbox/Koriolan/Technique/Projets_Qt/koriolan/build-shipheart-ShipHeart_sur_CM4-Profile + /home/koriolan/Dropbox/Koriolan/Technique/Projets_Qt/koriolan/build-shipheart-ShipHeart_sur_CM4-Profile + + + true + QtProjectManager.QMakeBuildStep + false + + + + true + Qt4ProjectManager.MakeStep + + 2 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + true + Qt4ProjectManager.MakeStep + clean + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + Profile + Qt4ProjectManager.Qt4BuildConfiguration + 0 + 0 + 0 + + 3 + + + + true + RemoteLinux.KillAppStep + + + + + + + + + true + RemoteLinux.RsyncDeployStep + + + + + + + -av + + 2 + Deploy + Deploy + ProjectExplorer.BuildSteps.Deploy + + 1 + + false + DeployToGenericLinux + + 1 + + true + true + true + + 1 + + shipheart (on %{Device:Name})2 + RemoteLinuxRunConfiguration:/home/koriolan/SharePoint_Koriolan_Documents/Technique/Projets_Qt/koriolan/shipheart/shipheart.pro + /home/koriolan/SharePoint_Koriolan_Documents/Technique/Projets_Qt/koriolan/shipheart/shipheart.pro + 1 + false + true + false + true + :0 + + 1 + + + + ProjectExplorer.Project.TargetCount + 2 + + + ProjectExplorer.Project.Updater.FileVersion + 22 + + + Version + 22 + + diff --git a/shipheart.pro.user b/shipheart.pro.user new file mode 100755 index 0000000..f52acf2 --- /dev/null +++ b/shipheart.pro.user @@ -0,0 +1,573 @@ + + + + + + EnvironmentId + {5b3dea33-5bbe-4cdf-a144-b777c9e3122e} + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + false + true + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + UTF-8 + false + 4 + false + 80 + true + true + 1 + false + true + false + 0 + true + true + 0 + 8 + true + false + 1 + true + true + true + *.md, *.MD, Makefile + false + true + true + + + + ProjectExplorer.Project.PluginSettings + + + true + false + true + true + true + true + + + 0 + true + + false + Builtin.Questionable + + true + true + Builtin.DefaultTidyAndClazy + 4 + + + + true + + + + + ProjectExplorer.Project.Target.0 + + GenericLinuxOsType + ShipHeart + ShipHeart + {a206e9a6-616e-4362-9a28-a1446ae1ee0c} + 1 + 0 + 0 + + 0 + /home/koriolan/qt/koriolan/build-shipheart-ShipHeart-Debug + /home/koriolan/qt/koriolan/build-shipheart-ShipHeart-Debug + + + true + QtProjectManager.QMakeBuildStep + false + + + + true + Qt4ProjectManager.MakeStep + + 2 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + true + Qt4ProjectManager.MakeStep + clean + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + Debug + Qt4ProjectManager.Qt4BuildConfiguration + 2 + 0 + + + /home/koriolan/qt/koriolan/build-shipheart-ShipHeart-Release + /home/koriolan/qt/koriolan/build-shipheart-ShipHeart-Release + + + true + QtProjectManager.QMakeBuildStep + false + + + + true + Qt4ProjectManager.MakeStep + + 2 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + true + Qt4ProjectManager.MakeStep + clean + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + Release + Qt4ProjectManager.Qt4BuildConfiguration + 0 + 1 + 0 + + + 0 + /home/koriolan/qt/koriolan/build-shipheart-ShipHeart-Profile + /home/koriolan/qt/koriolan/build-shipheart-ShipHeart-Profile + + + true + QtProjectManager.QMakeBuildStep + false + + + + true + Qt4ProjectManager.MakeStep + + 2 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + true + Qt4ProjectManager.MakeStep + clean + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + Profile + Qt4ProjectManager.Qt4BuildConfiguration + 0 + 0 + 0 + 0 + + 3 + + + + true + RemoteLinux.KillAppStep + + + + + + + + + true + RemoteLinux.DirectUploadStep + + /home/koriolan/qt/koriolan/build-shipheart-ShipHeart-Release/Shipheart_Qt.bin + /home/koriolan/qt/koriolan/build-shipheart-ShipHeart-Release/shipheart + /home/koriolan/qt/koriolan/build-shipheart-ShipHeart-Release/shipheart_qt + /home/koriolan/qt/koriolan/build-shipheart-ShipHeart-Release/shipheart_qt + /home/koriolan/qt/koriolan/build-shipheart-ShipHeart-Release/shipheart_qt + /home/koriolan/qt/koriolan/build-shipheart-ShipHeart-Release/shipheart_qt + /home/koriolan/qt/koriolan/build-shipheart-ShipHeart-Release/shipheart_qt + /home/koriolan/qt/koriolan/build-shipheart-ShipHeart-Release/shipheart_qt + /home/koriolan/qt/koriolan/build-shipheart-ShipHeart-Release/shipheart_qt + /home/koriolan/qt/koriolan/build-shipheart-ShipHeart-Release/shipheart_qt + /home/koriolan/qt/koriolan/build-shipheart-ShipHeart-Release/shipheart_qt.bin + /home/koriolan/qt/koriolan/build-shipheart-ShipHeart-Release/shipheart + /home/koriolan/qt/koriolan/build-shipheart-ShipHeart-Release/shipheart_qt + /home/koriolan/qt/koriolan/build-shipheart-ShipHeart-Release/shipheart_qt + /home/koriolan/qt/koriolan/build-shipheart-ShipHeart-Release/shipheart_qt + + + 192.168.1.30 + 192.168.1.52 + 192.168.1.197 + 192.168.1.5 + 192.168.1.214 + 192.168.1.32 + 192.168.1.238 + 192.168.1.30 + 192.168.1.30 + 192.168.1.12 + 192.168.1.30 + 192.168.1.52 + 192.168.1.31 + 192.168.1.195 + 192.168.1.30 + + + /home/pi/projets/qt + /home/pi/projets/qt + /home/koriolan/shipheart/versions/current + /home/koriolan/shipheart/versions/current + /home/koriolan/shipheart/versions/current + /home/koriolan/shipheart/versions/current + /home/koriolan/shipheart/versions/current + /home/koriolan/shipheart/versions/current + /home/pi/shipheart/versions/current + /home/koriolan/shipheart/versions/current + /home/pi/projets/qt + /home/pi + /home/koriolan/shipheart/versions/current + /home/koriolan/shipheart/versions/current + /home/pi/projets/qt + + + /home/koriolan/qt/raspi/sysroot + /home/koriolan/qt/raspi/sysroot + /home/koriolan/qt/raspi/sysroot + /home/koriolan/qt/raspi/sysroot + /home/koriolan/qt/raspi/sysroot + /home/koriolan/qt/raspi/sysroot + /home/koriolan/qt/raspi/sysroot + /home/koriolan/qt/raspi/sysroot + /home/koriolan/qt/raspi/sysroot + /home/koriolan/qt/raspi/sysroot + /home/koriolan/qt/raspi/sysroot + /home/koriolan/qt/raspi/sysroot + /home/koriolan/qt/raspi/sysroot + /home/koriolan/qt/raspi/sysroot + /home/koriolan/qt/raspi/sysroot + + + 2021-05-11T16:11:27.863 + 2021-03-09T19:33:16.796 + 2023-03-28T18:52:40.648 + 2025-08-01T11:33:24.420 + 2025-08-13T18:03:01.320 + 2024-03-25T11:41:08.358 + 2026-08-04T11:46:19.684 + 2022-08-08T12:23:15.358 + 2021-07-22T15:47:04.936 + 2024-05-30T11:53:17.091 + 2021-05-11T16:16:58.187 + 2021-02-11T17:19:57.456 + 2025-11-16T08:47:58.765 + 2023-07-07T09:03:30.239 + 2021-06-16T10:01:30.498 + + + 2021-05-11T16:11:30.000 + 2021-03-09T19:33:19.000 + 2023-03-28T18:52:42.000 + 2025-08-01T11:33:32.000 + 2025-08-13T18:03:02.000 + 2024-03-25T11:41:09.000 + 2026-08-04T11:46:20.000 + 2022-08-08T12:23:19.000 + 2021-07-22T15:47:08.000 + 2024-05-30T11:53:20.000 + 2021-05-11T16:17:01.000 + 2021-02-11T17:19:58.000 + 2025-11-16T08:48:00.000 + 2023-07-07T09:03:32.000 + 2021-06-16T10:01:40.000 + + + 2 + Deploy + Deploy + ProjectExplorer.BuildSteps.Deploy + + 1 + + false + DeployToGenericLinux + + 1 + + true + true + true + + 1 + + shipheart (on %{Device:Name}) + RemoteLinuxRunConfiguration:/home/koriolan/SharePoint_Koriolan_Documents/Technique/Projets_Qt/koriolan/shipheart/shipheart.pro + /home/koriolan/SharePoint_Koriolan_Documents/Technique/Projets_Qt/koriolan/shipheart/shipheart.pro + 1 + false + true + false + true + :0 + + 1 + + + + ProjectExplorer.Project.Target.1 + + GenericLinuxOsType + ShipHeart V2 - Test + ShipHeart V2 - Test + {78724f45-faee-4be3-83bc-2b00146f2d14} + 1 + 0 + 0 + + 0 + /home/koriolan/Dropbox/Koriolan/Technique/Projets_Qt/koriolan/build-shipheart-ShipHeart_sur_CM4-Debug + /home/koriolan/Dropbox/Koriolan/Technique/Projets_Qt/koriolan/build-shipheart-ShipHeart_sur_CM4-Debug + + + true + QtProjectManager.QMakeBuildStep + false + + + + true + Qt4ProjectManager.MakeStep + + 2 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + true + Qt4ProjectManager.MakeStep + clean + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + Debug + Qt4ProjectManager.Qt4BuildConfiguration + 2 + + + /home/koriolan/Dropbox/Koriolan/Technique/Projets_Qt/koriolan/build-shipheart-ShipHeart_sur_CM4-Release + /home/koriolan/Dropbox/Koriolan/Technique/Projets_Qt/koriolan/build-shipheart-ShipHeart_sur_CM4-Release + + + true + QtProjectManager.QMakeBuildStep + false + + + + true + Qt4ProjectManager.MakeStep + + 2 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + true + Qt4ProjectManager.MakeStep + clean + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + Release + Qt4ProjectManager.Qt4BuildConfiguration + 0 + 0 + + + 0 + /home/koriolan/Dropbox/Koriolan/Technique/Projets_Qt/koriolan/build-shipheart-ShipHeart_sur_CM4-Profile + /home/koriolan/Dropbox/Koriolan/Technique/Projets_Qt/koriolan/build-shipheart-ShipHeart_sur_CM4-Profile + + + true + QtProjectManager.QMakeBuildStep + false + + + + true + Qt4ProjectManager.MakeStep + + 2 + Build + Build + ProjectExplorer.BuildSteps.Build + + + + true + Qt4ProjectManager.MakeStep + clean + + 1 + Clean + Clean + ProjectExplorer.BuildSteps.Clean + + 2 + false + + false + + Profile + Qt4ProjectManager.Qt4BuildConfiguration + 0 + 0 + 0 + + 3 + + + + true + RemoteLinux.KillAppStep + + + + + + + + + true + RemoteLinux.RsyncDeployStep + + + + + + + -av + + 2 + Deploy + Deploy + ProjectExplorer.BuildSteps.Deploy + + 1 + + false + DeployToGenericLinux + + 1 + + true + true + true + + 1 + + shipheart (on %{Device:Name})2 + RemoteLinuxRunConfiguration:/home/koriolan/SharePoint_Koriolan_Documents/Technique/Projets_Qt/koriolan/shipheart/shipheart.pro + /home/koriolan/SharePoint_Koriolan_Documents/Technique/Projets_Qt/koriolan/shipheart/shipheart.pro + 1 + false + true + false + true + :0 + + 1 + + + + ProjectExplorer.Project.TargetCount + 2 + + + ProjectExplorer.Project.Updater.FileVersion + 22 + + + Version + 22 + + diff --git a/shipheart_ca_ES.qm b/shipheart_ca_ES.qm new file mode 100755 index 0000000..ec1b006 Binary files /dev/null and b/shipheart_ca_ES.qm differ diff --git a/shipheart_ca_ES.ts b/shipheart_ca_ES.ts new file mode 100755 index 0000000..562b7e8 --- /dev/null +++ b/shipheart_ca_ES.ts @@ -0,0 +1,5528 @@ + + + + + Shipheart_boite_dialogue + + + OK + OK + + + + Annuler + Cancel · lar + + + + Plus tard + Més tard + + + + Shipheart_boite_dialogue_action_circuit + + + Action à appliquer au circuit lorsque l'évènement se déclenche : + Acció a aplicar al circuit quan es desencadena l'esdeveniment: + + + + Aucune + Cap + + + + Le circuit <b>bascule</b> + El circuit <b>canvia</b> + + + + [passe à <b>ON</b> s'il est <b>OFF</b><br /> ou à <b>OFF</b> s'il est <b>ON</b>] + [ <b>s'encén</b> si <b>està desactivat</b><br /> o a <b>OFF</b> si està <b>ON</b> ] + + + + OFF + OFF + + + + ON + ON + + + + Annuler + Cancel · lar + + + + Shipheart_boite_dialogue_affichage_duree + + + Ok + OK + + + + Shipheart_boite_dialogue_condition_horaire + + + OK + OK + + + + Annuler + Cancel · lar + + + + Supprimer + ELIMINAR + + + + Aube nautique + Alba nàutica + + + + Lever du soleil + Sortida del sol + + + + Zénith + Zenit + + + + Coucher du soleil + Posta de sol + + + + Crépuscule nautique + Crepuscle nàutic + + + + Shipheart_boite_dialogue_entrees_aux + + + Entrées Auxiliaires + Entrades auxiliars + + + + Affectation de l'entrée n° %1 du %2 + Assignació del número d'entrada %1 de %2 + + + + Annuler + Cancel · lar + + + + Shipheart_boite_dialogue_entrees_level_sensor + + + Entrées Level Sensor + Entrades del sensor de nivell + + + + Affectation de l'entrée du réservoir + Assignació d'entrada del dipòsit + + + + Annuler + Cancel · lar + + + + Shipheart_boite_dialogue_liste_alarmes + + + Ok + OK + + + + Shipheart_boite_dialogue_minuteur + + + Heures + Hores + + + + Minutes + Minuts + + + + Secondes + Segons + + + + Annuler + Cancel · lar + + + + Démarrer + Per posar en marxa + + + + Shipheart_boite_dialogue_nettoyage_ecran + + + Nettoyage de l'écran + Neteja de la pantalla + + + + 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. + Actualment, la pantalla està congelada per permetre't netejar-la sense el risc de desencadenar accions no desitjades.<br /><br /> Mantingueu premut el botó de sota durant més de %1 segons per sortir d'aquest mode. + + + + Sortie + Sortida + + + + Shipheart_boite_dialogue_reveils + + + Annuler + Cancel · lar + + + + Enregistrer + Desa + + + + Shipheart_boite_dialogue_validation_securisee + + + OK + OK + + + + Annuler + Cancel · lar + + + + --- + --- + + + + Shipheart_bouton_circuit + + + + + Off + OFF + + + + + On + ON + + + + batterie + + + + Aucune consommation d'énergie sur cette période... + No hi ha consum d'energia durant aquest període... + + + + Aucune donnée n'est disponible pour cette période + No hi ha dades disponibles per a aquest període + + + + Le module assurant la supervision de cette batterie n'est pas accessible !<br /><br />Si des ajouts/suppression/déplacements de modules ont eu lieu récemment, mettez à jour la configuration correspondant dans le menu MODULES de PARAMETRES AVANCES.<br /><br />Dans le cas où aucune modification n'a été effectuée récemment, vérifier les connexions de tous les modules. + El mòdul que garanteix la supervisió d'aquesta bateria no és accessible!<br /><br /> Si s'han afegit/suprimit/mogut mòduls recentment, actualitzeu la configuració corresponent al menú MÒDULS de CONFIGURACIÓ AVANÇADA.<br /><br /> En cas que no s'hagin fet canvis recentment, comproveu les connexions de tots els mòduls. + + + + capteur + + + Max + Màx + + + + Moyen + MITJANA + + + + Min + Min + + + + Delta (Max - Min) + Delta (1h) + Delta (màx. - mínim) + + + + Aucune donnée n'est disponible pour cette période + No hi ha dades disponibles per a aquest període + + + + La sonde One Wire correspondant à ce capteur n'est pas accessible.<br />Vérifier son câblage entre le port One Wire à l'arrière de ShipBase et la sonde. + La sonda One Wire corresponent a aquest sensor no és accessible.<br /> Comproveu el cablejat entre el port One Wire a la part posterior de ShipBase i la sonda. + + + + Le module assurant la supervision de ce capteur n'est pas accessible !<br /><br />Si des ajouts/suppression/déplacements de modules ont eu lieu récemment, mettez à jour la configuration correspondant dans le menu MODULES de PARAMETRES AVANCES.<br /><br />Dans le cas où aucune modification n'a été effectuée récemment, vérifier les connexions de tous les modules. + El mòdul que controla aquest sensor no és accessible!<br /><br /> Si s'han afegit/suprimit/mogut mòduls recentment, actualitzeu la configuració corresponent al menú MÒDULS de CONFIGURACIÓ AVANÇADA.<br /><br /> En cas que no s'hagin fet canvis recentment, comproveu les connexions de tots els mòduls. + + + + La sonde One Wire du capteur est détectée en défaut.<br />Vérifier son câblage depuis l'arrière de ShipBase. + La sonda One Wire del sensor es detecta com a defectuosa.<br /> Comproveu el cablejat des de la part posterior de ShipBase. + + + + Le capteur n'a pas reçu de mise à jour sur le réseau NMEA depuis<br />%1<br />Les données affichées sont donc probablement obsolètes. + El sensor no ha rebut cap actualització a la xarxa NMEA des del<br />%1<br />Per tant, les dades mostrades probablement estan desactualitzades. + + + + circuit + + + + + + Off + OFF + + + + + On + ON + + + + On +%1% + Nosaltres + %1% + + + + Aucune donnée n'est disponible pour cette période + No hi ha dades disponibles per a aquest període + + + + Aucune consommation d'énergie sur cette période... + No hi ha consum d'energia durant aquest període... + + + + Le module assurant le pilotage de ce circuit n'est pas accessible !<br /><br />Si des ajouts/suppression/déplacements de modules ont eu lieu récemment, mettez à jour la configuration correspondant dans le menu [Réseau ShipHeart] de [Paramètres Avancés].<br /><br />Dans le cas où aucune modification n'a été effectuée récemment, vérifier les connexions de tous les modules. + El mòdul que controla aquest circuit no és accessible!<br /><br /> Si s'han afegit/eliminat/mogut mòduls recentment, actualitzeu la configuració corresponent al menú [Xarxa ShipHeart] de [Configuració avançada].<br /><br /> En cas que no s'hagin fet canvis recentment, comproveu les connexions de tots els mòduls. + + + + Ce circuit est configuré comme <i>Non Affecté</i> et n'est donc pas accessible !<br /><br />Pour accéder à nouveau à ce circuit, merci de l'affecter à un circuit disponible dans le menu [Circuits] de [Paramètres Avancés]. + Aquest circuit està configurat com <i>a No assignat</i> i, per tant, no és accessible!<br /><br /> Per tornar a accedir a aquest circuit, assigneu-lo a un circuit disponible al menú [Circuits] de [Configuració avançada]. + + + + Non défini + Sense definir + + + + Le module pilotant ce circuit n'est pas alimentée correctement. + Vérifier l'alimentation correspondante. + El mòdul que controla aquest circuit no està alimentat correctament. + Comproveu la font d'alimentació corresponent. + + + + Le module pilotant ce circuit est en mode MANUEL. + Repositionnez le module en mode AUTO pour commander à nouveau ce circuit normalement. + El mòdul que controla aquest circuit està en mode MANUAL. + Torneu el mòdul al mode AUTO per tornar a controlar aquest circuit amb normalitat. + + + + Le port USB du bas est en défaut. + El port USB inferior és defectuós. + + + + Le port USB du milieu est en défaut. + El port USB central és defectuós. + + + + Les 2 ports USB du milieu et du bas sont en défaut. + Els 2 ports USB central i inferior són defectuosos. + + + + Le port USB du haut est en défaut. + El port USB superior està defectuós. + + + + Les 2 ports USB du haut et du bas sont en défaut. + Els 2 ports USB de la part superior i inferior són defectuosos. + + + + Les 2 ports USB du haut et du milieu sont en défaut. + Els 2 ports USB superior i mitjà estan defectuosos. + + + + Les 3 ports USB du haut, du milieu et du bas sont en défaut. + Els 3 ports USB superior, mitjà i inferior són defectuosos. + + + + Le port USB est en défaut. + El port USB és defectuós. + + + + L'alimentation du circuit a été coupée + car sa limite de courant (%1 A) + a été dépassée. + S'ha tallat l'alimentació del circuit + perquè el seu límit de corrent (%1 A) + es va superar. + + + + L'alimentation du circuit a été coupée + car les circuits de protection interne ont détecté une anomalie. + S'ha tallat l'alimentació del circuit + perquè els circuits de protecció interns han detectat una anomalia. + + + + L'alimentation du circuit a été coupée + car le seuil de disjonction du circuit a été dépassé. + S'ha tallat l'alimentació del circuit + perquè s'ha superat el llindar d'activació del circuit. + + + + Le circuit est en court-circuit avec le + batterie. + El circuit està en curtcircuit a la bateria +. + + + + L'alimentation du circuit a été coupée<br />car la consommation totale du module a dépassé %1 A pendant plus de %2 secondes (limite du module) + S'ha tallat l'alimentació del circuit<br /> perquè el consum total del mòdul va superar %1 A durant més de %2 segons (límit del mòdul) + + + + La tension du circuit est anormalement basse. + La tensió del circuit és anormalment baixa. + + + + La phase et le neutre sont inversés sur ce circuit. + La fase i el neutre estan invertits en aquest circuit. + + + + DANGER : Le neutre n'est pas référencé à la terre sur ce circuit ("absence de terre"). + DANGER : la terre est absente de ce circuit. + PERILL: El neutre no té referència a terra en aquest circuit ("sense terra"). + + + + La masse est absente du connecteur d'alimentation du module + Falta terra al connector d'alimentació del mòdul + + + + Evènements actuellement actifs qui sont susceptibles de commander ce circuit : + Esdeveniments actius actualment que poden controlar aquest circuit: + + + + + + Etat inconnu... + Estat desconegut... + + + + config_acces_parametres + + + Configuration de l'accès aux paramètres avancés + Configuració de l'accés a la configuració avançada + + + + Durée de maintien de l'accès + Durada del manteniment de l'accés + + + + Nouveau code + Nou codi + + + + Code d'accès + Codi d'accés + + + + Répéter le code d'accès + Repetiu la contrasenya + + + + Enregistrer + Desa + + + + Aucune (saisie du code à chaque accès) + Cap (entrada de codi cada vegada que accediu) + + + + 1 minute + 1 minut + + + + 5 minutes + 5 minuts + + + + 15 minutes + 15 minuts + + + + 1 heure + 1 hora + + + + Infinie (aucune protection des paramètres avancés) + Infinit (sense protecció de configuració avançada) + + + + Les deux valeurs saisies doivent être identiques ! + +De plus, le code doit contenir : +- %1 chiffres au minimum +- %2 chiffres au maximum. + Els dos valors introduïts han de ser idèntics! + + A més, el codi ha de contenir: + - %1 dígit mínim + - Màxim %2 dígits. + + + + Le nouveau code doit contenir : +- %1 chiffres au minimum +- %2 chiffres au maximum. + +Le code saisi ne répond pas à ces critères et sa mise à jour n'est donc pas effectuée. + +Merci de saisir un code au format valide si vous souhaitez le modifier. + El nou codi ha de contenir: + - %1 dígit mínim + - Màxim %2 dígits. + + El codi introduït no compleix aquests criteris i, per tant, no s'actualitza. + + Introduïu un codi en un format vàlid si voleu modificar-lo. + + + + config_affichage + + + Configuration de l'affichage + Configuració de la pantalla + + + + Nom du bateau + Nom del vaixell + + + + Fuseau horaire + Fus horari + + + + Temporisaton économiseur d'écran + Temps d'espera de l'estalvi de pantalla + + + + Thème d'affichage + Mostra el tema + + + + Enregistrer + Desa + + + + UTC-12 (Yankee) + UTC-12 (Yankee) + + + + UTC-11 (X-Ray) + UTC-11 (raigs X) + + + + UTC-10 (Whisky) + UTC-10 (Whiskey) + + + + UTC-9 (Victor) + UTC-9 (Víctor) + + + + UTC-8 (Uniform) + UTC-8 (uniforme) + + + + UTC-7 (Tango) + UTC-7 (Tango) + + + + UTC-6 (Sierra) + UTC-6 (Serra) + + + + UTC-5 (Romeo) + UTC-5 (Romeu) + + + + UTC-4 (Quebec) + UTC-4 (Quebec) + + + + UTC-3 (Papa) + UTC-3 (pare) + + + + UTC-2 (Oscar) + UTC-2 (Oscar) + + + + UTC-1 (November) + UTC-1 (novembre) + + + + UTC (Zoulou) + UTC (zulú) + + + + UTC+1 (Alpha) + UTC+1 (alfa) + + + + UTC+2 (Bravo) + UTC+2 (ben fet) + + + + UTC+3 (Charlie) + UTC+3 (Charlie) + + + + UTC+4 (Delta) + UTC+4 (Delta) + + + + UTC+5 (Echo) + UTC+5 (eco) + + + + UTC+6 (Foxtrot) + UTC+6 (Foxtrot) + + + + UTC+7 (Golf) + UTC+7 (Golf) + + + + UTC+8 (Hotel) + UTC+8 (hotel) + + + + UTC+9 (India) + UTC+9 (Índia) + + + + UTC+10 (Kilo) + UTC+10 (quilo) + + + + UTC+11 (Lima) + UTC+11 (Lima) + + + + UTC+12 (Mike) + UTC+12 (Mike) + + + + 15 secondes + 15 segons + + + + 30 secondes + 30 segons + + + + 1 minute + 1 minut + + + + 3 minutes + 3 minuts + + + + 10 minutes + 10 minuts + + + + Aucune limite + Sense límit + + + + config_audio + + + Configuration audio + Configuració d'àudio + + + + Bips de clic + Feu clic a sons + + + + Fonctionnement de la sortie Audio + Funcionament de sortida d'àudio + + + + Enregistrer + Desa + + + + Aucun bip + Sense bip + + + + Bip par défaut + Bip predeterminat + + + + Bip 2 + Bip 2 + + + + Bip 3 + Bip 3 + + + + Bip 4 + Bip 4 + + + + Bip 5 + Bip 5 + + + + Bip 6 + Bip 6 + + + + Bip 7 + Bip 7 + + + + Bip 8 + Bip 8 + + + + Bip 9 + Bip 9 + + + + Bip 10 + Bip 10 + + + + Bip 11 + Bip 11 + + + + Bip 12 + Bip 12 + + + + Bip 13 + Bip 13 + + + + Bip 14 + Bip 14 + + + + Le son de ShipBase est coupé. Le son est uniquement diffusé sur la sortie AUDIO + L'àudio de ShipBase està silenciat. El so només surt des de la sortida d'ÀUDIO + + + + Le son est diffusé sur ShipBase et sur la sortie AUDIO + L'àudio es transmet a ShipBase i a la sortida d'ÀUDIO + + + + config_batterie + + + Nom de la batterie + Nom de la bateria + + + + Tension nominale + Tensió nominal + + + + Créer la batterie + Crea la bateria + + + + Enregistrer + Desa + + + + Supprimer + ELIMINAR + + + + + Confirmer + Confirmeu + + + + Etalonner + Etalonnage + Calibrar + + + + + Non défini + Sense definir + + + + Création d'un parc de batteries + Creació d'un banc de bateries + + + + Configuration du parc de batteries + Configuració del banc de bateries + + + + Groupe de batteries + Grup de bateries + + + + Point de mesure + Punt de mesura + + + + Type de batterie(s) + Tipus de bateria + + + + La modification du <b>type</b> de batterie(s) va nécessiter la remise en <i>configuration usine</i> de certains paramètres.<br /><br />Si vous ne souhaitez pas que cette reconfiguration soit effectuée, notamment si vous avez effectué des réglages spécifiques, cliquez sur ANNULER. <br /><br />Sinon, cliquez sur CONFIRMER pour valider le changement. + Si canvieu el <b>tipus</b> de bateries, caldrà restablir determinats paràmetres a <i>la configuració de fàbrica</i> .<br /><br /> Si no voleu que es realitzi aquesta reconfiguració, sobretot si heu fet una configuració específica, feu clic a CANCEL·LA.<br /><br /> En cas contrari, feu clic a CONFIRMAR per validar el canvi. + + + + La modification de la <b>tension nominale</b> du parc de batteries va nécessiter la remise en <i>configuration usine</i> de certains paramètres.<br /><br />Si vous ne souhaitez pas que cette reconfiguration soit effectuée, notamment si vous avez effectué des réglages spécifiques, cliquez sur ANNULER. <br /><br />Sinon, cliquez sur CONFIRMER pour valider le changement. + Si canvieu la <b>tensió nominal</b> del banc de bateries, caldrà restablir determinats paràmetres a <i>la configuració de fàbrica</i> .<br /><br /> Si no voleu que es realitzi aquesta reconfiguració, sobretot si heu fet una configuració específica, feu clic a CANCEL·LA.<br /><br /> En cas contrari, feu clic a CONFIRMAR per validar el canvi. + + + + Capacité + Capacitat + + + + + Ah + Ah + + + + Masquer les paramètres avancés + Amaga la configuració avançada + + + + Afficher les paramètres avancés + Mostra la configuració avançada + + + + Coefficient correcteur d'entrée de tension + Coeficient de correcció d'entrada de tensió + + + + + + + + + Caractéristiques du parc de batteries + Característiques del banc de bateries + + + + Durée correspondant à la capacité + Durada corresponent a l'aforament + + + + + h + h + + + + Capacité 2 + Capacitat 2 + + + + Durée de capacité 2 + Capacitat Durada 2 + + + + Coefficient de Peukert + coeficient de Peukert + + + + Résistance interne + Resistència interna + + + + mΩ + + + + + Soh actuel + Soh actual + + + + % + % + + + + Paramètres de pleine charge + Configuració de càrrega completa + + + + Tension mini pleine charge + Tensió mínima a plena càrrega + + + + + V + V + + + + Courant maxi pleine charge + Corrent màxima a plena càrrega + + + + A + + + + + Temporisation pleine charge + Retard de càrrega completa + + + + + s + s + + + + Efficacité de charge + Eficiència de càrrega + + + + Caractéristiques de charge nulle + Característiques de càrrega zero + + + + Tension de détection charge nulle + Tensió de detecció de càrrega zero + + + + Temporisation charge nulle + Retard de càrrega zero + + + + Alimentation %1 + Font d'alimentació %1 + + + + 48V + 48V + + + + Cette batterie est utilisée par l'évènement ci-dessous.<br />Vous devez modifier ou supprimer cet évènement pour qu'il ne dépende plus de cette batterie avant de pouvoir la supprimer. + Aquesta bateria l'utilitza l'esdeveniment següent.<br /> Heu de modificar o suprimir aquest esdeveniment perquè ja no depengui d'aquesta bateria abans de poder eliminar-lo. + + + + Cette batterie est utilisée par les %1 évènements ci-dessous.<br />Vous devez modifier ou supprimer ces évènements pour qu'ils ne dépendent plus de cette batterie avant de pouvoir la supprimer. + Aquesta bateria l'utilitzen els %1 esdeveniments següents.<br /> Heu de modificar o suprimir aquests esdeveniments perquè ja no depenguin d'aquesta granja abans de poder eliminar-los. + + + + Cette batterie est utilisée par le capteur calculé ci-dessous.<br />Vous devez modifier ou supprimer ce capteur calculé pour qu'il ne dépende plus de cette id_batterie avant de pouvoir la supprimer. + Aquesta bateria l'utilitza el sensor que es calcula a continuació.<br /> Heu de modificar o suprimir aquest sensor calculat perquè ja no depengui d'aquest battery_id abans de poder suprimir-lo. + + + + Cette id_batterie est utilisée par les %1 capteurs calculés ci-dessous.<br />Vous devez modifier ou supprimer ces capteurs calculés pour qu'ils ne dépendent plus de cette id_batterie avant de pouvoir la supprimer. + Aquest identificador de bateria l'utilitzen els sensors %1 calculats a continuació.<br /> Heu de modificar o suprimir aquests sensors calculats perquè ja no depenguin d'aquest battery_id abans de poder suprimir-lo. + + + + Ok + OK + + + + Historique + Històric + + + + Nombre de cycles de charge + Nombre de cicles de càrrega + + + + Nombre de décharges complètes + Nombre de descàrregues completes + + + + Forcer Pleine Charge + Força la càrrega completa + + + + Réinitialiser SOH + Restableix SOH + + + + Réinitialiser Compteurs + Restablir comptadors + + + + ShipBS [@ %1] + ShipBS[@%1] + + + + Entrée VOLT n° %1 + entrada VOLT núm %1 + + + + Plomb - Acide liquide + Plom - Àcid líquid + + + + Plomb - AGM / VRLA + Responsable - AGM / VRLA + + + + Plomb - Gel + Plom - Gel + + + + Plomb - Carbone + Plom - Carboni + + + + Lithium + Liti + + + + Non définie + Sense definir + + + + 12V + 12V + + + + 24V + 24V + + + + config_batteries + + + Configuration des batteries + Configuració de la bateria + + + + Aucune batterie n'est encore configurée... + Encara no hi ha piles configurades... + + + + + + + + + + + config_capteur + + + Création d'un capteur + Creació d'un sensor + + + + Configuration du capteur + Configuració del sensor + + + + Nom du capteur + Nom del sensor + + + + Type de capteur + Tipus de sensor + + + + Module + Mòdul + + + + Affectation + Encàrrec + + + + %1 : Non définie + %1: no definit + + + + %1 : %2 + %1 : %2 + + + + Mode du capteur + Mode sensor + + + + Groupe de capteurs + Grup de sensors + + + + Libellé du capteur pour la valeur %1 + Etiqueta del sensor per al valor %1 + + + + + + + Non défini + Sense definir + + + + Entrées Auxiliaires (AUX INPUTS) + Entrades auxiliars (AUX INPUTS) + + + + Entrées Niveau (LEVEL SENSORS) + Entrades de nivell (SENSORS DE NIVELL) + + + + Entrées Tension (VOLTAGE INPUTS) + Entrades de tensió (ENTRADES DE TENSIÓ) + + + + Capteurs de température (ONE WIRE) + Sensors de temperatura (UN CABLE) + + + + Entrées NMEA2000 + Entrades NMEA2000 + + + + Capteurs sur modules + Sensors en mòduls + + + + Calculé (conditions logiques) + Calculat (condicions lògiques) + + + + + <i>Entrée non utilisée</i> + <i>Entrada no utilitzada</i> + + + + Pression Atmosphérique + Pressió atmosfèrica + + + + + + Température module + Temperatura del mòdul + + + + + Tension d'entrée module + Tensió d'entrada del mòdul + + + + Consommation module + Mòdul de consum + + + + Consommation ports USB + Consum del port USB + + + + Chocs + Xocs + + + + Accélération X + Acceleració + + + + Accélération Y + Acceleració Y + + + + Accélération Z + Acceleració Z + + + + GNSS - SOG<br />Speed Over Ground + GNSS - SOG<br /> Velocitat sobre terra + + + + GNSS - COG<br />Course Over Ground + GNSS - COG<br /> Carrera per terra + + + + GNSS - SIV<br />Satellites In View + GNSS - SIV<br /> Satèl·lits a la vista + + + + GNSS - HPA<br />Horizontal Precision Accuracy + GNSS - HPA<br /> Exactitud de precisió horitzontal + + + + GNSS - VPA<br />Vertical Precision Accuracy + GNSS - VPA<br /> Precisió de precisió vertical + + + + Modem 4G/LTE - RSSI<br />Received Signal Strength Indicator + Mòdem 4G/LTE - RSSI<br /> Indicador de força del senyal rebut + + + + Modem 4G/LTE - SINR<br />Signal to Interference & Noise Ratio + Mòdem 4G/LTE - SINR<br /> Relació senyal/interferència i soroll + + + + Normal + Normal + + + + Inversé + Revés + + + + Tension 0 - 10 V + Tensió 0 - 10 V + + + + Résistance 0 - 500 Ohms + Resistència 0 - 500 ohms + + + + Courant 4 - 20 mA + Corrent 4 - 20 mA + + + + Défaut d'isolement + Falla d'aïllament + + + + Ce capteur est utilisé par l'évènement ci-dessous.<br />Vous devez modifier ou supprimer cet évènement pour qu'il ne dépende plus de ce capteur avant de pouvoir le supprimer. + Aquest sensor l'utilitza l'esdeveniment següent.<br /> Heu de modificar o suprimir aquest esdeveniment perquè ja no depengui d'aquest sensor abans de poder suprimir-lo. + + + + Ce capteur est utilisé par les %1 évènements ci-dessous.<br />Vous devez modifier ou supprimer ces évènements pour qu'ils ne dépendent plus de ce capteur avant de pouvoir le supprimer. + Aquest sensor l'utilitzen els %1 esdeveniments següents.<br /> Heu de modificar o suprimir aquests esdeveniments perquè ja no depenguin d'aquest sensor abans de poder eliminar-lo. + + + + Ce capteur est utilisé par le capteur calculé ci-dessous.<br />Vous devez modifier ou supprimer ce capteur calculé pour qu'il ne dépende plus de ce capteur avant de pouvoir le supprimer. + Aquest sensor l'utilitza el sensor calculat a continuació.<br /> Heu de modificar o suprimir aquest sensor calculat perquè ja no depengui d'aquest sensor abans de poder suprimir-lo. + + + + Ce capteur est utilisé par les %1 capteurs calculés ci-dessous.<br />Vous devez modifier ou supprimer ces capteurs calculés pour qu'ils ne dépendent plus de ce capteur avant de pouvoir le supprimer. + Aquest sensor l'utilitzen els sensors %1 calculats a continuació.<br /> Heu de modificar o suprimir aquests sensors calculats perquè ja no depenguin d'aquest sensor abans de poder eliminar-lo. + + + + Masquer sur la page Capteurs + Amaga a la pàgina Sensors + + + + Créer le capteur + Crea el sensor + + + + Enregistrer + Desa + + + + Equation + Equació + + + + Supprimer + ELIMINAR + + + + Etalonner + Calibrar + + + + Humidité + Humitat + + + + GNSS - Latitude + GNSS - Latitud + + + + GNSS - Longitude + GNSS - Longitud + + + + GNSS - Altitude + GNSS - Altitud + + + + config_capteur_calcule_booleen + + + Equation du capteur calculé [%1] + Equació del sensor calculada [%1] + + + + Enregistrer + Desa + + + + Supprimer + ELIMINAR + + + + Le nombre de conditions par capteur est limité à %1.<br /><br />Vous ne pouvez pas ajouter de groupe ou de nouvelle condition avant d'en avoir supprimé préalablement. + El nombre de condicions per sensor està limitat a %1.<br /><br /> No podeu afegir un grup o una condició nova fins que n'hagueu suprimit un primer. + + + + Des modifications ont été apportées au capteur<br />mais n'ont pas été enregistrées.<br /><br />Cliquer sur ANNULER pour revenir au menu en cours.<br /><br />Cliquer sur Ok pour sortir sans enregistrer. + S'han fet canvis al sensor<br /> però no es van registrar.<br /><br /> Feu clic a CANCEL·LA per tornar al menú actual.<br /><br /> Feu clic a D'acord per sortir sense desar. + + + + est actif + està actiu + + + + est inactif + està inactiu + + + + Ou + O + + + + Et + I + + + + X-Ou + X-O + + + + config_capteur_calcule_booleen_condition + + + Création d'une condition du capteur [%1] + S'està creant una condició de sensor [%1] + + + + Type + amable + + + + Source + Font + + + + Variable + Variable + + + + Test + Prova + + + + Seuil + Llindar + + + + Créer la condition + Crear condició + + + + Enregistrer + Desa + + + + + + + Non défini + Sense definir + + + + Circuit + Circuit + + + + Capteur + Sensor + + + + Réservoir + Dipòsit + + + + Batterie + Bateria + + + + Actif + Actiu + + + + Inactif + Inactiu + + + + &lt; au seuil + < llindar + + + + &le; au seuil + ≤ al llindar + + + + = au seuil + = al llindar + + + + &ge; au seuil + ≥ al llindar + + + + &gt; au seuil + > al llindar + + + + config_capteurs + + + Configuration des capteurs + Configuració de sensors + + + + Aucun capteur n'est encore configuré... + Encara no s'ha configurat cap sensor... + + + + + + + + + + + config_circuit + + + Configuration du circuit + Configuració del circuit + + + + Nom du circuit + Nom de la gira + + + + Affectation + Encàrrec + + + + Circuit renfort + Circuit de reforç + + + + Mode de commande + Mètode de comanda + + + + Vitesse de démarrage/arrêt + Velocitat d'inici/aturada + + + + Seuil de disjonction + Llindar de disjunció + + + + Vitesse de disjonction + Velocitat de disjunció + + + + Filtrage du courant consommé + Filtrat de corrent consumida + + + + Masquer sur la page d'accueil + Amaga a la pàgina d'inici + + + + Créer le circuit + Crea el circuit + + + + Enregistrer + Desa + + + + L'affectation du circuit vient d'être modifiée alors que le circuit était actif. +Avant d'effectuer ce changement, le circuit a été passé sur OFF. + +Pensez à le réactiver si besoin... + L'assignació del circuit s'acaba de modificar mentre el circuit estava actiu. + Abans de fer aquest canvi, el circuit es va apagar. + + Recordeu reactivar-lo si cal... + + + + Supprimer + ELIMINAR + + + + Aucun + Cap + + + + ShipPower812 [@ %1] + ShipPower812 [@%1] + + + + ShipPower4AC [@ %1] + ShipPower4AC [@%1] + + + + ShipPower8DC [@ %1] + ShipPower8DC [@%1] + + + + + Circuit %1 + Circuit %1 + + + + Groupe de circuits + Groupe de circuit + Grup de circuits + + + + Commande impulsionnelle + Control d'impulsos + + + + + %1 - %2 + %1 - %2 + + + + Non affecté + No afectat + + + + On-Off + On-Off + + + + On-Off progressif + On-Off progressiu + + + + Variateur + Dimmer + + + + Aucun filtrage + Sense filtres + + + + Très faible + Molt feble + + + + Faible + Feble + + + + Moyen + MITJANA + + + + Elevé + Alumna + + + + Très élevé + Molt alt + + + + + Très rapide + Molt ràpid + + + + + Rapide + Ràpid + + + + + Moyenne + Mitjana + + + + + Lente + Lent + + + + + Très lente + Molt lent + + + + Non + No + + + + 1 seconde + 1 segon + + + + 2 secondes + 2 segons + + + + 5 secondes + 5 segons + + + + Ce circuit est utilisé pour la commande du moteur.<br />Vous devez d'abord affecter la commande moteur à un autre circuit avant de pouvoir supprimer celui-ci. + Aquest circuit s'utilitza per al control del motor.<br /> Primer heu d'assignar el control del motor a un altre circuit abans de poder eliminar aquest circuit. + + + + Ce circuit est utilisé par l'évènement ci-dessous.<br />Vous devez modifier ou supprimer cet évènement pour qu'il ne dépende plus de ce circuit avant de pouvoir le supprimer. + Aquest circuit és utilitzat per l'esdeveniment següent.<br /> Heu de modificar o eliminar aquest esdeveniment perquè ja no depengui d'aquest circuit abans de poder eliminar-lo. + + + + Ce circuit est utilisé par les %1 évènements ci-dessous.<br />Vous devez modifier ou supprimer ces évènements pour qu'ils ne dépendent plus de ce circuit avant de pouvoir le supprimer. + Aquest circuit l'utilitzen els esdeveniments %1 següents.<br /> Heu de modificar o eliminar aquests esdeveniments perquè ja no depenguin d'aquest circuit abans de poder eliminar-lo. + + + + Ce circuit est utilisé par le capteur calculé ci-dessous.<br />Vous devez modifier ou supprimer ce capteur calculé pour qu'il ne dépende plus de ce circuit avant de pouvoir le supprimer. + Aquest circuit és utilitzat pel sensor que es calcula a continuació.<br /> Heu de modificar o eliminar aquest sensor calculat perquè ja no depengui d'aquest circuit abans de poder eliminar-lo. + + + + Ce circuit est utilisé par les %1 capteurs calculés ci-dessous.<br />Vous devez modifier ou supprimer ces capteurs calculés pour qu'ils ne dépendent plus de ce circuit avant de pouvoir le supprimer. + Aquest circuit l'utilitzen els sensors %1 calculats a continuació.<br /> Heu de modificar o eliminar aquests sensors calculats perquè ja no depenguin d'aquest circuit abans de poder eliminar-lo. + + + + 15 secondes + 15 segons + + + + 30 secondes + 30 segons + + + + 45 secondes + 45 segons + + + + 1 minute + 1 minut + + + + 5 minutes + 5 minuts + + + + 15 minutes + 15 minuts + + + + 1 heure + 1 hora + + + + 4 heures + 4 hores + + + + L'utilisation d'un circuit de renfort rend l'utilisation du mode de commande [Variateur] impossible.<br /><br />Le mode de commande vient donc d'être ramené à [On-Off Progressif]. + L'ús d'un circuit de reforç fa que l'ús del mode de control [Dimmer] sigui impossible.<br /><br /> Per tant, el mode de control s'acaba de tornar a [Progressiu On-Off]. + + + + config_circuits + + + Configuration des circuits + Configuració del circuit + + + + Pack de batteries : + Paquet de bateries: + + + + Aucun capteur n'est encore configuré... + Encara no s'ha configurat cap sensor... + + + + Oui + + + + + Non + No + + + + Le module n'est affecté à aucune batterie... + El mòdul no està assignat a cap bateria... + + + + Circuit non utilisé + Circuit no utilitzat + + + + Circuits Non Affectés + Circuits no afectats + + + + Ce circuit est configuré comme renfort du circuit <b>%1</b> et ne peut donc pas être configuré individuellement.<br /><br />Merci de cliquer sur le circuit <b>%1</b> de ce même module pour accéder à leurs paramètres communs<br />(y compris pour supprimer le circuit de renfort actuel). + Aquest circuit està configurat com a còpia de seguretat del circuit <b>%1</b> i, per tant, no es pot configurar individualment.<br /><br /> Feu clic al circuit <b>%1</b> d'aquest mateix mòdul per accedir als seus paràmetres comuns<br /> (inclòs eliminar el circuit de reforç actual). + + + + Type de carte inconnu... + Tipus de targeta desconegut... + + + + Le module <br /><b>%1</b><br /> n'est affecté à aucun pack de batteries. <br /><br />Souhaitez-vous laisser la configuration en l'état ? + El mòdul<br /> <b>%1</b><br /> no està assignat a cap paquet de bateries. <br /><br />Voleu deixar la configuració tal com està? + + + + Les modules suivants ne sont affectés à aucun pack de batteries :<br /><b>%1</b><br /><br /><br />Souhaitez-vous laisser la configuration en l'état ? + Els mòduls següents no estan assignats a cap paquet de bateries:<br /> <b>%1</b><br /><br /><br /> Voleu deixar la configuració tal com està? + + + + config_event + + + Création d'un évènement + Creació d'un esdeveniment + + + + Configuration de l'évènement + Configuració d'esdeveniments + + + + Nom de l'évènement + Nom de l'esdeveniment + + + + Type de la source + Tipus de font + + + + Source + Font + + + + Variable de la source + Variable font + + + + Déclenchement si + Activat si + + + + Seuil de déclenchement + Punt disparador + + + + Temporisation de déclenchement + Retard del disparador + + + + s + s + + + + Masquer sur la page d'accueil + Amaga a la pàgina d'inici + + + + Conditions horaire + Condicions temporals + + + + Le nombre maximal de conditions horaires [%1] est atteint : ajout impossible... + S'ha assolit el nombre màxim de condicions de temps [%1]: addició impossible... + + + + Aucune condition horaire n'est configurée pour cet évènement... + No s'han configurat condicions de temps per a aquest esdeveniment... + + + + Signalisation + Senyalització + + + + Alarme sonore + Alarma sonora + + + + La validation des alarmes sonores a nécessité de valider également l'affichage des messages liés à cet évènement.<br /><br />Cet affichage est en effet nécessaire au fonctionnement des alarmes sonores, afin de pouvoir les acquitter. + La validació de les alarmes sonores també va requerir validar la visualització dels missatges relacionats amb aquest esdeveniment.<br /><br /> De fet, aquesta visualització és necessària per al funcionament de les alarmes sonores, per tal de poder reconèixer-les. + + + + Alarme sur LED + Alarma en LED + + + + La validation des alarmes sur LED a nécessité de valider également l'affichage des messages liés à cet évènement.<br /><br />Cet affichage est en effet nécessaire au fonctionnement des alarmes sur LED, afin de pouvoir les acquitter. + La validació d'alarmes en LED també va requerir validar la visualització dels missatges relacionats amb aquest esdeveniment.<br /><br /> De fet, aquesta pantalla és necessària perquè funcionin les alarmes LED, per poder reconèixer-les. + + + + Alarme sur sortie(s) de soutien + Alarma a les sortides de suport + + + + La validation des alarmes sur sortie(s) de soutien a nécessité de valider également l'affichage des messages liés à cet évènement.<br /><br />Cet affichage est en effet nécessaire au fonctionnement des alarmes sur sortie(s) de soutien, afin de pouvoir les acquitter. + La validació de les alarmes a les sortides de suport també va requerir la validació de la visualització de missatges vinculats a aquest esdeveniment.<br /><br /> De fet, aquesta visualització és necessària per al funcionament de les alarmes a les sortides de suport, per tal de poder reconèixer-les. + + + + Alarme sur la source + Alarma a la font + + + + Affichage message sur ShipBase + Visualització de missatges a ShipBase + + + + La dévalidation de l'affichage des messages a nécessité de dévalider également :<ul><li>les alarmes sonores,</li><li>les alarmes sur led</li><li>et les alarmes sur sortie(s) de soutien</li></ul><br />L'affichage de message est en effet nécessaire à leur fonctionnement, afin de pouvoir les acquitter. + La desactivació de la visualització de missatges també va requerir desvalidar:<ul><li> alarmes sonores,</li><li> Alarmes LED</li><li> i alarmes a les sortides de suport</li></ul><br /> La visualització de missatges és, de fet, necessària per al seu funcionament, per tal de poder reconèixer-los. + + + + Texte du message à afficher + Text del missatge per mostrar + + + + Emission SMS + Transmissió de SMS + + + + Texte du SMS à envoyer + Text de l'SMS per enviar + + + + Emission Email + Transmissió per correu electrònic + + + + Texte de l'email à envoyer + Text del correu electrònic a enviar + + + + Action sur circuits + Acció sobre circuits + + + + Aucune + Cap + + + + Le circuit "bascule" + El circuit de "canvi" + + + + Le circuit passe à OFF + El circuit s'apaga + + + + Le circuit passe à ON + El circuit s'encén + + + + Le nombre de circuits commandés par un évènement est limité à %1.<br /><br />Vous ne pouvez pas ajouter d'action sur un nouveau circuit avant d'en avoir supprimé préalablement. + El nombre de circuits controlats per un esdeveniment està limitat a %1.<br /><br /> No podeu afegir una acció a un circuit nou abans d'haver-ne suprimit una. + + + + Créer l'évènement + Crea l'esdeveniment + + + + Enregistrer + Desa + + + + Supprimer + ELIMINAR + + + + + + + Non défini + Sense definir + + + + Condition horaire seule + Només condició de temps + + + + Circuit + Circuit + + + + Capteur + Sensor + + + + Réservoir + Dipòsit + + + + Batterie + Bateria + + + + Passage à <b>actif</b> + Canvia a <b>actiu</b> + + + + Passage à <b>inactif</b> + Canviant a <b>inactiu</b> + + + + &lt; au seuil + &lt; llindar + + + + &le; au seuil + &le; al llindar + + + + = au seuil + = al llindar + + + + &ge; au seuil + &ge; al llindar + + + + &gt; au seuil + &gt; al llindar + + + + config_events + + + Configuration des évènements + Configuració d'esdeveniments + + + + Aucun évènement n'est encore configuré... + Encara no s'ha configurat cap esdeveniment... + + + + 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. + El nombre total d'esdeveniments està limitat a %1.<br /><br /> No podeu afegir un esdeveniment nou abans d'haver-ne suprimit un. + + + + Sur circuits + En circuits + + + + Sur capteurs + Sobre sensors + + + + Sur réservoirs + En tancs + + + + Sur batteries + Amb piles + + + + Horaire seulement + Només amb horari + + + + config_groupe_elements + + + Création d'un groupe + Creació d'un grup + + + + Modification d'un groupe + Edició d'un grup + + + + Nom du groupe + Nom del grup + + + + Créer le groupe + Crea el grup + + + + Enregistrer + Desa + + + + Supprimer + ELIMINAR + + + + batteries + bateries + + + + capteurs + sensors + + + + circuits + circuits + + + + réservoirs + tancs + + + + 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). + Aquest grup és l'últim encara vigent.<br /><br /> Només podreu esborrar-lo després d'haver creat prèviament almenys un altre (no és possible operar sense cap grup de %1). + + + + Ce groupe comprend encore %1 %2.<br /><br />Il est nécessaire d'affecter ces %2 à un autre groupe avant de pouvoir le supprimer. + Aquest grup encara inclou %1 %2.<br /><br /> Cal assignar aquests %2 a un altre grup abans de poder eliminar-lo. + + + + 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. + Aquest grup encara inclou %1 %2,<br /> inclòs %3 configurat com a "ocult".<br /><br /> Cal assignar aquests %2 a un altre grup abans de poder eliminar-lo. + + + + config_image_accueil + + + Image d'accueil + Imatge de casa + + + + Aucune image n'a encore été chargée... + Encara no s'ha carregat cap imatge... + + + + Sélectionner l'image par défaut + Seleccioneu la imatge predeterminada + + + + Sélectionner cette image + Seleccioneu aquesta imatge + + + + Copier + Per copiar + + + + Supprimer + ELIMINAR + + + + Ejection + Expulsió + + + + Insérer une clé USB dans le port <u>du bas</u>, à droite + Inseriu una clau USB al port <u>inferior</u> dret + + + + Vous pouvez retirer la clé en toute sécurité... + Pots treure la clau amb seguretat... + + + + Seuls les fichiers de type '.jpg' ou '.png' de taille inférieure à %1 sont autorisés. + Només es permeten fitxers de tipus ".jpg" o ".png" de mida inferior a %1. + + + + La clé USB a été <i>éjectée</i> automatiquement.<br />Vous pouvez la retirer dès maintenant en toute sécurité... + La unitat USB s'ha <i>expulsat</i> automàticament.<br /> Ara pots eliminar-lo amb seguretat... + + + + USB Arrière + USB posterior + + + + Spare + De recanvi + + + + USB Avant + USB frontal + + + + Touch pad + Touchpad + + + + La clé USB a été retirée sans avoir préalablement été <i>éjectée</i> !<br />Cela peut conduire à des pertes de données sur la clé, voire sur ShipHeart.<br /><br />Lors de vos prochaines utilisations, pensez à <i>éjecter</i> la clé avec le bouton en haut de page avant de la retirer... Merci ! + El llapis USB s'ha retirat sense haver- <i>lo expulsat</i> abans!<br /> Això pot provocar la pèrdua de dades a la clau, o fins i tot a ShipHeart.<br /><br /> La propera vegada que l'utilitzeu, recordeu <i>expulsar</i> la clau amb el botó de la part superior de la pàgina abans d'eliminar-la... GRÀCIES! + + + + config_installation + + + Configuration de l'installation + Configuració de la instal·lació + + + + Raison sociale + Raó social + + + + N° & Rue + No i carrer + + + + Complément d'adresse + Adreça addicional + + + + Code postal + Codi Postal + + + + Ville + ciutat + + + + Nom du contact + Nom de contacte + + + + Téléphone + Telèfon + + + + Email + Correu electrònic + + + + Site web + Lloc web + + + + Enregistrer + Desa + + + + Rapports + Informes + + + + config_koriolan + + + Accès réservé Koriolan + Accés reservat Koriolan + + + + Client spécifique + Client específic + + + + Mode de mise à jour des firmwares + Mode d'actualització del firmware + + + + Enregistrer + Desa + + + + Tests matériel + Proves de maquinari + + + + Nombre jours avant suppression historique + Nombre de dies abans de la supressió històrica + + + + Nombre jours avant suppression mesures + Nombre de dies abans de la supressió de mesures + + + + Période de sauvegarde BDD + Període de còpia de seguretat de BDD + + + + Période de vérification download + Període de verificació de la baixada + + + + Date de dernier archivage mesures + Data d'arxiu de l'última mesura + + + + Aucune spécificité + Sense especificitat + + + + Client Suncy Concept + Concepte assolellat del client + + + + Normal (si version installée est antérieure à la version en cours) + Normal (si la versió instal·lada és més antiga que la versió actual) + + + + Différente (si version installée est différente de version en cours) + Diferent (si la versió instal·lada és diferent de la versió actual) + + + + Toujours (à utiliser avec modération...) + Sempre (utilitzar amb moderació...) + + + + config_module + + + Modifier + Per modificar + + + + Localiser le module + Localitzeu el mòdul + + + + Paramètres du module [%1] + Configuració del mòdul [%1] + + + + Paramètres du module [%1] à l'adresse [%2] + Paràmetres del mòdul [%1] a l'adreça [%2] + + + + N° de série + Número de sèrie + + + + Nom du firmware + Nom del firmware + + + + Version du firmware + Versió de firmware + + + + Version matérielle + Versió de maquinari + + + + Résistance de terminaison + Resistència de terminació + + + + Oui + + + + + Non + No + + + + CRC du firmware + CRC de firmware + + + + Courant de masses sur réseau + Corrent de terra a la xarxa + + + + <i>--- Circuit non affecté ---</i> + <i>--- Circuit no afectat ---</i> + + + + [renfort] + [reforç] + + + + Affectations + Encàrrecs + + + + <i>--- Aucune batterie affectée ---</i> + <i>--- Cap bateria afectada ---</i> + + + + Affectation + Encàrrec + + + + Version processeur + Versió del processador + + + + Emplacement du module à bord + Ubicació del mòdul a bord + + + + Commentaires + Comentaris + + + + config_module_modification + + + Configuration du module [%1] à l'adresse [%2] + Configuració del mòdul [%1] a l'adreça [%2] + + + + Emplacement du module à bord + Ubicació del mòdul a bord + + + + Commentaires + Comentaris + + + + Courant de masses max. sur réseau + Corrent màxim de terra a la xarxa + + + + A + A + + + + Enregistrer + Desa + + + + config_ordre_elements + + + 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... + Per moure un grup, manteniu-lo premut i arrossegueu-lo.<br /> Per editar o suprimir un grup, feu doble clic al grup.<br /> Per afegir un grup, feu clic a "+".<br /><br /> Nota: si només hi ha un grup, no es mostra cap pestanya a la pàgina en qüestió... + + + + Aucun groupe n'est actuellement configuré... + No hi ha cap grup configurat actualment... + + + + Aucun élément n'est actuellement configuré... + No hi ha res configurat actualment... + + + + Aucun groupe de batteries n'est actuellement configuré... + No hi ha cap banc de bateries configurat actualment... + + + + Aucune batterie n'est actuellement affectée à ce groupe... + Actualment no hi ha piles assignades a aquest grup... + + + + Affichage des batteries sur la page d'accueil + Mostrant les piles a la pàgina d'inici + + + + Aucun capteur n'est actuellement affecté ce groupe... + Actualment no hi ha cap sensor assignat a aquest grup... + + + + Affichage des capteurs sur la page d'accueil + Visualització dels sensors a la pàgina d'inici + + + + Aucun circuit n'est actuellement affecté à ce groupe... + Actualment no hi ha cap circuit assignat a aquest grup... + + + + Affichage des circuits sur la page d'accueil + Visualització de circuits a la pàgina d'inici + + + + Aucun groupe de réservoirs n'est actuellement configuré... + No hi ha cap grup de tancs configurat actualment... + + + + Aucun réservoir n'est actuellement affecté à ce groupe... + Actualment no hi ha cap tanc assignat a aquest grup... + + + + Affichage des réservoirs sur la page d'accueil + Es mostren els tancs a la pàgina d'inici + + + + Aucun groupe de capteurs n'est actuellement configuré... + No hi ha cap grup de sensors configurat actualment... + + + + Aucun groupe de circuits n'est actuellement configuré... + No hi ha cap grup de circuits configurat actualment... + + + + config_page + + + Création d'une page + Creació d'una pàgina + + + + Configuration de la page + Configuració de la pàgina + + + + Nom de la page + Nom de la pàgina + + + + Opacité de la silhouette + Opacitat de la silueta + + + + Fichier de silhouette + Arxiu de siluetes + + + + Créer la page + Crea la pàgina + + + + Enregistrer + Desa + + + + Silhouette + Silueta + + + + Supprimer + ELIMINAR + + + + + Aucun + Cap + + + + config_page_edition + + + Edition de la page [%1] + S'està editant la pàgina [%1] + + + + Aucun équipement n'est configuré sur cette page pour le moment... + No hi ha cap equip configurat en aquesta pàgina de moment... + + + + Page + Page + + + + Enregistrer + Desa + + + + 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. + Heu fet canvis que no s'han desat<br /> Feu clic a Cancel·la per tornar enrere i desar-los.<br /> Feu clic a D'acord per sortir sense desar. + + + + config_page_point + + + Création d'un point + Creació d'un punt + + + + Configuration du point + Configuració de punts + + + + Type de la source + Tipus de font + + + + Source + Font + + + + Type de point + Tipus de puntada + + + + Taille du point + Mida del punt + + + + Enregistrer + Desa + + + + Créer le point + Crea el punt + + + + Supprimer + ELIMINAR + + + + + Non défini + Sense definir + + + + Capteur + Sensor + + + + Circuit + Circuit + + + + Réservoir + Dipòsit + + + + Batterie + Bateria + + + + Modules + Mòduls + + + + config_page_silhouette + + + Silhouette de la page + Silueta de pàgina + + + + Aucune image n'a encore été chargée... + Encara no s'ha carregat cap imatge... + + + + Aucune image + Sense imatges + + + + Sélectionner cette image + Seleccioneu aquesta imatge + + + + Copier + Per copiar + + + + Supprimer + ELIMINAR + + + + Ejection + Expulsió + + + + Insérer une clé USB dans le port <u>du bas</u>, à droite + Inseriu una clau USB al port <u>inferior</u> dret + + + + Vous pouvez retirer la clé en toute sécurité... + Pots treure la clau amb seguretat... + + + + Seuls les fichiers de type '.jpg' ou '.png' de taille inférieure à %1 sont autorisés. + Només es permeten fitxers de tipus ".jpg" o ".png" de mida inferior a %1. + + + + La clé USB a été <i>éjectée</i> automatiquement.<br />Vous pouvez la retirer dès maintenant en toute sécurité... + La unitat USB s'ha <i>expulsat</i> automàticament.<br /> Ara pots eliminar-lo amb seguretat... + + + + USB Arrière + USB posterior + + + + Spare + De recanvi + + + + USB Avant + USB frontal + + + + Touch pad + Touchpad + + + + La clé USB a été retirée sans avoir préalablement été <i>éjectée</i> !<br />Cela peut conduire à des pertes de données sur la clé, voire sur ShipHeart.<br /><br />Lors de vos prochaines utilisations, pensez à <i>éjecter</i> la clé avec le bouton en haut de page avant de la retirer... Merci ! + El llapis USB s'ha retirat sense haver- <i>lo expulsat</i> abans!<br /> Això pot provocar la pèrdua de dades a la clau, o fins i tot a ShipHeart.<br /><br /> La propera vegada que l'utilitzeu, recordeu <i>expulsar</i> la clau amb el botó de la part superior de la pàgina abans d'eliminar-la... GRÀCIES! + + + + config_pages + + + Configuration des pages + Configuració de la pàgina + + + + Aucune page n'est encore configurée... + Encara no s'ha configurat cap pàgina... + + + + Image accueil + Imatge de casa + + + + + + + + + + + config_pdf + + + Ship2net + Ship2net + + + + Enregistrer + Desa + + + + config_rapports + + + Rapports d'installation + Informes d'instal·lació + + + + Aucun rapport d'installation n'est encore disponible... + Encara no hi ha cap informe d'instal·lació disponible... + + + + Nouveau rapport d'installation + Nou informe d'instal·lació + + + + Copier + Per copiar + + + + Déplacer + Moure's + + + + Supprimer + ELIMINAR + + + + Ejection + Expulsió + + + + Insérer une clé USB dans le port <u>du bas</u>, à droite + Inseriu una clau USB al port <u>inferior</u> dret + + + + Vous pouvez retirer la clé en toute sécurité... + Pots treure la clau amb seguretat... + + + + La clé USB a été <i>éjectée</i> automatiquement.<br />Vous pouvez la retirer dès maintenant en toute sécurité... + La unitat USB s'ha <i>expulsat</i> automàticament.<br /> Ara pots eliminar-lo amb seguretat... + + + + USB Arrière + USB posterior + + + + Spare + De recanvi + + + + USB Avant + USB frontal + + + + Touch pad + Touchpad + + + + La clé USB a été retirée sans avoir préalablement été <i>éjectée</i> !<br />Cela peut conduire à des pertes de données sur la clé, voire sur ShipHeart.<br /><br />Lors de vos prochaines utilisations, pensez à <i>éjecter</i> la clé avec le bouton en haut de page avant de la retirer... Merci ! + El llapis USB s'ha retirat sense haver- <i>lo expulsat</i> abans!<br /> Això pot provocar la pèrdua de dades a la clau, o fins i tot a ShipHeart.<br /><br /> La propera vegada que l'utilitzeu, recordeu <i>expulsar</i> la clau amb el botó de la part superior de la pàgina abans d'eliminar-la... GRÀCIES! + + + + Le rapport d'installation<br /><br /><b>%1</b><br /><br />a été généré. + L'informe d'instal·lació<br /><br /> <b>%1</b><br /><br /> es va generar. + + + + config_reseau_ethernet_wifi + + + Réseau Ethernet & Wifi + Xarxa Ethernet i Wifi + + + + + Modifier + Per modificar + + + + Ethernet + Ethernet + + + + + + Adresse IP + adreça IP + + + + + + Non connecté + No connectat + + + + Connexion à un réseau existant + Connexió a una xarxa existent + + + + + Etat + Estat + + + + + On + ON + + + + + Off + OFF + + + + + Nom du réseau [SSID] + Nom de la xarxa [SSID] + + + + Génération d'un réseau spécifique + Generació d'una xarxa específica + + + + Canal + Canal + + + + config_reseau_k_bus + + + Réseau ShipHeart + Xarxa ShipHeart + + + + Modules physiquement présents + Mòduls presents físicament + + + + %1 - %2 + %1 - %2 + + + + Modules utilisés par la configuration actuelle + Mòduls utilitzats per la configuració actual + + + + [@ %1] : %2 + [@ %1] : %2 + + + + La configuration actuelle ne fait appel à aucun autre module que ShipBase... + La configuració actual no utilitza cap altre mòdul que ShipBase... + + + + Module non utilisé en configuration + Mòdul no utilitzat en la configuració + + + + [renfort] + [reforç] + + + + Enregistrer + Desa + + + + Retour + esquena + + + + Quitter + Deixar + + + + Aucune modification n'a été apportée à la configuration actuelle.<br />Celle-ci contient toujours des anomalies !<br /><br /><br />Souhaitez-vous :<br />Poursuivre les modifications [%1]<br />Quitter ce menu sans enregistrer les modifications [%2] + No s'ha fet cap canvi a la configuració actual.<br /> Això sempre conté anomalies!<br /><br /><br /> T'agradaria:<br /> Continua editant [%1]<br /> Sortiu d'aquest menú sense desar els canvis [%2] + + + + La configuration actuelle contient toujours des anomalies !<br /><br /><br />Souhaitez-vous :<br />Enregistrer cette nouvelle configuration et quitter ce menu [%1]<br />Poursuivre les modifications [%2]<br />Quitter ce menu sans enregistrer les modifications [%3] + La configuració actual encara conté anomalies!<br /><br /><br /> T'agradaria:<br /> Desa aquesta nova configuració i surt d'aquest menú [%1]<br /> Continua editant [%2]<br /> Sortiu d'aquest menú sense desar els canvis [%3] + + + + La configuration actuelle est correcte <br />mais n'a pas encore été enregistrée.<br /><br /><br />Souhaitez-vous :<br />Enregistrer cette nouvelle configuration et quitter ce menu [%1]<br />Poursuivre les modifications [%2]<br />Quitter ce menu sans enregistrer les modifications [%3] + La configuració actual és correcta<br /> però encara no s'ha registrat.<br /><br /><br /> T'agradaria:<br /> Desa aquesta nova configuració i surt d'aquest menú [%1]<br /> Continua editant [%2]<br /> Sortiu d'aquest menú sense desar els canvis [%3] + + + + config_reseau_nmea + + + Réseau NMEA2000 + Xarxa NMEA2000 + + + + Aucun PGN n'a encore été détecté sur le réseau NMEA2000... + Encara no s'ha detectat cap PGN a la xarxa NMEA2000... + + + + PGN non affecté + PGN no assignat + + + + config_reseau_one_wire + + + Réseau One Wire + Xarxa d'un cable + + + + Aucune sonde n'est encore installée... + Encara no hi ha cap sonda instal·lada... + + + + 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. + Actualment es detecta que el bus One Wire està en curtcircuit. <br />Aquest estat no presenta cap perill però n'impedeix el seu funcionament. <br /><br />Comproveu el cablejat corresponent fins que desaparegui aquest missatge. + + + + Type inconnu + Tipus desconegut + + + + Sonde non affectée + Sonda no assignada + + + + config_reseau_one_wire_modification + + + Configuration de la sonde [%1] + Configuració de la sonda [%1] + + + + Emplacement de la sonde + Ubicació de la sonda + + + + Enregistrer + Desa + + + + config_reseau_wifi_ap + + + Configuration Wifi en mode AP + Configuració wifi en mode AP + + + + Etat + Estat + + + + Nom du réseau (SSID) + Nom de xarxa (SSID) + + + + Mot de passe d'accès au réseau + Contrasenya d'accés a la xarxa + + + + Canal + Canal + + + + Adresse IP + adreça IP + + + + Non connecté + No connectat + + + + Enregistrer + Desa + + + + Off + OFF + + + + On + ON + + + + Canal %1 - [%2GHz] + Canal %1 - [%2GHz] + + + + Le nom du réseau (SSID) doit comprendre entre 1 et 32 caractères. <br />Merci d'entrer un nom valide. + El nom de xarxa (SSID) ha de tenir entre 1 i 32 caràcters.<br /> Introduïu un nom vàlid. + + + + 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. + La contrasenya d'accés a la xarxa ha de tenir entre 8 i 63 caràcters.<br /> Introduïu una contrasenya vàlida. + + + + 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. + El nom de la xarxa (SSID) només ha d'incloure:<br /> - lletres majúscules [A - Z],<br /> - lletres minúscules [a - z],<br /> - números [0 - 9]<br /> - caràcters especials [%1].<br /><br /> Introduïu un nom vàlid. + + + + 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. + La contrasenya d'accés a la xarxa només ha d'incloure:<br /> - lletres majúscules [A - Z],<br /> - lletres minúscules [a - z],<br /> - números [0 - 9]<br /> - caràcters especials [%1].<br /><br /> Introduïu un nom vàlid. + + + + config_reseau_wifi_sta + + + Configuration Wifi en mode STA + Configuració wifi en mode STA + + + + Etat + Estat + + + + Réseau + Xarxa + + + + Mot de passe d'accès au réseau + Contrasenya d'accés a la xarxa + + + + Enregistrer + Desa + + + + Réseaux connus + Xarxes conegudes + + + + Off + OFF + + + + On + ON + + + + Aucun réseau... + Sense xarxa... + + + + config_reseau_wifi_sta_liste + + + Liste des réseaux Wifi connus + Llista de xarxes WiFi conegudes + + + + Aucun réseau n'a été détecté... + No s'ha detectat cap xarxa... + + + + Oublier tous les réseaux + Oblida't de totes les xarxes + + + + Oublier ce réseau + Oblida't d'aquesta xarxa + + + + config_reservoir + + + Création d'un réservoir + Creació d'un dipòsit + + + + Configuration du réservoir + Configuració del tanc + + + + Nom du réservoir + Nom de l'embassament + + + + Famille de réservoirs + Família de tancs + + + + Type de capteur de niveau + Tipus de sensor de nivell + + + + %1 : Non définie + %1: no definit + + + + %1 : %2 + %1 : %2 + + + + Sonde la plus basse dans le réservoir + Sonda més baixa del dipòsit + + + + Non définie + Sense definir + + + + Logique d'alarme + Lògica d'alarma + + + + Filtrage des mesures + Mesures de filtratge + + + + Créer le réservoir + Crea el tanc + + + + Enregistrer + Desa + + + + Supprimer + ELIMINAR + + + + Etalonnage + Calibració + + + + + AUX INPUT %1 + ENTRADA AUXILIAR %1 + + + + + LEVEL SENSOR %1 + SENSOR DE NIVELL %1 + + + + Confirmer + Confirmeu + + + + Capacité du réservoir + Capacitat del dipòsit + + + + litres + litres + + + + Logique des entrées inversée + Lògica d'entrada invertida + + + + La modification du <b>type de capteur</b> va nécessiter la remise en <i>configuration usine</i> de tous les paramètres du réservoir.<br /><br />Si vous ne souhaitez pas que cette reconfiguration soit effectuée, cliquez sur ANNULER. <br /><br />Sinon, cliquez sur CONFIRMER pour valider le changement. + Per canviar el <b>tipus de sensor</b> caldrà restablir tots els paràmetres del dipòsit a <i>la configuració de fàbrica</i> .<br /><br /> Si no voleu que es realitzi aquesta reconfiguració, feu clic a CANCEL·LA. <br /><br />En cas contrari, feu clic a CONFIRMAR per validar el canvi. + + + + Non défini + Sense definir + + + + Electrodes plongées ou contacts secs + Elèctrodes immersos o contactes secs + + + + Résistif 0 - 190Ω + Resistència 0 - 190Ω + + + + Résistif 240 - 30Ω + Resistència 240 - 30Ω + + + + Résistif 0 - 700Ω + Resistència 0 - 700Ω + + + + Boucle de courant 4 - 20mA + Bucle de corrent 4 - 20 mA + + + + Tension 0 - 10V + Tensió 0 - 10V + + + + Aucun filtrage + Sense filtres + + + + Très faible + Molt feble + + + + Faible + Feble + + + + Moyen + MITJANA + + + + Elevé + Alumna + + + + Très élevé + Molt alt + + + + Ce réservoir est utilisé par l'évènement ci-dessous.<br />Vous devez modifier ou supprimer cet évènement pour qu'il ne dépende plus de ce réservoir avant de pouvoir le supprimer. + Aquest tanc l'utilitza l'esdeveniment següent.<br /> Heu de modificar o suprimir aquest esdeveniment perquè ja no depengui d'aquest tanc abans de poder eliminar-lo. + + + + Ce réservoir est utilisé par les %1 évènements ci-dessous.<br />Vous devez modifier ou supprimer ces évènements pour qu'ils ne dépendent plus de ce réservoir avant de pouvoir le supprimer. + Aquest dipòsit l'utilitzen els %1 esdeveniments següents.<br /> Heu de modificar o suprimir aquests esdeveniments perquè ja no depenguin d'aquest tanc abans de poder eliminar-lo. + + + + Ce réservoir est utilisé par le capteur calculé ci-dessous.<br />Vous devez modifier ou supprimer ce capteur calculé pour qu'il ne dépende plus de ce réservoir avant de pouvoir le supprimer. + Aquest dipòsit l'utilitza el sensor que es calcula a continuació.<br /> Heu de modificar o suprimir aquest sensor calculat perquè ja no depengui d'aquest tanc abans de poder eliminar-lo. + + + + Ce réservoir est utilisé par les %1 capteurs calculés ci-dessous.<br />Vous devez modifier ou supprimer ces capteurs calculés pour qu'ils ne dépendent plus de ce réservoir avant de pouvoir le supprimer. + Aquest dipòsit l'utilitzen els sensors %1 calculats a continuació.<br /> Heu de canviar o suprimir aquests sensors calculats perquè ja no depenguin d'aquest dipòsit abans de poder eliminar-lo. + + + + Alerte sur niveau faible + Alerta de baix nivell + + + + Alerte sur niveau élevé + Alerta d'alt nivell + + + + config_reservoirs + + + Configuration des réservoirs + Configuració del tanc + + + + Aucun réservoir n'est encore configuré... + Encara no s'ha configurat cap tanc... + + + + + + + + + + + config_ship2net + + + Ship2net + Ship2net + + + + Période des sauvegardes + Període de còpia de seguretat + + + + Période de connexion à Ship2net + Període de connexió Ship2net + + + + Mode de validation des mises à jour + Actualitzar el mode de validació + + + + Accès distant WebGL #1 + Accés remot de WebGL #1 + + + + Accès distant WebGL #2 + Accés remot de WebGL #2 + + + + Accès distant WebGL #3 + Accés remot de WebGL #3 + + + + Enregistrer + Desa + + + + + Jamais + Mai + + + + + 2 minutes + 2 minuts + + + + + 30 minutes + 30 minuts + + + + + 1 heure + 1 hora + + + + 2 heures + 2 hores + + + + + 4 heures + 4 hores + + + + + 12 heures + 12 hores + + + + + 24 heures + 24 hores + + + + + + Dévalidé + Invalidat + + + + + + Valide [port %1] + Vàlid [port % 1] + + + + + 10 minutes + 10 minuts + + + + Aucune mise à jour + No hi ha actualitzacions + + + + Validation manuelle des mises à jour reçues + Validació manual de les actualitzacions rebudes + + + + Validation automatique des mises à jour reçues + Validació automàtica de les actualitzacions rebudes + + + + config_specifique_client_suncy + + + Configuration spécifique à Suncy Concept + Configuració específica de Sunny Concept + + + + Circuit d'activation moteur + Circuit d'activació del motor + + + + Nouveau code + Nou codi + + + + Code d'accès au bateau + Codi d'accés del vaixell + + + + Répéter le code d'accès + Repetiu la contrasenya + + + + Enregistrer + Desa + + + + Aucune + Cap + + + + [module %1 - circuit %2] %3 + [mòdul %1 - circuit %2] %3 + + + + Les deux valeurs saisies doivent être identiques ! + +De plus, le code doit contenir : +- %1 chiffres au minimum +- %2 chiffres au maximum. + Els dos valors introduïts han de ser idèntics! + + A més, el codi ha de contenir: + - %1 dígit mínim + - Màxim %2 dígits. + + + + Le nouveau code doit contenir : +- %1 chiffres au minimum +- %2 chiffres au maximum. + +Le code saisi ne répond pas à ces critères et sa mise à jour n'est donc pas effectuée. + +Merci de saisir un code au format valide si vous souhaitez le modifier. + El nou codi ha de contenir: + - %1 dígit mínim + - Màxim %2 dígits. + + El codi introduït no compleix aquests criteris i, per tant, no s'actualitza. + + Introduïu un codi en un format vàlid si voleu modificar-lo. + + + + config_valeurs_niveaux + + + Aucun point de conversion n'est configuré pour le moment... + No hi ha cap punt de conversió configurat en aquest moment... + + + + Le nombre maximal de points d'étalonnage a été atteint (%1 points)<br />Vous ne pouvez pas en ajouter sans en avoir prélablement supprimé. + S'ha assolit el nombre màxim de punts de calibratge (%1 punts).<br />No podeu afegir-ne més sense esborrar-ne alguns primer. + + + + Courbe usine + Corba de fàbrica + + + + Enregistrer + Desa + + + + La valeur lue sur les electrodes plongées de ce réservoir est incohérente.<br />Vérifier l'ordre de cablage des électrodes sur les entrées auxiliaires à l'arrière de ShipBase. + La lectura dels elèctrodes d'immersió d'aquest tanc és inconsistent.<br />Comproveu l'ordre de cablejat dels elèctrodes a les entrades auxiliars de la part posterior de ShipBase. + + + + Aucune donnée n'est disponible... + No hi ha dades disponibles... + + + + 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. + Heu fet canvis que no s'han desat<br /> Feu clic a Cancel·la per tornar enrere i desar-los.<br /> Feu clic a D'acord per sortir sense desar. + + + + Aucun point n'est actuellement configuré pour cette batterie... + Actualment no hi ha cap punt configurat per a aquesta bateria... + + + + + Courbe de conversion de [%1] + Corba de conversió de [%1] + + + + Aucun réservoir n'est actuellement configuré... + No hi ha tancs configurats actualment... + + + + Aucun point n'est actuellement configuré pour cet élément... + Actualment no hi ha cap punt configurat per a aquest element... + + + + Courbe de conversion de type INCONNU + Corba de conversió de tipus DESCONEGUT + + + + config_version + + + Version + Versió + + + + %1 : %2 + %1 : %2 + + + + 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 : + La versió <b>%1</b> està disponible.<br /><br /> S'instal·larà automàticament la propera vegada que inicieu ShipHeart.<br /> A menys que trieu una de les opcions següents: + + + + La version <b>%1</b> est disponible.<br /><br />Souhaitez-vous : + La versió <b>%1</b> està disponible.<br /><br /> T'agradaria: + + + + + L'installer +maintenant + Instal·leu-lo + ARA + + + + L'installer au prochain démarrage de ShipHeart + Instal·leu-lo la propera vegada que inicieu ShipHeart + + + + + Ne jamais l'installer + No l'instal·lis mai + + + + Supprimer + ELIMINAR + + + + Si vous confirmez, cette mise à jour sera définitivement supprimée.<br />Cliquez sur Annuler pour revenir en arrière et la conserver. + Si confirmeu, aquesta actualització se suprimirà permanentment.<br />Feu clic a Cancel·la per tornar enrere i conservar-la. + + + + Installer + Instal·lar + + + + 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 la conserver pour une installation ultérieure. + Si confirmeu, aquesta actualització pot trigar <u>uns minuts</u> durant els quals <b>no es podrà accedir al vostre sistema ShipHeart</b>.<br /><br />No cal que confirmeu el la instal·lació només si us trobeu en una situació de seguretat (a port, àncora, etc.) i la pèrdua de control dels vostres sistemes a bord durant aquest període de temps és sense cap perill!<br /><br />Feu clic a Cancel·la per tornar enrere i desar-lo per a una instal·lació posterior. + + + + 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 'shipheart.tech' ou de nous contacter à l'adresse 'contact@shipheart.tech'. + 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 'shipheart.tech' ou de nous contacter à l'adresser 'contact@shipheart.tech'. + Aquest producte està dissenyat i fabricat per l'empresa Koriolan que disposa de totes les llicències i drets d'explotació de les imatges, programari i patents utilitzats tant per al seu disseny com per al seu funcionament. ShipHeart™, Ship2net™ i Koriolan™ són marques comercials registrades per l'empresa Koriolan. Si teniu cap pregunta sobre aquest producte, visiteu 'shipheart.tech' o poseu-vos en contacte amb nosaltres a 'contact@shipheart.tech'. + + + + Version du package logiciel + Versió del paquet de programari + + + + Version de l'application + Versió de l'aplicació + + + + Version de l'interface graphique + Versió GUI + + + + Version du firmware du modem + Versió del firmware del mòdem + + + + Numéro d'IMEI + Número IMEI + + + + Numéro d'ICCID + Número ICCID + + + + Numéro d'IMSI + Número IMSI + + + + ephemeride + + + Ephéméride + Efemèrides + + + + Heure d'hiver + Hora d'hivern + + + + Heure d'été + Hora d'estiu + + + + Aube nautique + Alba nàutica + + + + Lever du soleil + Sortida del sol + + + + Zénith + Zenit + + + + Coucher du soleil + Posta de sol + + + + Crépuscule nautique + Crepuscle nàutic + + + + Lune + Lluna + + + + Latitude + Latitud + + + + Longitude + Longitud + + + + etalonnage_capteur + + + Etalonnage du capteur [%1] + Calibració del sensor [%1] + + + + Valeur brute actuelle + Valor brut actual + + + + Valeur corrigée actuelle (%1) + Valor actual corregit (%1) + + + + Correction + Correcció + + + + Enregistrer + Desa + + + + etalonnage_carte + + + Etalonnage du module [%1 - #%2] + Calibració del mòdul [%1 - #%2] + + + + Point 1 + Punt 1 + + + + Point 2 + Punt 2 + + + + Courant de décharge + Corrent de descàrrega + + + + Courant différentiel + Corrent diferencial + + + + + Recalculer ce point + Torna a calcular aquest punt + + + + + Mémoriser ce point + Memoritza aquest punt + + + + Off + OFF + + + + On + ON + + + + On (%1 %%) + Nosaltres (%1%%) + + + + Enregistrer + Desa + + + + Aide + Ajuda + + + + 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 /> + El calibratge no es pot fer amb dos punts idèntics.<br /><br /> + Intenteu modificar almenys un dels dos punts de referència ajustant els controls del circuit a continuació.<br /> + + + + 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. + El principi de calibratge és comparar en 2 punts diferents el valor de corrent diferencial mesurat pel ShipBS d'una banda i + d'altra banda, el corrent de descàrrega mesurat pel sistema ShipHeart. + Per exemple, sotmetre el ShipBS que s'està calibrant a una potència baixa o nul·la (primer punt) + després encendre un o més dispositius per obtenir un consum de diversos amperes si és possible (segon punt). + Molt important : durant tota la fase de calibratge no s'ha d'aplicar cap corrent de càrrega a ShipBS! + Per tant, és imprescindible desconnectar tots els carregadors, reguladors solars, etc. del sistema durant el calibratge. + En cas contrari, els valors de calibratge seran incorrectes... + Observacions : + - tot el consum ha de passar pel sistema ShipHeart! Per tant, cal assegurar-se que no hi ha cap càrrega connectada directament + al parc de bateries. + - els valors actuals no importen. + - el corrent al punt 2 pot ser inferior o superior al del punt 1 (però tan "allunyat" l'un de l'altre com sigui possible). + - s'aconsella escollir càrregues el consum de les quals sigui relativament estable o, com a mínim, canviï poc en un període d'uns segons. + + + + fonctions + + + Modèle inconnu + Model desconegut + + + + Circuit + Circuit + + + + Capteur + Sensor + + + + Réservoir + Dipòsit + + + + Batterie + Bateria + + + + Type inconnu + Tipus desconegut + + + + Consigne + Ordre + + + + + + Tension + Tensió + + + + Courant + Fluït + + + + Fréquence + Freqüència + + + + + Puissance + Poder + + + + + Energie + Energia + + + + Température + Temperatura + + + + Courant différentiel + Corrent diferencial + + + + Courant de charge + Corrent de càrrega + + + + Courant de décharge + Corrent de descàrrega + + + + SOH (state Of Health) + SOH (estat de salut) + + + + SOC (State Of Charge) + SOC (estat de càrrega) + + + + Autonomie + Autonomia + + + + fonctions_date_heure + + + 1 heure + 1 hora + + + + 24 heures + 24 hores + + + + 7 jours + 7 dies + + + + 30 jours + 30 dies + + + + Fin de nuit + Final de nit + + + + Aube nautique + Alba nàutica + + + + Aube + Alba + + + + Lever du soleil + Sortida del sol + + + + Zénith + Zenit + + + + Coucher du soleil + Posta de sol + + + + Crépuscule + Capvespre + + + + Crépuscule nautique + Crepuscle nàutic + + + + Début de nuit + Primera nit + + + + %1h + %1h + + + + Dimanche + diumenge + + + + Lundi + dilluns + + + + Mardi + dimarts + + + + Mercredi + dimecres + + + + Jeudi + DIJOUS + + + + Vendredi + divendres + + + + Samedi + DISSABTE + + + + Tous les jours + Cada dia + + + + janvier + gener + + + + février + FEBRER + + + + mars + març + + + + avril + abril + + + + mai + maig + + + + juin + juny + + + + juillet + juliol + + + + août + Agost + + + + septembre + setembre + + + + octobre + octubre + + + + novembre + de novembre + + + + décembre + desembre + + + + fonctions_historique + + + Commande 'OFF' du circuit %1 + Ordre 'OFF' per al circuit %1 + + + + Commande 'ON' du circuit %1 + Ordre 'ON' per al circuit %1 + + + + Commande à %1 % du circuit %2 + Control a %1% del circuit %2 + + + + Le circuit %1 est revenu à son état de fonctionnement normal + El circuit %1 ha tornat al seu estat de funcionament normal + + + + L'alimentation du circuit %1 a été coupée car sa limite de courant (%2 A) a été dépassée + S'ha tallat la font d'alimentació del circuit %1 perquè s'ha superat el límit de corrent (%2 A) + + + + L'alimentation du circuit %1 a été coupée car les circuits de protection interne ont détecté une anomalie + S'ha tallat l'alimentació al circuit %1 perquè els circuits de protecció interns van detectar una anomalia + + + + L'alimentation du circuit %1 a été coupée car le seuil de disjonction a été dépassé + S'ha tallat la font d'alimentació al circuit %1 perquè s'ha superat el llindar d'activació + + + + Le circuit %1 est en court-circuit avec le + batterie + El circuit %1 està curtcircuitat amb la bateria + + + + + L'alimentation du circuit %1 a été coupée car la consommation totale du module a été dépassé + S'ha tallat l'alimentació al circuit %1 perquè s'ha superat el consum total del mòdul + + + + Le circuit %1 a été créé + S'ha creat el circuit %1 + + + + La configuration du circuit %1 a été modifiée + S'ha modificat la configuració del circuit %1 + + + + Le circuit %1 a été supprimé + El circuit %1 s'ha suprimit + + + + La configuration du circuit %1 est invalide car le module sur lequel le circuit est configuré n'est pas présent + La configuració del circuit %1 no és vàlida perquè el mòdul on està configurat el circuit no és present + + + + Le circuit %1 a fonctionné trop longtemps (> %2 secondes). Il a donc été désactivé automatiquement. + El circuit %1 ha estat executant massa temps (> %2 segons). Per tant, es va desactivar automàticament. + + + + Evénement de type CIRCUITS avec code de sous-type inconnu [%1] + Esdeveniment de tipus CIRCUITS amb codi de subtipus desconegut [%1] + + + + Le capteur %1 est repassé à l'état normal + El sensor %1 ha tornat a l'estat normal + + + + Le capteur %1 est passé à l'état ALERTE + El sensor %1 ha passat a l'estat ALERTA + + + + Le capteur %1 est passé à l'état ALARME + El sensor %1 ha passat a l'estat d'ALARMA + + + + Evénement de type CAPTEURS avec code de sous-type inconnu [%1] + Esdeveniment de tipus SENSORS amb codi de subtipus desconegut [%1] + + + + Le niveau de charge de la batterie %1 est repassé au niveau normal + El nivell de càrrega de la bateria %1 ha tornat al nivell normal + + + + Le niveau de charge de la batterie %1 est passé en dessous du niveau d'alerte + El nivell de càrrega de la bateria %1 ha caigut per sota del nivell d'alerta + + + + Le niveau de charge de la batterie %1 est passé au-dessus du niveau d'alarme (il est maintenant au niveau d'alerte uniquement) + El nivell de càrrega de la bateria %1 ha augmentat per sobre del nivell d'alarma (ara només està al nivell d'alerta) + + + + Le niveau de charge de la batterie %1 est passé en-dessous du niveau d'alarme + El nivell de càrrega de la bateria %1 ha caigut per sota del nivell d'alarma + + + + Evénement de type BATTERIES avec code de sous-type inconnu [%1] + Esdeveniment de tipus BATERIES amb codi de subtipus desconegut [%1] + + + + Le niveau du réservoir %1 est repassé au niveau normal + El nivell del tanc %1 ha tornat al nivell normal + + + + Le niveau du réservoir %1 est passé en dessous du niveau d'alerte + El nivell del dipòsit %1 ha caigut per sota del nivell d'alerta + + + + Le niveau du réservoir %1 est passé au-dessus du niveau d'alarme (il est maintenant au niveau d'alerte uniquement) + El nivell del dipòsit %1 ha pujat per sobre del nivell d'alarma (ara només està al nivell d'alerta) + + + + Le niveau du réservoir %1 est passé en-dessous du niveau d'alarme + El nivell del tanc %1 ha caigut per sota del nivell d'alarma + + + + Evénement de type RESERVOIRS avec code de sous-type inconnu [%1] + Esdeveniment de tipus TANKS amb codi de subtipus desconegut [%1] + + + + La consigne des ports USB est passée à %1 + El punt de consigna dels ports USB ha canviat a %1 + + + + L'état des ports USB est redevenu normal + L'estat dels ports USB ha tornat a la normalitat + + + + Défaut détecté sur les ports USB + S'ha detectat un error als ports USB + + + + Evénement de type USB avec code de sous-type inconnu [%1] + Esdeveniment de tipus USB amb codi de subtipus desconegut [%1] + + + + Evénement de type INCONNU (avec code de sous-type [%1] + Esdeveniment de tipus DESCONEGUT (amb codi de subtipus [%1] + + + + home + + + Aucun circuit n'est configuré pour ce groupe...<br /><br />Si ce groupe n'a pas d'utilité, vous pouvez le supprimer dans le menu [Circuits] des Paramètres Avancés. + No hi ha cap circuit configurat per a aquest grup...<br /><br /> Si aquest grup no és necessari, podeu suprimir-lo al menú [Circuits] de la configuració avançada. + + + + Aucun capteur n'est configuré pour ce groupe...<br /><br />Si ce groupe n'a pas d'utilité, vous pouvez le supprimer dans le menu [Capteurs] des Paramètres Avancés. + No hi ha cap sensor configurat per a aquest grup...<br /><br /> Si aquest grup no és necessari, podeu suprimir-lo al menú [Sensors] de la configuració avançada. + + + + Aucun réservoir n'est configuré pour ce groupe...<br /><br />Si ce groupe n'a pas d'utilité, vous pouvez le supprimer dans le menu [Réservoirs] des Paramètres Avancés. + No hi ha cap dipòsit configurat per a aquest grup...<br /><br /> Si aquest grup no és necessari, podeu suprimir-lo al menú [Tancs] de la configuració avançada. + + + + Aucun parc de batterie n'est configuré pour ce groupe...<br /><br />Si ce groupe n'a pas d'utilité, vous pouvez le supprimer dans le menu [Batteries] des Paramètres Avancés. + No s'ha configurat cap banc de bateries per a aquest grup...<br /><br /> Si aquest grup no és necessari, podeu suprimir-lo al menú [Bateries] de la configuració avançada. + + + + Cette page est actuellement en travaux. <br />Elle sera rendue disponible très rapidement à travers une mise à jour.<br /><br />Merci de votre patience...<br /><br />L'équipe ShipHeart + Aquesta pàgina està actualment en construcció. <br />Estarà disponible molt ràpidament mitjançant una actualització.<br /><br /> Gràcies per la teva paciència...<br /><br /> L'equip ShipHeart + + + + + + Déconnecté + Desconnectat + + + + Nombre de satellites visibles + Nombre de satèl·lits visibles + + + + + Connecté + Connectat + + + + + OFF + OFF + + + + + ON + ON + + + + Niveau + Nivell + + + + Actif + Actiu + + + + Inactif + Inactiu + + + + + + <b>%1</b> + <b>%1</b> + + + + Démarrage + Posada en marxa + + + + Firmware de <b>ShipBase</b> + Firmware <b>ShipBase</b> + + + + Firmware du <b>ShipPower812</b> à l'adresse <b>%1</b> + Microprogramari <b>ShipPower812</b> a l'adreça <b>%1</b> + + + + Firmware du <b>ShipBS</b> à l'adresse <b>%1</b> + Microprogramari <b>ShipBS</b> a l'adreça <b>%1</b> + + + + Firmware du <b>ShipPower4AC</b> à l'adresse <b>%1</b> + Microprogramari <b>ShipPower4AC</b> a l'adreça <b>%1</b> + + + + Firmware du <b>ShipPower8DC</b> à l'adresse <b>%1</b> + Microprogramari <b>ShipPower8DC</b> a l'adreça <b>%1</b> + + + + Firmware du module à l'adresse <b>%1</b> + Microprogramari del mòdul a l'adreça <b>%1</b> + + + + Merci de patienter et de ne rien débrancher<br />avant la fin de la mise à jour. + Si us plau, tingueu paciència i no desconnecteu res.<br /> abans que finalitzi l'actualització. + + + + Chargement des mises à jour effectué avec succès !<br /><br />L'activation des nouvelles version est en cours sur tous les modules concernés.<br /><br />Merci de patienter encore quelques secondes... + Les actualitzacions s'han carregat correctament!<br /><br /> L'activació de noves versions està en curs a tots els mòduls implicats.<br /><br /> Si us plau, espereu uns segons més... + + + + ShipHeart va redémarrer pour effectuer une mise à jour.<br /><br />Cette opération va prendre quelques minutes au maximum.<br />Merci de patienter et de ne rien débrancher jusqu'au redémarrage final... + ShipHeart es reiniciarà per realitzar una actualització.<br /><br /> Aquesta operació durarà uns minuts com a màxim.<br /> Espereu i no desconnecteu res fins al reinici final... + + + + Votre système ShipHeart est dorénavant équipé de la version<br /><br /><b>%1</b><br /><br />(la version précédente était la %2) + El vostre sistema ShipHeart ara està equipat amb la versió<br /><br /> <b>%1</b><br /><br /> (la versió anterior era %2) + + + + Le nombre de modules détectés sur le réseau ShipHeart est insuffisant par rapport à la configuration du bateau.<br /><br />Vérifiez les connexions entre le module <b>%1</b> à la <b>position @%2</b> %3 et le module <b>%4</b> suivant%5<br /><br />Vous pouvez visualiser l'état complet du réseau ShipHeart et les anomalies détectées dans le menu 'Réseau > ShipHeart' dans les Paramètres Avancés + El nombre de mòduls detectats a la xarxa ShipHeart és insuficient en comparació amb la configuració del vaixell.<br /><br /> Comproveu les connexions entre el mòdul <b>%1</b> a <b>la posició @%2</b> %3 i el mòdul <b>%4</b> al costat de %5<br /><br /> Podeu veure l'estat complet de la xarxa ShipHeart i les anomalies detectades al menú "Xarxa > ShipHeart" a la configuració avançada + + + + Le modules détecté en <b>position @%1</b> est un <b>%2</b>. Cela ne correspond pas à la configuration actuelle du bateau (<b>%3</b>).<br /><br />Cela peut provenir de l'ajout, de la suppression ou d'un déplacement de module.<br /><br />Vous pouvez visualiser toutes les anomalies détectées et les corriger dans le menu 'Réseau > ShipHeart' dans les Paramètres Avancés + El mòdul detectat a la <b>posició @%1</b> és un <b>%2</b> . Això no es correspon amb la configuració actual del vaixell ( <b>%3</b> ).<br /><br /> Això pot provenir d'afegir, eliminar o moure un mòdul.<br /><br /> Podeu veure totes les anomalies detectades i corregir-les al menú "Xarxa > ShipHeart" a la configuració avançada + + + + Code inconnu + Codi desconegut + + + + home_accueil + + + Bienvenue à bord de + Benvingut a bord + + + + home_suncy + + + L'accès au bateau est protégé. +Merci d'entrer votre code de déverrouillage pour y accéder... + L'accés al vaixell està protegit. + Introduïu el vostre codi de desbloqueig per accedir-hi... + + + + journal_de_bord + + + + + + Tous + Tots + + + + Batteries + Bateries + + + + Capteurs + Sensors + + + + Circuits + Tours + + + + Réservoirs + Tancs + + + + Système + Sistema + + + + Ports USB + Ports USB + + + + Journal de bord + Llibre de registre + + + + Aucun type n'est configuré... + No hi ha cap tipus configurat... + + + + %1<br /><br /><br />%2 + %1<br /><br /><br /> %2 + + + + Aucune entrée d'historique n'est disponible pour cette sélection... + No hi ha cap entrada d'historial disponible per a aquesta selecció... + + + + Toutes + Tots + + + + main + + + Type d'installation : +0 : ShipBase standard, +1 : écran déporté + Tipus d'instal·lació: + 0: Standard ShipBase, + 1: pantalla remota + + + + + valeur + valor + + + + Adresse IPv4 de ShipBase dans le cas d'une installation déportée + Adreça IPv4 de ShipBase en el cas d'una instal·lació remota + + + + xxx:xxx:xxx:xxx + xxx:xxx:xxx:xxx + + + + Taille de l'écran en pouces : +7, +10 (ShipBase standard), +22 + Mida de la pantalla en polzades: + 7, + 10 (ShipBase estàndard), + 22 + + + + Original + Original + + + + Sombre + Fosc + + + + Métallique + Metàl·lic + + + + Triangles + Triangles + + + + Sable + Sorra + + + + Thème 5 + Tema 5 + + + + Thème 6 + Tema 6 + + + + Thème 7 + Tema 7 + + + + Thème 8 + Tema 8 + + + + page_personnalisee + + + <i>--- Circuit non affecté ---</i> + <i>--- Circuit no afectat ---</i> + + + + [renfort] + [reforç] + + + + <i>--- Aucune batterie affectée ---</i> + <i>--- Cap bateria afectada ---</i> + + + + parametres + + + Paramètres + Configuració + + + + Langue + Llenguatge + + + + Températures + Temperatures + + + + Volumes + Volums + + + + Affichage + Mostra + + + + Date et heure + Data i hora + + + + Protection + Protecció + + + + Son + Ella + + + + Luminosité + Brillantor + + + + Economiseur d'écran : désactivé + Salvapantalles: desactivat + + + + Economiseur d'écran : normal + Salvapantalles: normal + + + + Flash LEDs : désactivé + Flaix LED: desactivat + + + + Flash LEDs : normal + Flaix LED: normal + + + + Nettoyage de l'écran + Neteja de la pantalla + + + + Heure d'été + Hora d'estiu + + + + Heure d'hiver + Hora d'hivern + + + + Verrouiller le bateau + Tanca el vaixell + + + + parametres_avances + + + Paramètres avancés + configuració avançada + + + + Réseaux + Xarxes + + + + Cette page est actuellement en travaux. <br />Elle sera rendue disponible très rapidement à travers une mise à jour.<br /><br />Merci de votre patience...<br /><br />L'équipe ShipHeart + Aquesta pàgina està actualment en construcció. <br />Estarà disponible molt ràpidament mitjançant una actualització.<br /><br /> Gràcies per la teva paciència...<br /><br /> L'equip ShipHeart + + + + Circuits + Tours + + + + Réservoirs + Tancs + + + + Batteries + Bateries + + + + Capteurs + Sensors + + + + Menu accueil + Menú de casa + + + + Evènements + Esdeveniments + + + + ShipHeart + ShipHeart + + + + Ethernet & Wifi + Ethernet i Wifi + + + + One Wire + Un cable + + + + NMEA 2000 + NMEA 2000 + + + + J1939 + J1939 + + + + DMX + DMX + + + + Journal de bord + Llibre de registre + + + + Vos paramètres + La teva configuració + + + + Votre installation + La teva instal·lació + + + + Système + Sistema + + + + Affichage + Mostra + + + + Audio + Àudio + + + + Ship2net + Ship2net + + + + Accès au paramètres + Accés a la configuració + + + + Configuration ShipRS + Configuració ShipRS + + + + Installation + Instal·lació + + + + Version + Versió + + + + Accès réservé Koriolan + Accés reservat Koriolan + + + + Spécifique Suncy + Suncy específic + + + + protection + + + Accès protégé + Accés protegit + + + + L'accès aux paramètres avancés est protégé. +Merci d'entrer le code de déverrouillage pour y accéder... + L'accés a la configuració avançada està protegit. +Introduïu el codi de desbloqueig per accedir-hi... + + + + Mode administrateur validé<br />Entrer votre code dédié + Mode d'administrador validat<br />Introduïu el vostre codi dedicat + + + + reservoir + + + [ %1 % ] + [ %1 % ] + + + + Le module assurant la supervision de ce réservoir n'est pas accessible !<br /><br />Si des ajouts/suppression/déplacements de modules ont eu lieu récemment, mettez à jour la configuration correspondant dans le menu MODULES de PARAMETRES AVANCES.<br /><br />Dans le cas où aucune modification n'a été effectuée récemment, vérifier les connexions de tous les modules. + El mòdul que controla aquest dipòsit no és accessible!<br /><br />Si s'han afegit/suprimit/s'han mogut mòduls recentment, actualitzeu la configuració corresponent al menú MÒDULS de PARÀMETRES AVANÇATS <br /><br />Si no s'han fet modificacions recentment, comproveu les connexions de tots els mòduls. + + + + Niveau + Nivell + + + + La valeur lue sur les electrodes plongées de ce réservoir est incohérente.<br />Vérifier l'ordre de cablage des électrodes sur les entrées auxiliaires à l'arrière de ShipBase. + El valor llegit als elèctrodes submergits d'aquest dipòsit és inconsistent.<br />Comproveu l'ordre de cablejat dels elèctrodes a les entrades auxiliars de la part posterior de ShipBase. + + + + Aucune donnée n'est disponible pour cette période + No hi ha dades disponibles per a aquest període + + + + shipheart_test_config + + + Vitesse de test de l'écran + Velocitat de prova de pantalla + + + + Nombre de colonnes de test du touchpad + Nombre de columnes de prova del touchpad + + + + Nombre de lignes de test du touchpad + Nombre de línies de prova del touchpad + + + + shipheart_test_home + + + Tests matériel + Proves de maquinari + + + + Configuration des tests + Prova de configuració + + + + Test du backlight + Prova de retroiluminació + + + + Test de l'écran + Prova de pantalla + + + + Test du touchpad + Prova del touchpad + + + + Liste des fonts disponibles + Llista de tipus de lletra disponibles + + + + shipheart_test_liste_fonts + + + Liste des fonts disponibles + Llista de tipus de lletra disponibles + + + + test_batterie + + + Batteries de servitude + Servei de bateries + + + + Autonomie optimale + Autonomia òptima + + + + Autonomie actuelle + Autonomia actual + + + + Autonomie<br />maximale + Màxima<br />autonomia + + + + dans + en + + + + environ + aproximadament + + + + test_tri_liste + + + TEST DE TRI DE LISTE + PROVA D'ORDENACIÓ DE LLISTA + + + diff --git a/shipheart_de_DE.qm b/shipheart_de_DE.qm new file mode 100755 index 0000000..449c512 Binary files /dev/null and b/shipheart_de_DE.qm differ diff --git a/shipheart_de_DE.ts b/shipheart_de_DE.ts new file mode 100755 index 0000000..9df7c33 --- /dev/null +++ b/shipheart_de_DE.ts @@ -0,0 +1,5516 @@ + + + + + Shipheart_boite_dialogue + + + OK + OK + + + + Annuler + Abbrechen + + + + Plus tard + Später + + + + Shipheart_boite_dialogue_action_circuit + + + Action à appliquer au circuit lorsque l'évènement se déclenche : + Aktion, die auf die Schaltung angewendet wird, wenn das Ereignis ausgelöst wird : + + + + Aucune + Keine + + + + Le circuit <b>bascule</b> + Die Schaltung < b>schaltet um< / b> + + + + [passe à <b>ON</b> s'il est <b>OFF</b><br /> ou à <b>OFF</b> s'il est <b>ON</b>] + [wechselt zu <B > ON < /b>, wenn es <B>OFF</b > <br / >IST, oder zu <B> OFF</b>, wenn es <b>ON</B > ist] + + + + OFF + OFF + + + + ON + ON + + + + Annuler + Abbrechen + + + + Shipheart_boite_dialogue_affichage_duree + + + Ok + OK + + + + Shipheart_boite_dialogue_condition_horaire + + + OK + OK + + + + Annuler + Abbrechen + + + + Supprimer + Löschen + + + + Aube nautique + Nautische Morgendämmerung + + + + Lever du soleil + Sonnenaufgang + + + + Zénith + Zenit + + + + Coucher du soleil + Sonnenuntergang + + + + Crépuscule nautique + Nautische Dämmerung + + + + Shipheart_boite_dialogue_entrees_aux + + + Entrées Auxiliaires + Hilfseingänge + + + + Affectation de l'entrée n° %1 du %2 + Zuordnung der Eintragsnummer %1 von %2 + + + + Annuler + Abbrechen + + + + Shipheart_boite_dialogue_entrees_level_sensor + + + Entrées Level Sensor + Level Sensor Eingänge + + + + Affectation de l'entrée du réservoir + Zuordnung des tankeinlasses + + + + Annuler + Abbrechen + + + + Shipheart_boite_dialogue_liste_alarmes + + + Ok + OK + + + + Shipheart_boite_dialogue_minuteur + + + Heures + Stunden + + + + Minutes + Minuten + + + + Secondes + Sekunden + + + + Annuler + Abbrechen + + + + Démarrer + Starten + + + + Shipheart_boite_dialogue_nettoyage_ecran + + + Nettoyage de l'écran + Bildschirmreinigung + + + + 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. + Der Bildschirm ist derzeit eingefroren, damit Sie ihn reinigen können, ohne dass unerwünschte Aktionen ausgelöst werden.<br /><br / > halten Sie die Taste unten länger als %1 Sekunden Gedrückt, um diesen Modus zu verlassen. + + + + Sortie + Ausgang + + + + Shipheart_boite_dialogue_reveils + + + Annuler + Abbrechen + + + + Enregistrer + Speichern + + + + Shipheart_boite_dialogue_validation_securisee + + + OK + OK + + + + Annuler + Abbrechen + + + + --- + + + + + Shipheart_bouton_circuit + + + + + Off + OFF + + + + + On + ON + + + + batterie + + + + Aucune consommation d'énergie sur cette période... + Kein Energieverbrauch in diesem Zeitraum... + + + + Aucune donnée n'est disponible pour cette période + Für diesen Zeitraum sind keine Daten verfügbar + + + + Le module assurant la supervision de cette batterie n'est pas accessible !<br /><br />Si des ajouts/suppression/déplacements de modules ont eu lieu récemment, mettez à jour la configuration correspondant dans le menu MODULES de PARAMETRES AVANCES.<br /><br />Dans le cas où aucune modification n'a été effectuée récemment, vérifier les connexions de tous les modules. + Auf das Modul, das diese Batterie überwacht, kann nicht zugegriffen werden!<br /><br />Wenn kürzlich Module hinzugefügt/gelöscht/verschoben wurden, aktualisieren Sie die entsprechende Konfiguration im Menü MODULE der ERWEITERTEN PARAMETER. <br /><br />Falls Es wurden in letzter Zeit keine Änderungen vorgenommen. Überprüfen Sie die Anschlüsse aller Module. + + + + capteur + + + Max + Max + + + + Moyen + Mittel + + + + Min + Min + + + + Delta (Max - Min) + Delta (1h) + Delta (Max-Min) + + + + Aucune donnée n'est disponible pour cette période + Für diesen Zeitraum sind keine Daten verfügbar + + + + La sonde One Wire correspondant à ce capteur n'est pas accessible.<br />Vérifier son câblage entre le port One Wire à l'arrière de ShipBase et la sonde. + Die diesem Sensor entsprechende one Wire-sonde ist nicht zugänglich.< br />überprüfen Sie die Verkabelung zwischen dem one Wire-Anschluss auf der Rückseite der ShipBase und der sonde. + + + + Le module assurant la supervision de ce capteur n'est pas accessible !<br /><br />Si des ajouts/suppression/déplacements de modules ont eu lieu récemment, mettez à jour la configuration correspondant dans le menu MODULES de PARAMETRES AVANCES.<br /><br />Dans le cas où aucune modification n'a été effectuée récemment, vérifier les connexions de tous les modules. + Das Modul zur überwachung dieses Sensors ist nicht zugänglich !<br /><br/ > wenn in letzter Zeit Module Hinzugefügt/entfernt / verschoben wurden, aktualisieren Sie die entsprechende Konfiguration im MENÜ Module der VORAUSEINSTELLUNGEN.<br /> < br />falls in letzter Zeit keine änderungen vorgenommen wurden, überprüfen Sie die Anschlüsse aller Module. + + + + La sonde One Wire du capteur est détectée en défaut.<br />Vérifier son câblage depuis l'arrière de ShipBase. + Die One Wire-sonde des Sensors wird als defekt erkannt.< br />Überprüfen Sie die Verkabelung von der Rückseite von ShipBase. + + + + Le capteur n'a pas reçu de mise à jour sur le réseau NMEA depuis<br />%1<br />Les données affichées sont donc probablement obsolètes. + Der Sensor hat seit<br />%1<br />keine Aktualisierung mehr über das NMEA-Netzwerk erhalten. Die angezeigten Daten sind daher wahrscheinlich veraltet. + + + + circuit + + + + + + Off + OFF + + + + + On + ON + + + + On +%1% + Wir +%1% + + + + Aucune donnée n'est disponible pour cette période + Für diesen Zeitraum sind keine Daten verfügbar + + + + Aucune consommation d'énergie sur cette période... + Kein Energieverbrauch in diesem Zeitraum... + + + + Le module assurant le pilotage de ce circuit n'est pas accessible !<br /><br />Si des ajouts/suppression/déplacements de modules ont eu lieu récemment, mettez à jour la configuration correspondant dans le menu [Réseau ShipHeart] de [Paramètres Avancés].<br /><br />Dans le cas où aucune modification n'a été effectuée récemment, vérifier les connexions de tous les modules. + Auf das Modul, das diesen Schaltkreis steuert, kann nicht zugegriffen werden!<br /><br />Wenn kürzlich Module hinzugefügt/gelöscht/verschoben wurden, aktualisieren Sie die entsprechende Konfiguration im Menü [ShipHeart Network] unter [Erweiterte Einstellungen].<br />< br />Falls in letzter Zeit keine Änderungen vorgenommen wurden, überprüfen Sie die Anschlüsse aller Module. + + + + Ce circuit est configuré comme <i>Non Affecté</i> et n'est donc pas accessible !<br /><br />Pour accéder à nouveau à ce circuit, merci de l'affecter à un circuit disponible dans le menu [Circuits] de [Paramètres Avancés]. + Dieser Schaltkreis ist als <i>Nicht zugewiesen</i> konfiguriert und daher nicht zugänglich!<br /><br />Um erneut auf diesen Schaltkreis zuzugreifen, weisen Sie ihn bitte einem Schaltkreis zu, der im Menü [Schaltkreise] der [Erweiterten Einstellungen] verfügbar ist ]. + + + + Non défini + Nicht definiert + + + + Le module pilotant ce circuit n'est pas alimentée correctement. + Vérifier l'alimentation correspondante. + Das Modul, das diese Schaltung antreibt, wird nicht richtig mit Strom versorgt. + Überprüfen Sie die entsprechende Stromversorgung. + + + + Le module pilotant ce circuit est en mode MANUEL. + Repositionnez le module en mode AUTO pour commander à nouveau ce circuit normalement. + Das Modul, das diese Schaltung antreibt, befindet sich im MANUELLEN Modus. + Positionieren Sie das Modul wieder im AUTO-Modus, um diese Schaltung wieder normal zu Steuern. + + + + Le port USB du bas est en défaut. + Der untere USB-Anschluss ist defekt. + + + + Le port USB du milieu est en défaut. + Der mittlere USB-Anschluss ist defekt. + + + + Les 2 ports USB du milieu et du bas sont en défaut. + Die mittleren und unteren 2 USB-Anschlüsse sind defekt. + + + + Le port USB du haut est en défaut. + Der Obere USB-Anschluss ist defekt. + + + + Les 2 ports USB du haut et du bas sont en défaut. + Die oberen und unteren 2 USB-Anschlüsse sind defekt. + + + + Les 2 ports USB du haut et du milieu sont en défaut. + Die oberen und mittleren 2 USB-Anschlüsse sind defekt. + + + + Les 3 ports USB du haut, du milieu et du bas sont en défaut. + Die oberen, mittleren und unteren 3 USB-Anschlüsse sind defekt. + + + + Le port USB est en défaut. + Der USB-Anschluss ist defekt. + + + + L'alimentation du circuit a été coupée + car sa limite de courant (%1 A) + a été dépassée. + Die Stromversorgung des Stromkreises wurde unterbrochen + weil seine Strombegrenzung (%1 A) + wurde überholt. + + + + L'alimentation du circuit a été coupée + car les circuits de protection interne ont détecté une anomalie. + Die Stromversorgung des Stromkreises wurde unterbrochen + da die internen Schutzschaltungen eine anomalie erkannt haben. + + + + L'alimentation du circuit a été coupée + car le seuil de disjonction du circuit a été dépassé. + Die Stromversorgung des Stromkreises wurde unterbrochen + weil die disjunktionsschwelle der Schaltung überschritten wurde. + + + + Le circuit est en court-circuit avec le + batterie. + Der Stromkreis ist mit dem kurzgeschlossen + batterie. + + + + L'alimentation du circuit a été coupée<br />car la consommation totale du module a dépassé %1 A pendant plus de %2 secondes (limite du module) + Die Stromversorgung der Schaltung wurde unterbrochen<br / > da der Gesamtverbrauch des Moduls mehr als %1 A für mehr als %2 Sekunden überschritt (modulgrenze) + + + + La tension du circuit est anormalement basse. + Die schaltungsspannung ist ungewöhnlich niedrig. + + + + La phase et le neutre sont inversés sur ce circuit. + Phase und Neutralleiter sind in diesem Stromkreis vertauscht. + + + + DANGER : Le neutre n'est pas référencé à la terre sur ce circuit ("absence de terre"). + DANGER : la terre est absente de ce circuit. + GEFAHR: Der Neutralleiter ist auf diesem Stromkreis nicht auf die Erde bezogen („keine Erde“). + + + + La masse est absente du connecteur d'alimentation du module + Masse fehlt am Stromanschluss des Moduls + + + + Evènements actuellement actifs qui sont susceptibles de commander ce circuit : + Derzeit aktive Ereignisse, die diese Tour wahrscheinlich bestellen werden : + + + + + + Etat inconnu... + Unbekannter Zustand... + + + + config_acces_parametres + + + Configuration de l'accès aux paramètres avancés + Konfigurieren des Zugriffs auf erweiterte Einstellungen + + + + Durée de maintien de l'accès + Dauer der Aufrechterhaltung des Zugriffs + + + + Nouveau code + Neuer code + + + + Code d'accès + Zugangscode + + + + Répéter le code d'accès + Passcode wiederholen + + + + Enregistrer + Speichern + + + + Aucune (saisie du code à chaque accès) + Keine (Eingabe des Codes bei jedem Zugriff) + + + + 1 minute + 1 minute + + + + 5 minutes + 5 Minuten + + + + 15 minutes + 15 Minuten + + + + 1 heure + 1 Stunde + + + + Infinie (aucune protection des paramètres avancés) + Unendlich (kein Schutz vor erweiterten Einstellungen) + + + + Les deux valeurs saisies doivent être identiques ! + +De plus, le code doit contenir : +- %1 chiffres au minimum +- %2 chiffres au maximum. + Die beiden eingegebenen Werte müssen identisch sein! + + Darüber hinaus muss der Code Folgendes enthalten: + - Mindestens %1 Ziffer + - Maximal %2 Ziffern. + + + + Le nouveau code doit contenir : +- %1 chiffres au minimum +- %2 chiffres au maximum. + +Le code saisi ne répond pas à ces critères et sa mise à jour n'est donc pas effectuée. + +Merci de saisir un code au format valide si vous souhaitez le modifier. + Der neue Code muss enthalten: + - Mindestens %1 Ziffer + - Maximal %2 Ziffern. + + Der eingegebene Code erfüllt diese Kriterien nicht und wird daher nicht aktualisiert. + + Bitte geben Sie einen Code in einem gültigen Format ein, wenn Sie ihn ändern möchten. + + + + config_affichage + + + Configuration de l'affichage + Konfiguration der Anzeige + + + + Nom du bateau + Name des Bootes + + + + Fuseau horaire + Zeitzone + + + + Temporisaton économiseur d'écran + Temporisaton Bildschirmschoner + + + + Thème d'affichage + Display Thema + + + + Enregistrer + Speichern + + + + UTC-12 (Yankee) + UTC-12 (Yankee) + + + + UTC-11 (X-Ray) + UTC-11 (X-Ray) + + + + UTC-10 (Whisky) + UTC-10 (Whisky) + + + + UTC-9 (Victor) + UTC - 9 (Victor) + + + + UTC-8 (Uniform) + UTC-8 (Uniform) + + + + UTC-7 (Tango) + UTC-7 (Tango) + + + + UTC-6 (Sierra) + UTC - 6 (Sierra) + + + + UTC-5 (Romeo) + UTC - 5 (Romeo) + + + + UTC-4 (Quebec) + UTC-4 (Quebec) + + + + UTC-3 (Papa) + UTC-3 (Papa) + + + + UTC-2 (Oscar) + UTC - 2 (Oscar) + + + + UTC-1 (November) + UTC - 1 (November) + + + + UTC (Zoulou) + UTC (Zulu) + + + + UTC+1 (Alpha) + UTC + 1 (Alpha) + + + + UTC+2 (Bravo) + UTC + 2 (Bravo) + + + + UTC+3 (Charlie) + UTC + 3 (Charlie) + + + + UTC+4 (Delta) + UTC + 4 (Delta) + + + + UTC+5 (Echo) + UTC + 5 (Echo) + + + + UTC+6 (Foxtrot) + UTC + 6 (Foxtrott) + + + + UTC+7 (Golf) + UTC + 7 (Golf) + + + + UTC+8 (Hotel) + UTC + 8 (Hotel) + + + + UTC+9 (India) + UTC + 9 (India) + + + + UTC+10 (Kilo) + UTC + 10 (Kilo) + + + + UTC+11 (Lima) + UTC + 11 (Lima) + + + + UTC+12 (Mike) + UTC + 12 (Mike) + + + + 15 secondes + 15 Sekunden + + + + 30 secondes + 30 Sekunden + + + + 1 minute + 1 minute + + + + 3 minutes + 3 Minuten + + + + 10 minutes + 10 Minuten + + + + Aucune limite + Keine Grenzen + + + + config_audio + + + Configuration audio + Audio-Setup + + + + Bips de clic + Klick-Pieptöne + + + + Fonctionnement de la sortie Audio + Funktionsweise des Audioausgangs + + + + Enregistrer + Speichern + + + + Aucun bip + Kein PIEPEN + + + + Bip par défaut + Standard beep + + + + Bip 2 + Bip 2 + + + + Bip 3 + Bip 3 + + + + Bip 4 + Bip 4 + + + + Bip 5 + Bip 5 + + + + Bip 6 + Bip 6 + + + + Bip 7 + Bip 7 + + + + Bip 8 + Bip 8 + + + + Bip 9 + Bip 9 + + + + Bip 10 + Bip 10 + + + + Bip 11 + Bip 11 + + + + Bip 12 + Bip 12 + + + + Bip 13 + Bip 13 + + + + Bip 14 + Bip 14 + + + + Le son de ShipBase est coupé. Le son est uniquement diffusé sur la sortie AUDIO + Der Sound von ShipBase ist stummgeschaltet. Der Ton wird nur über den AUDIOAUSGANG wiedergegeben + + + + Le son est diffusé sur ShipBase et sur la sortie AUDIO + Der Ton wird auf ShipBase und auf der AUDIOAUSGABE gestreamt + + + + config_batterie + + + Nom de la batterie + Name der batterie + + + + Tension nominale + Nennspannung + + + + Créer la batterie + Batterie erstellen + + + + Enregistrer + Speichern + + + + Supprimer + Löschen + + + + + Confirmer + Bestätigen + + + + Etalonner + Etalonnage + Erweitern + + + + + Non défini + Nicht definiert + + + + Création d'un parc de batteries + Aufbau einer Batteriebank + + + + Configuration du parc de batteries + Konfiguration der Batteriebank + + + + Groupe de batteries + Batterie Gruppe + + + + Point de mesure + Messpunkt + + + + Type de batterie(s) + Batterietyp(en) + + + + La modification du <b>type</b> de batterie(s) va nécessiter la remise en <i>configuration usine</i> de certains paramètres.<br /><br />Si vous ne souhaitez pas que cette reconfiguration soit effectuée, notamment si vous avez effectué des réglages spécifiques, cliquez sur ANNULER. <br /><br />Sinon, cliquez sur CONFIRMER pour valider le changement. + Wenn Sie den <b>Typ</b> der Batterie(n) ändern, müssen bestimmte Parameter auf die <i>Werkskonfiguration</i> zurückgesetzt werden.<br /><br />Wenn Sie nicht möchten, dass diese Neukonfiguration durchgeführt wird, Insbesondere wenn Sie bestimmte Einstellungen vorgenommen haben, klicken Sie auf ABBRECHEN. <br /><br />Andernfalls klicken Sie auf BESTÄTIGEN, um die Änderung zu bestätigen. + + + + La modification de la <b>tension nominale</b> du parc de batteries va nécessiter la remise en <i>configuration usine</i> de certains paramètres.<br /><br />Si vous ne souhaitez pas que cette reconfiguration soit effectuée, notamment si vous avez effectué des réglages spécifiques, cliquez sur ANNULER. <br /><br />Sinon, cliquez sur CONFIRMER pour valider le changement. + La modification de la <b>tension nominale</b> du parc de batteries va nécessiter la remise en <i>configuration usine</i> de certains paramètres.<br /><br />Si vous ne souhaitez pas que cette reconfiguration soit effectuée, notamment si vous avez effectué des réglages spécifiques, cliquez sur ANNULER. <br /><br />Sinon, cliquez sur CONFIRMER pour valider le changement. + + + + Capacité + Fähigkeit + + + + + Ah + Ah + + + + Masquer les paramètres avancés + Verberge erweiterte Einstellungen + + + + Afficher les paramètres avancés + Erweiterte Einstellungen anzeigen + + + + Coefficient correcteur d'entrée de tension + Korrekturkoeffizient des Spannungseingangs + + + + + + + + + Caractéristiques du parc de batteries + Eigenschaften der Batteriebank + + + + Durée correspondant à la capacité + Dauer entsprechend der Kapazität + + + + + h + h + + + + Capacité 2 + Fähigkeit 2 + + + + Durée de capacité 2 + Kapazitätsdauer 2 + + + + Coefficient de Peukert + Peukert-Koeffizient + + + + Résistance interne + Innenwiderstand + + + + mΩ + mΩ + + + + Soh actuel + Aktuelle Soh + + + + % + % + + + + Paramètres de pleine charge + Vollständige Ladeeinstellungen + + + + Tension mini pleine charge + Minimale Volllastspannung + + + + + V + V + + + + Courant maxi pleine charge + Maximaler Volllaststrom + + + + A + A + + + + Temporisation pleine charge + Volllastverzögerung + + + + + s + s + + + + Efficacité de charge + Ladeeffizienz + + + + Caractéristiques de charge nulle + Nulllasteigenschaften + + + + Tension de détection charge nulle + Nulllast-Erkennungsspannung + + + + Temporisation charge nulle + Null-Last-Verzögerung + + + + Alimentation %1 + Ernährung %1 + + + + 48V + 48V + + + + Cette batterie est utilisée par l'évènement ci-dessous.<br />Vous devez modifier ou supprimer cet évènement pour qu'il ne dépende plus de cette batterie avant de pouvoir la supprimer. + Diese batterie wird von der unten stehenden Veranstaltung verwendet.<br />Sie müssen dieses Ereignis ändern oder löschen, damit es nicht mehr von dieser batterie abhängig ist, bevor Sie es löschen können. + + + + Cette batterie est utilisée par les %1 évènements ci-dessous.<br />Vous devez modifier ou supprimer ces évènements pour qu'ils ne dépendent plus de cette batterie avant de pouvoir la supprimer. + Diese batterie wird von den unten aufgeführten %1-Ereignissen verwendet.<br />Sie müssen diese Ereignisse ändern oder löschen, damit Sie nicht mehr von dieser batterie abhängig sind, bevor Sie Sie löschen können. + + + + Cette batterie est utilisée par le capteur calculé ci-dessous.<br />Vous devez modifier ou supprimer ce capteur calculé pour qu'il ne dépende plus de cette id_batterie avant de pouvoir la supprimer. + Diese batterie wird vom unten berechneten Sensor verwendet.<br />Sie müssen diesen berechneten Sensor ändern oder entfernen, damit er nicht mehr von dieser Batterie-id abhängt, bevor Sie ihn entfernen können. + + + + Cette id_batterie est utilisée par les %1 capteurs calculés ci-dessous.<br />Vous devez modifier ou supprimer ces capteurs calculés pour qu'ils ne dépendent plus de cette id_batterie avant de pouvoir la supprimer. + Diese batterie_id wird von den unten berechneten %1-sensoren verwendet.<br />Sie müssen diese berechneten sensoren ändern oder entfernen, damit Sie nicht mehr von dieser Batterie-id abhängen, bevor Sie Sie entfernen können. + + + + Ok + OK + + + + Historique + Historisch + + + + Nombre de cycles de charge + Anzahl der Ladezyklen + + + + Nombre de décharges complètes + Anzahl vollständiger Entladungen + + + + Forcer Pleine Charge + Volllast erzwingen + + + + Réinitialiser SOH + SOH zurücksetzen + + + + Réinitialiser Compteurs + Zähler zurücksetzen + + + + ShipBS [@ %1] + ShipBS [@ %1] + + + + Entrée VOLT n° %1 + Eingang VOLT N ° %1 + + + + Plomb - Acide liquide + Blei-Säure Flüssigkeit + + + + Plomb - AGM / VRLA + Blei-AGM / VRLA + + + + Plomb - Gel + Blei-Gel + + + + Plomb - Carbone + Blei-Kohlenstoff + + + + Lithium + Lithium + + + + Non définie + Nicht definiert + + + + 12V + 12V + + + + 24V + 24V + + + + config_batteries + + + Configuration des batteries + Konfiguration der Batterien + + + + Aucune batterie n'est encore configurée... + Es ist noch keine batterie konfiguriert... + + + + + + + + + + + config_capteur + + + Création d'un capteur + Erstellen eines Sensors + + + + Configuration du capteur + Sensor-Konfiguration + + + + Nom du capteur + Name des Sensors + + + + Type de capteur + Sensor Typ + + + + Module + Modul + + + + Affectation + Zuordnung + + + + %1 : Non définie + %1: nicht definiert + + + + %1 : %2 + %1 : %2 + + + + Mode du capteur + Sensor-Modus + + + + Groupe de capteurs + Sensorgruppe + + + + Libellé du capteur pour la valeur %1 + Sensorbezeichnung für Wert %1 + + + + + + + Non défini + Nicht definiert + + + + Entrées Auxiliaires (AUX INPUTS) + Hilfseingänge (AUX INPUTS) + + + + Entrées Niveau (LEVEL SENSORS) + Level-Eingänge (LEVEL SENSORS) + + + + Entrées Tension (VOLTAGE INPUTS) + Spannungseingänge (VOLTAGE INPUTS) + + + + Capteurs de température (ONE WIRE) + Temperatursensoren (ONE WIRE) + + + + Entrées NMEA2000 + NMEA2000-Einträge + + + + Capteurs sur modules + Sensoren auf Modulen + + + + Calculé (conditions logiques) + Berechnet (logische Bedingungen) + + + + + <i>Entrée non utilisée</i> + <i > nicht verwendete Eingabe< / i> + + + + Pression Atmosphérique + Atmosphärischer Druck + + + + + + Température module + Temperatur Modul + + + + + Tension d'entrée module + Eingang Spannung Modul + + + + Consommation module + Verbrauch Modul + + + + Consommation ports USB + Verbrauch USB-Anschlüsse + + + + Chocs + Schocks + + + + Accélération X + Beschleunigung X + + + + Accélération Y + Beschleunigung Y + + + + Accélération Z + Z-Beschleunigung + + + + GNSS - SOG<br />Speed Over Ground + GNSS-sog < br />Speed Over Ground + + + + GNSS - COG<br />Course Over Ground + GNSS-COG < br />Course Over Ground + + + + GNSS - SIV<br />Satellites In View + GNSS-SIV < br / >Satelliten in View + + + + GNSS - HPA<br />Horizontal Precision Accuracy + GNSS-hPa < br />Horizontal Precision Accuracy + + + + GNSS - VPA<br />Vertical Precision Accuracy + GNSS-VPA < br />Vertical Precision Accuracy + + + + Modem 4G/LTE - RSSI<br />Received Signal Strength Indicator + Modem 4G / LTE-RSSI < br />Received Signal Strength Indicator + + + + Modem 4G/LTE - SINR<br />Signal to Interference & Noise Ratio + 4G/LTE Modem-SINR < br />Signal to Interference & Noise Ratio + + + + Normal + Normal + + + + Inversé + Invertiert + + + + Tension 0 - 10 V + Spannung 0-10 V + + + + Résistance 0 - 500 Ohms + Widerstand 0-500 OHM + + + + Courant 4 - 20 mA + Strom 4-20 mA + + + + Défaut d'isolement + Isolationsfehler + + + + Ce capteur est utilisé par l'évènement ci-dessous.<br />Vous devez modifier ou supprimer cet évènement pour qu'il ne dépende plus de ce capteur avant de pouvoir le supprimer. + Dieser Sensor wird von dem unten stehenden Ereignis verwendet.<br />Sie müssen dieses Ereignis ändern oder löschen, damit es nicht mehr von diesem Sensor abhängig ist, bevor Sie es löschen können. + + + + Ce capteur est utilisé par les %1 évènements ci-dessous.<br />Vous devez modifier ou supprimer ces évènements pour qu'ils ne dépendent plus de ce capteur avant de pouvoir le supprimer. + Dieser Sensor wird von den folgenden %1-Ereignissen verwendet.<br />Sie müssen diese Ereignisse ändern oder löschen, damit Sie nicht mehr von diesem Sensor abhängig sind, bevor Sie ihn löschen können. + + + + Ce capteur est utilisé par le capteur calculé ci-dessous.<br />Vous devez modifier ou supprimer ce capteur calculé pour qu'il ne dépende plus de ce capteur avant de pouvoir le supprimer. + Dieser Sensor wird von dem unten berechneten Sensor verwendet.<br />Sie müssen diesen berechneten Sensor ändern oder entfernen, damit er nicht mehr von diesem Sensor abhängig ist, bevor Sie ihn entfernen können. + + + + Ce capteur est utilisé par les %1 capteurs calculés ci-dessous.<br />Vous devez modifier ou supprimer ces capteurs calculés pour qu'ils ne dépendent plus de ce capteur avant de pouvoir le supprimer. + Dieser Sensor wird von den unten berechneten %1-sensoren verwendet.<br />Sie müssen diese berechneten sensoren ändern oder entfernen, damit Sie nicht mehr von diesem Sensor abhängig sind, bevor Sie ihn entfernen können. + + + + Masquer sur la page Capteurs + Auf der Seite Sensoren ausblenden + + + + Créer le capteur + Sensor erstellen + + + + Enregistrer + Speichern + + + + Equation + Gleichung + + + + Supprimer + Löschen + + + + Etalonner + Erweitern + + + + Humidité + Feuchtigkeit + + + + GNSS - Latitude + GNSS-Latitude + + + + GNSS - Longitude + GNSS-Längengrad + + + + GNSS - Altitude + GNSS-Höhe + + + + config_capteur_calcule_booleen + + + Equation du capteur calculé [%1] + Berechnete sensorgleichung [%1] + + + + Enregistrer + Speichern + + + + Supprimer + Löschen + + + + Le nombre de conditions par capteur est limité à %1.<br /><br />Vous ne pouvez pas ajouter de groupe ou de nouvelle condition avant d'en avoir supprimé préalablement. + Die Anzahl der Bedingungen pro Sensor ist auf %1 begrenzt.<br /><br / > Sie können keine Gruppe oder neue Bedingung hinzufügen, bevor Sie Sie zuvor entfernt haben. + + + + Des modifications ont été apportées au capteur<br />mais n'ont pas été enregistrées.<br /><br />Cliquer sur ANNULER pour revenir au menu en cours.<br /><br />Cliquer sur Ok pour sortir sans enregistrer. + Änderungen wurden am<br /> - Sensor vorgenommen, aber nicht gespeichert.<br /> < br />klicken Sie auf ABBRECHEN, um zum aktuellen Menü zurückzukehren.<br /> < br />klicken Sie auf Ok, um zu beenden, ohne zu speichern. + + + + est actif + ist aktiv + + + + est inactif + ist inaktiv + + + + Ou + Oder + + + + Et + Und + + + + X-Ou + X-Oder + + + + config_capteur_calcule_booleen_condition + + + Création d'une condition du capteur [%1] + Erstellen einer sensorbedingung [%1] + + + + Type + Typ + + + + Source + Quelle + + + + Variable + Variable + + + + Test + Test + + + + Seuil + Schwelle + + + + Créer la condition + Bedingung erstellen + + + + Enregistrer + Speichern + + + + + + + Non défini + Nicht definiert + + + + Circuit + Schaltung + + + + Capteur + Sensor + + + + Réservoir + Tank + + + + Batterie + Batterie + + + + Actif + Aktiv + + + + Inactif + Inaktiv + + + + &lt; au seuil + & lt; an der Schwelle + + + + &le; au seuil + & le; an der Schwelle + + + + = au seuil + = an der Schwelle + + + + &ge; au seuil + & ge; an der Schwelle + + + + &gt; au seuil + &gt; an der Schwelle + + + + config_capteurs + + + Configuration des capteurs + Konfiguration der sensoren + + + + Aucun capteur n'est encore configuré... + Es ist noch kein Sensor konfiguriert... + + + + + + + + + + + config_circuit + + + Configuration du circuit + Konfiguration der Schaltung + + + + Nom du circuit + Name der Schaltung + + + + Affectation + Zuordnung + + + + Circuit renfort + Schaltung Verstärkung + + + + Mode de commande + Steuermodus + + + + Vitesse de démarrage/arrêt + Start/Stopp-Geschwindigkeit + + + + Seuil de disjonction + Disjunktionsschwelle + + + + Vitesse de disjonction + Disjunktionsgeschwindigkeit + + + + Filtrage du courant consommé + Filtern des verbrauchten Stroms + + + + Masquer sur la page d'accueil + Auf der Startseite ausblenden + + + + Créer le circuit + Schaltung erstellen + + + + Enregistrer + Speichern + + + + L'affectation du circuit vient d'être modifiée alors que le circuit était actif. +Avant d'effectuer ce changement, le circuit a été passé sur OFF. + +Pensez à le réactiver si besoin... + Die Schaltkreiszuordnung wurde gerade geändert, während der Schaltkreis aktiv war. + Bevor diese Änderung vorgenommen wurde, wurde der Stromkreis ausgeschaltet. + + Denken Sie daran, es bei Bedarf erneut zu aktivieren ... + + + + Supprimer + Löschen + + + + Aucun + Keine + + + + ShipPower812 [@ %1] + ShipPower812 [@ %1] + + + + ShipPower4AC [@ %1] + ShipPower4AC [@ %1] + + + + ShipPower8DC [@ %1] + ShipPower8DC [@ %1] + + + + + Circuit %1 + Schaltung %1 + + + + Groupe de circuits + Groupe de circuit + Gruppe von schaltungen + + + + Commande impulsionnelle + Impulssteuerung + + + + + %1 - %2 + %1 - %2 + + + + Non affecté + Nicht betroffen + + + + On-Off + An-Aus + + + + On-Off progressif + Progressives An-Aus + + + + Variateur + Variator + + + + Aucun filtrage + Keine Filterung + + + + Très faible + Sehr schwach + + + + Faible + Niedrig + + + + Moyen + Mittel + + + + Elevé + Hoch + + + + Très élevé + Sehr hoch + + + + + Très rapide + Sehr schnell + + + + + Rapide + Schnell + + + + + Moyenne + Durchschnitt + + + + + Lente + Langsam + + + + + Très lente + Sehr langsam + + + + Non + Nein + + + + 1 seconde + 1 Sekunde + + + + 2 secondes + 15 Sekunden {2 ?} + + + + 5 secondes + 15 Sekunden {5 ?} + + + + Ce circuit est utilisé pour la commande du moteur.<br />Vous devez d'abord affecter la commande moteur à un autre circuit avant de pouvoir supprimer celui-ci. + Diese Schaltung wird zur Motorsteuerung verwendet.<br />zuerst müssen Sie die Motorsteuerung einem anderen Stromkreis zuweisen, bevor Sie diesen löschen können. + + + + Ce circuit est utilisé par l'évènement ci-dessous.<br />Vous devez modifier ou supprimer cet évènement pour qu'il ne dépende plus de ce circuit avant de pouvoir le supprimer. + Diese Schaltung wird von der unten stehenden Veranstaltung genutzt.<br />Sie müssen dieses Ereignis ändern oder löschen, damit es nicht mehr von dieser Schaltung abhängt, bevor Sie es löschen können. + + + + Ce circuit est utilisé par les %1 évènements ci-dessous.<br />Vous devez modifier ou supprimer ces évènements pour qu'ils ne dépendent plus de ce circuit avant de pouvoir le supprimer. + Diese Schaltung wird von den folgenden %1-Ereignissen verwendet.<br />Sie müssen diese Ereignisse ändern oder löschen, damit Sie nicht mehr von dieser Schaltung abhängig sind, bevor Sie Sie löschen können. + + + + Ce circuit est utilisé par le capteur calculé ci-dessous.<br />Vous devez modifier ou supprimer ce capteur calculé pour qu'il ne dépende plus de ce circuit avant de pouvoir le supprimer. + Diese Schaltung wird von dem unten berechneten Sensor verwendet.<br />Sie müssen diesen berechneten Sensor ändern oder entfernen, damit er nicht mehr von dieser Schaltung abhängig ist, bevor Sie ihn entfernen können. + + + + Ce circuit est utilisé par les %1 capteurs calculés ci-dessous.<br />Vous devez modifier ou supprimer ces capteurs calculés pour qu'ils ne dépendent plus de ce circuit avant de pouvoir le supprimer. + Diese Schaltung wird von den unten berechneten %1-sensoren verwendet.<br />Sie müssen diese berechneten sensoren ändern oder entfernen, damit Sie nicht mehr von dieser Schaltung abhängig sind, bevor Sie Sie entfernen können. + + + + 15 secondes + 15 Sekunden + + + + 30 secondes + 30 Sekunden + + + + 45 secondes + 15 Sekunden {45 ?} + + + + 1 minute + 1 minute + + + + 5 minutes + 5 Minuten + + + + 15 minutes + 15 Minuten + + + + 1 heure + 1 Stunde + + + + 4 heures + 4 Stunden + + + + L'utilisation d'un circuit de renfort rend l'utilisation du mode de commande [Variateur] impossible.<br /><br />Le mode de commande vient donc d'être ramené à [On-Off Progressif]. + Die Verwendung einer verstärkungsschaltung macht die Verwendung des Steuermodus [Variator] unmöglich.<br /><br / > der Steuermodus wurde soeben auf [progressives An-Aus] zurückgesetzt. + + + + config_circuits + + + Configuration des circuits + Konfiguration der schaltungen + + + + Pack de batteries : + Akku Pack : + + + + Aucun capteur n'est encore configuré... + Es ist noch kein Sensor konfiguriert... + + + + Oui + Ja + + + + Non + Nein + + + + Le module n'est affecté à aucune batterie... + Das Modul ist keiner batterie zugeordnet... + + + + Circuit non utilisé + Schaltung nicht verwendet + + + + Circuits Non Affectés + Nicht Betroffene Schaltungen + + + + Ce circuit est configuré comme renfort du circuit <b>%1</b> et ne peut donc pas être configuré individuellement.<br /><br />Merci de cliquer sur le circuit <b>%1</b> de ce même module pour accéder à leurs paramètres communs<br />(y compris pour supprimer le circuit de renfort actuel). + Diese Schaltung ist als Verstärkung der Schaltung <b>%1</B> konfiguriert und kann daher nicht einzeln konfiguriert werden.<br /><br/>Bitte klicken Sie auf die Schaltung <b>%1</B >desselben Moduls, um auf Ihre gemeinsamen Einstellungen zuzugreifen<br / > (einschließlich des Entfernens der aktuellen verstärkungsschaltung). + + + + Type de carte inconnu... + Unbekannter Kartentyp... + + + + Le module <br /><b>%1</b><br /> n'est affecté à aucun pack de batteries. <br /><br />Souhaitez-vous laisser la configuration en l'état ? + Das Modul <br/><b>%1< / B > < br / > ist keinem Akkupack zugeordnet. <br /><br / > möchten Sie die Konfiguration unverändert lassen ? + + + + Les modules suivants ne sont affectés à aucun pack de batteries :<br /><b>%1</b><br /><br /><br />Souhaitez-vous laisser la configuration en l'état ? + Die folgenden Module sind keinem Akkupack zugeordnet: <br/><b>%1</b ><br /><br /><br / > möchten Sie die Konfiguration unverändert lassen ? + + + + config_event + + + Création d'un évènement + Erstellen eines Events + + + + Configuration de l'évènement + Event-Konfiguration + + + + Nom de l'évènement + Name der Veranstaltung + + + + Type de la source + Art der Quelle + + + + Source + Quelle + + + + Variable de la source + Variable aus der Quelle + + + + Déclenchement si + Auslösen, wenn + + + + Seuil de déclenchement + Auslöseschwelle + + + + Temporisation de déclenchement + Trigger-Timeout + + + + s + s + + + + Masquer sur la page d'accueil + Auf der Startseite ausblenden + + + + Conditions horaire + Stündliche Bedingungen + + + + Le nombre maximal de conditions horaires [%1] est atteint : ajout impossible... + Die maximale Anzahl der Zeitbedingungen [%1] ist erreicht : hinzufügen nicht möglich... + + + + Aucune condition horaire n'est configurée pour cet évènement... + Für dieses Ereignis sind keine Zeitbedingungen konfiguriert... + + + + Signalisation + Signalisierung + + + + Alarme sonore + Akustischer Alarm + + + + La validation des alarmes sonores a nécessité de valider également l'affichage des messages liés à cet évènement.<br /><br />Cet affichage est en effet nécessaire au fonctionnement des alarmes sonores, afin de pouvoir les acquitter. + Die Validierung der akustischen Alarme erforderte auch die Validierung der Anzeige von Meldungen im Zusammenhang mit diesem Ereignis.<br /><br / > Diese Anzeige ist in der Tat notwendig, damit die akustischen Alarme funktionieren, um Sie zu empfangen. + + + + Alarme sur LED + Alarm auf LED + + + + La validation des alarmes sur LED a nécessité de valider également l'affichage des messages liés à cet évènement.<br /><br />Cet affichage est en effet nécessaire au fonctionnement des alarmes sur LED, afin de pouvoir les acquitter. + Die Validierung von LED-Alarmen erforderte auch die Validierung der Anzeige von Meldungen im Zusammenhang mit diesem Ereignis.<br /><br / > Diese Anzeige ist für den Betrieb der LED-Alarme notwendig, um Sie zu bezahlen. + + + + Alarme sur sortie(s) de soutien + Alarm auf Ausgang(s) Unterstützung + + + + La validation des alarmes sur sortie(s) de soutien a nécessité de valider également l'affichage des messages liés à cet évènement.<br /><br />Cet affichage est en effet nécessaire au fonctionnement des alarmes sur sortie(s) de soutien, afin de pouvoir les acquitter. + Die Validierung von Alarmen an unterstützenden Ausgängen erforderte auch die Validierung der Anzeige von Meldungen im Zusammenhang mit diesem Ereignis.<br /><br / > Diese Anzeige ist in der Tat notwendig, damit die Alarme an den unterstützenden Ausgängen funktionieren, um Sie bezahlen zu können. + + + + Alarme sur la source + Alarm an der Quelle + + + + Affichage message sur ShipBase + Anzeige Nachricht auf ShipBase + + + + La dévalidation de l'affichage des messages a nécessité de dévalider également :<ul><li>les alarmes sonores,</li><li>les alarmes sur led</li><li>et les alarmes sur sortie(s) de soutien</li></ul><br />L'affichage de message est en effet nécessaire à leur fonctionnement, afin de pouvoir les acquitter. + Die entvalidierung der Meldungsanzeige erforderte auch die entvalidierung:<ul><li>die akustischen Alarme,</li><li>die LED-Alarme</li><li>und die unterstützenden ausgangsalarme</li></ul> < br />die Meldungsanzeige ist in der Tat für Ihren Betrieb erforderlich, um Sie zu entwerten. + + + + Texte du message à afficher + Text der anzuzeigenden Nachricht + + + + Emission SMS + SMS-Sendung + + + + Texte du SMS à envoyer + Text der zu sendenden SMS + + + + Emission Email + Emission Email + + + + Texte de l'email à envoyer + Text der zu sendenden E-Mail + + + + Action sur circuits + Aktion auf schaltungen + + + + Aucune + Keine + + + + Le circuit "bascule" + Die Schaltung"rockt" + + + + Le circuit passe à OFF + Die Schaltung geht auf OFF + + + + Le circuit passe à ON + Die Schaltung wechselt zu ON + + + + Le nombre de circuits commandés par un évènement est limité à %1.<br /><br />Vous ne pouvez pas ajouter d'action sur un nouveau circuit avant d'en avoir supprimé préalablement. + Die Anzahl der von einer Veranstaltung bestellten Touren ist auf %1 begrenzt.<br /><br / > Sie können einer neuen Schaltung keine Aktion hinzufügen, bevor Sie Sie zuvor entfernt haben. + + + + Créer l'évènement + Event erstellen + + + + Enregistrer + Speichern + + + + Supprimer + Löschen + + + + + + + Non défini + Nicht definiert + + + + Condition horaire seule + Stündliche Bedingung allein + + + + Circuit + Schaltung + + + + Capteur + Sensor + + + + Réservoir + Tank + + + + Batterie + Batterie + + + + Passage à <b>actif</b> + Wechsel zu < B > aktiv< / b> + + + + Passage à <b>inactif</b> + Wechsel zu < b>inaktiv< / b> + + + + &lt; au seuil + &lt; an der Schwelle + + + + &le; au seuil + &le; an der Schwelle + + + + = au seuil + = an der Schwelle + + + + &ge; au seuil + &ge; an der Schwelle + + + + &gt; au seuil + &gt; an der Schwelle + + + + config_events + + + Configuration des évènements + Konfigurieren von Ereignissen + + + + Aucun évènement n'est encore configuré... + Es ist noch kein Ereignis konfiguriert... + + + + 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. + Die Gesamtzahl der Ereignisse ist auf %1 begrenzt.<br /><br / > Sie können kein neues Ereignis hinzufügen, bevor Sie es zuvor gelöscht haben. + + + + Sur circuits + Auf schaltungen + + + + Sur capteurs + Über sensoren + + + + Sur réservoirs + Auf Tanks + + + + Sur batteries + Auf Batterien + + + + Horaire seulement + Nur Zeitplan + + + + config_groupe_elements + + + Création d'un groupe + Erstellen einer Gruppe + + + + Modification d'un groupe + Ändern einer Gruppe + + + + Nom du groupe + Name der Gruppe + + + + Créer le groupe + Gruppe erstellen + + + + Enregistrer + Speichern + + + + Supprimer + Löschen + + + + batteries + Batterien + + + + capteurs + sensoren + + + + circuits + schaltungen + + + + réservoirs + Tanks + + + + 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). + Diese Gruppe ist die Letzte, die noch gültig ist.<br /><br / > Sie können es nur löschen, nachdem Sie zuvor mindestens eine weitere erstellt haben (es ist nicht möglich, ohne eine Gruppe von %1 zu arbeiten). + + + + Ce groupe comprend encore %1 %2.<br /><br />Il est nécessaire d'affecter ces %2 à un autre groupe avant de pouvoir le supprimer. + Diese Gruppe umfasst noch %1 %2.<br /><br />Diese %2 müssen einer anderen Gruppe zugewiesen werden, bevor Sie gelöscht werden können. + + + + 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. + Diese Gruppe enthält noch %1 %2,<br />davon %3 konfiguriert als "versteckt".<br /><br />Diese %2 müssen einer anderen Gruppe zugewiesen werden, bevor Sie gelöscht werden können. + + + + config_image_accueil + + + Image d'accueil + Startseite Bild + + + + Aucune image n'a encore été chargée... + Es wurden noch keine Bilder geladen... + + + + Sélectionner l'image par défaut + Standardbild auswählen + + + + Sélectionner cette image + Dieses Bild auswählen + + + + Copier + Kopieren + + + + Supprimer + Löschen + + + + Ejection + Ejection + + + + Insérer une clé USB dans le port <u>du bas</u>, à droite + Stecken Sie einen USB-Stick in den unteren <u> - Anschluss</u> rechts + + + + Vous pouvez retirer la clé en toute sécurité... + Sie können den Schlüssel sicher entfernen... + + + + Seuls les fichiers de type '.jpg' ou '.png' de taille inférieure à %1 sont autorisés. + Nur Dateien vom Typ'.jpg' oder '.png ' Größe kleiner als %1 sind erlaubt. + + + + La clé USB a été <i>éjectée</i> automatiquement.<br />Vous pouvez la retirer dès maintenant en toute sécurité... + Der USB-Stick wurde automatisch<i>ausgeworfen < /i>.<br />Sie können es jetzt sicher entfernen... + + + + USB Arrière + USB Hinten + + + + Spare + Spare + + + + USB Avant + USB Front + + + + Touch pad + Touch pad + + + + La clé USB a été retirée sans avoir préalablement été <i>éjectée</i> !<br />Cela peut conduire à des pertes de données sur la clé, voire sur ShipHeart.<br /><br />Lors de vos prochaines utilisations, pensez à <i>éjecter</i> la clé avec le bouton en haut de page avant de la retirer... Merci ! + Der USB-Stick wurde entfernt ,ohne vorher<i>ausgeworfen < /i> !<br />Dies kann zu Datenverlusten auf dem Schlüssel oder sogar auf ShipHeart führen.<br /><br />denken Sie bei Ihren nächsten Anwendungen daran,<I>den Schlüssel mit der Taste oben auf der Seite auszuwerfen, bevor Sie ihn entfernen... Danke ! + + + + config_installation + + + Configuration de l'installation + Setup-Konfiguration + + + + Raison sociale + Sozialer name + + + + N° & Rue + N ° & Straße + + + + Complément d'adresse + Add-on-adresse + + + + Code postal + Postleitzahl + + + + Ville + Stadt + + + + Nom du contact + Name des Kontakts + + + + Téléphone + Telefon + + + + Email + Email + + + + Site web + Website + + + + Enregistrer + Speichern + + + + Rapports + Berichte + + + + config_koriolan + + + Accès réservé Koriolan + Koriolan reservierter Zugang + + + + Client spécifique + Spezifischer Kunde + + + + Mode de mise à jour des firmwares + Modus zum aktualisieren von firmwares + + + + Enregistrer + Speichern + + + + Tests matériel + Hardware-Tests + + + + Nombre jours avant suppression historique + Anzahl Tage vor dem löschen Geschichte + + + + Nombre jours avant suppression mesures + Anzahl Tage vor Löschung Messungen + + + + Période de sauvegarde BDD + BDD-Sicherungszeitraum + + + + Période de vérification download + Überprüfungszeitraum download + + + + Date de dernier archivage mesures + Datum der letzten Archivierung Messungen + + + + Aucune spécificité + Keine Spezifität + + + + Client Suncy Concept + Suncy Concept Client + + + + Normal (si version installée est antérieure à la version en cours) + Normal (wenn die installierte version älter als die aktuelle version ist) + + + + Différente (si version installée est différente de version en cours) + Anders (wenn installierte version ist anders als aktuelle version) + + + + Toujours (à utiliser avec modération...) + Immer (in Maßen verwenden...) + + + + config_module + + + Modifier + Bearbeiten + + + + Localiser le module + Modul lokalisieren + + + + Paramètres du module [%1] + Moduleinstellungen [%1] + + + + Paramètres du module [%1] à l'adresse [%2] + Modulparameter [%1] unter [%2] + + + + N° de série + Seriennummer + + + + Nom du firmware + Name der firmware + + + + Version du firmware + Firmware-Version + + + + Version matérielle + Hardware Version + + + + Résistance de terminaison + Abschlusswiderstand + + + + Oui + Ja + + + + Non + Nein + + + + CRC du firmware + CRC der firmware + + + + Courant de masses sur réseau + Massenstrom im Netz + + + + <i>--- Circuit non affecté ---</i> + <i>--- Stromkreis nicht betroffen ---</i> + + + + [renfort] + [Verstärkung] + + + + Affectations + Zuordnung + + + + <i>--- Aucune batterie affectée ---</i> + <i>--- Keine Batterie betroffen ---</i> + + + + Affectation + Zuordnung + + + + Version processeur + Prozessor-Version + + + + Emplacement du module à bord + Modulstandort an Bord + + + + Commentaires + Kommentare + + + + config_module_modification + + + Configuration du module [%1] à l'adresse [%2] + Konfiguration des Moduls [%1] an Adresse [%2] + + + + Emplacement du module à bord + Modulstandort an Bord + + + + Commentaires + Kommentare + + + + Courant de masses max. sur réseau + Max. Massenstrom im Netzwerk + + + + A + A + + + + Enregistrer + Speichern + + + + config_ordre_elements + + + 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... + Um eine Gruppe zu verschieben, halten Sie Sie gedrückt und ziehen Sie Sie dann.<br />um eine Gruppe zu Bearbeiten oder zu löschen, doppelklicken Sie auf die Gruppe.<br / > um eine Gruppe hinzuzufügen, klicken Sie auf'+'.<br /> < br />Hinweis : wenn nur eine Gruppe vorhanden ist, wird auf der betreffenden Seite keine Registerkarte angezeigt... + + + + Aucun groupe n'est actuellement configuré... + Derzeit sind keine Gruppen konfiguriert... + + + + Aucun élément n'est actuellement configuré... + Derzeit sind keine Elemente konfiguriert... + + + + Aucun groupe de batteries n'est actuellement configuré... + Derzeit sind keine batteriegruppen konfiguriert... + + + + Aucune batterie n'est actuellement affectée à ce groupe... + Dieser Gruppe sind derzeit keine Batterien zugeordnet... + + + + Affichage des batteries sur la page d'accueil + Anzeige der Batterien auf der Homepage + + + + Aucun capteur n'est actuellement affecté ce groupe... + Dieser Gruppe sind derzeit keine sensoren zugeordnet... + + + + Affichage des capteurs sur la page d'accueil + Anzeige der sensoren auf der Startseite + + + + Aucun circuit n'est actuellement affecté à ce groupe... + Dieser Gruppe sind derzeit keine schaltkreise zugeordnet... + + + + Affichage des circuits sur la page d'accueil + Schaltungen auf der Homepage anzeigen + + + + Aucun groupe de réservoirs n'est actuellement configuré... + Derzeit sind keine tankgruppen konfiguriert... + + + + Aucun réservoir n'est actuellement affecté à ce groupe... + Dieser Gruppe sind derzeit keine Tanks zugeordnet... + + + + Affichage des réservoirs sur la page d'accueil + Anzeigen von Tanks auf der Homepage + + + + Aucun groupe de capteurs n'est actuellement configuré... + Derzeit sind keine sensorgruppen konfiguriert... + + + + Aucun groupe de circuits n'est actuellement configuré... + Derzeit sind keine Schaltungsgruppen konfiguriert... + + + + config_page + + + Création d'une page + Eine Seite erstellen + + + + Configuration de la page + Seiteneinrichtung + + + + Nom de la page + Seitenname + + + + Opacité de la silhouette + Silhouetten-Deckkraft + + + + Fichier de silhouette + Silhouette-Datei + + + + Créer la page + Erstellen Sie die Seite + + + + Enregistrer + Speichern + + + + Silhouette + Silhouette + + + + Supprimer + Löschen + + + + + Aucun + Keine + + + + config_page_edition + + + Edition de la page [%1] + Bearbeiten der Seite [%1] + + + + Aucun équipement n'est configuré sur cette page pour le moment... + Auf dieser Seite ist derzeit kein Gerät konfiguriert... + + + + Page + Seite + + + + Enregistrer + Speichern + + + + 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. + Sie haben änderungen vorgenommen, die nicht gespeichert wurden<br />klicken Sie auf Abbrechen, um zurückzugehen und Sie zu speichern.< br / > klicken Sie auf OK, um zu beenden, ohne zu speichern. + + + + config_page_point + + + Création d'un point + Einen Punkt erstellen + + + + Configuration du point + Punktkonfiguration + + + + Type de la source + Art der Quelle + + + + Source + Quelle + + + + Type de point + Stichart + + + + Taille du point + Punktgröße + + + + Enregistrer + Speichern + + + + Créer le point + Erstellen Sie den Punkt + + + + Supprimer + Löschen + + + + + Non défini + Nicht definiert + + + + Capteur + Sensor + + + + Circuit + Schaltung + + + + Réservoir + Tank + + + + Batterie + Batterie + + + + Modules + Module + + + + config_page_silhouette + + + Silhouette de la page + Seitensilhouette + + + + Aucune image n'a encore été chargée... + Es wurden noch keine Bilder geladen... + + + + Aucune image + Keine Bilder + + + + Sélectionner cette image + Dieses Bild auswählen + + + + Copier + Kopieren + + + + Supprimer + Löschen + + + + Ejection + Ejection + + + + Insérer une clé USB dans le port <u>du bas</u>, à droite + Stecken Sie einen USB-Stick in den unteren <u> - Anschluss</u> rechts + + + + Vous pouvez retirer la clé en toute sécurité... + Sie können den Schlüssel sicher entfernen... + + + + Seuls les fichiers de type '.jpg' ou '.png' de taille inférieure à %1 sont autorisés. + Nur Dateien vom Typ'.jpg' oder '.png ' Größe kleiner als %1 sind erlaubt. + + + + La clé USB a été <i>éjectée</i> automatiquement.<br />Vous pouvez la retirer dès maintenant en toute sécurité... + Der USB-Stick wurde automatisch<i>ausgeworfen < /i>.<br />Sie können es jetzt sicher entfernen... + + + + USB Arrière + USB Hinten + + + + Spare + Spare + + + + USB Avant + USB Front + + + + Touch pad + Touch pad + + + + La clé USB a été retirée sans avoir préalablement été <i>éjectée</i> !<br />Cela peut conduire à des pertes de données sur la clé, voire sur ShipHeart.<br /><br />Lors de vos prochaines utilisations, pensez à <i>éjecter</i> la clé avec le bouton en haut de page avant de la retirer... Merci ! + Der USB-Stick wurde entfernt ,ohne vorher<i>ausgeworfen < /i> !<br />Dies kann zu Datenverlusten auf dem Schlüssel oder sogar auf ShipHeart führen.<br /><br />denken Sie bei Ihren nächsten Anwendungen daran,<I>den Schlüssel mit der Taste oben auf der Seite auszuwerfen, bevor Sie ihn entfernen... Danke ! + + + + config_pages + + + Configuration des pages + Seiteneinrichtung + + + + Aucune page n'est encore configurée... + Es ist noch keine Seite konfiguriert... + + + + Image accueil + Startseite Bild + + + + + + + + + + + config_pdf + + + Ship2net + Ship2net + + + + Enregistrer + Speichern + + + + config_rapports + + + Rapports d'installation + Installationsberichte + + + + Aucun rapport d'installation n'est encore disponible... + Es sind noch keine Installationsberichte verfügbar... + + + + Nouveau rapport d'installation + Neuer Installationsbericht + + + + Copier + Kopieren + + + + Déplacer + Bewegen + + + + Supprimer + Löschen + + + + Ejection + Ejection + + + + Insérer une clé USB dans le port <u>du bas</u>, à droite + Stecken Sie einen USB-Stick in den unteren <u> - Anschluss</u> rechts + + + + Vous pouvez retirer la clé en toute sécurité... + Sie können den Schlüssel sicher entfernen... + + + + La clé USB a été <i>éjectée</i> automatiquement.<br />Vous pouvez la retirer dès maintenant en toute sécurité... + Der USB-Stick wurde automatisch<i>ausgeworfen < /i>.<br />Sie können es jetzt sicher entfernen... + + + + USB Arrière + USB Hinten + + + + Spare + Spare + + + + USB Avant + USB Front + + + + Touch pad + Touch pad + + + + La clé USB a été retirée sans avoir préalablement été <i>éjectée</i> !<br />Cela peut conduire à des pertes de données sur la clé, voire sur ShipHeart.<br /><br />Lors de vos prochaines utilisations, pensez à <i>éjecter</i> la clé avec le bouton en haut de page avant de la retirer... Merci ! + Der USB-Stick wurde entfernt ,ohne vorher<i>ausgeworfen < /i> !<br />Dies kann zu Datenverlusten auf dem Schlüssel oder sogar auf ShipHeart führen.<br /><br />denken Sie bei Ihren nächsten Anwendungen daran,<I>den Schlüssel mit der Taste oben auf der Seite auszuwerfen, bevor Sie ihn entfernen... Danke ! + + + + Le rapport d'installation<br /><br /><b>%1</b><br /><br />a été généré. + Der Installationsbericht<br /><br /><b>%1</B><br /> < br />wurde generiert. + + + + config_reseau_ethernet_wifi + + + Réseau Ethernet & Wifi + Ethernet & Wifi Netzwerk + + + + + Modifier + Bearbeiten + + + + Ethernet + Ethernet + + + + + + Adresse IP + IP-Adresse + + + + + + Non connecté + Nicht verbunden + + + + Connexion à un réseau existant + Verbindung zu einem bestehenden Netzwerk + + + + + Etat + Staat + + + + + On + ON + + + + + Off + OFF + + + + + Nom du réseau [SSID] + Netzwerkname [SSID] + + + + Génération d'un réseau spécifique + Generieren eines bestimmten Netzwerks + + + + Canal + Kanal + + + + config_reseau_k_bus + + + Réseau ShipHeart + ShipHeart-Netzwerk + + + + Modules physiquement présents + Module physisch vorhanden + + + + %1 - %2 + %1 - %2 + + + + Modules utilisés par la configuration actuelle + Von der aktuellen Konfiguration verwendete Module + + + + [@ %1] : %2 + [@ %1] : %2 + + + + La configuration actuelle ne fait appel à aucun autre module que ShipBase... + Die aktuelle Konfiguration verwendet kein anderes Modul als ShipBase... + + + + Module non utilisé en configuration + Modul nicht in der Konfiguration verwendet + + + + [renfort] + [Verstärkung] + + + + Enregistrer + Speichern + + + + Retour + Zurück + + + + Quitter + Verlassen + + + + Aucune modification n'a été apportée à la configuration actuelle.<br />Celle-ci contient toujours des anomalies !<br /><br /><br />Souhaitez-vous :<br />Poursuivre les modifications [%1]<br />Quitter ce menu sans enregistrer les modifications [%2] + An der aktuellen Konfiguration wurden keine Änderungen vorgenommen.<br />Sie enthält immer noch Anomalien!<br /><br /><br />Möchten Sie:<br />Weitere Änderungen vornehmen [%1 ]<br / >Dieses Menü verlassen, ohne die Änderungen zu speichern [%2] + + + + La configuration actuelle contient toujours des anomalies !<br /><br /><br />Souhaitez-vous :<br />Enregistrer cette nouvelle configuration et quitter ce menu [%1]<br />Poursuivre les modifications [%2]<br />Quitter ce menu sans enregistrer les modifications [%3] + Die aktuelle Konfiguration enthält immer noch Anomalien!<br /><br /><br />Möchten Sie:<br />Diese neue Konfiguration speichern und dieses Menü verlassen [%1]<br />Mit den Änderungen fortfahren [%2 ]<br />Dieses Menü verlassen, ohne die Änderungen zu speichern [%3] + + + + La configuration actuelle est correcte <br />mais n'a pas encore été enregistrée.<br /><br /><br />Souhaitez-vous :<br />Enregistrer cette nouvelle configuration et quitter ce menu [%1]<br />Poursuivre les modifications [%2]<br />Quitter ce menu sans enregistrer les modifications [%3] + Die aktuelle Konfiguration ist korrekt <br />wurde aber noch nicht gespeichert.<br /><br /><br />Möchten Sie:<br />Diese neue Konfiguration speichern und dieses Menü verlassen [%1] < br />Änderungen fortsetzen [%2]<br />Dieses Menü verlassen, ohne Änderungen zu speichern [%3] + + + + config_reseau_nmea + + + Réseau NMEA2000 + NMEA2000-Netzwerk + + + + Aucun PGN n'a encore été détecté sur le réseau NMEA2000... + Bisher wurde im NMEA2000-Netzwerk kein PGN erkannt... + + + + PGN non affecté + PGN nicht zugewiesen + + + + config_reseau_one_wire + + + Réseau One Wire + One Wire Netzwerk + + + + Aucune sonde n'est encore installée... + Es ist noch keine sonde installiert... + + + + 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. + Der One Wire-bus wird derzeit als Kurzschluss erkannt. <br />Dieser Zustand stellt keine Gefahr dar, verhindert jedoch, dass er funktioniert. <br /> < br />überprüfen Sie die entsprechende Verkabelung, bis diese Meldung verschwindet. + + + + Type inconnu + Unbekannter Typ + + + + Sonde non affectée + Nicht betroffene Sonde + + + + config_reseau_one_wire_modification + + + Configuration de la sonde [%1] + Konfiguration der sonde [%1] + + + + Emplacement de la sonde + Position der sonde + + + + Enregistrer + Speichern + + + + config_reseau_wifi_ap + + + Configuration Wifi en mode AP + WiFi-Konfiguration im AP-Modus + + + + Etat + Staat + + + + Nom du réseau (SSID) + Netzwerkname (SSID) + + + + Mot de passe d'accès au réseau + Passwort für den Netzwerkzugriff + + + + Canal + Kanal + + + + Adresse IP + IP-Adresse + + + + Non connecté + Nicht verbunden + + + + Enregistrer + Speichern + + + + Off + OFF + + + + On + ON + + + + Canal %1 - [%2GHz] + Kanal %1 - [%2GHz] + + + + Le nom du réseau (SSID) doit comprendre entre 1 et 32 caractères. <br />Merci d'entrer un nom valide. + Der Netzwerkname (SSID) muss zwischen 1 und 32 Zeichen lang sein. <br / > bitte geben Sie einen gültigen Namen ein. + + + + 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. + Das netzwerkzugriffskennwort muss zwischen 8 und 63 Zeichen lang sein. <br / > bitte geben Sie ein gültiges Passwort ein. + + + + 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. + Der Netzwerkname (SSID) darf nur Folgendes enthalten :<br />- Großbuchstaben [A - Z],<br />- Kleinbuchstaben [a - z],<br />- Ziffern [0 - 9]<br />- Sonderzeichen [%1].<br /><br / > bitte geben Sie einen gültigen Namen ein. + + + + 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. + Das netzwerkzugriffspasswort darf nur Folgendes enthalten :<br / > - Großbuchstaben [A - Z],<br / > - Kleinbuchstaben [a - z],<br / > - Ziffern [0 - 9]<br / > - Sonderzeichen [%1].<br /><br / > bitte geben Sie einen gültigen Namen ein. + + + + config_reseau_wifi_sta + + + Configuration Wifi en mode STA + WIFI-Konfiguration im STA-Modus + + + + Etat + Staat + + + + Réseau + Netzwerk + + + + Mot de passe d'accès au réseau + Passwort für den Netzwerkzugriff + + + + Enregistrer + Speichern + + + + Réseaux connus + Bekannte Netzwerke + + + + Off + OFF + + + + On + ON + + + + Aucun réseau... + Kein Netzwerk... + + + + config_reseau_wifi_sta_liste + + + Liste des réseaux Wifi connus + Liste bekannter Wifi-Netzwerke + + + + Aucun réseau n'a été détecté... + Es wurde kein Netzwerk erkannt... + + + + Oublier tous les réseaux + Alle Netzwerke vergessen + + + + Oublier ce réseau + Dieses Netzwerk vergessen + + + + config_reservoir + + + Création d'un réservoir + Erstellen eines Reservoirs + + + + Configuration du réservoir + Tank-Konfiguration + + + + Nom du réservoir + Name des Tanks + + + + Famille de réservoirs + Familie von Tanks + + + + Type de capteur de niveau + Level Sensor Typ + + + + %1 : Non définie + %1: nicht definiert + + + + %1 : %2 + %1 : %2 + + + + Sonde la plus basse dans le réservoir + Niedrigste Sonde im Tank + + + + Non définie + Nicht definiert + + + + Logique d'alarme + Alarm Logik + + + + Filtrage des mesures + Filtern von Messungen + + + + Créer le réservoir + Tank erstellen + + + + Enregistrer + Speichern + + + + Supprimer + Löschen + + + + Etalonnage + Kalibrierung + + + + + AUX INPUT %1 + AUX INPUT %1 + + + + + LEVEL SENSOR %1 + LEVEL SENSOR %1 + + + + Confirmer + Bestätigen + + + + Capacité du réservoir + Tank Kapazität + + + + litres + Liter + + + + Logique des entrées inversée + Invertierte eingangslogik + + + + La modification du <b>type de capteur</b> va nécessiter la remise en <i>configuration usine</i> de tous les paramètres du réservoir.<br /><br />Si vous ne souhaitez pas que cette reconfiguration soit effectuée, cliquez sur ANNULER. <br /><br />Sinon, cliquez sur CONFIRMER pour valider le changement. + Um den <B>Sensortyp</B> zu ändern, müssen alle tankeinstellungen auf <i>Werkseinstellungen</i> zurückgesetzt werden.<br /><br / > wenn Sie diese Neukonfiguration nicht durchführen möchten, klicken Sie auf ABBRECHEN. <br /><br / > wenn Nicht, klicken Sie auf BESTÄTIGEN, um die änderung zu bestätigen. + + + + Non défini + Nicht definiert + + + + Electrodes plongées ou contacts secs + Tauchelektroden oder Trockenkontakte + + + + Résistif 0 - 190Ω + Widerstrebend 0 - 190ω + + + + Résistif 240 - 30Ω + Resistiv 240-30Ω + + + + Résistif 0 - 700Ω + Resistiv 0–700 Ω + + + + Boucle de courant 4 - 20mA + Stromschleife 4-20mA + + + + Tension 0 - 10V + Spannung 0 - 10V + + + + Aucun filtrage + Keine Filterung + + + + Très faible + Sehr schwach + + + + Faible + Niedrig + + + + Moyen + Mittel + + + + Elevé + Hoch + + + + Très élevé + Sehr hoch + + + + Ce réservoir est utilisé par l'évènement ci-dessous.<br />Vous devez modifier ou supprimer cet évènement pour qu'il ne dépende plus de ce réservoir avant de pouvoir le supprimer. + Dieser Tank wird von der unten stehenden Veranstaltung genutzt.<br />Sie müssen dieses Ereignis ändern oder löschen, damit es nicht mehr von diesem Tank abhängig ist, bevor Sie es löschen können. + + + + Ce réservoir est utilisé par les %1 évènements ci-dessous.<br />Vous devez modifier ou supprimer ces évènements pour qu'ils ne dépendent plus de ce réservoir avant de pouvoir le supprimer. + Dieser Tank wird von den unten aufgeführten %1-Ereignissen verwendet.<br />Sie müssen diese Ereignisse ändern oder löschen, damit Sie nicht mehr von diesem Tank abhängig sind, bevor Sie ihn löschen können. + + + + Ce réservoir est utilisé par le capteur calculé ci-dessous.<br />Vous devez modifier ou supprimer ce capteur calculé pour qu'il ne dépende plus de ce réservoir avant de pouvoir le supprimer. + Dieser Tank wird von dem unten berechneten Sensor verwendet.<br />Sie müssen diesen berechneten Sensor ändern oder entfernen, damit er nicht mehr von diesem Tank abhängig ist, bevor Sie ihn entfernen können. + + + + Ce réservoir est utilisé par les %1 capteurs calculés ci-dessous.<br />Vous devez modifier ou supprimer ces capteurs calculés pour qu'ils ne dépendent plus de ce réservoir avant de pouvoir le supprimer. + Dieser Tank wird von den %1 sensoren verwendet, die unten berechnet werden.<br />Sie müssen diese berechneten sensoren ändern oder entfernen, damit Sie nicht mehr von diesem Tank abhängig sind, bevor Sie ihn entfernen können. + + + + Alerte sur niveau faible + Alarm auf niedrigem niveau + + + + Alerte sur niveau élevé + Alarm auf hohem niveau + + + + config_reservoirs + + + Configuration des réservoirs + Konfiguration der Tanks + + + + Aucun réservoir n'est encore configuré... + Es ist noch kein Tank konfiguriert... + + + + + + + + + + + config_ship2net + + + Ship2net + Ship2net + + + + Période des sauvegardes + Zeitraum der Backups + + + + Période de connexion à Ship2net + Ship2net-Verbindungszeitraum + + + + Mode de validation des mises à jour + Validierungsmodus für Updates + + + + Accès distant WebGL #1 + WebGL #1 Fernzugriff + + + + Accès distant WebGL #2 + WebGL #2 Fernzugriff + + + + Accès distant WebGL #3 + WebGL #3 Fernzugriff + + + + Enregistrer + Speichern + + + + + Jamais + Niemals + + + + + 2 minutes + 2 Minuten + + + + + 30 minutes + 30 Minuten + + + + + 1 heure + 1 Stunde + + + + 2 heures + 2 Stunden + + + + + 4 heures + 4 Stunden + + + + + 12 heures + 12 Stunden + + + + + 24 heures + 24 Stunden + + + + + + Dévalidé + Entwertet + + + + + + Valide [port %1] + Gültig [Port %1] + + + + + 10 minutes + 10 Minuten + + + + Aucune mise à jour + Keine Updates + + + + Validation manuelle des mises à jour reçues + Manuelle Validierung der empfangenen Updates + + + + Validation automatique des mises à jour reçues + Automatische Validierung der empfangenen Updates + + + + config_specifique_client_suncy + + + Configuration spécifique à Suncy Concept + Suncy Concept-spezifische Konfiguration + + + + Circuit d'activation moteur + Motoraktivierungsschaltung + + + + Nouveau code + Neuer code + + + + Code d'accès au bateau + Zugangscode zum Boot + + + + Répéter le code d'accès + Passcode wiederholen + + + + Enregistrer + Speichern + + + + Aucune + Keine + + + + [module %1 - circuit %2] %3 + [Modul %1-Schaltung %2] %3 + + + + Les deux valeurs saisies doivent être identiques ! + +De plus, le code doit contenir : +- %1 chiffres au minimum +- %2 chiffres au maximum. + Die beiden eingegebenen Werte müssen identisch sein! + + Darüber hinaus muss der Code Folgendes enthalten: + - Mindestens %1 Ziffer + - Maximal %2 Ziffern. + + + + Le nouveau code doit contenir : +- %1 chiffres au minimum +- %2 chiffres au maximum. + +Le code saisi ne répond pas à ces critères et sa mise à jour n'est donc pas effectuée. + +Merci de saisir un code au format valide si vous souhaitez le modifier. + Der neue Code muss enthalten: + - Mindestens %1 Ziffer + - Maximal %2 Ziffern. + + Der eingegebene Code erfüllt diese Kriterien nicht und wird daher nicht aktualisiert. + + Bitte geben Sie einen Code in einem gültigen Format ein, wenn Sie ihn ändern möchten. + + + + config_valeurs_niveaux + + + Aucun point de conversion n'est configuré pour le moment... + Derzeit sind keine konvertierungspunkte konfiguriert... + + + + Le nombre maximal de points d'étalonnage a été atteint (%1 points)<br />Vous ne pouvez pas en ajouter sans en avoir prélablement supprimé. + Die maximale Anzahl an Kalibrierungspunkten wurde erreicht (%1 Punkte).<br />Sie können keine weiteren hinzufügen, ohne vorher einige zu löschen. + + + + Courbe usine + Kurve Fabrik + + + + Enregistrer + Speichern + + + + La valeur lue sur les electrodes plongées de ce réservoir est incohérente.<br />Vérifier l'ordre de cablage des électrodes sur les entrées auxiliaires à l'arrière de ShipBase. + Der Wert, der von den tauchelektroden dieses Tanks gelesen wird, ist inkonsistent.< br />Überprüfen Sie die kabelreihenfolge der Elektroden an den hilfseingängen auf der Rückseite von ShipBase. + + + + Aucune donnée n'est disponible... + Es sind keine Daten verfügbar... + + + + 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. + Sie haben änderungen vorgenommen, die nicht gespeichert wurden<br />klicken Sie auf Abbrechen, um zurückzugehen und Sie zu speichern.< br / > klicken Sie auf OK, um zu beenden, ohne zu speichern. + + + + Aucun point n'est actuellement configuré pour cette batterie... + Für diese batterie ist derzeit kein Punkt konfiguriert... + + + + + Courbe de conversion de [%1] + Umrechnungskurve von [%1] + + + + Aucun réservoir n'est actuellement configuré... + Derzeit ist kein Tank konfiguriert... + + + + Aucun point n'est actuellement configuré pour cet élément... + Für dieses Element ist derzeit kein Punkt konfiguriert... + + + + Courbe de conversion de type INCONNU + Konvertierungskurve UNBEKANNTEN Typs + + + + config_version + + + Version + Version + + + + %1 : %2 + %1 : %2 + + + + 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 : + Die version <b > %1 < / b> ist verfügbar.<br /><br / > Sie wird beim nächsten Start von ShipHeart automatisch installiert.<br / > Es sei denn, Sie wählen eine der folgenden Optionen : + + + + La version <b>%1</b> est disponible.<br /><br />Souhaitez-vous : + Die version <b > %1 < / b> ist verfügbar.<br / > < br />möchten Sie : + + + + + L'installer +maintenant + Es installieren + JETZT + + + + L'installer au prochain démarrage de ShipHeart + Installieren Sie es beim nächsten Start von ShipHeart + + + + + Ne jamais l'installer + Installieren Sie es niemals + + + + Supprimer + Löschen + + + + Si vous confirmez, cette mise à jour sera définitivement supprimée.<br />Cliquez sur Annuler pour revenir en arrière et la conserver. + Wenn Sie bestätigen, wird dieses Update dauerhaft gelöscht.<br />Klicken Sie auf „Abbrechen“, um zurückzugehen und es zu behalten. + + + + Installer + Installieren + + + + 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 la conserver pour une installation ultérieure. + Wenn Sie bestätigen, kann dieses Update <u>einige Minuten</u> dauern, in denen <b>Ihr ShipHeart-System nicht erreichbar ist</b>.<br /><br />Sie müssen das nicht bestätigen Installation nur, wenn Sie sich in einer sicheren Situation befinden (im Hafen, vor Anker etc.) und der Verlust der Kontrolle über Ihre Bordsysteme in diesem Zeitraum ohne Gefahr ist!<br /><br />Klicken Sie auf Abbrechen, um zurückzugehen und es für eine spätere Installation zu speichern. + + + + 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 'shipheart.tech' ou de nous contacter à l'adresse 'contact@shipheart.tech'. + 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 'shipheart.tech' ou de nous contacter à l'adresser 'contact@shipheart.tech'. + Dieses Produkt wird von der Firma Koriolan entworfen und hergestellt, die über alle Lizenzen und Verwertungsrechte an Bildern, Software und Patenten verfügt, die sowohl für das Design als auch für den Betrieb verwendet werden. ShipHeart™, Ship2net™ und Koriolan™ sind eingetragene Marken der Firma Koriolan. Bei Fragen zu diesem Produkt besuchen Sie bitte die Website 'shipheart.tech 'oder Kontaktieren Sie uns unter' contact@shipheart.tech'. + + + + Version du package logiciel + Software-Paket-Version + + + + Version de l'application + App-Version + + + + Version de l'interface graphique + GUI-Version + + + + Version du firmware du modem + Modem firmware Version + + + + Numéro d'IMEI + IMEI-Nummer + + + + Numéro d'ICCID + ICCID-Nummer + + + + Numéro d'IMSI + IMSI-Nummer + + + + ephemeride + + + Ephéméride + EPHEMERiD + + + + Heure d'hiver + Winterzeit + + + + Heure d'été + Sommerzeit + + + + Aube nautique + Nautische Morgendämmerung + + + + Lever du soleil + Sonnenaufgang + + + + Zénith + Zenit + + + + Coucher du soleil + Sonnenuntergang + + + + Crépuscule nautique + Nautische Dämmerung + + + + Lune + Mond + + + + Latitude + Latitude + + + + Longitude + Längengrad + + + + etalonnage_capteur + + + Etalonnage du capteur [%1] + Kalibrierung des Sensors [%1] + + + + Valeur brute actuelle + Aktueller bruttowert + + + + Valeur corrigée actuelle (%1) + Aktueller korrigierter Wert (%1) + + + + Correction + Korrektur + + + + Enregistrer + Speichern + + + + etalonnage_carte + + + Etalonnage du module [%1 - #%2] + Kalibrierung des Moduls [%1 - #%2] + + + + Point 1 + Punkt 1 + + + + Point 2 + Punkt 2 + + + + Courant de décharge + Entladestrom + + + + Courant différentiel + Differenzstrom + + + + + Recalculer ce point + Diesen Punkt neu berechnen + + + + + Mémoriser ce point + Merken Sie sich diesen Punkt + + + + Off + OFF + + + + On + ON + + + + On (%1 %%) + An (%1 %%) + + + + Enregistrer + Speichern + + + + Aide + Hilfe + + + + 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 /> + Die Kalibrierung kann nicht mit zwei identischen Punkten durchgeführt werden.<br /><br /> + Versuchen Sie, mindestens einen der beiden Referenzpunkte zu ändern, indem Sie die folgenden Schaltkreissteuerungen anpassen.<br /> + + + + 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. + Das Prinzip der Kalibrierung besteht darin, in <U>2 verschiedenen Punkten</u> den vom ShipBS gemessenen differenzstromwert einerseits zu vergleichen und der vom ShipHeart-System gemessene Entladestrom hingegen.<br /> Zum Beispiel durch aussetzen des zu kalibrierenden ShipBS bei geringem oder keinem Verbrauch (Erster Punkt) dann ein oder mehrere Geräte in Betrieb nehmen, um möglichst mehrere Ampere zu verbrauchen (zweiter Punkt).<br /> <br /><u><b>Sehr wichtig </b> : während der gesamten kalibrierphase darf kein Strom von<B>Last < /B> an ShipBS angelegt werden !< / u> Daher ist es wichtig, alle Ladegeräte, Solarregler usw. zu trennen... des Systems während der Kalibrierung. Andernfalls sind die kalibrierungswerte falsch...<br / > <br /> Anmerkungen: <br / > - der gesamte Verbrauch muss über das ShipHeart-System erfolgen ! Daher muss sichergestellt werden, dass keine Last direkt angeschlossen ist im batteriepark.<br /> - stromwerte spielen keine Rolle.<br /> - der Strom von Punkt 2 kann kleiner oder größer sein als der von Punkt 1 (aber so weit wie möglich voneinander entfernt).<br /> - es ist ratsam, Lasten zu wählen, deren Verbrauch relativ stabil ist oder sich zumindest über einen Zeitraum von wenigen Sekunden kaum ändert. + + + + fonctions + + + Modèle inconnu + Unbekanntes Modell + + + + Circuit + Schaltung + + + + Capteur + Sensor + + + + Réservoir + Tank + + + + Batterie + Batterie + + + + Type inconnu + Unbekannter Typ + + + + Consigne + Anweisung + + + + + + Tension + Spannung + + + + Courant + Strom + + + + Fréquence + Frequenz + + + + + Puissance + Macht + + + + + Energie + Energie + + + + Température + Temperatur + + + + Courant différentiel + Differenzstrom + + + + Courant de charge + Ladestrom + + + + Courant de décharge + Entladestrom + + + + SOH (state Of Health) + SOH (state of Health) + + + + SOC (State Of Charge) + SoC (State of Charge) + + + + Autonomie + Autonomie + + + + fonctions_date_heure + + + 1 heure + 1 Stunde + + + + 24 heures + 24 Stunden + + + + 7 jours + 7 Tage + + + + 30 jours + 30 Tage + + + + Fin de nuit + Späte Nacht + + + + Aube nautique + Nautische Morgendämmerung + + + + Aube + Morgendämmerung + + + + Lever du soleil + Sonnenaufgang + + + + Zénith + Zenit + + + + Coucher du soleil + Sonnenuntergang + + + + Crépuscule + Dämmerung + + + + Crépuscule nautique + Nautische Dämmerung + + + + Début de nuit + Beginn der Nacht + + + + %1h + %1h + + + + Dimanche + Sonntag + + + + Lundi + Montag + + + + Mardi + Dienstag + + + + Mercredi + Mittwoch + + + + Jeudi + Donnerstag + + + + Vendredi + Freitag + + + + Samedi + Samstag + + + + Tous les jours + Jeden Tag + + + + janvier + Januar + + + + février + Februar + + + + mars + mars + + + + avril + April + + + + mai + mai + + + + juin + Juni + + + + juillet + Juli + + + + août + August + + + + septembre + September + + + + octobre + Oktober + + + + novembre + November + + + + décembre + Dezember + + + + fonctions_historique + + + Commande 'OFF' du circuit %1 + Befehl 'OFF' von Schaltkreis %1 + + + + Commande 'ON' du circuit %1 + Befehl 'ON' von Schaltkreis %1 + + + + Commande à %1 % du circuit %2 + Befehl bei %1 % des Schaltkreises %2 + + + + Le circuit %1 est revenu à son état de fonctionnement normal + Die %1-Schaltung ist in den normalen Betriebszustand zurückgekehrt + + + + L'alimentation du circuit %1 a été coupée car sa limite de courant (%2 A) a été dépassée + Die Stromversorgung des Stromkreises %1 wurde unterbrochen, da seine Strombegrenzung (%2 A) überschritten wurde + + + + L'alimentation du circuit %1 a été coupée car les circuits de protection interne ont détecté une anomalie + Die Stromversorgung der %1-Schaltung wurde unterbrochen, da die internen Schutzschaltungen eine anomalie festgestellt haben + + + + L'alimentation du circuit %1 a été coupée car le seuil de disjonction a été dépassé + Die Stromversorgung der %1-Schaltung wurde unterbrochen, da die disjunktionsschwelle überschritten wurde + + + + Le circuit %1 est en court-circuit avec le + batterie + Stromkreis %1 hat einen Kurzschluss mit dem + der Batterie + + + + L'alimentation du circuit %1 a été coupée car la consommation totale du module a été dépassé + Die Stromversorgung der %1-Schaltung wurde unterbrochen, da der Gesamtverbrauch des Moduls überschritten wurde + + + + Le circuit %1 a été créé + Schaltung %1 wurde erstellt + + + + La configuration du circuit %1 a été modifiée + Schaltungskonfiguration %1 wurde geändert + + + + Le circuit %1 a été supprimé + Schaltung %1 wurde entfernt + + + + La configuration du circuit %1 est invalide car le module sur lequel le circuit est configuré n'est pas présent + Die schaltungskonfiguration %1 ist ungültig, da das Modul, auf dem die Schaltung konfiguriert ist, nicht vorhanden ist + + + + Le circuit %1 a fonctionné trop longtemps (> %2 secondes). Il a donc été désactivé automatiquement. + Schaltung %1 lief zu lange (>%2 Sekunden). Es wurde also automatisch deaktiviert. + + + + Evénement de type CIRCUITS avec code de sous-type inconnu [%1] + Ereignis vom Typ SCHALTUNGEN mit unbekanntem subtypcode [%1] + + + + Le capteur %1 est repassé à l'état normal + Sensor %1 wird wieder in den Normalzustand versetzt + + + + Le capteur %1 est passé à l'état ALERTE + Sensor %1 wird in den ALARMZUSTAND versetzt + + + + Le capteur %1 est passé à l'état ALARME + Sensor %1 ist in den ALARMZUSTAND übergegangen + + + + Evénement de type CAPTEURS avec code de sous-type inconnu [%1] + Ereignis vom Typ SENSOREN mit unbekanntem subtypcode [%1] + + + + Le niveau de charge de la batterie %1 est repassé au niveau normal + Der Ladezustand der batterie %1 wird auf den normalen Wert zurückgesetzt + + + + Le niveau de charge de la batterie %1 est passé en dessous du niveau d'alerte + Der Ladezustand der batterie %1 ist unter den Alarmwert gefallen + + + + Le niveau de charge de la batterie %1 est passé au-dessus du niveau d'alarme (il est maintenant au niveau d'alerte uniquement) + Der Batterieladezustand %1 hat die Alarmstufe überschritten (jetzt nur noch die Alarmstufe) + + + + Le niveau de charge de la batterie %1 est passé en-dessous du niveau d'alarme + Der Ladezustand der batterie %1 ist unter den Alarmwert gesunken + + + + Evénement de type BATTERIES avec code de sous-type inconnu [%1] + BATTERIETYPEREIGNIS mit unbekanntem subtypcode [%1] + + + + Le niveau du réservoir %1 est repassé au niveau normal + Der tankstand %1 wird wieder auf den normalen Stand gebracht + + + + Le niveau du réservoir %1 est passé en dessous du niveau d'alerte + Der tankstand %1 ist unter die Alarmstufe gefallen + + + + Le niveau du réservoir %1 est passé au-dessus du niveau d'alarme (il est maintenant au niveau d'alerte uniquement) + Der tankstand %1 ist über die Alarmstufe gestiegen (jetzt nur noch auf Alarmstufe) + + + + Le niveau du réservoir %1 est passé en-dessous du niveau d'alarme + Das Niveau des Behälters %1 ist unter das Alarmniveau gegangen + + + + Evénement de type RESERVOIRS avec code de sous-type inconnu [%1] + Ereignis vom Typ RESERVOIRS mit unbekanntem subtypcode [%1] + + + + La consigne des ports USB est passée à %1 + Der USB-Port-Sollwert wurde auf %1 geändert + + + + L'état des ports USB est redevenu normal + Der Status der USB-Anschlüsse ist wieder normal + + + + Défaut détecté sur les ports USB + Fehler an USB-Anschlüssen erkannt + + + + Evénement de type USB avec code de sous-type inconnu [%1] + USB - Ereignis mit unbekanntem Subtyp-code [%1] + + + + Evénement de type INCONNU (avec code de sous-type [%1] + UNBEKANNTES typereignis (mit subtypcode [%1] + + + + home + + + Aucun circuit n'est configuré pour ce groupe...<br /><br />Si ce groupe n'a pas d'utilité, vous pouvez le supprimer dans le menu [Circuits] des Paramètres Avancés. + Für diese Gruppe ist keine Schaltung konfiguriert...<br /><br / > wenn diese Gruppe keine Verwendung hat, können Sie Sie im Menü [Schaltungen] der Erweiterten Einstellungen entfernen. + + + + Aucun capteur n'est configuré pour ce groupe...<br /><br />Si ce groupe n'a pas d'utilité, vous pouvez le supprimer dans le menu [Capteurs] des Paramètres Avancés. + Für diese Gruppe ist kein Sensor konfiguriert...<br /><br / > wenn diese Gruppe keine Verwendung hat, können Sie Sie im Menü [Sensoren] der Erweiterten Einstellungen entfernen. + + + + Aucun réservoir n'est configuré pour ce groupe...<br /><br />Si ce groupe n'a pas d'utilité, vous pouvez le supprimer dans le menu [Réservoirs] des Paramètres Avancés. + Für diese Gruppe ist kein Tank konfiguriert...<br /><br / > wenn diese Gruppe keine Verwendung hat, können Sie Sie im Menü [Tanks] der Erweiterten Einstellungen entfernen. + + + + Aucun parc de batterie n'est configuré pour ce groupe...<br /><br />Si ce groupe n'a pas d'utilité, vous pouvez le supprimer dans le menu [Batteries] des Paramètres Avancés. + Für diese Gruppe ist kein batteriepark konfiguriert...<br /><br / > wenn diese Gruppe keine Verwendung hat, können Sie Sie im Menü [Batterien] der Erweiterten Einstellungen entfernen. + + + + Cette page est actuellement en travaux. <br />Elle sera rendue disponible très rapidement à travers une mise à jour.<br /><br />Merci de votre patience...<br /><br />L'équipe ShipHeart + Diese Seite ist derzeit in Arbeit. <br / > Sie wird sehr schnell durch ein Update verfügbar gemacht.<br /><br / > Vielen Dank für Ihre Geduld...<br /> < br />das ShipHeart-Team + + + + + + Déconnecté + Offline + + + + Nombre de satellites visibles + Anzahl der sichtbaren Satelliten + + + + + Connecté + Verbunden + + + + + OFF + OFF + + + + + ON + ON + + + + Niveau + Niveau + + + + Actif + Aktiv + + + + Inactif + Inaktiv + + + + + + <b>%1</b> + <b > %1</b> + + + + Démarrage + Start + + + + Firmware de <b>ShipBase</b> + Firmware von < B>ShipBase< / b> + + + + Firmware du <b>ShipPower812</b> à l'adresse <b>%1</b> + Firmware des < B>ShipPower812< / b > unter <B > %1</b> + + + + Firmware du <b>ShipBS</b> à l'adresse <b>%1</b> + Firmware des < B > ShipBS< / b > unter <b > %1< / b> + + + + Firmware du <b>ShipPower4AC</b> à l'adresse <b>%1</b> + Firmware des < B>ShipPower4AC< / b > unter <B > %1</b> + + + + Firmware du <b>ShipPower8DC</b> à l'adresse <b>%1</b> + Firmware des < B>ShipPower8DC< / b > unter <B > %1</b> + + + + Firmware du module à l'adresse <b>%1</b> + Firmware des Moduls unter <B > %1< / b> + + + + Merci de patienter et de ne rien débrancher<br />avant la fin de la mise à jour. + Bitte warten Sie und trennen Sie nichts<br/>, bevor das Update abgeschlossen ist. + + + + Chargement des mises à jour effectué avec succès !<br /><br />L'activation des nouvelles version est en cours sur tous les modules concernés.<br /><br />Merci de patienter encore quelques secondes... + Laden von Updates erfolgreich durchgeführt !<br /><br / > die Aktivierung neuer Versionen ist auf allen betroffenen Modulen im Gange.<br /><br / > bitte warten Sie noch ein paar Sekunden... + + + + ShipHeart va redémarrer pour effectuer une mise à jour.<br /><br />Cette opération va prendre quelques minutes au maximum.<br />Merci de patienter et de ne rien débrancher jusqu'au redémarrage final... + ShipHeart wird neu gestartet, um ein Update durchzuführen.<br /><br / > Dieser Vorgang dauert höchstens einige Minuten.<br / > bitte warten Sie und trennen Sie nichts bis zum letzten Neustart... + + + + Votre système ShipHeart est dorénavant équipé de la version<br /><br /><b>%1</b><br /><br />(la version précédente était la %2) + Ihr ShipHeart-System ist jetzt mit der version<br /><br /><b>%1</b><br /><br />ausgestattet(die Vorherige version war %2) + + + + Le nombre de modules détectés sur le réseau ShipHeart est insuffisant par rapport à la configuration du bateau.<br /><br />Vérifiez les connexions entre le module <b>%1</b> à la <b>position @%2</b> %3 et le module <b>%4</b> suivant%5<br /><br />Vous pouvez visualiser l'état complet du réseau ShipHeart et les anomalies détectées dans le menu 'Réseau > ShipHeart' dans les Paramètres Avancés + Die Anzahl der im ShipHeart-Netzwerk erkannten Module ist im Vergleich zur Konfiguration des Bootes unzureichend.<br /> < br />überprüfen Sie die verbindungen zwischen dem Modul <b > %1</b > an der < B>position @%2< / B > %3 und dem folgenden Modul <b>%4</B>%5<br /> < br />Sie können den vollständigen Status des ShipHeart-Netzwerks und die erkannten Anomalien im Menü "Netzwerk > ShipHeart" in den Erweiterten Einstellungen anzeigen + + + + Le modules détecté en <b>position @%1</b> est un <b>%2</b>. Cela ne correspond pas à la configuration actuelle du bateau (<b>%3</b>).<br /><br />Cela peut provenir de l'ajout, de la suppression ou d'un déplacement de module.<br /><br />Vous pouvez visualiser toutes les anomalies détectées et les corriger dans le menu 'Réseau > ShipHeart' dans les Paramètres Avancés + Das Module erkannt in <b> position @%1</B>ist ein <b>%2</B>. Dies entspricht nicht der aktuellen Konfiguration des Bootes (<B > %3</b>).<br /><br / > Dies kann durch hinzufügen, entfernen oder verschieben eines Moduls entstehen.<br /><br / > Sie können alle erkannten Anomalien im Menü "Netzwerk > ShipHeart" in den Erweiterten Einstellungen anzeigen und beheben + + + + Code inconnu + Unbekannter Code + + + + home_accueil + + + Bienvenue à bord de + Willkommen an bord von + + + + home_suncy + + + L'accès au bateau est protégé. +Merci d'entrer votre code de déverrouillage pour y accéder... + Der Zugang zum Boot ist geschützt. + Bitte geben Sie Ihren Freischaltcode ein, um darauf zuzugreifen... + + + + journal_de_bord + + + + + + Tous + Alle + + + + Batteries + Batterien + + + + Capteurs + Sensoren + + + + Circuits + Schaltungen + + + + Réservoirs + Tanks + + + + Système + System + + + + Ports USB + USB-Anschlüsse + + + + Journal de bord + Logbuch + + + + Aucun type n'est configuré... + Es ist kein Typ konfiguriert... + + + + %1<br /><br /><br />%2 + %1<br / > <br / > <br / > %2 + + + + Aucune entrée d'historique n'est disponible pour cette sélection... + Für diese Auswahl sind keine Verlaufseinträge verfügbar... + + + + Toutes + Alle + + + + main + + + Type d'installation : +0 : ShipBase standard, +1 : écran déporté + Installationstyp: + 0: Standard ShipBase, + 1: Remote-Bildschirm + + + + + valeur + Wert + + + + Adresse IPv4 de ShipBase dans le cas d'une installation déportée + IPv4-Adresse von ShipBase bei einer Remote-installation + + + + xxx:xxx:xxx:xxx + xxx: xxx: xxx: xxx + + + + Taille de l'écran en pouces : +7, +10 (ShipBase standard), +22 + Bildschirmgröße in Zoll: + 7, + 10 (Standard ShipBase), + 22 + + + + Original + Original + + + + Sombre + Dunkel + + + + Métallique + Metallisch + + + + Triangles + Dreiecke + + + + Sable + Sand + + + + Thème 5 + Thema 5 + + + + Thème 6 + Thema 6 + + + + Thème 7 + Thema 7 + + + + Thème 8 + Thema 8 + + + + page_personnalisee + + + <i>--- Circuit non affecté ---</i> + <i>--- Stromkreis nicht betroffen ---</i> + + + + [renfort] + [Verstärkung] + + + + <i>--- Aucune batterie affectée ---</i> + <i>--- Keine Batterie betroffen ---</i> + + + + parametres + + + Paramètres + Einstellungen + + + + Langue + Sprache + + + + Températures + Temperaturen + + + + Volumes + Volumen + + + + Affichage + Anzeige + + + + Date et heure + Datum und Uhrzeit + + + + Protection + Schutz + + + + Son + Seine + + + + Luminosité + Helligkeit + + + + Economiseur d'écran : désactivé + Bildschirmschoner: deaktiviert + + + + Economiseur d'écran : normal + Bildschirmschoner: normal + + + + Flash LEDs : désactivé + Flash-LEDs: deaktiviert + + + + Flash LEDs : normal + Flash-LEDs: normal + + + + Nettoyage de l'écran + Bildschirmreinigung + + + + Heure d'été + Sommerzeit + + + + Heure d'hiver + Winterzeit + + + + Verrouiller le bateau + Schloss das Boot + + + + parametres_avances + + + Paramètres avancés + Erweiterte Einstellungen + + + + Réseaux + Netzwerke + + + + Cette page est actuellement en travaux. <br />Elle sera rendue disponible très rapidement à travers une mise à jour.<br /><br />Merci de votre patience...<br /><br />L'équipe ShipHeart + Diese Seite ist derzeit in Arbeit. <br / > Sie wird sehr schnell durch ein Update verfügbar gemacht.<br /><br / > Vielen Dank für Ihre Geduld...<br /> < br />das ShipHeart-Team + + + + Circuits + Schaltungen + + + + Réservoirs + Tanks + + + + Batteries + Batterien + + + + Capteurs + Sensoren + + + + Menu accueil + Home-Menü + + + + Evènements + Veranstaltungen + + + + ShipHeart + ShipHeart + + + + Ethernet & Wifi + Ethernet & Wifi + + + + One Wire + One Wire + + + + NMEA 2000 + NMEA 2000 + + + + J1939 + J1939 + + + + DMX + DMX + + + + Journal de bord + Logbuch + + + + Vos paramètres + Ihre Einstellungen + + + + Votre installation + Ihre installation + + + + Système + System + + + + Affichage + Anzeige + + + + Audio + Audio + + + + Ship2net + Ship2net + + + + Accès au paramètres + Zugriff auf die Einstellungen + + + + Configuration ShipRS + ShipRS-Konfiguration + + + + Installation + Installation + + + + Version + Version + + + + Accès réservé Koriolan + Koriolan reservierter Zugang + + + + Spécifique Suncy + Spezifische Suncy + + + + protection + + + Accès protégé + Geschützter Zugang + + + + L'accès aux paramètres avancés est protégé. +Merci d'entrer le code de déverrouillage pour y accéder... + Der Zugriff auf erweiterte Einstellungen ist geschützt. + Bitte geben Sie den Freischaltcode ein, um darauf zuzugreifen... + + + + Mode administrateur validé<br />Entrer votre code dédié + Validierter Administratormodus<br / > geben Sie Ihren dedizierten code Ein + + + + reservoir + + + [ %1 % ] + [ %1 % ] + + + + Le module assurant la supervision de ce réservoir n'est pas accessible !<br /><br />Si des ajouts/suppression/déplacements de modules ont eu lieu récemment, mettez à jour la configuration correspondant dans le menu MODULES de PARAMETRES AVANCES.<br /><br />Dans le cas où aucune modification n'a été effectuée récemment, vérifier les connexions de tous les modules. + Das Modul zur überwachung dieses Tanks ist nicht zugänglich !<br /><br/ > wenn in letzter Zeit Module Hinzugefügt/entfernt / verschoben wurden, aktualisieren Sie die entsprechende Konfiguration im MENÜ Module der VORAUSEINSTELLUNGEN.<br /> < br />falls in letzter Zeit keine änderungen vorgenommen wurden, überprüfen Sie die Anschlüsse aller Module. + + + + Niveau + Niveau + + + + La valeur lue sur les electrodes plongées de ce réservoir est incohérente.<br />Vérifier l'ordre de cablage des électrodes sur les entrées auxiliaires à l'arrière de ShipBase. + Der Wert, der von den tauchelektroden dieses Tanks gelesen wird, ist inkonsistent.< br />Überprüfen Sie die kabelreihenfolge der Elektroden an den hilfseingängen auf der Rückseite von ShipBase. + + + + Aucune donnée n'est disponible pour cette période + Für diesen Zeitraum sind keine Daten verfügbar + + + + shipheart_test_config + + + Vitesse de test de l'écran + Bildschirm test Geschwindigkeit + + + + Nombre de colonnes de test du touchpad + Anzahl der touchpad - testspalten + + + + Nombre de lignes de test du touchpad + Anzahl der touchpad - testzeilen + + + + shipheart_test_home + + + Tests matériel + Hardware-Tests + + + + Configuration des tests + Einrichten von tests + + + + Test du backlight + Testen des hintergrundlichts + + + + Test de l'écran + Bildschirm testen + + + + Test du touchpad + Touchpad-Test + + + + Liste des fonts disponibles + Liste der verfügbaren Schriftarten + + + + shipheart_test_liste_fonts + + + Liste des fonts disponibles + Liste der verfügbaren Schriftarten + + + + test_batterie + + + Batteries de servitude + Bondage-Batterien + + + + Autonomie optimale + Optimale Autonomie + + + + Autonomie actuelle + Aktuelle Autonomie + + + + Autonomie<br />maximale + Maximale Autonomie<br /> + + + + dans + in + + + + environ + ungefähr + + + + test_tri_liste + + + TEST DE TRI DE LISTE + TEST DE TRI DE LISTE + + + diff --git a/shipheart_en_EN.qm b/shipheart_en_EN.qm new file mode 100755 index 0000000..66996b4 Binary files /dev/null and b/shipheart_en_EN.qm differ diff --git a/shipheart_en_EN.ts b/shipheart_en_EN.ts new file mode 100755 index 0000000..499d099 --- /dev/null +++ b/shipheart_en_EN.ts @@ -0,0 +1,5516 @@ + + + + + Shipheart_boite_dialogue + + + OK + OK + + + + Annuler + Cancel + + + + Plus tard + Later on + + + + Shipheart_boite_dialogue_action_circuit + + + Action à appliquer au circuit lorsque l'évènement se déclenche : + Action to be applied to the circuit when the event is triggered : + + + + Aucune + No + + + + Le circuit <b>bascule</b> + The <b>toggle</b> circuit + + + + [passe à <b>ON</b> s'il est <b>OFF</b><br /> ou à <b>OFF</b> s'il est <b>ON</b>] + [changes to <b>ON</b> if <b>OFF</b><br /> or <b>OFF</b> if <b>ON</b>] + + + + OFF + OFF + + + + ON + ON + + + + Annuler + Cancel + + + + Shipheart_boite_dialogue_affichage_duree + + + Ok + Ok + + + + Shipheart_boite_dialogue_condition_horaire + + + OK + OK + + + + Annuler + Cancel + + + + Supprimer + Delete + + + + Aube nautique + Nautical dawn + + + + Lever du soleil + Sunrise + + + + Zénith + Zenith + + + + Coucher du soleil + Sunset + + + + Crépuscule nautique + Nautical twilight + + + + Shipheart_boite_dialogue_entrees_aux + + + Entrées Auxiliaires + Auxiliary inputs + + + + Affectation de l'entrée n° %1 du %2 + Assignment of input no. %1 of %2 + + + + Annuler + Cancel + + + + Shipheart_boite_dialogue_entrees_level_sensor + + + Entrées Level Sensor + Level Sensor inputs + + + + Affectation de l'entrée du réservoir + Tank inlet assignment + + + + Annuler + Cancel + + + + Shipheart_boite_dialogue_liste_alarmes + + + Ok + Ok + + + + Shipheart_boite_dialogue_minuteur + + + Heures + Hours + + + + Minutes + Minutes + + + + Secondes + Seconds + + + + Annuler + Cancel + + + + Démarrer + Start + + + + Shipheart_boite_dialogue_nettoyage_ecran + + + Nettoyage de l'écran + Screen cleaning + + + + 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. + The screen is currently frozen to allow you to clean it without the risk of triggering unwanted actions.<br /><br />Hold the button below for more than %1 seconds to exit this mode. + + + + Sortie + Output + + + + Shipheart_boite_dialogue_reveils + + + Annuler + Cancel + + + + Enregistrer + Save + + + + Shipheart_boite_dialogue_validation_securisee + + + OK + OK + + + + Annuler + Cancel + + + + --- + + + + + Shipheart_bouton_circuit + + + + + Off + Off + + + + + On + On + + + + batterie + + + + Aucune consommation d'énergie sur cette période... + No energy consumption during this period... + + + + Aucune donnée n'est disponible pour cette période + No data available for this period + + + + Le module assurant la supervision de cette batterie n'est pas accessible !<br /><br />Si des ajouts/suppression/déplacements de modules ont eu lieu récemment, mettez à jour la configuration correspondant dans le menu MODULES de PARAMETRES AVANCES.<br /><br />Dans le cas où aucune modification n'a été effectuée récemment, vérifier les connexions de tous les modules. + The module monitoring this battery is not accessible!<br /><br />If modules have been added/deleted/moved recently, update the corresponding configuration in the MODULES menu of ADVANCED PARAMETERS. <br /><br />In case no modifications have been made recently, check the connections of all modules. + + + + capteur + + + Max + Max + + + + Moyen + Medium + + + + Min + Min + + + + Delta (Max - Min) + Delta (1h) + Delta (Max - Min) + + + + Aucune donnée n'est disponible pour cette période + No data available for this period + + + + La sonde One Wire correspondant à ce capteur n'est pas accessible.<br />Vérifier son câblage entre le port One Wire à l'arrière de ShipBase et la sonde. + The One Wire probe corresponding to this sensor is not accessible.<br />Check the wiring between the One Wire port on the back of ShipBase and the probe. + + + + Le module assurant la supervision de ce capteur n'est pas accessible !<br /><br />Si des ajouts/suppression/déplacements de modules ont eu lieu récemment, mettez à jour la configuration correspondant dans le menu MODULES de PARAMETRES AVANCES.<br /><br />Dans le cas où aucune modification n'a été effectuée récemment, vérifier les connexions de tous les modules. + The module monitoring this sensor is not accessible!<br /><br />If modules have been added/deleted/moved recently, update the corresponding configuration in the MODULES menu of ADVANCED PARAMETERS.<br /><br />If no changes have been made recently, check the connections of all modules. + + + + La sonde One Wire du capteur est détectée en défaut.<br />Vérifier son câblage depuis l'arrière de ShipBase. + The sensor's One Wire probe is detected as faulty.<br />Check its wiring from the back of ShipBase. + + + + Le capteur n'a pas reçu de mise à jour sur le réseau NMEA depuis<br />%1<br />Les données affichées sont donc probablement obsolètes. + The sensor has not received an update on the NMEA network since<br />%1<br />The data displayed is therefore likely to be out of date. + + + + circuit + + + + + + Off + Off + + + + + On + On + + + + On +%1% + On +%1% + + + + Aucune donnée n'est disponible pour cette période + No data available for this period + + + + Aucune consommation d'énergie sur cette période... + No energy consumption during this period... + + + + Le module assurant le pilotage de ce circuit n'est pas accessible !<br /><br />Si des ajouts/suppression/déplacements de modules ont eu lieu récemment, mettez à jour la configuration correspondant dans le menu [Réseau ShipHeart] de [Paramètres Avancés].<br /><br />Dans le cas où aucune modification n'a été effectuée récemment, vérifier les connexions de tous les modules. + The module controlling this circuit is not accessible!<br /><br />If modules have been added/deleted/moved recently, update the corresponding configuration in the [ShipHeart Network] menu of [Advanced Settings].<br /><br />In case no changes have been made recently, check the connections of all modules. + + + + Ce circuit est configuré comme <i>Non Affecté</i> et n'est donc pas accessible !<br /><br />Pour accéder à nouveau à ce circuit, merci de l'affecter à un circuit disponible dans le menu [Circuits] de [Paramètres Avancés]. + This circuit is configured as <i>Unassigned</i> and is therefore not accessible!<br /><br />To access this circuit again, please assign it to a circuit available in the menu [Circuits] of [Advanced Settings]. + + + + Non défini + Undefined + + + + Le module pilotant ce circuit n'est pas alimentée correctement. + Vérifier l'alimentation correspondante. + The module driving this circuit is not powered correctly. + Check the corresponding power supply. + + + + Le module pilotant ce circuit est en mode MANUEL. + Repositionnez le module en mode AUTO pour commander à nouveau ce circuit normalement. + The module controlling this circuit is in MANUAL mode. + Put the module back in AUTO mode to control this circuit normally. + + + + Le port USB du bas est en défaut. + The bottom USB port is faulty. + + + + Le port USB du milieu est en défaut. + The middle USB port is faulty. + + + + Les 2 ports USB du milieu et du bas sont en défaut. + The 2 USB ports in the middle and bottom are faulty. + + + + Le port USB du haut est en défaut. + The top USB port is faulty. + + + + Les 2 ports USB du haut et du bas sont en défaut. + The 2 USB ports on the top and bottom are faulty. + + + + Les 2 ports USB du haut et du milieu sont en défaut. + The top and middle 2 USB ports are faulty. + + + + Les 3 ports USB du haut, du milieu et du bas sont en défaut. + The top, middle and bottom 3 USB ports are faulty. + + + + Le port USB est en défaut. + The USB port is faulty. + + + + L'alimentation du circuit a été coupée + car sa limite de courant (%1 A) + a été dépassée. + The power supply to the circuit has been cut off + because its current limit (%1 A) + has been exceeded. + + + + L'alimentation du circuit a été coupée + car les circuits de protection interne ont détecté une anomalie. + The power supply to the circuit has been cut off + because the internal protection circuits have detected an anomaly. + + + + L'alimentation du circuit a été coupée + car le seuil de disjonction du circuit a été dépassé. + The power supply to the circuit has been cut off + because the circuit break threshold has been exceeded. + + + + Le circuit est en court-circuit avec le + batterie. + The circuit is short-circuited with the + battery. + + + + L'alimentation du circuit a été coupée<br />car la consommation totale du module a dépassé %1 A pendant plus de %2 secondes (limite du module) + The power supply to the circuit has been cut off<br />because the total consumption of the module has exceeded %1 A for more than %2 seconds (module limit) + + + + La tension du circuit est anormalement basse. + Circuit voltage is abnormally low. + + + + La phase et le neutre sont inversés sur ce circuit. + Phase and neutral are reversed on this circuit. + + + + DANGER : Le neutre n'est pas référencé à la terre sur ce circuit ("absence de terre"). + DANGER : la terre est absente de ce circuit. + DANGER: The neutral is not referenced to earth on this circuit (‘no earth’). + + + + La masse est absente du connecteur d'alimentation du module + No ground on module power connector + + + + Evènements actuellement actifs qui sont susceptibles de commander ce circuit : + Currently active events that may control this circuit: + + + + + + Etat inconnu... + State unknown... + + + + config_acces_parametres + + + Configuration de l'accès aux paramètres avancés + Configuring access to advanced settings + + + + Durée de maintien de l'accès + Duration of access + + + + Nouveau code + New code + + + + Code d'accès + Access code + + + + Répéter le code d'accès + Repeat access code + + + + Enregistrer + Save + + + + Aucune (saisie du code à chaque accès) + None (code entry at each access) + + + + 1 minute + 1 minute + + + + 5 minutes + 5 minutes + + + + 15 minutes + 15 minutes + + + + 1 heure + 1 hour + + + + Infinie (aucune protection des paramètres avancés) + Infinite (no advanced settings protection) + + + + Les deux valeurs saisies doivent être identiques ! + +De plus, le code doit contenir : +- %1 chiffres au minimum +- %2 chiffres au maximum. + The two values entered must be identical! + +In addition, the code must contain : +- %1 digits minimum +- %2 digits maximum. + + + + Le nouveau code doit contenir : +- %1 chiffres au minimum +- %2 chiffres au maximum. + +Le code saisi ne répond pas à ces critères et sa mise à jour n'est donc pas effectuée. + +Merci de saisir un code au format valide si vous souhaitez le modifier. + The new code must contain : +- %1 digits minimum +- %2 digits maximum. + +If the code you have entered does not meet these criteria, it will not be updated. + +Please enter a valid code if you wish to change it. + + + + config_affichage + + + Configuration de l'affichage + Display configuration + + + + Nom du bateau + Boat name + + + + Fuseau horaire + Time zone + + + + Temporisaton économiseur d'écran + Screen saver timer + + + + Thème d'affichage + Display theme + + + + Enregistrer + Save + + + + UTC-12 (Yankee) + UTC-12 (Yankee) + + + + UTC-11 (X-Ray) + UTC-11 (X-Ray) + + + + UTC-10 (Whisky) + UTC-10 (Whisky) + + + + UTC-9 (Victor) + UTC-9 (Victor) + + + + UTC-8 (Uniform) + UTC-8 (Uniform) + + + + UTC-7 (Tango) + UTC-7 (Tango) + + + + UTC-6 (Sierra) + UTC-6 (Sierra) + + + + UTC-5 (Romeo) + UTC-5 (Romeo) + + + + UTC-4 (Quebec) + UTC-4 (Quebec) + + + + UTC-3 (Papa) + UTC-3 (Dad) + + + + UTC-2 (Oscar) + UTC-2 (Oscar) + + + + UTC-1 (November) + UTC-1 (November) + + + + UTC (Zoulou) + UTC (Zulu) + + + + UTC+1 (Alpha) + UTC+1 (Alpha) + + + + UTC+2 (Bravo) + UTC+2 (Bravo) + + + + UTC+3 (Charlie) + UTC+3 (Charlie) + + + + UTC+4 (Delta) + UTC+4 (Delta) + + + + UTC+5 (Echo) + UTC+5 (Echo) + + + + UTC+6 (Foxtrot) + UTC+6 (Foxtrot) + + + + UTC+7 (Golf) + UTC+7 (Golf) + + + + UTC+8 (Hotel) + UTC+8 (Hotel) + + + + UTC+9 (India) + UTC+9 (India) + + + + UTC+10 (Kilo) + UTC+10 (Kilo) + + + + UTC+11 (Lima) + UTC+11 (Lima) + + + + UTC+12 (Mike) + UTC+12 (Mike) + + + + 15 secondes + 15 seconds + + + + 30 secondes + 30 seconds + + + + 1 minute + 1 minute + + + + 3 minutes + 3 minutes + + + + 10 minutes + 10 minutes + + + + Aucune limite + No limits + + + + config_audio + + + Configuration audio + Audio configuration + + + + Bips de clic + Click beeps + + + + Fonctionnement de la sortie Audio + Audio output operation + + + + Enregistrer + Save + + + + Aucun bip + No beep + + + + Bip par défaut + Default beeper + + + + Bip 2 + Beep 2 + + + + Bip 3 + Beep 3 + + + + Bip 4 + Beep 4 + + + + Bip 5 + Beep 5 + + + + Bip 6 + Beep 6 + + + + Bip 7 + Beep 7 + + + + Bip 8 + Beep 8 + + + + Bip 9 + Beep 9 + + + + Bip 10 + Beep 10 + + + + Bip 11 + Beep 11 + + + + Bip 12 + Beep 12 + + + + Bip 13 + Beep 13 + + + + Bip 14 + Beep 14 + + + + Le son de ShipBase est coupé. Le son est uniquement diffusé sur la sortie AUDIO + The ShipBase sound is muted. Sound is only output on the AUDIO + + + + Le son est diffusé sur ShipBase et sur la sortie AUDIO + Sound is broadcast to ShipBase and the AUDIO output + + + + config_batterie + + + Nom de la batterie + Battery name + + + + Tension nominale + Rated voltage + + + + Créer la batterie + Create the battery + + + + Enregistrer + Save + + + + Supprimer + Delete + + + + + Confirmer + Confirm + + + + Etalonner + Etalonnage + Calibrate + + + + + Non défini + Undefined + + + + Création d'un parc de batteries + Creation of a battery bank + + + + Configuration du parc de batteries + Battery bank configuration + + + + Groupe de batteries + Battery pack + + + + Point de mesure + Measuring point + + + + Type de batterie(s) + Battery type(s) + + + + La modification du <b>type</b> de batterie(s) va nécessiter la remise en <i>configuration usine</i> de certains paramètres.<br /><br />Si vous ne souhaitez pas que cette reconfiguration soit effectuée, notamment si vous avez effectué des réglages spécifiques, cliquez sur ANNULER. <br /><br />Sinon, cliquez sur CONFIRMER pour valider le changement. + Changing the <b>type</b> of battery(s) will require resetting certain parameters to <i>factory configuration</i>.<br /><br />If you do not want this reconfiguration is carried out, especially if you have made specific settings, click on CANCEL. <br /><br />Otherwise, click CONFIRM to validate the change. + + + + La modification de la <b>tension nominale</b> du parc de batteries va nécessiter la remise en <i>configuration usine</i> de certains paramètres.<br /><br />Si vous ne souhaitez pas que cette reconfiguration soit effectuée, notamment si vous avez effectué des réglages spécifiques, cliquez sur ANNULER. <br /><br />Sinon, cliquez sur CONFIRMER pour valider le changement. + Changing the <b>nominal voltage</b> of the battery bank will require resetting certain parameters to <i>factory configuration</i>.<br /><br />If you do not want this reconfiguration is carried out, especially if you have made specific settings, click on CANCEL. <br /><br />Otherwise, click CONFIRM to validate the change. + + + + Capacité + capacity + + + + + Ah + Ah + + + + Masquer les paramètres avancés + Hide advanced settings + + + + Afficher les paramètres avancés + Show advanced settings + + + + Coefficient correcteur d'entrée de tension + Voltage input correction coefficient + + + + + + + + + Caractéristiques du parc de batteries + Battery bank characteristics + + + + Durée correspondant à la capacité + Duration corresponding to capacity + + + + + h + h + + + + Capacité 2 + Capacity 2 + + + + Durée de capacité 2 + Capacity Duration 2 + + + + Coefficient de Peukert + Peukert coefficient + + + + Résistance interne + Internal resistance + + + + mΩ + mΩ + + + + Soh actuel + Current Soh + + + + % + % + + + + Paramètres de pleine charge + Full Load Settings + + + + Tension mini pleine charge + Minimum full load voltage + + + + + V + V + + + + Courant maxi pleine charge + Maximum full load current + + + + A + A + + + + Temporisation pleine charge + Full load delay + + + + + s + s + + + + Efficacité de charge + Charging efficiency + + + + Caractéristiques de charge nulle + Zero Load Characteristics + + + + Tension de détection charge nulle + Zero load detection voltage + + + + Temporisation charge nulle + Zero load delay + + + + Alimentation %1 + Power supply %1 + + + + 48V + 48V + + + + Cette batterie est utilisée par l'évènement ci-dessous.<br />Vous devez modifier ou supprimer cet évènement pour qu'il ne dépende plus de cette batterie avant de pouvoir la supprimer. + This battery is used by the event below.<br />You must modify or delete this event so that it no longer depends on this battery before you can delete it. + + + + Cette batterie est utilisée par les %1 évènements ci-dessous.<br />Vous devez modifier ou supprimer ces évènements pour qu'ils ne dépendent plus de cette batterie avant de pouvoir la supprimer. + This battery is used by the %1 events below.<br />You must modify or delete these events so that they no longer depend on this battery before you can delete it. + + + + Cette batterie est utilisée par le capteur calculé ci-dessous.<br />Vous devez modifier ou supprimer ce capteur calculé pour qu'il ne dépende plus de cette id_batterie avant de pouvoir la supprimer. + This battery is used by the calculated sensor below.<br />You must modify or delete this calculated sensor so that it no longer depends on this battery id before you can delete it. + + + + Cette id_batterie est utilisée par les %1 capteurs calculés ci-dessous.<br />Vous devez modifier ou supprimer ces capteurs calculés pour qu'ils ne dépendent plus de cette id_batterie avant de pouvoir la supprimer. + This battery id is used by the %1 sensors calculated below.<br />You must modify or delete these calculated sensors so that they no longer depend on this battery id before you can delete it. + + + + Ok + Ok + + + + Historique + Historical + + + + Nombre de cycles de charge + Number of charge cycles + + + + Nombre de décharges complètes + Number of complete discharges + + + + Forcer Pleine Charge + Force Full Load + + + + Réinitialiser SOH + Reset SOH + + + + Réinitialiser Compteurs + Reset Counters + + + + ShipBS [@ %1] + ShipBS [@ %1] + + + + Entrée VOLT n° %1 + VOLT input n° %1 + + + + Plomb - Acide liquide + Lead - Liquid acid + + + + Plomb - AGM / VRLA + Lead - AGM / VRLA + + + + Plomb - Gel + Lead - Gel + + + + Plomb - Carbone + Lead - Carbon + + + + Lithium + Lithium + + + + Non définie + Not defined + + + + 12V + 12V + + + + 24V + 24V + + + + config_batteries + + + Configuration des batteries + Battery configuration + + + + Aucune batterie n'est encore configurée... + No battery is configured yet... + + + + + + + + + + + config_capteur + + + Création d'un capteur + Sensor creation + + + + Configuration du capteur + Sensor configuration + + + + Nom du capteur + Sensor name + + + + Type de capteur + Sensor type + + + + Module + Module + + + + Affectation + Assignment + + + + %1 : Non définie + %1 : Not defined + + + + %1 : %2 + %1 : %2 + + + + Mode du capteur + Sensor mode + + + + Groupe de capteurs + Sensor group + + + + Libellé du capteur pour la valeur %1 + Sensor label for value %1 + + + + + + + Non défini + Undefined + + + + Entrées Auxiliaires (AUX INPUTS) + Auxiliary inputs (AUX INPUTS) + + + + Entrées Niveau (LEVEL SENSORS) + Level inputs (LEVEL SENSORS) + + + + Entrées Tension (VOLTAGE INPUTS) + VOLTAGE INPUTS + + + + Capteurs de température (ONE WIRE) + Temperature sensors (ONE WIRE) + + + + Entrées NMEA2000 + NMEA2000 inputs + + + + Capteurs sur modules + Sensors on modules + + + + Calculé (conditions logiques) + Calculated (logical conditions) + + + + + <i>Entrée non utilisée</i> + <i>Input not used</i> + + + + Pression Atmosphérique + Atmospheric pressure + + + + + + Température module + Module temperature + + + + + Tension d'entrée module + Module input voltage + + + + Consommation module + Module consumption + + + + Consommation ports USB + USB port consumption + + + + Chocs + Shocks + + + + Accélération X + X acceleration + + + + Accélération Y + Y acceleration + + + + Accélération Z + Z acceleration + + + + GNSS - SOG<br />Speed Over Ground + GNSS - SOG<br />Speed Over Ground + + + + GNSS - COG<br />Course Over Ground + GNSS - COG<br />Course Over Ground + + + + GNSS - SIV<br />Satellites In View + GNSS - SIV<br />Satellites In View + + + + GNSS - HPA<br />Horizontal Precision Accuracy + GNSS - HPA<br />Horizontal Precision Accuracy + + + + GNSS - VPA<br />Vertical Precision Accuracy + GNSS - VPA<br />Vertical Precision Accuracy + + + + Modem 4G/LTE - RSSI<br />Received Signal Strength Indicator + 4G/LTE Modem - RSSI<br />Received Signal Strength Indicator + + + + Modem 4G/LTE - SINR<br />Signal to Interference & Noise Ratio + 4G/LTE Modem - SINR<br />Signal to Interference & Noise Ratio + + + + Normal + Normal + + + + Inversé + Inverted + + + + Tension 0 - 10 V + Voltage 0 - 10 V + + + + Résistance 0 - 500 Ohms + Resistance 0 - 500 Ohms + + + + Courant 4 - 20 mA + Current 4 - 20 mA + + + + Défaut d'isolement + Insulation fault + + + + Ce capteur est utilisé par l'évènement ci-dessous.<br />Vous devez modifier ou supprimer cet évènement pour qu'il ne dépende plus de ce capteur avant de pouvoir le supprimer. + This sensor is used by the event below.<br />You must modify or delete this event so that it no longer depends on this sensor before you can delete it. + + + + Ce capteur est utilisé par les %1 évènements ci-dessous.<br />Vous devez modifier ou supprimer ces évènements pour qu'ils ne dépendent plus de ce capteur avant de pouvoir le supprimer. + This sensor is used by the %1 events below.<br />You must modify or delete these events so that they no longer depend on this sensor before you can delete it. + + + + Ce capteur est utilisé par le capteur calculé ci-dessous.<br />Vous devez modifier ou supprimer ce capteur calculé pour qu'il ne dépende plus de ce capteur avant de pouvoir le supprimer. + This sensor is used by the calculated sensor below.<br />You must modify or delete this calculated sensor so that it no longer depends on this sensor before you can delete it. + + + + Ce capteur est utilisé par les %1 capteurs calculés ci-dessous.<br />Vous devez modifier ou supprimer ces capteurs calculés pour qu'ils ne dépendent plus de ce capteur avant de pouvoir le supprimer. + This sensor is used by the %1 calculated sensors below.<br />You must modify or delete these calculated sensors so that they no longer depend on this sensor before you can delete it. + + + + Masquer sur la page Capteurs + Hide on Sensors page + + + + Créer le capteur + Create sensor + + + + Enregistrer + Save + + + + Equation + Equation + + + + Supprimer + Delete + + + + Etalonner + Calibrate + + + + Humidité + Humidity + + + + GNSS - Latitude + GNSS - Latitude + + + + GNSS - Longitude + GNSS - Longitude + + + + GNSS - Altitude + GNSS - Altitude + + + + config_capteur_calcule_booleen + + + Equation du capteur calculé [%1] + Calculated sensor equation [%1] + + + + Enregistrer + Save + + + + Supprimer + Delete + + + + Le nombre de conditions par capteur est limité à %1.<br /><br />Vous ne pouvez pas ajouter de groupe ou de nouvelle condition avant d'en avoir supprimé préalablement. + The number of conditions per sensor is limited to %1.<br /><br />You can't add a group or a new condition until you've deleted one. + + + + Des modifications ont été apportées au capteur<br />mais n'ont pas été enregistrées.<br /><br />Cliquer sur ANNULER pour revenir au menu en cours.<br /><br />Cliquer sur Ok pour sortir sans enregistrer. + Changes have been made to the sensor<br />but have not been saved.<br /><br />Click on CANCEL to return to the current menu.<br /><br />Click on Ok to exit without saving. + + + + est actif + is active + + + + est inactif + is inactive + + + + Ou + Or + + + + Et + And + + + + X-Ou + X-Ou + + + + config_capteur_calcule_booleen_condition + + + Création d'une condition du capteur [%1] + Creation of a sensor condition [%1] + + + + Type + Type + + + + Source + Source + + + + Variable + Variable + + + + Test + Test + + + + Seuil + Threshold + + + + Créer la condition + Create condition + + + + Enregistrer + Save + + + + + + + Non défini + Undefined + + + + Circuit + Circuit + + + + Capteur + Sensor + + + + Réservoir + Tank + + + + Batterie + Battery + + + + Actif + Assets + + + + Inactif + Inactive + + + + &lt; au seuil + &lt; at the threshold + + + + &le; au seuil + &le; at the threshold + + + + = au seuil + = at threshold + + + + &ge; au seuil + at the threshold + + + + &gt; au seuil + &gt; at the threshold + + + + config_capteurs + + + Configuration des capteurs + Sensor configuration + + + + Aucun capteur n'est encore configuré... + No sensor is configured yet... + + + + + + + + + + + config_circuit + + + Configuration du circuit + Circuit configuration + + + + Nom du circuit + Circuit name + + + + Affectation + Assignment + + + + Circuit renfort + Reinforcement circuit + + + + Mode de commande + Control mode + + + + Vitesse de démarrage/arrêt + Start/stop speed + + + + Seuil de disjonction + Tripping threshold + + + + Vitesse de disjonction + Disjunction speed + + + + Filtrage du courant consommé + Current filtering + + + + Masquer sur la page d'accueil + Hide on home page + + + + Créer le circuit + Create circuit + + + + Enregistrer + Save + + + + L'affectation du circuit vient d'être modifiée alors que le circuit était actif. +Avant d'effectuer ce changement, le circuit a été passé sur OFF. + +Pensez à le réactiver si besoin... + The circuit assignment has been changed while the circuit was active. +Before making this change, the circuit was switched OFF. + +Remember to reactivate it if necessary... + + + + Supprimer + Delete + + + + Aucun + No + + + + ShipPower812 [@ %1] + ShipPower812 [@ %1] + + + + ShipPower4AC [@ %1] + ShipPower4AC [@ %1] + + + + ShipPower8DC [@ %1] + ShipPower8DC [@ %1] + + + + + Circuit %1 + Circuit %1 + + + + Groupe de circuits + Groupe de circuit + Circuit groups + + + + Commande impulsionnelle + Pulse control + + + + + %1 - %2 + %1 - %2 + + + + Non affecté + Unallocated + + + + On-Off + On-Off + + + + On-Off progressif + On-Off progressive + + + + Variateur + Dimmer switch + + + + Aucun filtrage + No filtering + + + + Très faible + Very low + + + + Faible + Low + + + + Moyen + Medium + + + + Elevé + High + + + + Très élevé + Very high + + + + + Très rapide + Very fast + + + + + Rapide + Fast + + + + + Moyenne + Average + + + + + Lente + Slow + + + + + Très lente + Very slow + + + + Non + No + + + + 1 seconde + 1 second + + + + 2 secondes + 2 seconds + + + + 5 secondes + 5 seconds + + + + Ce circuit est utilisé pour la commande du moteur.<br />Vous devez d'abord affecter la commande moteur à un autre circuit avant de pouvoir supprimer celui-ci. + This circuit is used for motor control.<br />You must first assign motor control to another circuit before you can delete this one. + + + + Ce circuit est utilisé par l'évènement ci-dessous.<br />Vous devez modifier ou supprimer cet évènement pour qu'il ne dépende plus de ce circuit avant de pouvoir le supprimer. + This circuit is used by the event below.<br />You must modify or delete this event so that it no longer depends on this circuit before you can delete it. + + + + Ce circuit est utilisé par les %1 évènements ci-dessous.<br />Vous devez modifier ou supprimer ces évènements pour qu'ils ne dépendent plus de ce circuit avant de pouvoir le supprimer. + This circuit is used by the %1 events below.<br />You must modify or delete these events so that they no longer depend on this circuit before you can delete it. + + + + Ce circuit est utilisé par le capteur calculé ci-dessous.<br />Vous devez modifier ou supprimer ce capteur calculé pour qu'il ne dépende plus de ce circuit avant de pouvoir le supprimer. + This circuit is used by the calculated sensor below.<br />You must modify or delete this calculated sensor so that it no longer depends on this circuit before you can delete it. + + + + Ce circuit est utilisé par les %1 capteurs calculés ci-dessous.<br />Vous devez modifier ou supprimer ces capteurs calculés pour qu'ils ne dépendent plus de ce circuit avant de pouvoir le supprimer. + This circuit is used by the %1 calculated sensors below.<br />You must modify or delete these calculated sensors so that they no longer depend on this circuit before you can delete it. + + + + 15 secondes + 15 seconds + + + + 30 secondes + 30 seconds + + + + 45 secondes + 15 seconds {45 ?} + + + + 1 minute + 1 minute + + + + 5 minutes + 5 minutes + + + + 15 minutes + 15 minutes + + + + 1 heure + 1 hour + + + + 4 heures + 4 hours + + + + L'utilisation d'un circuit de renfort rend l'utilisation du mode de commande [Variateur] impossible.<br /><br />Le mode de commande vient donc d'être ramené à [On-Off Progressif]. + The use of a reinforcement circuit makes it impossible to use the [Dimmer] control mode.<br /><br />The control mode has therefore been changed back to [On-Off Progressive]. + + + + config_circuits + + + Configuration des circuits + Circuit configuration + + + + Pack de batteries : + Battery pack : + + + + Aucun capteur n'est encore configuré... + No sensor is configured yet... + + + + Oui + Yes + + + + Non + No + + + + Le module n'est affecté à aucune batterie... + The module is not assigned to any battery... + + + + Circuit non utilisé + Circuit not used + + + + Circuits Non Affectés + Unaffected Circuits + + + + Ce circuit est configuré comme renfort du circuit <b>%1</b> et ne peut donc pas être configuré individuellement.<br /><br />Merci de cliquer sur le circuit <b>%1</b> de ce même module pour accéder à leurs paramètres communs<br />(y compris pour supprimer le circuit de renfort actuel). + This circuit is configured as a reinforcement for circuit <b>%1</b> and therefore cannot be configured individually.<br /><br />Please click on the <b>%1</b> circuit of this same module to access their common parameters<br />(including to delete the current reinforcement circuit). + + + + Type de carte inconnu... + Card type unknown... + + + + Le module <br /><b>%1</b><br /> n'est affecté à aucun pack de batteries. <br /><br />Souhaitez-vous laisser la configuration en l'état ? + The <br /><b>%1</b><br /> module is not assigned to any battery pack. <br /><br />Do you want to leave the configuration as it is? + + + + Les modules suivants ne sont affectés à aucun pack de batteries :<br /><b>%1</b><br /><br /><br />Souhaitez-vous laisser la configuration en l'état ? + The following modules are not assigned to any battery pack:<br /><b>%1</b><br /><br /><br />Do you want to leave the configuration as it is? + + + + config_event + + + Création d'un évènement + Creating an event + + + + Configuration de l'évènement + Event configuration + + + + Nom de l'évènement + Event name + + + + Type de la source + Source type + + + + Source + Source + + + + Variable de la source + Source variable + + + + Déclenchement si + Triggered if + + + + Seuil de déclenchement + Trigger threshold + + + + Temporisation de déclenchement + Trigger delay + + + + s + s + + + + Masquer sur la page d'accueil + Hide on home page + + + + Conditions horaire + Hourly conditions + + + + Le nombre maximal de conditions horaires [%1] est atteint : ajout impossible... + The maximum number of time conditions [%1] has been reached: cannot be added... + + + + Aucune condition horaire n'est configurée pour cet évènement... + No time conditions have been set for this event... + + + + Signalisation + Signage + + + + Alarme sonore + Audible alarm + + + + La validation des alarmes sonores a nécessité de valider également l'affichage des messages liés à cet évènement.<br /><br />Cet affichage est en effet nécessaire au fonctionnement des alarmes sonores, afin de pouvoir les acquitter. + Validating the audible alarms also meant validating the display of messages related to this event.<br /><br />This display is in fact necessary for the operation of the audible alarms, in order to be able to acknowledge them. + + + + Alarme sur LED + LED alarm + + + + La validation des alarmes sur LED a nécessité de valider également l'affichage des messages liés à cet évènement.<br /><br />Cet affichage est en effet nécessaire au fonctionnement des alarmes sur LED, afin de pouvoir les acquitter. + To validate the LED alarms, we also had to validate the display of messages related to this event.<br /><br />This display is necessary for the LED alarms to function, so that they can be acknowledged. + + + + Alarme sur sortie(s) de soutien + Alarm on support output(s) + + + + La validation des alarmes sur sortie(s) de soutien a nécessité de valider également l'affichage des messages liés à cet évènement.<br /><br />Cet affichage est en effet nécessaire au fonctionnement des alarmes sur sortie(s) de soutien, afin de pouvoir les acquitter. + To validate alarms on support output(s), we also had to validate the display of messages related to this event.<br /><br />This display is in fact necessary for the operation of alarms on support output(s), in order to be able to acknowledge them. + + + + Alarme sur la source + Source alarm + + + + Affichage message sur ShipBase + Message display on ShipBase + + + + La dévalidation de l'affichage des messages a nécessité de dévalider également :<ul><li>les alarmes sonores,</li><li>les alarmes sur led</li><li>et les alarmes sur sortie(s) de soutien</li></ul><br />L'affichage de message est en effet nécessaire à leur fonctionnement, afin de pouvoir les acquitter. + Devalidating the message display required also devalidating:<ul><li>audio alarms,</li><li>led alarms</li><li>and alarms on support output(s)</li></ul><br />Message display is indeed necessary for their operation, so that they can be acknowledged. + + + + Texte du message à afficher + Message text to be displayed + + + + Emission SMS + SMS transmission + + + + Texte du SMS à envoyer + Text of SMS to be sent + + + + Emission Email + Emission Email + + + + Texte de l'email à envoyer + Text of email to send + + + + Action sur circuits + Action on circuits + + + + Aucune + No + + + + Le circuit "bascule" + The "toggle" circuit + + + + Le circuit passe à OFF + Circuit switches to OFF + + + + Le circuit passe à ON + Circuit switches to ON + + + + Le nombre de circuits commandés par un évènement est limité à %1.<br /><br />Vous ne pouvez pas ajouter d'action sur un nouveau circuit avant d'en avoir supprimé préalablement. + The number of circuits controlled by an event is limited to %1.<br /><br />You can't add an action to a new circuit until you've deleted one. + + + + Créer l'évènement + Create the event + + + + Enregistrer + Save + + + + Supprimer + Delete + + + + + + + Non défini + Undefined + + + + Condition horaire seule + Hourly condition only + + + + Circuit + Circuit + + + + Capteur + Sensor + + + + Réservoir + Tank + + + + Batterie + Battery + + + + Passage à <b>actif</b> + Change to <b>active</b> + + + + Passage à <b>inactif</b> + Change to <b>inactive</b> + + + + &lt; au seuil + &lt; at the threshold + + + + &le; au seuil + &le; at the threshold + + + + = au seuil + = at threshold + + + + &ge; au seuil + at the threshold + + + + &gt; au seuil + &gt; at the threshold + + + + config_events + + + Configuration des évènements + Event configuration + + + + Aucun évènement n'est encore configuré... + No event has yet been configured... + + + + 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. + The total number of events is limited to %1.<br /><br />You can't add a new event until you've deleted one. + + + + Sur circuits + On circuits + + + + Sur capteurs + On sensors + + + + Sur réservoirs + On tanks + + + + Sur batteries + On batteries + + + + Horaire seulement + Schedule only + + + + config_groupe_elements + + + Création d'un groupe + Creating a group + + + + Modification d'un groupe + Modifying a group + + + + Nom du groupe + Group name + + + + Créer le groupe + Create group + + + + Enregistrer + Save + + + + Supprimer + Delete + + + + batteries + batteries + + + + capteurs + sensors + + + + circuits + circuits + + + + réservoirs + tanks + + + + 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). + This group is the last one still valid.<br /><br />You can only delete it after creating at least one other group (it is not possible to operate without any %1 group). + + + + Ce groupe comprend encore %1 %2.<br /><br />Il est nécessaire d'affecter ces %2 à un autre groupe avant de pouvoir le supprimer. + This group still includes %1 %2.<br /><br />It is necessary to assign these %2 to another group before it can be deleted. + + + + 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. + This group still includes %1 %2,<br />of which %3 configured as "hidden".<br /><br />It is necessary to assign these %2 to another group before it can be deleted. + + + + config_image_accueil + + + Image d'accueil + Home image + + + + Aucune image n'a encore été chargée... + No images have been uploaded yet... + + + + Sélectionner l'image par défaut + Select default image + + + + Sélectionner cette image + Select this image + + + + Copier + Copy + + + + Supprimer + Delete + + + + Ejection + Ejection + + + + Insérer une clé USB dans le port <u>du bas</u>, à droite + Insert a USB key in the <u>bottom</u> port, on the right + + + + Vous pouvez retirer la clé en toute sécurité... + You can safely remove the key... + + + + Seuls les fichiers de type '.jpg' ou '.png' de taille inférieure à %1 sont autorisés. + Only '.jpg' or '.png' files smaller than %1 are allowed. + + + + La clé USB a été <i>éjectée</i> automatiquement.<br />Vous pouvez la retirer dès maintenant en toute sécurité... + The USB key has been <i>automatically ejected</i>.<br />You can safely remove it now... + + + + USB Arrière + USB Rear + + + + Spare + Spare + + + + USB Avant + USB Front + + + + Touch pad + Touch pad + + + + La clé USB a été retirée sans avoir préalablement été <i>éjectée</i> !<br />Cela peut conduire à des pertes de données sur la clé, voire sur ShipHeart.<br /><br />Lors de vos prochaines utilisations, pensez à <i>éjecter</i> la clé avec le bouton en haut de page avant de la retirer... Merci ! + The USB key has been removed without first <i>ejecting</i> it!<br />This can lead to data loss on the key, or even on ShipHeart.<br /><br />When you next use it, remember to <i>eject</i> the key with the button at the top of the page before removing it... Thank you! + + + + config_installation + + + Configuration de l'installation + System configuration + + + + Raison sociale + Company name + + + + N° & Rue + N° & Street + + + + Complément d'adresse + Additional address + + + + Code postal + Postal code + + + + Ville + City + + + + Nom du contact + Contact name + + + + Téléphone + Phone + + + + Email + Email + + + + Site web + Website + + + + Enregistrer + Save + + + + Rapports + Reports + + + + config_koriolan + + + Accès réservé Koriolan + Reserved access Koriolan + + + + Client spécifique + Customer-specific + + + + Mode de mise à jour des firmwares + Firmware update mode + + + + Enregistrer + Save + + + + Tests matériel + Hardware testing + + + + Nombre jours avant suppression historique + Number of days to historical deletion + + + + Nombre jours avant suppression mesures + Number of days before removal measures + + + + Période de sauvegarde BDD + DB backup period + + + + Période de vérification download + Verification period download + + + + Date de dernier archivage mesures + Last archiving date measurements + + + + Aucune spécificité + No specificity + + + + Client Suncy Concept + Customer Suncy Concept + + + + Normal (si version installée est antérieure à la version en cours) + Normal (if installed prior to current version) + + + + Différente (si version installée est différente de version en cours) + Different (if installed version is different from current version) + + + + Toujours (à utiliser avec modération...) + Always (use in moderation...) + + + + config_module + + + Modifier + Edit + + + + Localiser le module + Locate module + + + + Paramètres du module [%1] + Module parameters [%1] + + + + Paramètres du module [%1] à l'adresse [%2] + Module parameters [%1] at address [%2] + + + + N° de série + Serial no + + + + Nom du firmware + Firmware name + + + + Version du firmware + Firmware version + + + + Version matérielle + Harware version + + + + Résistance de terminaison + Termination resistor + + + + Oui + Yes + + + + Non + No + + + + CRC du firmware + Firmware CRC + + + + Courant de masses sur réseau + Ground current on the network + + + + <i>--- Circuit non affecté ---</i> + <i>--- Circuit not used ---</i> + + + + [renfort] + [reinforcement] + + + + Affectations + Assignments + + + + <i>--- Aucune batterie affectée ---</i> + <i>--- No battery assigned ---</i> + + + + Affectation + Assignment + + + + Version processeur + Processor version + + + + Emplacement du module à bord + Module location on board + + + + Commentaires + Comments + + + + config_module_modification + + + Configuration du module [%1] à l'adresse [%2] + Configuration of module [%1] at address [%2] + + + + Emplacement du module à bord + Module location on board + + + + Commentaires + Comments + + + + Courant de masses max. sur réseau + Max ground current on the network + + + + A + A + + + + Enregistrer + Save + + + + config_ordre_elements + + + 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... + To move a group, hold down and drag.<br />To edit or delete a group, double-click on it.<br />To add a group, click on '+'.<br /><br />Note: if only one group is selected, no tab is displayed on the relevant page... + + + + Aucun groupe n'est actuellement configuré... + No group is currently configured... + + + + Aucun élément n'est actuellement configuré... + No element is currently configured... + + + + Aucun groupe de batteries n'est actuellement configuré... + No battery groups are currently configured... + + + + Aucune batterie n'est actuellement affectée à ce groupe... + No batteries are currently assigned to this group... + + + + Affichage des batteries sur la page d'accueil + Battery display on home page + + + + Aucun capteur n'est actuellement affecté ce groupe... + No sensors are currently assigned to this group... + + + + Affichage des capteurs sur la page d'accueil + Sensor display on home page + + + + Aucun circuit n'est actuellement affecté à ce groupe... + No circuits are currently assigned to this group... + + + + Affichage des circuits sur la page d'accueil + Circuit display on home page + + + + Aucun groupe de réservoirs n'est actuellement configuré... + No tank groups are currently configured... + + + + Aucun réservoir n'est actuellement affecté à ce groupe... + No tank is currently assigned to this group... + + + + Affichage des réservoirs sur la page d'accueil + Tank display on home page + + + + Aucun groupe de capteurs n'est actuellement configuré... + No sensor groups are currently configured... + + + + Aucun groupe de circuits n'est actuellement configuré... + No circuit groups are currently configured... + + + + config_page + + + Création d'une page + Creating a page + + + + Configuration de la page + Page Configuration + + + + Nom de la page + Page Name + + + + Opacité de la silhouette + Silhouette Opacity + + + + Fichier de silhouette + Silhouette file + + + + Créer la page + Create the page + + + + Enregistrer + Save + + + + Silhouette + Silhouette + + + + Supprimer + Delete + + + + + Aucun + None + + + + config_page_edition + + + Edition de la page [%1] + Editing page [%1] + + + + Aucun équipement n'est configuré sur cette page pour le moment... + No equipment is configured on this page at the moment... + + + + Page + Page + + + + Enregistrer + Save + + + + 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. + You have made changes that have not been saved<br />Click Cancel to go back and save them.<br />Click OK to exit without saving. + + + + config_page_point + + + Création d'un point + Creating a point + + + + Configuration du point + Point configuration + + + + Type de la source + Source type + + + + Source + Source + + + + Type de point + Point type + + + + Taille du point + Point size + + + + Enregistrer + Save + + + + Créer le point + Create the point + + + + Supprimer + Delete + + + + + Non défini + Undefined + + + + Capteur + Sensor + + + + Circuit + Circuit + + + + Réservoir + Tank + + + + Batterie + Battery + + + + Modules + Modules + + + + config_page_silhouette + + + Silhouette de la page + Silhouette of the page + + + + Aucune image n'a encore été chargée... + No images have been uploaded yet... + + + + Aucune image + No image + + + + Sélectionner cette image + Select this image + + + + Copier + Copy + + + + Supprimer + Delete + + + + Ejection + Ejection + + + + Insérer une clé USB dans le port <u>du bas</u>, à droite + Insert a USB key in the <u>bottom</u> port, on the right + + + + Vous pouvez retirer la clé en toute sécurité... + You can safely remove the key... + + + + Seuls les fichiers de type '.jpg' ou '.png' de taille inférieure à %1 sont autorisés. + Only '.jpg' or '.png' files smaller than %1 are allowed. + + + + La clé USB a été <i>éjectée</i> automatiquement.<br />Vous pouvez la retirer dès maintenant en toute sécurité... + The USB key has been <i>automatically ejected</i>.<br />You can safely remove it now... + + + + USB Arrière + USB Rear + + + + Spare + Spare + + + + USB Avant + USB Front + + + + Touch pad + Touch pad + + + + La clé USB a été retirée sans avoir préalablement été <i>éjectée</i> !<br />Cela peut conduire à des pertes de données sur la clé, voire sur ShipHeart.<br /><br />Lors de vos prochaines utilisations, pensez à <i>éjecter</i> la clé avec le bouton en haut de page avant de la retirer... Merci ! + The USB key has been removed without first <i>ejecting</i> it!<br />This can lead to data loss on the key, or even on ShipHeart.<br /><br />When you next use it, remember to <i>eject</i> the key with the button at the top of the page before removing it... Thank you! + + + + config_pages + + + Configuration des pages + Page Configuration + + + + Aucune page n'est encore configurée... + No pages are configured yet... + + + + Image accueil + Home page image + + + + + + + + + + + config_pdf + + + Ship2net + Ship2net + + + + Enregistrer + Save + + + + config_rapports + + + Rapports d'installation + Installation reports + + + + Aucun rapport d'installation n'est encore disponible... + No installation report is yet available... + + + + Nouveau rapport d'installation + New installation report + + + + Copier + Copy + + + + Déplacer + Move + + + + Supprimer + Delete + + + + Ejection + Ejection + + + + Insérer une clé USB dans le port <u>du bas</u>, à droite + Insert a USB key in the <u>bottom</u> port, on the right + + + + Vous pouvez retirer la clé en toute sécurité... + You can safely remove the key... + + + + La clé USB a été <i>éjectée</i> automatiquement.<br />Vous pouvez la retirer dès maintenant en toute sécurité... + The USB key has been <i>automatically ejected</i>.<br />You can safely remove it now... + + + + USB Arrière + USB Rear + + + + Spare + Spare + + + + USB Avant + USB Front + + + + Touch pad + Touch pad + + + + La clé USB a été retirée sans avoir préalablement été <i>éjectée</i> !<br />Cela peut conduire à des pertes de données sur la clé, voire sur ShipHeart.<br /><br />Lors de vos prochaines utilisations, pensez à <i>éjecter</i> la clé avec le bouton en haut de page avant de la retirer... Merci ! + The USB key has been removed without first <i>ejecting</i> it!<br />This can lead to data loss on the key, or even on ShipHeart.<br /><br />When you next use it, remember to <i>eject</i> the key with the button at the top of the page before removing it... Thank you! + + + + Le rapport d'installation<br /><br /><b>%1</b><br /><br />a été généré. + The installation report<br /><br /><b>%1</b><br /><br />has been generated. + + + + config_reseau_ethernet_wifi + + + Réseau Ethernet & Wifi + Ethernet & Wifi network + + + + + Modifier + Edit + + + + Ethernet + Ethernet + + + + + + Adresse IP + IP address + + + + + + Non connecté + Not connected + + + + Connexion à un réseau existant + Connection to an existing network + + + + + Etat + Status + + + + + On + On + + + + + Off + Off + + + + + Nom du réseau [SSID] + Network name [SSID] + + + + Génération d'un réseau spécifique + Specific network generation + + + + Canal + Channel + + + + config_reseau_k_bus + + + Réseau ShipHeart + ShipHeart network + + + + Modules physiquement présents + Modules physically present + + + + %1 - %2 + %1 - %2 + + + + Modules utilisés par la configuration actuelle + Modules used by current configuration + + + + [@ %1] : %2 + [@ %1] : %2 + + + + La configuration actuelle ne fait appel à aucun autre module que ShipBase... + The current configuration does not use any other module than ShipBase... + + + + Module non utilisé en configuration + Module not used in configuration + + + + [renfort] + [reinforcement] + + + + Enregistrer + Save + + + + Retour + Back + + + + Quitter + Quit + + + + Aucune modification n'a été apportée à la configuration actuelle.<br />Celle-ci contient toujours des anomalies !<br /><br /><br />Souhaitez-vous :<br />Poursuivre les modifications [%1]<br />Quitter ce menu sans enregistrer les modifications [%2] + No changes have been made to the current configuration.<br />It still contains anomalies!<br /><br /><br />Would you like to:<br />Continue modifications [%1]<br />Exit this menu without saving changes [%2] + + + + La configuration actuelle contient toujours des anomalies !<br /><br /><br />Souhaitez-vous :<br />Enregistrer cette nouvelle configuration et quitter ce menu [%1]<br />Poursuivre les modifications [%2]<br />Quitter ce menu sans enregistrer les modifications [%3] + The current configuration still contains anomalies!<br /><br /><br />Would you like to:<br />Save this new configuration and exit this menu [%1]<br />Continue with modifications [%2]<br />Exit this menu without saving changes [%3] + + + + La configuration actuelle est correcte <br />mais n'a pas encore été enregistrée.<br /><br /><br />Souhaitez-vous :<br />Enregistrer cette nouvelle configuration et quitter ce menu [%1]<br />Poursuivre les modifications [%2]<br />Quitter ce menu sans enregistrer les modifications [%3] + The current configuration is correct <br />but has not yet been saved.<br /><br /><br />Would you like to:<br />Save this new configuration and exit this menu [%1] <br />Continue changes [%2]<br />Exit this menu without saving changes [%3] + + + + config_reseau_nmea + + + Réseau NMEA2000 + NMEA2000 network + + + + Aucun PGN n'a encore été détecté sur le réseau NMEA2000... + No PGNs have been detected on the NMEA2000 network yet... + + + + PGN non affecté + PGN not assigned + + + + config_reseau_one_wire + + + Réseau One Wire + One Wire network + + + + Aucune sonde n'est encore installée... + No probe has yet been installed... + + + + 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. + The One Wire bus is currently detected as short-circuited. <br />This condition presents no danger, but it does prevent it from working. <br /><br />Check the corresponding wiring until this message disappears. + + + + Type inconnu + Type unknown + + + + Sonde non affectée + Probe not assigned + + + + config_reseau_one_wire_modification + + + Configuration de la sonde [%1] + Probe configuration [%1] + + + + Emplacement de la sonde + Probe location + + + + Enregistrer + Save + + + + config_reseau_wifi_ap + + + Configuration Wifi en mode AP + Wifi configuration in AP mode + + + + Etat + Status + + + + Nom du réseau (SSID) + Network name (SSID) + + + + Mot de passe d'accès au réseau + Network access password + + + + Canal + Channel + + + + Adresse IP + IP address + + + + Non connecté + Not connected + + + + Enregistrer + Save + + + + Off + Off + + + + On + On + + + + Canal %1 - [%2GHz] + %1 - [%2GHz] channel + + + + Le nom du réseau (SSID) doit comprendre entre 1 et 32 caractères. <br />Merci d'entrer un nom valide. + The network name (SSID) must be between 1 and 32 characters long. <br />Please enter a valid name. + + + + 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. + The network access password must be between 8 and 63 characters long. <br />Please enter a valid password. + + + + 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. + The network name (SSID) must include only:<br />- uppercase letters [A - Z],<br />- lowercase letters [a - z],<br />- numbers [0 - 9]<br />- special characters [%1].<br /><br />Please enter a valid name. + + + + 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. + The network access password must include only:<br />- uppercase letters [A - Z],<br />- lowercase letters [a - z],<br />- numbers [0 - 9]<br />- special characters [%1].<br /><br />Please enter a valid name. + + + + config_reseau_wifi_sta + + + Configuration Wifi en mode STA + Wifi configuration in STA mode + + + + Etat + Status + + + + Réseau + Network + + + + Mot de passe d'accès au réseau + Network access password + + + + Enregistrer + Save + + + + Réseaux connus + Known networks + + + + Off + Off + + + + On + On + + + + Aucun réseau... + No network... + + + + config_reseau_wifi_sta_liste + + + Liste des réseaux Wifi connus + List of known Wifi networks + + + + Aucun réseau n'a été détecté... + No network detected... + + + + Oublier tous les réseaux + Forget all the networks + + + + Oublier ce réseau + Forget this network + + + + config_reservoir + + + Création d'un réservoir + Tank creation + + + + Configuration du réservoir + Tank configuration + + + + Nom du réservoir + Tank name + + + + Famille de réservoirs + Tank family + + + + Type de capteur de niveau + Level sensor type + + + + %1 : Non définie + %1 : Not defined + + + + %1 : %2 + %1 : %2 + + + + Sonde la plus basse dans le réservoir + Lowest probe in tank + + + + Non définie + Not defined + + + + Logique d'alarme + Alarm logic + + + + Filtrage des mesures + Measurement filtering + + + + Créer le réservoir + Create the tank + + + + Enregistrer + Save + + + + Supprimer + Delete + + + + Etalonnage + Calibration + + + + + AUX INPUT %1 + AUX INPUT %1 + + + + + LEVEL SENSOR %1 + LEVEL SENSOR %1 + + + + Confirmer + Confirm + + + + Capacité du réservoir + Tank capacity + + + + litres + liters + + + + Logique des entrées inversée + Reverse input logic + + + + La modification du <b>type de capteur</b> va nécessiter la remise en <i>configuration usine</i> de tous les paramètres du réservoir.<br /><br />Si vous ne souhaitez pas que cette reconfiguration soit effectuée, cliquez sur ANNULER. <br /><br />Sinon, cliquez sur CONFIRMER pour valider le changement. + Changing the <b>sensor type</b> will require all tank parameters to be reset to <i>factory configuration</i>.<br /><br />If you don't want this reconfiguration to take place, click on CANCEL. <br /><br />If not, click CONFIRM to confirm the change. + + + + Non défini + Undefined + + + + Electrodes plongées ou contacts secs + Immersed electrodes or dry contacts + + + + Résistif 0 - 190Ω + Resistive 0 - 190Ω + + + + Résistif 240 - 30Ω + Resistive 240 - 30Ω + + + + Résistif 0 - 700Ω + Resistive 240 - 30Ω {0 ?} {700Ω?} + + + + Boucle de courant 4 - 20mA + Current loop 4 - 20mA + + + + Tension 0 - 10V + Voltage 0 - 10V + + + + Aucun filtrage + No filtering + + + + Très faible + Very low + + + + Faible + Low + + + + Moyen + Medium + + + + Elevé + High + + + + Très élevé + Very high + + + + Ce réservoir est utilisé par l'évènement ci-dessous.<br />Vous devez modifier ou supprimer cet évènement pour qu'il ne dépende plus de ce réservoir avant de pouvoir le supprimer. + This tank is used by the event below.<br />You must modify or delete this event so that it no longer depends on this tank before you can delete it. + + + + Ce réservoir est utilisé par les %1 évènements ci-dessous.<br />Vous devez modifier ou supprimer ces évènements pour qu'ils ne dépendent plus de ce réservoir avant de pouvoir le supprimer. + This tank is used by the %1 events below.<br />You must modify or delete these events so that they no longer depend on this tank before you can delete it. + + + + Ce réservoir est utilisé par le capteur calculé ci-dessous.<br />Vous devez modifier ou supprimer ce capteur calculé pour qu'il ne dépende plus de ce réservoir avant de pouvoir le supprimer. + This tank is used by the calculated sensor below.<br />You must modify or delete this calculated sensor so that it no longer depends on this tank before you can delete it. + + + + Ce réservoir est utilisé par les %1 capteurs calculés ci-dessous.<br />Vous devez modifier ou supprimer ces capteurs calculés pour qu'ils ne dépendent plus de ce réservoir avant de pouvoir le supprimer. + This tank is used by the %1 calculated sensors below.<br />You must modify or delete these calculated sensors so that they no longer depend on this tank before you can delete it. + + + + Alerte sur niveau faible + Low level alert + + + + Alerte sur niveau élevé + High level alert + + + + config_reservoirs + + + Configuration des réservoirs + Tank configuration + + + + Aucun réservoir n'est encore configuré... + No tank is configured yet... + + + + + + + + + + + config_ship2net + + + Ship2net + Ship2net + + + + Période des sauvegardes + Backup period + + + + Période de connexion à Ship2net + Ship2net connection period + + + + Mode de validation des mises à jour + Update validation mode + + + + Accès distant WebGL #1 + WebGL remote access #1 + + + + Accès distant WebGL #2 + WebGL remote access #2 + + + + Accès distant WebGL #3 + WebGL remote access #3 + + + + Enregistrer + Save + + + + + Jamais + Never + + + + + 2 minutes + 2 minutes + + + + + 30 minutes + 30 minutes + + + + + 1 heure + 1 hour + + + + 2 heures + 2 hours + + + + + 4 heures + 4 hours + + + + + 12 heures + 12 hours + + + + + 24 heures + 24 heures + + + + + + Dévalidé + Disabled + + + + + + Valide [port %1] + Valid [port %1] + + + + + 10 minutes + 10 minutes + + + + Aucune mise à jour + No updates + + + + Validation manuelle des mises à jour reçues + Manual validation of received updates + + + + Validation automatique des mises à jour reçues + Automatic validation of received updates + + + + config_specifique_client_suncy + + + Configuration spécifique à Suncy Concept + Configuration specific to Suncy Concept + + + + Circuit d'activation moteur + Motor activation circuit + + + + Nouveau code + New code + + + + Code d'accès au bateau + Boat access code + + + + Répéter le code d'accès + Repeat access code + + + + Enregistrer + Save + + + + Aucune + No + + + + [module %1 - circuit %2] %3 + [module %1 - circuit %2] %3 + + + + Les deux valeurs saisies doivent être identiques ! + +De plus, le code doit contenir : +- %1 chiffres au minimum +- %2 chiffres au maximum. + The two values entered must be identical! + +In addition, the code must contain : +- %1 digits minimum +- %2 digits maximum. + + + + Le nouveau code doit contenir : +- %1 chiffres au minimum +- %2 chiffres au maximum. + +Le code saisi ne répond pas à ces critères et sa mise à jour n'est donc pas effectuée. + +Merci de saisir un code au format valide si vous souhaitez le modifier. + The new code must contain : +- %1 digits minimum +- %2 digits maximum. + +The code entered does not meet these criteria and is therefore not updated. + +Please enter a valid code if you wish to change it. + + + + config_valeurs_niveaux + + + Aucun point de conversion n'est configuré pour le moment... + No conversion points have been configured yet... + + + + Le nombre maximal de points d'étalonnage a été atteint (%1 points)<br />Vous ne pouvez pas en ajouter sans en avoir prélablement supprimé. + The maximum number of calibration points has been reached (%1 points).<br />You cannot add any more without first deleting some. + + + + Courbe usine + Factory curve + + + + Enregistrer + Save + + + + La valeur lue sur les electrodes plongées de ce réservoir est incohérente.<br />Vérifier l'ordre de cablage des électrodes sur les entrées auxiliaires à l'arrière de ShipBase. + The value read on the dipped electrodes of this tank is inconsistent.<br />Check the wiring order of the electrodes on the auxiliary inputs at the rear of ShipBase. + + + + Aucune donnée n'est disponible... + No data available... + + + + 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. + You have made changes that have not been saved<br />Click Cancel to go back and save them.<br />Click OK to exit without saving. + + + + Aucun point n'est actuellement configuré pour cette batterie... + No points are currently configured for this battery... + + + + + Courbe de conversion de [%1] + Conversion curve for [%1] + + + + Aucun réservoir n'est actuellement configuré... + No tank is currently configured... + + + + Aucun point n'est actuellement configuré pour cet élément... + No points are currently configured for this element... + + + + Courbe de conversion de type INCONNU + Conversion curve type UNKNOWN + + + + config_version + + + Version + Version + + + + %1 : %2 + %1 : %2 + + + + 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 : + Version <b>%1</b> is available.<br /><br />It will be automatically installed the next time ShipHeart is started.<br />Unless you choose one of the options below: + + + + La version <b>%1</b> est disponible.<br /><br />Souhaitez-vous : + Version <b>%1</b> is available.<br /><br />Would you like to : + + + + + L'installer +maintenant + Installing it +now + + + + L'installer au prochain démarrage de ShipHeart + Install it the next time ShipHeart starts up + + + + + Ne jamais l'installer + Never install + + + + Supprimer + Delete + + + + Si vous confirmez, cette mise à jour sera définitivement supprimée.<br />Cliquez sur Annuler pour revenir en arrière et la conserver. + If you confirm, this update will be permanently deleted.<br />Click Cancel to go back and keep it. + + + + Installer + Install + + + + 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 la conserver pour une installation ultérieure. + If you confirm, this update may take <u>a few minutes</u> during which <b>your ShipHeart system will not be accessible</b>.<br /><br />You do not need to confirm the installation only if you are in a safe situation (in port, at anchor, etc.) and the loss of control of your on-board systems during this period of time is without any danger!<br /><br />Click on Cancel to go back and save it for later installation. + + + + 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 'shipheart.tech' ou de nous contacter à l'adresse 'contact@shipheart.tech'. + 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 'shipheart.tech' ou de nous contacter à l'adresser 'contact@shipheart.tech'. + This product is designed and manufactured by Koriolan, which holds all licenses and operating rights to the images, software and patents used in its design and operation. ShipHeart™, Ship2net™ and Koriolan™ are registered trademarks of the Koriolan company. If you have any questions about this product, please visit 'shipheart.tech' or contact us at 'contact@shipheart.tech'. + + + + Version du package logiciel + Software package version + + + + Version de l'application + Application version + + + + Version de l'interface graphique + GUI version + + + + Version du firmware du modem + Modem firmware version + + + + Numéro d'IMEI + IMEI number + + + + Numéro d'ICCID + ICCID number + + + + Numéro d'IMSI + IMSI number + + + + ephemeride + + + Ephéméride + Ephemeris + + + + Heure d'hiver + Winter time + + + + Heure d'été + Daylight saving time + + + + Aube nautique + Nautical dawn + + + + Lever du soleil + Sunrise + + + + Zénith + Zenith + + + + Coucher du soleil + Sunset + + + + Crépuscule nautique + Nautical twilight + + + + Lune + Moon + + + + Latitude + Latitude + + + + Longitude + Longitude + + + + etalonnage_capteur + + + Etalonnage du capteur [%1] + Sensor calibration [%1] + + + + Valeur brute actuelle + Current gross value + + + + Valeur corrigée actuelle (%1) + Current corrected value (%1) + + + + Correction + Correction + + + + Enregistrer + Save + + + + etalonnage_carte + + + Etalonnage du module [%1 - #%2] + Calibrate module [%1 - #%2] + + + + Point 1 + Point 1 + + + + Point 2 + Point 2 + + + + Courant de décharge + Discharge current + + + + Courant différentiel + Differential current + + + + + Recalculer ce point + Recalculate this point + + + + + Mémoriser ce point + Memorize this point + + + + Off + Off + + + + On + On + + + + On (%1 %%) + On (%1 %%) + + + + Enregistrer + Save + + + + Aide + Help + + + + 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 /> + Calibration cannot be performed with two identical points.<br /><br /> + Try to modify at least one of the two reference points by playing with the circuit controls below.<br /> + + + + 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. + The principle of calibration is to compare at <u>2 different points</u> the differential current value measured by the ShipBS on the one hand, and the discharge current measured by the ShipHeart system <br />. For example, by subjecting the ShipBS being calibrated to low or zero power consumption (first point) then operating one or more appliances to obtain a consumption of several amperes if possible (second point).<br />. <br /><u><b>Very important</b>: during the entire calibration phase no <b>charge current</b> should be applied to ShipBS!</u> It is therefore essential to disconnect all chargers, solar controllers, etc. from the system during calibration. Failure to do so will result in erroneous calibration values...<br /><br />. Remarks:<br /> - all consumption must go through the ShipHeart system! Make sure that no load is connected directly to the power supply. to the battery park.<br /> - current values are irrelevant <br />. - the current at point 2 may be lower or higher than that at point 1 (but as "far" apart as possible).<br />. - it is advisable to choose loads whose consumption is relatively stable or, at the very least, changes little over a period of a few seconds. + + + + fonctions + + + Modèle inconnu + Unknown model + + + + Circuit + Circuit + + + + Capteur + Sensor + + + + Réservoir + Tank + + + + Batterie + Battery + + + + Type inconnu + Type unknown + + + + Consigne + Setpoint + + + + + + Tension + Voltage + + + + Courant + Current + + + + Fréquence + Frequency + + + + + Puissance + Power + + + + + Energie + Energy + + + + Température + Temperature + + + + Courant différentiel + Differential current + + + + Courant de charge + Load current + + + + Courant de décharge + Discharge current + + + + SOH (state Of Health) + SOH (State Of Health) + + + + SOC (State Of Charge) + SOC (State Of Charge) + + + + Autonomie + Autonomy + + + + fonctions_date_heure + + + 1 heure + 1 hour + + + + 24 heures + 24 heures + + + + 7 jours + 7 days + + + + 30 jours + 30 days + + + + Fin de nuit + Late night + + + + Aube nautique + Nautical dawn + + + + Aube + Aube + + + + Lever du soleil + Sunrise + + + + Zénith + Zenith + + + + Coucher du soleil + Sunset + + + + Crépuscule + Twilight + + + + Crépuscule nautique + Nautical twilight + + + + Début de nuit + Early night + + + + %1h + %1h + + + + Dimanche + Sunday + + + + Lundi + Monday + + + + Mardi + Tuesday + + + + Mercredi + Wednesday + + + + Jeudi + Thursday + + + + Vendredi + Friday + + + + Samedi + Saturday + + + + Tous les jours + Every day + + + + janvier + January + + + + février + February + + + + mars + March + + + + avril + April + + + + mai + May + + + + juin + June + + + + juillet + July + + + + août + August + + + + septembre + September + + + + octobre + October + + + + novembre + November + + + + décembre + December + + + + fonctions_historique + + + Commande 'OFF' du circuit %1 + OFF' circuit command %1 + + + + Commande 'ON' du circuit %1 + ON' command for circuit %1 + + + + Commande à %1 % du circuit %2 + Control %1% of circuit %2 + + + + Le circuit %1 est revenu à son état de fonctionnement normal + Circuit %1 has returned to its normal operating state + + + + L'alimentation du circuit %1 a été coupée car sa limite de courant (%2 A) a été dépassée + The power supply to circuit %1 has been cut because its current limit (%2 A) has been exceeded + + + + L'alimentation du circuit %1 a été coupée car les circuits de protection interne ont détecté une anomalie + The power supply to circuit %1 has been cut off because the internal protection circuits have detected an anomaly + + + + L'alimentation du circuit %1 a été coupée car le seuil de disjonction a été dépassé + The power supply to circuit %1 has been cut because the trip threshold has been exceeded + + + + Le circuit %1 est en court-circuit avec le + batterie + Circuit %1 is short-circuited to + battery + + + + L'alimentation du circuit %1 a été coupée car la consommation totale du module a été dépassé + The power supply to circuit %1 has been cut because the module's total power consumption has been exceeded + + + + Le circuit %1 a été créé + Circuit %1 has been created + + + + La configuration du circuit %1 a été modifiée + The %1 circuit configuration has been modified + + + + Le circuit %1 a été supprimé + Circuit %1 has been deleted + + + + La configuration du circuit %1 est invalide car le module sur lequel le circuit est configuré n'est pas présent + Circuit configuration %1 is invalid because the module on which the circuit is configured is not present + + + + Le circuit %1 a fonctionné trop longtemps (> %2 secondes). Il a donc été désactivé automatiquement. + Circuit %1 has been running too long (> %2 seconds). It was therefore automatically deactivated. + + + + Evénement de type CIRCUITS avec code de sous-type inconnu [%1] + CIRCUITS event with unknown subtype code [%1] + + + + Le capteur %1 est repassé à l'état normal + Sensor %1 has returned to normal state + + + + Le capteur %1 est passé à l'état ALERTE + Sensor %1 has switched to ALERT status + + + + Le capteur %1 est passé à l'état ALARME + Sensor %1 has switched to ALARM status + + + + Evénement de type CAPTEURS avec code de sous-type inconnu [%1] + CAPTORS event with unknown subtype code [%1] + + + + Le niveau de charge de la batterie %1 est repassé au niveau normal + Battery charge level %1 has returned to normal level + + + + Le niveau de charge de la batterie %1 est passé en dessous du niveau d'alerte + Battery charge level %1 has fallen below warning level + + + + Le niveau de charge de la batterie %1 est passé au-dessus du niveau d'alarme (il est maintenant au niveau d'alerte uniquement) + Battery charge level %1 has risen above alarm level (now at alert level only) + + + + Le niveau de charge de la batterie %1 est passé en-dessous du niveau d'alarme + Battery charge level %1 has fallen below alarm level + + + + Evénement de type BATTERIES avec code de sous-type inconnu [%1] + BATTERIES event with unknown subtype code [%1] + + + + Le niveau du réservoir %1 est repassé au niveau normal + Tank level %1 has returned to normal level + + + + Le niveau du réservoir %1 est passé en dessous du niveau d'alerte + Tank level %1 has fallen below warning level + + + + Le niveau du réservoir %1 est passé au-dessus du niveau d'alarme (il est maintenant au niveau d'alerte uniquement) + Tank level %1 has risen above alarm level (now at alert level only) + + + + Le niveau du réservoir %1 est passé en-dessous du niveau d'alarme + Tank level %1 has fallen below alarm level + + + + Evénement de type RESERVOIRS avec code de sous-type inconnu [%1] + TANKS event with unknown subtype code [%1] + + + + La consigne des ports USB est passée à %1 + USB port setpoint changed to %1 + + + + L'état des ports USB est redevenu normal + USB port status has returned to normal + + + + Défaut détecté sur les ports USB + USB port fault detected + + + + Evénement de type USB avec code de sous-type inconnu [%1] + USB event with unknown subtype code [%1] + + + + Evénement de type INCONNU (avec code de sous-type [%1] + UNKNOWN event (with subtype code [%1]) + + + + home + + + Aucun circuit n'est configuré pour ce groupe...<br /><br />Si ce groupe n'a pas d'utilité, vous pouvez le supprimer dans le menu [Circuits] des Paramètres Avancés. + No circuit is configured for this group...<br /><br />If this group has no use, you can delete it in the [Circuits] menu of Advanced Settings. + + + + Aucun capteur n'est configuré pour ce groupe...<br /><br />Si ce groupe n'a pas d'utilité, vous pouvez le supprimer dans le menu [Capteurs] des Paramètres Avancés. + No sensors are configured for this group...<br /><br />If this group has no use, you can delete it in the [Sensors] menu of Advanced Settings. + + + + Aucun réservoir n'est configuré pour ce groupe...<br /><br />Si ce groupe n'a pas d'utilité, vous pouvez le supprimer dans le menu [Réservoirs] des Paramètres Avancés. + No tank is configured for this group...<br /><br />If this group has no use, you can delete it in the [Tanks] menu of Advanced Settings. + + + + Aucun parc de batterie n'est configuré pour ce groupe...<br /><br />Si ce groupe n'a pas d'utilité, vous pouvez le supprimer dans le menu [Batteries] des Paramètres Avancés. + No battery park is configured for this group...<br /><br />If this group has no use, you can delete it in the [Batteries] menu of Advanced Settings. + + + + Cette page est actuellement en travaux. <br />Elle sera rendue disponible très rapidement à travers une mise à jour.<br /><br />Merci de votre patience...<br /><br />L'équipe ShipHeart + This page is currently under construction. <br />It will be made available very soon through an update.<br /><br />Thank you for your patience...<br /><br />The ShipHeart team + + + + + + Déconnecté + Offline + + + + Nombre de satellites visibles + Number of visible satellites + + + + + Connecté + Connected + + + + + OFF + OFF + + + + + ON + ON + + + + Niveau + Level + + + + Actif + Assets + + + + Inactif + Inactive + + + + + + <b>%1</b> + <b>%1</b> + + + + Démarrage + Start + + + + Firmware de <b>ShipBase</b> + Firmware for <b>ShipBase</b> + + + + Firmware du <b>ShipPower812</b> à l'adresse <b>%1</b> + Firmware for the <b>ShipPower812</b> at <b>%1</b> + + + + Firmware du <b>ShipBS</b> à l'adresse <b>%1</b> + Firmware for <b>ShipBS</b> at <b>%1</b> + + + + Firmware du <b>ShipPower4AC</b> à l'adresse <b>%1</b> + <b>ShipPower4AC</b> firmware at <b>%1</b> + + + + Firmware du <b>ShipPower8DC</b> à l'adresse <b>%1</b> + <b>ShipPower8DC</b> firmware at <b>%1</b> + + + + Firmware du module à l'adresse <b>%1</b> + Module firmware at <b>%1</b> + + + + Merci de patienter et de ne rien débrancher<br />avant la fin de la mise à jour. + Please be patient and do not unplug anything<br />until the update is complete. + + + + Chargement des mises à jour effectué avec succès !<br /><br />L'activation des nouvelles version est en cours sur tous les modules concernés.<br /><br />Merci de patienter encore quelques secondes... + Updates successfully loaded!<br /><br />The new versions are being activated on all relevant modules.<br /><br />Please wait a few more seconds... + + + + ShipHeart va redémarrer pour effectuer une mise à jour.<br /><br />Cette opération va prendre quelques minutes au maximum.<br />Merci de patienter et de ne rien débrancher jusqu'au redémarrage final... + ShipHeart will reboot to perform an update.<br /><br />This operation will take a few minutes at most.<br />Please be patient and do not unplug anything until the final reboot... + + + + Votre système ShipHeart est dorénavant équipé de la version<br /><br /><b>%1</b><br /><br />(la version précédente était la %2) + Your ShipHeart system is now equipped with version<br /><br /><b>%1</b><br /><br />(the previous version was %2) + + + + Le nombre de modules détectés sur le réseau ShipHeart est insuffisant par rapport à la configuration du bateau.<br /><br />Vérifiez les connexions entre le module <b>%1</b> à la <b>position @%2</b> %3 et le module <b>%4</b> suivant%5<br /><br />Vous pouvez visualiser l'état complet du réseau ShipHeart et les anomalies détectées dans le menu 'Réseau > ShipHeart' dans les Paramètres Avancés + The number of modules detected on the ShipHeart network is insufficient for the boat configuration.<br /><br />Check the connections between the <b>%1</b> module at the <b>position @%2</b> %3 and the next <b>%4</b> module%5<br /><br />.br />You can view the complete status of the ShipHeart network and any anomalies detected in the 'Network > ShipHeart' menu in Advanced Settings + + + + Le modules détecté en <b>position @%1</b> est un <b>%2</b>. Cela ne correspond pas à la configuration actuelle du bateau (<b>%3</b>).<br /><br />Cela peut provenir de l'ajout, de la suppression ou d'un déplacement de module.<br /><br />Vous pouvez visualiser toutes les anomalies détectées et les corriger dans le menu 'Réseau > ShipHeart' dans les Paramètres Avancés + The module detected in <b>position @%1</b> is a <b>%2</b>. This does not correspond to the boat's current configuration (<b>%3</b>).<br /><br />This may be due to the addition, deletion or relocation of a module.<br /><br />You can view all detected anomalies and correct them in the 'Network > ShipHeart' menu in Advanced Settings + + + + Code inconnu + Unknown code + + + + home_accueil + + + Bienvenue à bord de + Welcome aboard + + + + home_suncy + + + L'accès au bateau est protégé. +Merci d'entrer votre code de déverrouillage pour y accéder... + Access to the boat is protected. +Please enter your unlock code to access... + + + + journal_de_bord + + + + + + Tous + All + + + + Batteries + Batteries + + + + Capteurs + Sensors + + + + Circuits + Circuits + + + + Réservoirs + Tanks + + + + Système + System + + + + Ports USB + USB ports + + + + Journal de bord + Logbook + + + + Aucun type n'est configuré... + No type is configured... + + + + %1<br /><br /><br />%2 + %1<br /><br /><br />%2 + + + + Aucune entrée d'historique n'est disponible pour cette sélection... + No history entries are available for this selection... + + + + Toutes + All + + + + main + + + Type d'installation : +0 : ShipBase standard, +1 : écran déporté + Type of installation : +0: ShipBase standard, +1: remote display + + + + + valeur + value + + + + Adresse IPv4 de ShipBase dans le cas d'une installation déportée + ShipBase IPv4 address for remote installation + + + + xxx:xxx:xxx:xxx + xxx:xxx:xxx:xxx + + + + Taille de l'écran en pouces : +7, +10 (ShipBase standard), +22 + Screen size in inches : +7, +10 (ShipBase standard), +22 + + + + Original + Original + + + + Sombre + Dark + + + + Métallique + Metallic + + + + Triangles + Triangles + + + + Sable + Sand + + + + Thème 5 + Theme 5 + + + + Thème 6 + Theme 6 + + + + Thème 7 + Theme 7 + + + + Thème 8 + Theme 8 + + + + page_personnalisee + + + <i>--- Circuit non affecté ---</i> + <i>--- Circuit not used ---</i> + + + + [renfort] + [reinforcement] + + + + <i>--- Aucune batterie affectée ---</i> + <i>--- No battery assigned ---</i> + + + + parametres + + + Paramètres + Parameters + + + + Langue + Language + + + + Températures + Temperatures + + + + Volumes + Volumes + + + + Affichage + Display + + + + Date et heure + Date and time + + + + Protection + Protection + + + + Son + Sound + + + + Luminosité + Brightness + + + + Economiseur d'écran : désactivé + Screen saver: disabled + + + + Economiseur d'écran : normal + Screen saver: normal + + + + Flash LEDs : désactivé + Flash LEDs: off + + + + Flash LEDs : normal + Flash LEDs: normal + + + + Nettoyage de l'écran + Screen cleaning + + + + Heure d'été + Daylight saving time + + + + Heure d'hiver + Winter time + + + + Verrouiller le bateau + Locking the boat + + + + parametres_avances + + + Paramètres avancés + Advanced settings + + + + Réseaux + Networks + + + + Cette page est actuellement en travaux. <br />Elle sera rendue disponible très rapidement à travers une mise à jour.<br /><br />Merci de votre patience...<br /><br />L'équipe ShipHeart + This page is currently under construction. <br />It will be made available very soon through an update.<br /><br />Thank you for your patience...<br /><br />The ShipHeart team + + + + Circuits + Circuits + + + + Réservoirs + Tanks + + + + Batteries + Batteries + + + + Capteurs + Sensors + + + + Menu accueil + Home menu + + + + Evènements + Events + + + + ShipHeart + ShipHeart + + + + Ethernet & Wifi + Ethernet & Wifi + + + + One Wire + One Wire + + + + NMEA 2000 + NMEA 2000 + + + + J1939 + J1939 + + + + DMX + DMX + + + + Journal de bord + Logbook + + + + Vos paramètres + Your settings + + + + Votre installation + Your installation + + + + Système + System + + + + Affichage + Display + + + + Audio + Audio + + + + Ship2net + Ship2net + + + + Accès au paramètres + Access to parameters + + + + Configuration ShipRS + ShipRS configuration + + + + Installation + Installation + + + + Version + Version + + + + Accès réservé Koriolan + Reserved access Koriolan + + + + Spécifique Suncy + Suncy specific + + + + protection + + + Accès protégé + Secure access + + + + L'accès aux paramètres avancés est protégé. +Merci d'entrer le code de déverrouillage pour y accéder... + Access to advanced settings is protected. +Please enter the unlock code to access... + + + + Mode administrateur validé<br />Entrer votre code dédié + Administrator mode enabled<br />Enter your dedicated code + + + + reservoir + + + [ %1 % ] + [ %1 % ] + + + + Le module assurant la supervision de ce réservoir n'est pas accessible !<br /><br />Si des ajouts/suppression/déplacements de modules ont eu lieu récemment, mettez à jour la configuration correspondant dans le menu MODULES de PARAMETRES AVANCES.<br /><br />Dans le cas où aucune modification n'a été effectuée récemment, vérifier les connexions de tous les modules. + The module supervising this tank is not accessible!<br /><br />If modules have been added/deleted/moved recently, update the corresponding configuration in the MODULES menu of ADVANCED PARAMETERS.<br /><br />If no changes have been made recently, check the connections of all modules. + + + + Niveau + Level + + + + La valeur lue sur les electrodes plongées de ce réservoir est incohérente.<br />Vérifier l'ordre de cablage des électrodes sur les entrées auxiliaires à l'arrière de ShipBase. + The value read on the dipped electrodes of this tank is inconsistent.<br />Check the wiring order of the electrodes on the auxiliary inputs at the rear of ShipBase. + + + + Aucune donnée n'est disponible pour cette période + No data available for this period + + + + shipheart_test_config + + + Vitesse de test de l'écran + Screen test speed + + + + Nombre de colonnes de test du touchpad + Number of touchpad test columns + + + + Nombre de lignes de test du touchpad + Number of touchpad test lines + + + + shipheart_test_home + + + Tests matériel + Hardware testing + + + + Configuration des tests + Test configuration + + + + Test du backlight + Backlight test + + + + Test de l'écran + Screen test + + + + Test du touchpad + Touchpad test + + + + Liste des fonts disponibles + List of available fonts + + + + shipheart_test_liste_fonts + + + Liste des fonts disponibles + List of available fonts + + + + test_batterie + + + Batteries de servitude + Service batteries + + + + Autonomie optimale + Optimum autonomy + + + + Autonomie actuelle + Current autonomy + + + + Autonomie<br />maximale + Autonomy<br />maximum + + + + dans + in + + + + environ + about + + + + test_tri_liste + + + TEST DE TRI DE LISTE + TEST DE TRI DE LISTE + + + diff --git a/shipheart_es_ES.qm b/shipheart_es_ES.qm new file mode 100755 index 0000000..16bcf8b Binary files /dev/null and b/shipheart_es_ES.qm differ diff --git a/shipheart_es_ES.ts b/shipheart_es_ES.ts new file mode 100755 index 0000000..e9b8034 --- /dev/null +++ b/shipheart_es_ES.ts @@ -0,0 +1,4409 @@ + + + + + Shipheart_boite_dialogue + + OK + OK + + + Annuler + Cancelar + + + Plus tard + Más tarde + + + + Shipheart_boite_dialogue_action_circuit + + Action à appliquer au circuit lorsque l'évènement se déclenche : + Acción que se aplicará al circuito cuando se active el evento : + + + Aucune + No + + + Le circuit <b>bascule</b> + El circuito <b>toggle</b> + + + [passe à <b>ON</b> s'il est <b>OFF</b><br /> ou à <b>OFF</b> s'il est <b>ON</b>] + [cambia a <b>ON</b> si está <b>OFF</b><br /> o a <b>OFF</b> si está <b>ON</b>] + + + OFF + OFF + + + ON + ON + + + Annuler + Cancelar + + + + Shipheart_boite_dialogue_affichage_duree + + Ok + OK + + + + Shipheart_boite_dialogue_condition_horaire + + OK + OK + + + Annuler + Cancelar + + + Supprimer + Borrar + + + Aube nautique + Amanecer náutico + + + Lever du soleil + Amanecer + + + Zénith + Zenith + + + Coucher du soleil + Puesta de sol + + + Crépuscule nautique + Crepúsculo náutico + + + + Shipheart_boite_dialogue_entrees_aux + + Entrées Auxiliaires + Entradas auxiliares + + + Annuler + Cancelar + + + Affectation de l'entrée n° %1 du %2 + Asignación del número de entrada %1 de %2 + + + + Shipheart_boite_dialogue_entrees_level_sensor + + Entrées Level Sensor + Entradas del sensor de nivel + + + Affectation de l'entrée du réservoir + Asignación de la entrada del depósito + + + Annuler + Cancelar + + + + Shipheart_boite_dialogue_liste_alarmes + + Ok + OK + + + + Shipheart_boite_dialogue_minuteur + + Heures + Horas + + + Minutes + Actas + + + Secondes + Segundos + + + Annuler + Cancelar + + + Démarrer + Inicio + + + + Shipheart_boite_dialogue_nettoyage_ecran + + Nettoyage de l'écran + Limpieza de la pantalla + + + 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. + La pantalla está actualmente congelada para permitirle limpiarla sin riesgo de desencadenar acciones no deseadas.<br /><br />Mantenga pulsado el botón inferior durante más de %1 segundos para salir de este modo. + + + Sortie + Salida + + + + Shipheart_boite_dialogue_reveils + + Annuler + Cancelar + + + Enregistrer + Regístrese en + + + + Shipheart_boite_dialogue_validation_securisee + + OK + OK + + + Annuler + Cancelar + + + --- + + + + + Shipheart_bouton_circuit + + Off + OFF + + + On + ON + + + + batterie + + Aucune donnée n'est disponible pour cette période + No hay datos disponibles para este periodo + + + Le module assurant la supervision de cette batterie n'est pas accessible !<br /><br />Si des ajouts/suppression/déplacements de modules ont eu lieu récemment, mettez à jour la configuration correspondant dans le menu MODULES de PARAMETRES AVANCES.<br /><br />Dans le cas où aucune modification n'a été effectuée récemment, vérifier les connexions de tous les modules. + ¡No se puede acceder al módulo que monitorea esta batería!<br /><br />Si se han agregado/eliminado/movido módulos recientemente, actualice la configuración correspondiente en el menú MÓDULOS de PARÁMETROS AVANZADOS. <br /><br />En caso no se han realizado modificaciones recientemente, verificar las conexiones de todos los módulos. + + + Aucune consommation d'énergie sur cette période... + No hay consumo de energía durante este periodo... + + + + capteur + + Max + Max + + + Moyen + Medio + + + Min + Min + + + Delta (Max - Min) + Delta (Max - Min) + + + Aucune donnée n'est disponible pour cette période + No hay datos disponibles para este periodo + + + La sonde One Wire correspondant à ce capteur n'est pas accessible.<br />Vérifier son câblage entre le port One Wire à l'arrière de ShipBase et la sonde. + No se puede acceder a la sonda One Wire correspondiente a este sensor.<br />Compruebe el cableado entre el puerto One Wire de la parte posterior de ShipBase y la sonda. + + + Le module assurant la supervision de ce capteur n'est pas accessible !<br /><br />Si des ajouts/suppression/déplacements de modules ont eu lieu récemment, mettez à jour la configuration correspondant dans le menu MODULES de PARAMETRES AVANCES.<br /><br />Dans le cas où aucune modification n'a été effectuée récemment, vérifier les connexions de tous les modules. + <br /><br />Si se han añadido/eliminado/movido módulos recientemente, actualice la configuración correspondiente en el menú MÓDULOS de PARÁMETROS AVANZADOS.<br /><br />Si no se han realizado cambios recientemente, compruebe las conexiones de todos los módulos. + + + La sonde One Wire du capteur est détectée en défaut.<br />Vérifier son câblage depuis l'arrière de ShipBase. + La sonda One Wire del sensor se detecta como defectuosa.<br />Compruebe su cableado desde la parte posterior de ShipBase. + + + Le capteur n'a pas reçu de mise à jour sur le réseau NMEA depuis<br />%1<br />Les données affichées sont donc probablement obsolètes. + El sensor no ha recibido una actualización en la red NMEA desde el 1%. Por lo tanto, es probable que los datos mostrados estén desactualizados. + + + + circuit + + Off + OFF + + + On + ON + + + On +%1% + En +%1% + + + Aucune donnée n'est disponible pour cette période + No hay datos disponibles para este periodo + + + L'alimentation du circuit a été coupée + car sa limite de courant (%1 A) + a été dépassée. + La alimentación del circuito se ha cortado + porque su límite de corriente (%1 A) + ha sido sobrepasado. + + + L'alimentation du circuit a été coupée + car les circuits de protection interne ont détecté une anomalie. + La alimentación del circuito se ha cortado + porque los circuitos internos de protección han detectado una anomalía. + + + L'alimentation du circuit a été coupée + car le seuil de disjonction du circuit a été dépassé. + La alimentación del circuito se ha cortado + porque se ha superado el umbral de interrupción del circuito. + + + Le circuit est en court-circuit avec le + batterie. + El circuito está cortocircuitado con la batería +. + + + L'alimentation du circuit a été coupée<br />car la consommation totale du module a dépassé %1 A pendant plus de %2 secondes (limite du module) + La alimentación del circuito se ha cortado<br />porque el consumo total del módulo ha superado %1 A durante más de %2 segundos (límite del módulo) + + + La tension du circuit est anormalement basse. + La tensión del circuito es anormalmente baja. + + + La phase et le neutre sont inversés sur ce circuit. + La fase y el neutro están invertidos en este circuito. + + + Etat inconnu... + Estado desconocido... + + + Le module assurant le pilotage de ce circuit n'est pas accessible !<br /><br />Si des ajouts/suppression/déplacements de modules ont eu lieu récemment, mettez à jour la configuration correspondant dans le menu [Réseau ShipHeart] de [Paramètres Avancés].<br /><br />Dans le cas où aucune modification n'a été effectuée récemment, vérifier les connexions de tous les modules. + ¡No se puede acceder al módulo que controla este circuito!<br /><br />Si se agregaron/eliminaron/movieron módulos recientemente, actualice la configuración correspondiente en el menú [Red ShipHeart] de [Configuración avanzada].<br />< br />En caso de que no se hayan realizado cambios recientemente, verifique las conexiones de todos los módulos. + + + Ce circuit est configuré comme <i>Non Affecté</i> et n'est donc pas accessible !<br /><br />Pour accéder à nouveau à ce circuit, merci de l'affecter à un circuit disponible dans le menu [Circuits] de [Paramètres Avancés]. + ¡Este circuito está configurado como <i>Sin asignar</i> y, por lo tanto, no es accesible!<br /><br />Para acceder a este circuito nuevamente, asígnelo a un circuito disponible en el menú [Circuitos] de [Configuración avanzada ]. + + + Aucune consommation d'énergie sur cette période... + No hay consumo de energía durante este periodo... + + + Le module pilotant ce circuit n'est pas alimentée correctement. + Vérifier l'alimentation correspondante. + El módulo que controla este circuito no está correctamente alimentado. + Compruebe la fuente de alimentación correspondiente. + + + Le module pilotant ce circuit est en mode MANUEL. + Repositionnez le module en mode AUTO pour commander à nouveau ce circuit normalement. + El módulo que controla este circuito está en modo MANUAL. + Vuelva a poner el módulo en modo AUTO para controlar este circuito normalmente. + + + Le port USB du bas est en défaut. + El puerto USB inferior está defectuoso. + + + Le port USB du milieu est en défaut. + El puerto USB central está averiado. + + + Les 2 ports USB du milieu et du bas sont en défaut. + Los 2 puertos USB del medio y de abajo están defectuosos. + + + Le port USB du haut est en défaut. + El puerto USB superior está defectuoso. + + + Les 2 ports USB du haut et du bas sont en défaut. + Los 2 puertos USB de la parte superior e inferior están defectuosos. + + + Les 2 ports USB du haut et du milieu sont en défaut. + Los 2 puertos USB en la parte superior y en el centro están defectuosos. + + + Les 3 ports USB du haut, du milieu et du bas sont en défaut. + Los 3 puertos USB de la parte superior, central e inferior están defectuosos. + + + Le port USB est en défaut. + El puerto USB está averiado. + + + La masse est absente du connecteur d'alimentation du module + Falta la toma de tierra en el conector de alimentación del módulo + + + Evènements actuellement actifs qui sont susceptibles de commander ce circuit : + Eventos actualmente activos que probablemente controlen este circuito: + + + Non défini + No definido + + + DANGER : Le neutre n'est pas référencé à la terre sur ce circuit ("absence de terre"). + PELIGRO: El neutro no está referenciado a tierra en este circuito («sin tierra»). + + + + config_acces_parametres + + Configuration de l'accès aux paramètres avancés + Configurar el acceso a los ajustes avanzados + + + Durée de maintien de l'accès + Duración del acceso + + + Nouveau code + Nuevo código + + + Code d'accès + Código de acceso + + + Répéter le code d'accès + Repetir código de acceso + + + Enregistrer + Regístrese en + + + Aucune (saisie du code à chaque accès) + Ninguno (código introducido cada vez que se concede el acceso) + + + 1 minute + 1 minuto + + + 5 minutes + 5 minutos + + + 15 minutes + 15 minutos + + + 1 heure + 1 hora + + + Infinie (aucune protection des paramètres avancés) + Infinito (sin protección de ajustes avanzados) + + + Les deux valeurs saisies doivent être identiques ! + +De plus, le code doit contenir : +- %1 chiffres au minimum +- %2 chiffres au maximum. + Los dos valores introducidos deben ser idénticos. + +Además, el código debe contener : +- %1 dígitos como mínimo +- %2 dígitos como máximo. + + + Le nouveau code doit contenir : +- %1 chiffres au minimum +- %2 chiffres au maximum. + +Le code saisi ne répond pas à ces critères et sa mise à jour n'est donc pas effectuée. + +Merci de saisir un code au format valide si vous souhaitez le modifier. + El nuevo código debe contener : +- %1 dígitos mínimo +- %2 dígitos como máximo. + +El código introducido no cumple estos criterios y no será actualizado. + +Introduzca un código válido si desea modificarlo. + + + + config_affichage + + Configuration de l'affichage + Configuración de la pantalla + + + Temporisaton économiseur d'écran + Temporizador de salvapantallas + + + Enregistrer + Regístrese en + + + 15 secondes + 15 segundos + + + 30 secondes + 30 segundos + + + 1 minute + 1 minuto + + + 3 minutes + 3 minutos + + + 10 minutes + 10 minutos + + + Aucune limite + Sin límite + + + Nom du bateau + Nombre del barco + + + Fuseau horaire + Huso horario + + + Thème d'affichage + Mostrar tema + + + UTC-12 (Yankee) + UTC-12 (Yankee) + + + UTC-11 (X-Ray) + UTC-11 (Rayos X) + + + UTC-10 (Whisky) + UTC-10 (Whisky) + + + UTC-9 (Victor) + UTC-9 (Victor) + + + UTC-8 (Uniform) + UTC-8 (Uniforme) + + + UTC-7 (Tango) + UTC-7 (Tango) + + + UTC-6 (Sierra) + UTC-6 (Sierra) + + + UTC-5 (Romeo) + UTC-5 (Romeo) + + + UTC-4 (Quebec) + UTC-4 (Quebec) + + + UTC-3 (Papa) + UTC-3 (Papá) + + + UTC-2 (Oscar) + UTC-2 (Oscar) + + + UTC-1 (November) + UTC-1 (noviembre) + + + UTC (Zoulou) + UTC (zulú) + + + UTC+1 (Alpha) + UTC+1 (Alfa) + + + UTC+2 (Bravo) + UTC+2 (Bravo) + + + UTC+3 (Charlie) + UTC+3 (Charlie) + + + UTC+4 (Delta) + UTC+4 (Delta) + + + UTC+5 (Echo) + UTC+5 (Eco) + + + UTC+6 (Foxtrot) + UTC+6 (Foxtrot) + + + UTC+7 (Golf) + UTC+7 (Golf) + + + UTC+8 (Hotel) + UTC+8 (Hotel) + + + UTC+9 (India) + UTC+9 (India) + + + UTC+10 (Kilo) + UTC+10 (Kilo) + + + UTC+11 (Lima) + UTC+11 (Lima) + + + UTC+12 (Mike) + UTC+12 (Mike) + + + + config_audio + + Bips de clic + Pitidos de clic + + + Fonctionnement de la sortie Audio + Funcionamiento de la salida de audio + + + Enregistrer + Regístrese en + + + Aucun bip + Sin pitido + + + Bip par défaut + Pitido predeterminado + + + Bip 2 + Bip 2 + + + Bip 3 + Bip 3 + + + Bip 4 + Bip 4 + + + Bip 5 + Bip 5 + + + Bip 6 + Bip 6 + + + Bip 7 + Bip 7 + + + Bip 8 + Bip 8 + + + Bip 9 + Bip 9 + + + Bip 10 + Bip 10 + + + Bip 11 + Bip 11 + + + Bip 12 + Bip 12 + + + Bip 13 + Bip 13 + + + Bip 14 + Bip 14 + + + Configuration audio + Configuración de audio + + + Le son de ShipBase est coupé. Le son est uniquement diffusé sur la sortie AUDIO + El sonido de ShipBase se silencia. El sonido sólo se emite en la salida AUDIO + + + Le son est diffusé sur ShipBase et sur la sortie AUDIO + El sonido se emite en ShipBase y en la salida AUDIO + + + + config_batterie + + Nom de la batterie + Nombre de la batería + + + Tension nominale + Tensión nominal + + + Créer la batterie + Crear la batería + + + Enregistrer + Regístrese en + + + Supprimer + Borrar + + + Confirmer + Confirme + + + Etalonner + Calibre + + + Non défini + No definido + + + ShipBS [@ %1] + ShipBS [@ %1] + + + Entrée VOLT n° %1 + Entrada VOLT n° %1 + + + Plomb - Acide liquide + Plomo - Ácido líquido + + + Plomb - AGM / VRLA + Plomo - AGM / VRLA + + + Plomb - Gel + Plomo - Gel + + + Plomb - Carbone + Plomo - Carbono + + + Lithium + Litio + + + 12V + 12V + + + 24V + 24V + + + Création d'un parc de batteries + Creación de un banco de baterías + + + Configuration du parc de batteries + Configuración del banco de baterías + + + Point de mesure + Punto de medición + + + Type de batterie(s) + Tipos de batería + + + La modification du <b>type</b> de batterie(s) va nécessiter la remise en <i>configuration usine</i> de certains paramètres.<br /><br />Si vous ne souhaitez pas que cette reconfiguration soit effectuée, notamment si vous avez effectué des réglages spécifiques, cliquez sur ANNULER. <br /><br />Sinon, cliquez sur CONFIRMER pour valider le changement. + Cambiar el <b>tipo</b> de batería(s) requerirá restablecer ciertos parámetros a la <i>configuración de fábrica</i>.<br /><br />Si no desea que se realice esta reconfiguración, especialmente si ha realizado configuraciones específicas, haga clic en CANCELAR. <br /><br />De lo contrario, haga clic en CONFIRMAR para validar el cambio. + + + La modification de la <b>tension nominale</b> du parc de batteries va nécessiter la remise en <i>configuration usine</i> de certains paramètres.<br /><br />Si vous ne souhaitez pas que cette reconfiguration soit effectuée, notamment si vous avez effectué des réglages spécifiques, cliquez sur ANNULER. <br /><br />Sinon, cliquez sur CONFIRMER pour valider le changement. + Cambiar el <b>voltaje nominal</b> del banco de baterías requerirá restablecer ciertos parámetros a la <i>configuración de fábrica</i>.<br /><br />Si no desea que se realice esta reconfiguración, especialmente si ha realizado configuraciones específicas, haga clic en CANCELAR. <br /><br />De lo contrario, haga clic en CONFIRMAR para validar el cambio. + + + Capacité + Capacidad + + + Ah + Ah + + + Masquer les paramètres avancés + Ocultar configuración avanzada + + + Afficher les paramètres avancés + Mostrar configuración avanzada + + + Coefficient correcteur d'entrée de tension + Coeficiente de corrección de entrada de voltaje + + + + + + + Caractéristiques du parc de batteries + Características del banco de baterías + + + Durée correspondant à la capacité + Duración correspondiente a la capacidad + + + h + h + + + Capacité 2 + Capacidad 2 + + + Durée de capacité 2 + Capacidad Duración 2 + + + Coefficient de Peukert + coeficiente de peukert + + + Résistance interne + Resistencia interna + + + mΩ + mΩ + + + Soh actuel + Soh actual + + + % + % + + + Paramètres de pleine charge + Configuración de carga completa + + + Tension mini pleine charge + Tensión mínima de carga completa + + + V + V + + + Courant maxi pleine charge + Corriente máxima de carga completa + + + A + A + + + Temporisation pleine charge + Retraso de carga completa + + + s + s + + + Efficacité de charge + Eficiencia de carga + + + Caractéristiques de charge nulle + Características de carga cero + + + Tension de détection charge nulle + Tensión de detección de carga cero + + + Temporisation charge nulle + Retraso de carga cero + + + Historique + Histórico + + + Nombre de cycles de charge + Número de ciclos de carga + + + Nombre de décharges complètes + Número de altas completas + + + Forcer Pleine Charge + Forzar carga completa + + + Réinitialiser SOH + Restablecer SOH + + + Réinitialiser Compteurs + Restablecer contadores + + + Non définie + No definido + + + Groupe de batteries + Batería + + + Alimentation %1 + Alimentación %1 + + + Cette batterie est utilisée par l'évènement ci-dessous.<br />Vous devez modifier ou supprimer cet évènement pour qu'il ne dépende plus de cette batterie avant de pouvoir la supprimer. + Esta pila es utilizada por el evento de abajo.<br />Debe modificar o eliminar este evento para que ya no dependa de esta pila antes de poder eliminarlo. + + + Cette batterie est utilisée par les %1 évènements ci-dessous.<br />Vous devez modifier ou supprimer ces évènements pour qu'ils ne dépendent plus de cette batterie avant de pouvoir la supprimer. + Esta pila es utilizada por los eventos %1 a continuación.<br />Debe modificar o eliminar estos eventos para que ya no dependan de esta pila antes de poder eliminarla. + + + Cette batterie est utilisée par le capteur calculé ci-dessous.<br />Vous devez modifier ou supprimer ce capteur calculé pour qu'il ne dépende plus de cette id_batterie avant de pouvoir la supprimer. + Esta batería es utilizada por el sensor calculado a continuación.<br />Debe modificar o eliminar este sensor calculado para que ya no dependa de este id de batería antes de poder eliminarlo. + + + Cette id_batterie est utilisée par les %1 capteurs calculés ci-dessous.<br />Vous devez modifier ou supprimer ces capteurs calculés pour qu'ils ne dépendent plus de cette id_batterie avant de pouvoir la supprimer. + Este id de batería es utilizado por los sensores %1 calculados a continuación.<br />Debe modificar o eliminar estos sensores calculados para que ya no dependan de este id de batería antes de poder eliminarlo. + + + Ok + OK + + + 48V + 48V + + + + config_batteries + + Configuration des batteries + Configuración de la batería + + + Aucune batterie n'est encore configurée... + Todavía no está configurada la batería... + + + + + + + + + + config_capteur + + Création d'un capteur + Creación de un sensor + + + Configuration du capteur + Configuración de los sensores + + + Nom du capteur + Nombre del sensor + + + Affectation + Asignación + + + Masquer sur la page Capteurs + Ocultar en la página Sensores + + + Créer le capteur + Crear el sensor + + + Enregistrer + Regístrese en + + + Supprimer + Borrar + + + Etalonner + Calibre + + + Humidité + Humedad + + + GNSS - Latitude + GNSS - Latitud + + + GNSS - Longitude + GNSS - Longitud + + + GNSS - Altitude + GNSS - Altitud + + + Type de capteur + Tipo de sensor + + + Module + Módulo + + + Mode du capteur + Modo sensor + + + Groupe de capteurs + Grupo de sensores + + + Equation + Ecuación + + + Non défini + No definido + + + Entrées Auxiliaires (AUX INPUTS) + Entradas auxiliares (AUX INPUTS) + + + Entrées Niveau (LEVEL SENSORS) + Entradas de nivel (SENSORES DE NIVEL) + + + Entrées Tension (VOLTAGE INPUTS) + ENTRADAS DE TENSIÓN + + + Capteurs de température (ONE WIRE) + Sensores de temperatura (UN HILO) + + + Capteurs sur modules + Sensores en módulos + + + Calculé (conditions logiques) + Calculado (condiciones lógicas) + + + <i>Entrée non utilisée</i> + <i>Entrada no utilizada</i> + + + Pression Atmosphérique + Presión atmosférica + + + Température module + Temperatura del módulo + + + Tension d'entrée module + Tensión de entrada del módulo + + + Consommation module + Consumo del módulo + + + Consommation ports USB + Consumo del puerto USB + + + Chocs + Amortiguadores + + + Accélération X + X aceleración + + + Accélération Y + Aceleración Y + + + Accélération Z + Aceleración Z + + + GNSS - SOG<br />Speed Over Ground + GNSS - SOG<br />Velocidad sobre el suelo + + + GNSS - COG<br />Course Over Ground + GNSS - COG<br />Rumbo sobre el Terreno + + + GNSS - SIV<br />Satellites In View + GNSS - SIV<br />Satélites a la vista + + + GNSS - HPA<br />Horizontal Precision Accuracy + GNSS - HPA<br />Exactitud de precisión horizontal + + + GNSS - VPA<br />Vertical Precision Accuracy + GNSS - VPA<br />Exactitud de precisión vertical + + + Modem 4G/LTE - RSSI<br />Received Signal Strength Indicator + Módem 4G/LTE - RSSI<br />Indicador de intensidad de señal recibida + + + Modem 4G/LTE - SINR<br />Signal to Interference & Noise Ratio + Módem 4G/LTE - SINR<br />Relación señal/interferencia y ruido + + + Normal + Normal + + + Inversé + Invertido + + + Tension 0 - 10 V + Tensión 0 - 10 V + + + Résistance 0 - 500 Ohms + Resistencia 0 - 500 Ohmios + + + Courant 4 - 20 mA + Corriente 4 - 20 mA + + + Défaut d'isolement + Fallo de aislamiento + + + Ce capteur est utilisé par l'évènement ci-dessous.<br />Vous devez modifier ou supprimer cet évènement pour qu'il ne dépende plus de ce capteur avant de pouvoir le supprimer. + Este sensor es utilizado por el evento de abajo.<br />Debe modificar o eliminar este evento para que ya no dependa de este sensor antes de poder eliminarlo. + + + Ce capteur est utilisé par les %1 évènements ci-dessous.<br />Vous devez modifier ou supprimer ces évènements pour qu'ils ne dépendent plus de ce capteur avant de pouvoir le supprimer. + Este sensor es utilizado por los eventos %1 a continuación.<br />Debe modificar o eliminar estos eventos para que ya no dependan de este sensor antes de poder eliminarlo. + + + Ce capteur est utilisé par le capteur calculé ci-dessous.<br />Vous devez modifier ou supprimer ce capteur calculé pour qu'il ne dépende plus de ce capteur avant de pouvoir le supprimer. + Este sensor es utilizado por el sensor calculado a continuación.<br />Debe modificar o eliminar este sensor calculado para que ya no dependa de este sensor antes de poder eliminarlo. + + + Ce capteur est utilisé par les %1 capteurs calculés ci-dessous.<br />Vous devez modifier ou supprimer ces capteurs calculés pour qu'ils ne dépendent plus de ce capteur avant de pouvoir le supprimer. + Este sensor es utilizado por los sensores %1 calculados a continuación.<br />Debe modificar o eliminar estos sensores calculados para que ya no dependan de este sensor antes de poder eliminarlo. + + + %1 : Non définie + %1: No definido + + + %1 : %2 + %1 : %2 + + + Libellé du capteur pour la valeur %1 + Etiqueta del sensor para el valor %1 + + + Entrées NMEA2000 + Entradas NMEA2000 + + + + config_capteur_calcule_booleen + + Equation du capteur calculé [%1] + Ecuación calculada del sensor [%1] + + + Enregistrer + Regístrese en + + + Supprimer + Borrar + + + Le nombre de conditions par capteur est limité à %1.<br /><br />Vous ne pouvez pas ajouter de groupe ou de nouvelle condition avant d'en avoir supprimé préalablement. + El número de condiciones por sensor está limitado a %1.<br /><br />No puede añadir un grupo o una nueva condición hasta que no haya eliminado primero una. + + + Des modifications ont été apportées au capteur<br />mais n'ont pas été enregistrées.<br /><br />Cliquer sur ANNULER pour revenir au menu en cours.<br /><br />Cliquer sur Ok pour sortir sans enregistrer. + Se han realizado cambios en el sensor<br />pero no se han guardado.<br /><br />Haga clic en CANCELAR para volver al menú actual.<br /><br />Haga clic en Ok para salir sin guardar. + + + est actif + está activo + + + est inactif + está inactivo + + + Ou + O + + + Et + Y + + + X-Ou + X-Ou + + + + config_capteur_calcule_booleen_condition + + Création d'une condition du capteur [%1] + Creación de una condición de sensor [%1] + + + Type + Tipo + + + Source + Fuente + + + Variable + Variable + + + Test + Prueba + + + Seuil + Umbral + + + Créer la condition + Crear la condición + + + Enregistrer + Regístrese en + + + Non défini + No definido + + + Circuit + Circuito + + + Capteur + Sensor + + + Réservoir + Depósito + + + Batterie + Batería + + + Actif + Activos + + + Inactif + Inactivo + + + &lt; au seuil + &lt; en el umbral + + + &le; au seuil + en el umbral + + + = au seuil + = en el umbral + + + &ge; au seuil + en el umbral + + + &gt; au seuil + &gt; en el umbral + + + + config_capteurs + + Configuration des capteurs + Configuración de los sensores + + + Aucun capteur n'est encore configuré... + Aún no se ha configurado ningún sensor... + + + + + + + + + + config_circuit + + Configuration du circuit + Configuración del circuito + + + Nom du circuit + Nombre del circuito + + + Affectation + Asignación + + + Circuit renfort + Circuito de refuerzo + + + Mode de commande + Modo de control + + + Vitesse de démarrage/arrêt + Velocidad de arranque/parada + + + Seuil de disjonction + Umbral de disparo + + + Vitesse de disjonction + Velocidad de desconexión + + + Filtrage du courant consommé + Filtrado actual + + + Masquer sur la page d'accueil + Ocultar en la página de inicio + + + Créer le circuit + Crear el circuito + + + Enregistrer + Regístrese en + + + L'affectation du circuit vient d'être modifiée alors que le circuit était actif. +Avant d'effectuer ce changement, le circuit a été passé sur OFF. + +Pensez à le réactiver si besoin... + La asignación del circuito se acaba de cambiar mientras el circuito estaba activo. +Antes de realizar este cambio, el circuito estaba apagado. + +Recuerde reactivarlo si es necesario... + + + Supprimer + Borrar + + + Aucun + No + + + ShipPower812 [@ %1] + ShipPower812 [@ %1] + + + ShipPower4AC [@ %1] + ShipPower4AC [@ %1] + + + ShipPower8DC [@ %1] + ShipPower8DC [@ %1] + + + Circuit %1 + Circuito %1 + + + Groupe de circuits + Grupo de circuitos + + + %1 - %2 + %1 - %2 + + + Non affecté + Sin asignar + + + On-Off + Encendido y apagado + + + On-Off progressif + Encendido-apagado progresivo + + + Variateur + Regulador de intensidad + + + Aucun filtrage + Sin filtro + + + Très faible + Muy bajo + + + Faible + Bajo + + + Moyen + Medio + + + Elevé + Alta + + + Très élevé + Muy alta + + + Très rapide + Muy rápido + + + Rapide + Rápido + + + Moyenne + Media + + + Lente + Lento + + + Très lente + Muy lento + + + 15 secondes + 15 segundos + + + 1 minute + 1 minuto + + + 5 minutes + 5 minutos + + + 15 minutes + 15 minutos + + + 1 heure + 1 hora + + + 4 heures + 4 horas + + + L'utilisation d'un circuit de renfort rend l'utilisation du mode de commande [Variateur] impossible.<br /><br />Le mode de commande vient donc d'être ramené à [On-Off Progressif]. + El uso de un circuito de refuerzo hace imposible utilizar el modo de control [Dimmer].<br /><br />Por lo tanto, el modo de control acaba de volver a [On-Off progresivo]. + + + Commande impulsionnelle + Control de impulsos + + + Non + No + + + 1 seconde + 1 segundo + + + 2 secondes + 15 segundos {2 ?} + + + 5 secondes + 15 segundos {5 ?} + + + 30 secondes + 30 segundos + + + 45 secondes + 15 segundos {45 ?} + + + Ce circuit est utilisé pour la commande du moteur.<br />Vous devez d'abord affecter la commande moteur à un autre circuit avant de pouvoir supprimer celui-ci. + Este circuito se utiliza para controlar el motor.<br />Primero debe asignar el control del motor a otro circuito antes de poder borrar este. + + + Ce circuit est utilisé par l'évènement ci-dessous.<br />Vous devez modifier ou supprimer cet évènement pour qu'il ne dépende plus de ce circuit avant de pouvoir le supprimer. + Este circuito es utilizado por el evento de abajo.<br />Debes modificar o eliminar este evento para que ya no dependa de este circuito antes de poder eliminarlo. + + + Ce circuit est utilisé par les %1 évènements ci-dessous.<br />Vous devez modifier ou supprimer ces évènements pour qu'ils ne dépendent plus de ce circuit avant de pouvoir le supprimer. + Este circuito es utilizado por los eventos %1 a continuación.<br />Debe modificar o eliminar estos eventos para que ya no dependan de este circuito antes de poder eliminarlo. + + + Ce circuit est utilisé par le capteur calculé ci-dessous.<br />Vous devez modifier ou supprimer ce capteur calculé pour qu'il ne dépende plus de ce circuit avant de pouvoir le supprimer. + Este circuito es utilizado por el sensor calculado a continuación.<br />Debe modificar o eliminar este sensor calculado para que ya no dependa de este circuito antes de poder eliminarlo. + + + Ce circuit est utilisé par les %1 capteurs calculés ci-dessous.<br />Vous devez modifier ou supprimer ces capteurs calculés pour qu'ils ne dépendent plus de ce circuit avant de pouvoir le supprimer. + Este circuito es utilizado por los sensores %1 calculados a continuación.<br />Debe modificar o eliminar estos sensores calculados para que ya no dependan de este circuito antes de poder eliminarlo. + + + + config_circuits + + Configuration des circuits + Configuración del circuito + + + Pack de batteries : + Batería : + + + Aucun capteur n'est encore configuré... + Aún no se ha configurado ningún sensor... + + + Oui + + + + Non + No + + + Le module n'est affecté à aucune batterie... + El módulo no está asignado a ninguna batería... + + + Circuit non utilisé + Circuito no utilizado + + + Circuits Non Affectés + Circuitos no afectados + + + Ce circuit est configuré comme renfort du circuit <b>%1</b> et ne peut donc pas être configuré individuellement.<br /><br />Merci de cliquer sur le circuit <b>%1</b> de ce même module pour accéder à leurs paramètres communs<br />(y compris pour supprimer le circuit de renfort actuel). + Este circuito está configurado como reserva del circuito <b>%1</b> y, por lo tanto, no puede configurarse individualmente.<br /><br />Haga clic en el circuito <b>%1</b> de este mismo módulo para acceder a sus parámetros comunes<br />(incluida la eliminación del circuito de reserva actual). + + + Type de carte inconnu... + Tipo de tarjeta desconocido... + + + Le module <br /><b>%1</b><br /> n'est affecté à aucun pack de batteries. <br /><br />Souhaitez-vous laisser la configuration en l'état ? + El módulo <br /><b>%1</b><br /> no está asignado a ninguna batería. <br /><br />¿Quieres dejar la configuración como está? + + + Les modules suivants ne sont affectés à aucun pack de batteries :<br /><b>%1</b><br /><br /><br />Souhaitez-vous laisser la configuration en l'état ? + Los siguientes módulos no están asignados a ninguna batería:<br /><b>%1</b><br /><br /><br /><br />¿Desea dejar la configuración como está? + + + + config_event + + Création d'un évènement + Crear un evento + + + Configuration de l'évènement + Configuración de eventos + + + Nom de l'évènement + Nombre del acontecimiento + + + Type de la source + Tipo de fuente + + + Source + Fuente + + + Variable de la source + Fuente variable + + + Déclenchement si + Se activa si + + + Seuil de déclenchement + Umbral de activación + + + Temporisation de déclenchement + Retardo de activación + + + s + s + + + Masquer sur la page d'accueil + Ocultar en la página de inicio + + + Conditions horaire + Condiciones horarias + + + Le nombre maximal de conditions horaires [%1] est atteint : ajout impossible... + Se ha alcanzado el número máximo de condiciones de tiempo [%1]: no se puede añadir... + + + Aucune condition horaire n'est configurée pour cet évènement... + No se han configurado condiciones de tiempo para este evento... + + + Signalisation + Señalización + + + Alarme sonore + Alarma acústica + + + La validation des alarmes sonores a nécessité de valider également l'affichage des messages liés à cet évènement.<br /><br />Cet affichage est en effet nécessaire au fonctionnement des alarmes sonores, afin de pouvoir les acquitter. + La validación de las alarmas sonoras también implicó la validación de la visualización de los mensajes relacionados con este evento.<br /><br />Esta visualización es necesaria para que las alarmas sonoras funcionen, para que puedan ser reconocidas. + + + Alarme sur LED + Alarma LED + + + La validation des alarmes sur LED a nécessité de valider également l'affichage des messages liés à cet évènement.<br /><br />Cet affichage est en effet nécessaire au fonctionnement des alarmes sur LED, afin de pouvoir les acquitter. + Para validar las alarmas LED, también tuvimos que validar la visualización de mensajes relacionados con este evento.<br /><br />Esta visualización es necesaria para que las alarmas LED funcionen, para que puedan ser reconocidas. + + + Alarme sur sortie(s) de soutien + Alarma en salida(s) de apoyo + + + La validation des alarmes sur sortie(s) de soutien a nécessité de valider également l'affichage des messages liés à cet évènement.<br /><br />Cet affichage est en effet nécessaire au fonctionnement des alarmes sur sortie(s) de soutien, afin de pouvoir les acquitter. + Para validar las alarmas en la(s) salida(s) de apoyo, también era necesario validar la visualización de los mensajes relacionados con este evento.<br /><br />Esta visualización es, de hecho, necesaria para el funcionamiento de las alarmas en la(s) salida(s) de apoyo, con el fin de poder reconocerlas. + + + Alarme sur la source + Fuente alarma + + + Affichage message sur ShipBase + Visualización de mensajes en ShipBase + + + La dévalidation de l'affichage des messages a nécessité de dévalider également :<ul><li>les alarmes sonores,</li><li>les alarmes sur led</li><li>et les alarmes sur sortie(s) de soutien</li></ul><br />L'affichage de message est en effet nécessaire à leur fonctionnement, afin de pouvoir les acquitter. + Anular la visualización de mensajes significaba también anular:<ul><li>alarmas sonoras,</li><li>alarmas luminosas</li><li>y alarmas en salida(s) de apoyo</li><li>./li></ul><br />De hecho, la visualización de mensajes es necesaria para su funcionamiento, para poder acusar recibo de los mismos. + + + Texte du message à afficher + Texto del mensaje que se mostrará + + + Emission SMS + Transmisión de SMS + + + Texte du SMS à envoyer + Texto del SMS a enviar + + + Emission Email + Transmisión por correo electrónico + + + Texte de l'email à envoyer + Texto del correo electrónico que debe enviarse + + + Action sur circuits + Acción sobre los circuitos + + + Aucune + No + + + Le circuit "bascule" + El circuito "flip-flop + + + Le circuit passe à OFF + El circuito pasa a OFF + + + Le circuit passe à ON + El circuito pasa a ON + + + Le nombre de circuits commandés par un évènement est limité à %1.<br /><br />Vous ne pouvez pas ajouter d'action sur un nouveau circuit avant d'en avoir supprimé préalablement. + El número de circuitos controlados por un evento está limitado a %1.<br /><br />No puede añadir una acción a un circuito nuevo hasta que primero haya eliminado uno. + + + Créer l'évènement + Crear el evento + + + Enregistrer + Regístrese en + + + Supprimer + Borrar + + + Non défini + No definido + + + Condition horaire seule + Condición de sólo tiempo + + + Circuit + Circuito + + + Capteur + Sensor + + + Réservoir + Depósito + + + Batterie + Batería + + + Passage à <b>actif</b> + Cambia a <b>activo</b> + + + Passage à <b>inactif</b> + Cambia a <b>inactivo</b> + + + &lt; au seuil + &lt; en el umbral + + + &le; au seuil + &le; el umbral + + + = au seuil + = en el umbral + + + &ge; au seuil + &ge; el umbral + + + &gt; au seuil + &gt; en el umbral + + + + config_events + + Configuration des évènements + Configuración de eventos + + + Aucun évènement n'est encore configuré... + Aún no se ha configurado ningún evento... + + + 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. + El número total de eventos está limitado a %1.<br /><br />No puedes añadir un nuevo evento hasta que hayas eliminado uno. + + + Sur circuits + En circuitos + + + Sur capteurs + En los sensores + + + Sur réservoirs + En los tanques + + + Sur batteries + A pilas + + + Horaire seulement + Sólo horario + + + + config_groupe_elements + + Création d'un groupe + Crear un grupo + + + Modification d'un groupe + Modificar un grupo + + + Nom du groupe + Nombre del grupo + + + Créer le groupe + Crear un grupo + + + Enregistrer + Regístrese en + + + Supprimer + Borrar + + + capteurs + sensores + + + circuits + circuitos + + + 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). + Este grupo es el último aún válido.<br /><br />Sólo puede borrarlo después de crear al menos otro grupo (no es posible operar sin ningún grupo %1). + + + Ce groupe comprend encore %1 %2.<br /><br />Il est nécessaire d'affecter ces %2 à un autre groupe avant de pouvoir le supprimer. + Este grupo todavía incluye %1 %2.<br /><br />Estos %2 deben ser asignados a otro grupo antes de poder ser borrados. + + + 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. + Este grupo aún incluye %1 %2,<br />incluyendo %3 configurado como "oculto".<br /><br />Estos %2 deben ser asignados a otro grupo antes de poder ser eliminados. + + + batteries + pilas + + + réservoirs + depósitos + + + + config_image_accueil + + Image d'accueil + Imagen de inicio + + + Aucune image n'a encore été chargée... + Aún no se han subido imágenes... + + + Sélectionner l'image par défaut + Seleccionar imagen por defecto + + + Sélectionner cette image + Seleccione esta imagen + + + Copier + Copia + + + Supprimer + Borrar + + + Ejection + Expulsión + + + Insérer une clé USB dans le port <u>du bas</u>, à droite + Inserte una llave USB en el puerto <u>inferior</u> de la derecha + + + Vous pouvez retirer la clé en toute sécurité... + Puedes quitar la llave con seguridad... + + + Seuls les fichiers de type '.jpg' ou '.png' de taille inférieure à %1 sont autorisés. + Sólo se autorizan archivos '.jpg' o '.png' de tamaño inferior a %1. + + + La clé USB a été <i>éjectée</i> automatiquement.<br />Vous pouvez la retirer dès maintenant en toute sécurité... + La llave USB ha sido <i>expulsada automáticamente</i>.<br />Ya puede extraerla con seguridad... + + + USB Arrière + USB trasero + + + Spare + Recambio + + + USB Avant + USB frontal + + + Touch pad + Panel táctil + + + La clé USB a été retirée sans avoir préalablement été <i>éjectée</i> !<br />Cela peut conduire à des pertes de données sur la clé, voire sur ShipHeart.<br /><br />Lors de vos prochaines utilisations, pensez à <i>éjecter</i> la clé avec le bouton en haut de page avant de la retirer... Merci ! + Se ha extraído la llave USB sin <i>expulsarla</i> previamente<br />Esto puede provocar la pérdida de datos en la llave, e incluso en ShipHeart.<br /><br />La próxima vez que utilice la llave, recuerde <i>expulsarla</i> utilizando el botón situado en la parte superior de la página antes de extraerla.... ¡Muchas gracias! + + + + config_installation + + Configuration de l'installation + Configuración de la instalación + + + Raison sociale + Nombre de la empresa + + + N° & Rue + N° & Calle + + + Complément d'adresse + Dirección adicional + + + Code postal + Código postal + + + Ville + Ciudad + + + Nom du contact + Nombre de contacto + + + Téléphone + Teléfono + + + Email + Correo electrónico + + + Site web + Página web + + + Enregistrer + Regístrese en + + + Rapports + Informes + + + + config_koriolan + + Accès réservé Koriolan + Acceso reservado Koriolan + + + Client spécifique + Cliente específico + + + Enregistrer + Regístrese en + + + Nombre jours avant suppression historique + Número de días antes de que se borre el historial + + + Nombre jours avant suppression mesures + Número de días antes de las medidas de alejamiento + + + Période de sauvegarde BDD + Período de copia de seguridad de la base de datos + + + Période de vérification download + Descarga del periodo de verificación + + + Date de dernier archivage mesures + Fecha del último archivo de mediciones + + + Aucune spécificité + Ninguna especificidad + + + Client Suncy Concept + Cliente de Suncy Concept + + + Mode de mise à jour des firmwares + Modo de actualización del firmware + + + Tests matériel + Pruebas de hardware + + + Normal (si version installée est antérieure à la version en cours) + Normal (si la versión instalada es anterior a la actual) + + + Différente (si version installée est différente de version en cours) + Diferente (si la versión instalada es diferente de la actual) + + + Toujours (à utiliser avec modération...) + Siempre (con moderación...) + + + + config_module + + Emplacement du module à bord + Ubicación del módulo a bordo + + + Commentaires + Comentarios + + + Modifier + Modifique + + + Localiser le module + Localizar el módulo + + + Paramètres du module [%1] + Parámetros del módulo [%1] + + + Paramètres du module [%1] à l'adresse [%2] + Parámetros del módulo [%1] en la dirección [%2] + + + N° de série + Número de serie + + + Nom du firmware + Nombre del firmware + + + Version du firmware + Versión del firmware + + + Version matérielle + Versión del hardware + + + Résistance de terminaison + Resistencia de terminación + + + Oui + + + + Non + No + + + CRC du firmware + Firmware CRC + + + <i>--- Circuit non affecté ---</i> + <i>--- Circuito no afectado ---</i> + + + [renfort] + [reforzamiento] + + + Affectations + Asignación + + + <i>--- Aucune batterie affectée ---</i> + <i>--- Ninguna batería afectada ---</i> + + + Affectation + Asignación + + + Version processeur + Versión del procesador + + + Courant de masses sur réseau + Corriente de masas en red + + + + config_module_modification + + Configuration du module [%1] à l'adresse [%2] + Configuración del módulo [%1] en la dirección [%2] + + + Emplacement du module à bord + Ubicación del módulo a bordo + + + Commentaires + Comentarios + + + Enregistrer + Regístrese en + + + Courant de masses max. sur réseau + Corriente máxima de masa en la red + + + A + A + + + + config_ordre_elements + + 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... + Para desplazar un grupo, mantenga pulsado el botón del ratón y arrástrelo.<br />Para modificar o suprimir un grupo, haga doble clic en él.<br />Para añadir un grupo, haga clic en "+".<br /><br />Nota: si sólo hay un grupo, no aparece ninguna pestaña en la página correspondiente... + + + Aucun groupe n'est actuellement configuré... + Actualmente no hay grupos configurados... + + + Aucun élément n'est actuellement configuré... + No hay elementos configurados actualmente... + + + Aucun groupe de capteurs n'est actuellement configuré... + No hay grupos de sensores configurados... + + + Aucun groupe de circuits n'est actuellement configuré... + No hay grupos de circuitos configurados actualmente... + + + Aucun groupe de batteries n'est actuellement configuré... + No hay grupos de baterías configurados actualmente... + + + Aucune batterie n'est actuellement affectée à ce groupe... + Actualmente no hay baterías asignadas a este grupo... + + + Affichage des batteries sur la page d'accueil + Visualización de la batería en la página de inicio + + + Aucun capteur n'est actuellement affecté ce groupe... + Actualmente no hay sensores asignados a este grupo... + + + Affichage des capteurs sur la page d'accueil + Visualización de los sensores en la página de inicio + + + Aucun circuit n'est actuellement affecté à ce groupe... + Actualmente no hay circuitos asignados a este grupo... + + + Affichage des circuits sur la page d'accueil + Visitas guiadas en la página de inicio + + + Aucun groupe de réservoirs n'est actuellement configuré... + Actualmente no hay grupos de tanques configurados... + + + Aucun réservoir n'est actuellement affecté à ce groupe... + Actualmente no hay tanques asignados a este grupo... + + + Affichage des réservoirs sur la page d'accueil + Mostrar tanques en la página de inicio + + + + config_page + + Création d'une page + Creando una página + + + Configuration de la page + Configuración de página + + + Nom de la page + Nombre de la página + + + Opacité de la silhouette + Opacidad de la silueta + + + Fichier de silhouette + Archivo de silueta + + + Créer la page + crear la pagina + + + Enregistrer + Regístrese en + + + Silhouette + Silueta + + + Supprimer + Borrar + + + Aucun + No + + + + config_page_edition + + Edition de la page [%1] + Editando la página [%1] + + + Aucun équipement n'est configuré sur cette page pour le moment... + No hay ningún equipo configurado en esta página en este momento... + + + Page + Página + + + Enregistrer + Regístrese en + + + 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. + Ha realizado cambios que no se han guardado<br />Haga clic en Cancelar para volver atrás y guardarlos.<br />Haga clic en Aceptar para salir sin guardar. + + + + config_page_point + + Création d'un point + Creando un punto + + + Configuration du point + Configuración de puntos + + + Type de la source + Tipo de fuente + + + Source + Fuente + + + Type de point + tipo de puntada + + + Taille du point + Tamaño de punto + + + Enregistrer + Regístrese en + + + Créer le point + Crea el punto + + + Supprimer + Borrar + + + Non défini + No definido + + + Capteur + Sensor + + + Circuit + Circuito + + + Réservoir + Depósito + + + Batterie + Batería + + + Modules + Módulos + + + + config_page_silhouette + + Silhouette de la page + Silueta de página + + + Aucune image n'a encore été chargée... + Aún no se han subido imágenes... + + + Aucune image + Sin fotos + + + Sélectionner cette image + Seleccione esta imagen + + + Copier + Copia + + + Supprimer + Borrar + + + Ejection + Expulsión + + + Insérer une clé USB dans le port <u>du bas</u>, à droite + Inserte una llave USB en el puerto <u>inferior</u> de la derecha + + + Vous pouvez retirer la clé en toute sécurité... + Puedes quitar la llave con seguridad... + + + Seuls les fichiers de type '.jpg' ou '.png' de taille inférieure à %1 sont autorisés. + Sólo se autorizan archivos '.jpg' o '.png' de tamaño inferior a %1. + + + La clé USB a été <i>éjectée</i> automatiquement.<br />Vous pouvez la retirer dès maintenant en toute sécurité... + La llave USB ha sido <i>expulsada automáticamente</i>.<br />Ya puede extraerla con seguridad... + + + USB Arrière + USB trasero + + + Spare + Recambio + + + USB Avant + USB frontal + + + Touch pad + Panel táctil + + + La clé USB a été retirée sans avoir préalablement été <i>éjectée</i> !<br />Cela peut conduire à des pertes de données sur la clé, voire sur ShipHeart.<br /><br />Lors de vos prochaines utilisations, pensez à <i>éjecter</i> la clé avec le bouton en haut de page avant de la retirer... Merci ! + Se ha extraído la llave USB sin <i>expulsarla</i> previamente<br />Esto puede provocar la pérdida de datos en la llave, e incluso en ShipHeart.<br /><br />La próxima vez que utilice la llave, recuerde <i>expulsarla</i> utilizando el botón situado en la parte superior de la página antes de extraerla.... ¡Muchas gracias! + + + + config_pages + + Configuration des pages + Configuración de página + + + Aucune page n'est encore configurée... + Ninguna página está configurada todavía... + + + + + + + + + Image accueil + Imagen de inicio + + + + config_pdf + + Ship2net + Ship2net + + + Enregistrer + Regístrese en + + + + config_rapports + + Rapports d'installation + Informes de instalación + + + Aucun rapport d'installation n'est encore disponible... + Aún no hay informe de instalación... + + + Nouveau rapport d'installation + Informe de nueva instalación + + + Copier + Copia + + + Déplacer + Mover + + + Supprimer + Borrar + + + Ejection + Expulsión + + + Insérer une clé USB dans le port <u>du bas</u>, à droite + Inserte una llave USB en el puerto <u>inferior</u> de la derecha + + + Vous pouvez retirer la clé en toute sécurité... + Puedes quitar la llave con seguridad... + + + La clé USB a été <i>éjectée</i> automatiquement.<br />Vous pouvez la retirer dès maintenant en toute sécurité... + La llave USB ha sido <i>expulsada automáticamente</i>.<br />Ya puede extraerla con seguridad... + + + USB Arrière + USB trasero + + + Spare + Recambio + + + USB Avant + USB frontal + + + Touch pad + Panel táctil + + + La clé USB a été retirée sans avoir préalablement été <i>éjectée</i> !<br />Cela peut conduire à des pertes de données sur la clé, voire sur ShipHeart.<br /><br />Lors de vos prochaines utilisations, pensez à <i>éjecter</i> la clé avec le bouton en haut de page avant de la retirer... Merci ! + Se ha extraído la llave USB sin <i>expulsarla</i> previamente<br />Esto puede provocar la pérdida de datos en la llave, e incluso en ShipHeart.<br /><br />La próxima vez que utilice la llave, recuerde <i>expulsarla</i> utilizando el botón situado en la parte superior de la página antes de extraerla.... ¡Muchas gracias! + + + Le rapport d'installation<br /><br /><b>%1</b><br /><br />a été généré. + Se ha generado el informe de instalación<br /><br /><b>%1</b><br /><br />. + + + + config_reseau_ethernet_wifi + + Réseau Ethernet & Wifi + Red Ethernet y Wifi + + + Modifier + Modifique + + + Ethernet + Ethernet + + + Adresse IP + Dirección IP + + + Non connecté + No conectado + + + Connexion à un réseau existant + Conexión a una red existente + + + Etat + Estado + + + On + ON + + + Off + OFF + + + Nom du réseau [SSID] + Nombre de la red [SSID] + + + Génération d'un réseau spécifique + Generación de una red específica + + + Canal + Canal + + + + config_reseau_k_bus + + Réseau ShipHeart + Red ShipHeart + + + Modules physiquement présents + Módulos físicamente presentes + + + %1 - %2 + %1 - %2 + + + Modules utilisés par la configuration actuelle + Módulos utilizados por la configuración actual + + + [@ %1] : %2 + [@ %1] : %2 + + + La configuration actuelle ne fait appel à aucun autre module que ShipBase... + La configuración actual no utiliza ningún otro módulo que no sea ShipBase... + + + Module non utilisé en configuration + Módulo no utilizado en la configuración + + + [renfort] + [reforzamiento] + + + Enregistrer + Regístrese en + + + Retour + Atrás + + + Quitter + Dejar + + + Aucune modification n'a été apportée à la configuration actuelle.<br />Celle-ci contient toujours des anomalies !<br /><br /><br />Souhaitez-vous :<br />Poursuivre les modifications [%1]<br />Quitter ce menu sans enregistrer les modifications [%2] + No se han realizado cambios en la configuración actual.<br />¡Aún contiene anomalías!<br /><br /><br />Le gustaría:<br />Continuar realizando cambios [%1 ]<br / >Salir de este menú sin guardar los cambios [%2] + + + La configuration actuelle contient toujours des anomalies !<br /><br /><br />Souhaitez-vous :<br />Enregistrer cette nouvelle configuration et quitter ce menu [%1]<br />Poursuivre les modifications [%2]<br />Quitter ce menu sans enregistrer les modifications [%3] + ¡La configuración actual todavía contiene anomalías!<br /><br /><br />¿Le gustaría:<br />Guardar esta nueva configuración y salir de este menú [%1]<br />Continuar con las modificaciones [%2] ]<br />Salir de este menú sin guardar los cambios [%3] + + + La configuration actuelle est correcte <br />mais n'a pas encore été enregistrée.<br /><br /><br />Souhaitez-vous :<br />Enregistrer cette nouvelle configuration et quitter ce menu [%1]<br />Poursuivre les modifications [%2]<br />Quitter ce menu sans enregistrer les modifications [%3] + La configuración actual es correcta <br />pero aún no se ha guardado.<br /><br /><br />Le gustaría:<br />Guardar esta nueva configuración y salir de este menú [%1] < br />Continuar cambios [%2]<br />Salir de este menú sin guardar los cambios [%3] + + + + config_reseau_nmea + + Réseau NMEA2000 + Red NMEA2000 + + + Aucun PGN n'a encore été détecté sur le réseau NMEA2000... + Todavía no se ha detectado ningún PGN en la red NMEA2000... + + + PGN non affecté + PGN no asignado + + + + config_reseau_one_wire + + Réseau One Wire + Red One Wire + + + Aucune sonde n'est encore installée... + Aún no se ha instalado ninguna sonda... + + + 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. + El bus One Wire se detecta actualmente en cortocircuito. <br />Esta condición no presenta ningún peligro, pero impide su funcionamiento. <br /><br />Revise el cableado correspondiente hasta que desaparezca este mensaje. + + + Type inconnu + Tipo desconocido + + + Sonde non affectée + Sonda no asignada + + + + config_reseau_one_wire_modification + + Configuration de la sonde [%1] + Configuración del sensor [%1] + + + Emplacement de la sonde + Localización de la sonda + + + Enregistrer + Regístrese en + + + + config_reseau_wifi_ap + + Configuration Wifi en mode AP + Configuración Wifi en modo AP + + + Etat + Estado + + + Nom du réseau (SSID) + Nombre de la red (SSID) + + + Mot de passe d'accès au réseau + Contraseña de acceso a la red + + + Canal + Canal + + + Adresse IP + Dirección IP + + + Non connecté + No conectado + + + Enregistrer + Regístrese en + + + Off + OFF + + + On + ON + + + Canal %1 - [%2GHz] + Canal %1 - [%2GHz] + + + Le nom du réseau (SSID) doit comprendre entre 1 et 32 caractères. <br />Merci d'entrer un nom valide. + El nombre de la red (SSID) debe tener entre 1 y 32 caracteres. <br />Introduzca un nombre válido. + + + 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. + La contraseña de acceso a la red debe tener entre 8 y 63 caracteres. <br />Introduzca una contraseña válida. + + + 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. + El nombre de la red (SSID) debe incluir únicamente:<br />- letras mayúsculas [A - Z],<br />- letras minúsculas [a - z],<br />- dígitos [0 - 9]<br />- caracteres especiales [%1].<br /><br />Introduzca un nombre válido. + + + 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. + La contraseña de acceso a la red sólo debe contener:<br />- letras mayúsculas [A - Z],<br />- letras minúsculas [a - z],<br />- números [0 - 9]<br />- caracteres especiales [%1].<br /><br />Introduzca un nombre válido. + + + + config_reseau_wifi_sta + + Configuration Wifi en mode STA + Configuración Wifi en modo STA + + + Etat + Estado + + + Réseau + Red + + + Mot de passe d'accès au réseau + Contraseña de acceso a la red + + + Enregistrer + Regístrese en + + + Réseaux connus + Redes conocidas + + + Off + OFF + + + On + ON + + + Aucun réseau... + No hay red... + + + + config_reseau_wifi_sta_liste + + Liste des réseaux Wifi connus + Lista de redes Wifi conocidas + + + Aucun réseau n'a été détecté... + No se ha detectado ninguna red... + + + Oublier tous les réseaux + Olvídate de todas las redes + + + Oublier ce réseau + Olvida esta red + + + + config_reservoir + + Création d'un réservoir + Creación de un embalse + + + Configuration du réservoir + Configuración del depósito + + + Nom du réservoir + Nombre del embalse + + + Famille de réservoirs + Familia de tanques + + + Type de capteur de niveau + Tipo de sensor de nivel + + + %1 : Non définie + %1: No definido + + + %1 : %2 + %1 : %2 + + + Sonde la plus basse dans le réservoir + Sonda más baja del depósito + + + Non définie + No definido + + + Logique d'alarme + Lógica de alarma + + + Filtrage des mesures + Filtrado de medidas + + + Créer le réservoir + Creación del depósito + + + Enregistrer + Regístrese en + + + Supprimer + Borrar + + + Etalonnage + Calibración + + + AUX INPUT %1 + ENTRADA AUX %1 + + + LEVEL SENSOR %1 + SENSOR DE NIVEL %1 + + + Confirmer + Confirme + + + Non défini + No definido + + + Electrodes plongées ou contacts secs + Electrodos sumergidos o contactos secos + + + Résistif 0 - 190Ω + Resistivo 0 - 190Ω + + + Résistif 240 - 30Ω + Resistiva 240 - 30Ω + + + Boucle de courant 4 - 20mA + Bucle de corriente 4 - 20 mA + + + Tension 0 - 10V + Tensión 0 - 10V + + + Aucun filtrage + Sin filtro + + + Très faible + Muy bajo + + + Faible + Bajo + + + Moyen + Medio + + + Elevé + Alta + + + Très élevé + Muy alta + + + Alerte sur niveau faible + Alerta de nivel bajo + + + Alerte sur niveau élevé + Alerta de nivel alto + + + Capacité du réservoir + Capacidad del depósito + + + litres + litros + + + Logique des entrées inversée + Lógica de entrada inversa + + + La modification du <b>type de capteur</b> va nécessiter la remise en <i>configuration usine</i> de tous les paramètres du réservoir.<br /><br />Si vous ne souhaitez pas que cette reconfiguration soit effectuée, cliquez sur ANNULER. <br /><br />Sinon, cliquez sur CONFIRMER pour valider le changement. + Para cambiar el <b>tipo de sensor</b> será necesario restablecer todos los parámetros del depósito a la <i>configuración de fábrica</i>.<br /><br />Si no desea que se lleve a cabo esta reconfiguración, haga clic en CANCELAR. <br /><br />Si no es así, haga clic en CONFIRMAR para confirmar el cambio. + + + Ce réservoir est utilisé par l'évènement ci-dessous.<br />Vous devez modifier ou supprimer cet évènement pour qu'il ne dépende plus de ce réservoir avant de pouvoir le supprimer. + Este depósito es utilizado por el evento de abajo.<br />Debe modificar o eliminar este evento para que ya no dependa de este depósito antes de poder eliminarlo. + + + Ce réservoir est utilisé par les %1 évènements ci-dessous.<br />Vous devez modifier ou supprimer ces évènements pour qu'ils ne dépendent plus de ce réservoir avant de pouvoir le supprimer. + Este depósito es utilizado por los eventos %1 a continuación.<br />Debe modificar o eliminar estos eventos para que ya no dependan de este depósito antes de poder eliminarlo. + + + Ce réservoir est utilisé par le capteur calculé ci-dessous.<br />Vous devez modifier ou supprimer ce capteur calculé pour qu'il ne dépende plus de ce réservoir avant de pouvoir le supprimer. + Este tanque es utilizado por el sensor calculado a continuación.<br />Debe modificar o eliminar este sensor calculado para que ya no dependa de este tanque antes de poder eliminarlo. + + + Ce réservoir est utilisé par les %1 capteurs calculés ci-dessous.<br />Vous devez modifier ou supprimer ces capteurs calculés pour qu'ils ne dépendent plus de ce réservoir avant de pouvoir le supprimer. + Este depósito es utilizado por los sensores %1 calculados a continuación.<br />Debe modificar o eliminar estos sensores calculados para que ya no dependan de este depósito antes de poder eliminarlo. + + + Résistif 0 - 700Ω + Resistiva 0 - 700Ω + + + + config_reservoirs + + Configuration des réservoirs + Configuración del depósito + + + Aucun réservoir n'est encore configuré... + Aún no se ha configurado ningún tanque... + + + + + + + + + + config_ship2net + + Ship2net + Ship2net + + + Période des sauvegardes + Período de reserva + + + Mode de validation des mises à jour + Actualizar el modo de validación + + + Enregistrer + Regístrese en + + + Jamais + Nunca + + + 30 minutes + 30 minutos + + + 1 heure + 1 hora + + + 2 heures + 2 horas + + + 4 heures + 4 horas + + + 12 heures + 12 horas + + + 24 heures + 24 horas + + + Aucune mise à jour + No hay actualizaciones + + + Validation manuelle des mises à jour reçues + Validación manual de las actualizaciones recibidas + + + Validation automatique des mises à jour reçues + Validación automática de las actualizaciones recibidas + + + Période de connexion à Ship2net + Período de conexión de Ship2net + + + 10 minutes + 10 minutos + + + Accès distant WebGL #1 + Acceso remoto WebGL nº 1 + + + Accès distant WebGL #2 + Acceso remoto WebGL nº 2 + + + Accès distant WebGL #3 + Acceso remoto WebGL nº 3 + + + 2 minutes + 2 minutos + + + Dévalidé + Devaluado + + + Valide [port %1] + Válido [puerto %1] + + + + config_specifique_client_suncy + + Configuration spécifique à Suncy Concept + Configuración específica de Suncy Concept + + + Circuit d'activation moteur + Circuito de activación del motor + + + Nouveau code + Nuevo código + + + Code d'accès au bateau + Código de acceso al barco + + + Répéter le code d'accès + Repetir código de acceso + + + Enregistrer + Regístrese en + + + Aucune + No + + + [module %1 - circuit %2] %3 + [módulo %1 - circuito %2] %3 + + + Les deux valeurs saisies doivent être identiques ! + +De plus, le code doit contenir : +- %1 chiffres au minimum +- %2 chiffres au maximum. + Los dos valores introducidos deben ser idénticos. + +Además, el código debe contener : +- %1 dígitos como mínimo +- %2 dígitos como máximo. + + + Le nouveau code doit contenir : +- %1 chiffres au minimum +- %2 chiffres au maximum. + +Le code saisi ne répond pas à ces critères et sa mise à jour n'est donc pas effectuée. + +Merci de saisir un code au format valide si vous souhaitez le modifier. + El nuevo código debe contener : +- %1 dígitos mínimo +- %2 dígitos como máximo. + +El código introducido no cumple estos criterios y no será actualizado. + +Introduzca un código válido si desea modificarlo. + + + + config_valeurs_niveaux + + Aucun point de conversion n'est configuré pour le moment... + Aún no se han configurado puntos de conversión... + + + Courbe usine + Curva de fábrica + + + Enregistrer + Regístrese en + + + Aucune donnée n'est disponible... + No hay datos disponibles... + + + 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. + Ha realizado cambios que no se han guardado<br />Haga clic en Cancelar para volver atrás y guardarlos.<br />Haga clic en Aceptar para salir sin guardar. + + + Aucun point n'est actuellement configuré pour cette batterie... + Actualmente no hay puntos configurados para esta batería... + + + Courbe de conversion de [%1] + Curva de conversión para [%1] + + + Aucun réservoir n'est actuellement configuré... + Actualmente no hay ningún tanque configurado... + + + Aucun point n'est actuellement configuré pour cet élément... + Actualmente no hay puntos configurados para este elemento... + + + Courbe de conversion de type INCONNU + Tipo UNKNOWN curva de conversión + + + La valeur lue sur les electrodes plongées de ce réservoir est incohérente.<br />Vérifier l'ordre de cablage des électrodes sur les entrées auxiliaires à l'arrière de ShipBase. + El valor leído en los electrodos sumergidos de este depósito es incoherente. <br />Compruebe el orden de cableado de los electrodos en las entradas auxiliares de la parte trasera de ShipBase. + + + Le nombre maximal de points d'étalonnage a été atteint (%1 points)<br />Vous ne pouvez pas en ajouter sans en avoir prélablement supprimé. + Se ha alcanzado el número máximo de puntos de calibración (1% de puntos)<br />No puede agregar ninguno sin antes eliminar algunos. + + + + config_version + + Version + Versión + + + %1 : %2 + %1 : %2 + + + 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 : + La versión <b>%1</b> está disponible.<br /><br />Se instalará automáticamente la próxima vez que se inicie ShipHeart.<br />A menos que elija una de las opciones siguientes: + + + La version <b>%1</b> est disponible.<br /><br />Souhaitez-vous : + La versión <b>%1</b> está disponible.<br /><br />¿Desea : + + + L'installer +maintenant + Instalarlo + Ahora + + + L'installer au prochain démarrage de ShipHeart + Instálalo la próxima vez que inicies ShipHeart + + + Ne jamais l'installer + Nunca lo instale + + + 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 'shipheart.tech' ou de nous contacter à l'adresse 'contact@shipheart.tech'. + Este producto está diseñado y fabricado por la empresa Koriolan, que posee todas las licencias y derechos de explotación sobre las imágenes, software y patentes utilizadas tanto para su diseño como para su funcionamiento. ShipHeart™, Ship2net™ y Koriolan™ son marcas registradas de Koriolan. Si tiene alguna pregunta sobre este producto, visite 'shipheart.tech' o póngase en contacto con nosotros en 'contact@shipheart.tech'. + + + Version du package logiciel + Versión del paquete de software + + + Version de l'application + Versión de la aplicación + + + Version de l'interface graphique + Versión de interfaz gráfica + + + Version du firmware du modem + Versión del firmware del módem + + + Numéro d'IMEI + Número IMEI + + + Numéro d'ICCID + Número ICCID + + + Numéro d'IMSI + Número IMSI + + + Supprimer + Borrar + + + Si vous confirmez, cette mise à jour sera définitivement supprimée.<br />Cliquez sur Annuler pour revenir en arrière et la conserver. + Si confirma, esta actualización se eliminará permanentemente.<br />Haga clic en Cancelar para regresar y conservarla. + + + Installer + Instalar + + + 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 la conserver pour une installation ultérieure. + Si confirma, esta actualización puede tardar <u>unos minutos</u> durante los cuales <b>su sistema ShipHeart no estará accesible</b>.<br /><br />No necesita confirmar la instalación sólo si se encuentra en una situación segura (en puerto, fondeado, etc.) y la pérdida de control de sus sistemas a bordo durante este período de tiempo no presenta ningún peligro.<br /><br />Haga clic en Cancele para regresar y guardarlo para una instalación posterior. + + + + ephemeride + + Ephéméride + Efemérides + + + Heure d'hiver + Invierno + + + Heure d'été + Horario de verano + + + Aube nautique + Amanecer náutico + + + Lever du soleil + Amanecer + + + Zénith + Zenith + + + Coucher du soleil + Puesta de sol + + + Crépuscule nautique + Crepúsculo náutico + + + Lune + Luna + + + Latitude + Latitud + + + Longitude + Longitud + + + + etalonnage_capteur + + Etalonnage du capteur [%1] + Calibración del sensor [%1] + + + Valeur brute actuelle + Valor bruto actual + + + Valeur corrigée actuelle (%1) + Valor actual corregido (%1) + + + Correction + Corrección + + + Enregistrer + Regístrese en + + + + etalonnage_carte + + Etalonnage du module [%1 - #%2] + Calibración del módulo [%1 - #%2] + + + Point 1 + Punto 1 + + + Point 2 + Punto 2 + + + Courant de décharge + Corriente de descarga + + + Courant différentiel + Corriente diferencial + + + Recalculer ce point + Recalcular este punto + + + Mémoriser ce point + Recuerda este punto + + + Off + OFF + + + On + ON + + + On (%1 %%) + En (%1 %%) + + + Enregistrer + Regístrese en + + + Aide + Ayuda + + + 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 /> + La calibración no se puede realizar con dos puntos idénticos.<br /><br /> + Intente modificar al menos uno de los dos puntos de referencia ajustando los controles del circuito a continuación.<br /> + + + 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. + El principio de calibración consiste en comparar, en <u>2 puntos diferentes</u>, el valor de corriente diferencial medido por el ShipBS, por una parte, y la corriente de descarga medida por el sistema ShipHeart, por otra. la corriente de descarga medida por el sistema ShipHeart.<br /> Por ejemplo, sometiendo el ShipBS durante el calibrado a un consumo de energía bajo o nulo (primer punto) a continuación, haciendo funcionar uno o varios dispositivos para obtener un consumo de varios amperios si es posible (segundo punto).<br /> <br /><u><b>Muy importante</b>: ¡no debe aplicarse ninguna corriente de <b>carga</b> al ShipBS durante la fase de calibración!</u> Por lo tanto, es esencial desconectar todos los cargadores, reguladores solares, etc. del sistema durante la calibración. De lo contrario, los valores de calibración serán incorrectos...<br /><br /> Notas :<br /> - ¡todos los consumos deben pasar por el sistema ShipHeart! Por lo tanto, debe asegurarse de que ninguna carga esté conectada directamente al banco de baterías.<br /> - los valores de corriente no son importantes.<br /> - la corriente en el punto 2 puede ser inferior o superior a la del punto 1 (pero lo más alejada posible).<br /> - Es aconsejable elegir cargas cuyo consumo sea relativamente estable o, como mínimo, varíe poco en un periodo de unos segundos. + + + + fonctions + + Modèle inconnu + Modelo desconocido + + + Circuit + Circuito + + + Capteur + Sensor + + + Réservoir + Depósito + + + Batterie + Batería + + + Type inconnu + Tipo desconocido + + + Consigne + Instrucciones + + + Tension + Tensión + + + Courant + Actual + + + Fréquence + Frecuencia + + + Puissance + Potencia + + + Energie + Energía + + + Température + Temperatura + + + Courant différentiel + Corriente diferencial + + + Courant de charge + Corriente de carga + + + Courant de décharge + Corriente de descarga + + + SOH (state Of Health) + SOH (Estado de salud) + + + SOC (State Of Charge) + SOC (Estado de carga) + + + Autonomie + Autonomía + + + + fonctions_date_heure + + Dimanche + Domingo + + + Lundi + Lunes + + + Mardi + Martes + + + Mercredi + Miércoles + + + Jeudi + Jueves + + + Vendredi + Viernes + + + Samedi + Sábado + + + janvier + Enero + + + février + Febrero + + + mars + Marzo + + + avril + Abril + + + mai + Mayo + + + juin + Junio + + + juillet + Julio + + + août + Agosto + + + septembre + Septiembre + + + octobre + Octubre + + + novembre + Noviembre + + + décembre + Diciembre + + + 1 heure + 1 hora + + + 24 heures + 24 horas + + + 7 jours + 7 días + + + 30 jours + 30 días + + + Fin de nuit + Fin de la noche + + + Aube nautique + Amanecer náutico + + + Aube + Aube + + + Lever du soleil + Amanecer + + + Zénith + Zenith + + + Coucher du soleil + Puesta de sol + + + Crépuscule + Crepúsculo + + + Crépuscule nautique + Crepúsculo náutico + + + Début de nuit + Noche temprana + + + %1h + %1h + + + Tous les jours + Todos los días + + + + fonctions_historique + + Commande 'OFF' du circuit %1 + Comando "OFF" para el circuito %1 + + + Commande 'ON' du circuit %1 + Comando "ON" para el circuito %1 + + + Commande à %1 % du circuit %2 + Control %1% del circuito %2 + + + Le circuit %1 est revenu à son état de fonctionnement normal + El circuito %1 ha vuelto a su estado de funcionamiento normal + + + L'alimentation du circuit %1 a été coupée car sa limite de courant (%2 A) a été dépassée + La alimentación del circuito %1 se ha cortado porque se ha superado su límite de corriente (%2 A) + + + L'alimentation du circuit %1 a été coupée car les circuits de protection interne ont détecté une anomalie + Se ha cortado la alimentación del circuito %1 porque los circuitos internos de protección han detectado una anomalía + + + L'alimentation du circuit %1 a été coupée car le seuil de disjonction a été dépassé + La alimentación del circuito %1 se ha cortado porque se ha superado el umbral de disparo + + + Le circuit %1 est en court-circuit avec le + batterie + El circuito %1 está cortocircuitado con la batería + + + + L'alimentation du circuit %1 a été coupée car la consommation totale du module a été dépassé + Se ha cortado la alimentación del circuito %1 porque se ha superado el consumo total del módulo + + + Le circuit %1 a été créé + Se ha creado el circuito %1 + + + La configuration du circuit %1 a été modifiée + La configuración del circuito %1 ha sido modificada + + + Le circuit %1 a été supprimé + El circuito %1 ha sido eliminado + + + La configuration du circuit %1 est invalide car le module sur lequel le circuit est configuré n'est pas présent + La configuración del circuito %1 no es válida porque el módulo en el que está configurado el circuito no está presente + + + Le circuit %1 a fonctionné trop longtemps (> %2 secondes). Il a donc été désactivé automatiquement. + El circuito %1 ha estado funcionando durante demasiado tiempo (> %2 segundos). Por lo tanto, se ha desactivado automáticamente. + + + Evénement de type CIRCUITS avec code de sous-type inconnu [%1] + Evento CIRCUITOS con código de subtipo desconocido [%1] + + + Le capteur %1 est repassé à l'état normal + El sensor %1 ha vuelto al estado normal + + + Le capteur %1 est passé à l'état ALERTE + El sensor %1 ha pasado a estado de ALERTA + + + Le capteur %1 est passé à l'état ALARME + El sensor %1 ha pasado al estado de ALARMA + + + Evénement de type CAPTEURS avec code de sous-type inconnu [%1] + Evento CAPTORS con código de subtipo desconocido [%1] + + + Le niveau de charge de la batterie %1 est repassé au niveau normal + El nivel de carga de la batería %1 ha vuelto al nivel normal + + + Le niveau de charge de la batterie %1 est passé en dessous du niveau d'alerte + El nivel de carga de la batería %1 ha caído por debajo del nivel de alerta + + + Le niveau de charge de la batterie %1 est passé au-dessus du niveau d'alarme (il est maintenant au niveau d'alerte uniquement) + El nivel de carga de la batería %1 ha superado el nivel de alarma (ahora sólo está en el nivel de alerta) + + + Le niveau de charge de la batterie %1 est passé en-dessous du niveau d'alarme + El nivel de carga de la batería %1 ha caído por debajo del nivel de alarma + + + Evénement de type BATTERIES avec code de sous-type inconnu [%1] + Evento BATTERIES con código de subtipo desconocido [%1] + + + Le niveau du réservoir %1 est repassé au niveau normal + El nivel del depósito %1 ha vuelto al nivel normal + + + Le niveau du réservoir %1 est passé en dessous du niveau d'alerte + El nivel del depósito %1 ha caído por debajo del nivel de alerta + + + Le niveau du réservoir %1 est passé au-dessus du niveau d'alarme (il est maintenant au niveau d'alerte uniquement) + El nivel del depósito %1 ha superado el nivel de alarma (ahora sólo está en el nivel de alerta) + + + Le niveau du réservoir %1 est passé en-dessous du niveau d'alarme + El nivel del depósito %1 ha descendido por debajo del nivel de alarma + + + Evénement de type RESERVOIRS avec code de sous-type inconnu [%1] + Evento RESERVOIRS con código de subtipo desconocido [%1] + + + La consigne des ports USB est passée à %1 + La consigna del puerto USB se ha cambiado a %1 + + + L'état des ports USB est redevenu normal + El estado de los puertos USB ha vuelto a la normalidad + + + Défaut détecté sur les ports USB + Se ha detectado un fallo en el puerto USB + + + Evénement de type USB avec code de sous-type inconnu [%1] + Evento USB con código de subtipo desconocido [%1] + + + Evénement de type INCONNU (avec code de sous-type [%1] + Suceso UNKNOWN (con código de subtipo [%1]) + + + + home + + Démarrage + Inicio + + + Code inconnu + Código desconocido + + + Aucun circuit n'est configuré pour ce groupe...<br /><br />Si ce groupe n'a pas d'utilité, vous pouvez le supprimer dans le menu [Circuits] des Paramètres Avancés. + No hay ningún circuito configurado para este grupo...<br /><br />Si este grupo no tiene ninguna utilidad, puede eliminarlo en el menú [Circuitos] de Configuración avanzada. + + + Aucun capteur n'est configuré pour ce groupe...<br /><br />Si ce groupe n'a pas d'utilité, vous pouvez le supprimer dans le menu [Capteurs] des Paramètres Avancés. + No hay sensores configurados para este grupo...<br /><br />Si este grupo no es necesario, puede eliminarlo en el menú [Sensores] de Configuración avanzada. + + + Aucun réservoir n'est configuré pour ce groupe...<br /><br />Si ce groupe n'a pas d'utilité, vous pouvez le supprimer dans le menu [Réservoirs] des Paramètres Avancés. + No hay ningún tanque configurado para este grupo...<br /><br />Si este grupo no es necesario, puede eliminarlo desde el menú [Tanques] en Configuración avanzada. + + + Aucun parc de batterie n'est configuré pour ce groupe...<br /><br />Si ce groupe n'a pas d'utilité, vous pouvez le supprimer dans le menu [Batteries] des Paramètres Avancés. + No hay ningún parque de baterías configurado para este grupo...<br /><br />Si este grupo no tiene ninguna utilidad, puede eliminarlo en el menú [Baterías] de Configuración avanzada. + + + Cette page est actuellement en travaux. <br />Elle sera rendue disponible très rapidement à travers une mise à jour.<br /><br />Merci de votre patience...<br /><br />L'équipe ShipHeart + Esta página está actualmente en construcción. <br /><br />Gracias por su paciencia...<br /><br />El equipo de ShipHeart + + + Déconnecté + Desconectado + + + Nombre de satellites visibles + Número de satélites visibles + + + Connecté + En línea + + + OFF + OFF + + + ON + ON + + + Niveau + Nivel + + + Actif + Activos + + + Inactif + Inactivo + + + <b>%1</b> + <1%1</b> + + + Firmware de <b>ShipBase</b> + Firmware para <b>ShipBase</b> + + + Firmware du <b>ShipPower812</b> à l'adresse <b>%1</b> + Firmware para el <b>ShipPower812</b> en <b>%1</b> + + + Firmware du <b>ShipBS</b> à l'adresse <b>%1</b> + Firmware para <b>ShipBS</b> en <b>%1</b> + + + Firmware du <b>ShipPower4AC</b> à l'adresse <b>%1</b> + Firmware para el <b>ShipPower4AC</b> en <b>%1</b> + + + Firmware du <b>ShipPower8DC</b> à l'adresse <b>%1</b> + Firmware para el <b>ShipPower8DC</b> en <b>%1</b> + + + Firmware du module à l'adresse <b>%1</b> + Firmware del módulo en <b>%1</b> + + + Merci de patienter et de ne rien débrancher<br />avant la fin de la mise à jour. + Tenga paciencia y no desenchufe nada hasta que se complete la actualización. + + + Chargement des mises à jour effectué avec succès !<br /><br />L'activation des nouvelles version est en cours sur tous les modules concernés.<br /><br />Merci de patienter encore quelques secondes... + Actualizaciones cargadas correctamente<br /><br />Las nuevas versiones se están activando en todos los módulos afectados<br /><br />Por favor, espere unos segundos más... + + + ShipHeart va redémarrer pour effectuer une mise à jour.<br /><br />Cette opération va prendre quelques minutes au maximum.<br />Merci de patienter et de ne rien débrancher jusqu'au redémarrage final... + ShipHeart se reiniciará para realizar una actualización.<br /><br />Esta operación tardará unos minutos como máximo.<br />Por favor, sea paciente y no desenchufe nada hasta el reinicio final.... + + + Votre système ShipHeart est dorénavant équipé de la version<br /><br /><b>%1</b><br /><br />(la version précédente était la %2) + Su sistema ShipHeart está ahora equipado con la versión<br /><br /><b>%1</b><br /><br />(la versión anterior era %2) + + + Le nombre de modules détectés sur le réseau ShipHeart est insuffisant par rapport à la configuration du bateau.<br /><br />Vérifiez les connexions entre le module <b>%1</b> à la <b>position @%2</b> %3 et le module <b>%4</b> suivant%5<br /><br />Vous pouvez visualiser l'état complet du réseau ShipHeart et les anomalies détectées dans le menu 'Réseau > ShipHeart' dans les Paramètres Avancés + El número de módulos detectados en la red ShipHeart es insuficiente para la configuración de la nave.<br /><br />Comprueba las conexiones entre el módulo <b>%1</b> en la <b>posición @%2</b> %3 y el siguiente módulo <b>%4</b>%5<br /><br />.br />Puedes ver el estado completo de la red ShipHeart y cualquier anomalía detectada en el menú <b>Red > ShipHeart</b> de Configuración avanzada + + + Le modules détecté en <b>position @%1</b> est un <b>%2</b>. Cela ne correspond pas à la configuration actuelle du bateau (<b>%3</b>).<br /><br />Cela peut provenir de l'ajout, de la suppression ou d'un déplacement de module.<br /><br />Vous pouvez visualiser toutes les anomalies détectées et les corriger dans le menu 'Réseau > ShipHeart' dans les Paramètres Avancés + El módulo detectado en la <b>posición @%1</b> es un <b>%2</b>. No se corresponde con la configuración actual de la nave (<b>%3</b>).<br /><br />Esto puede deberse a que se ha añadido, eliminado o movido un módulo.<br /><br />Puedes ver todas las anomalías detectadas y corregirlas en el menú 'Red > ShipHeart' en Configuración avanzada + + + + home_accueil + + Bienvenue à bord de + Bienvenido a bordo + + + + home_suncy + + L'accès au bateau est protégé. +Merci d'entrer votre code de déverrouillage pour y accéder... + El acceso al barco está protegido. + Por favor ingrese su código de desbloqueo para acceder a él... + + + + journal_de_bord + + Tous + Todos + + + Batteries + Pilas + + + Capteurs + Sensores + + + Circuits + Circuitos + + + Réservoirs + Tanques + + + Système + Sistema + + + Ports USB + Puertos USB + + + Journal de bord + Bitácora + + + Aucun type n'est configuré... + No hay ningún tipo configurado... + + + %1<br /><br /><br />%2 + %1<br /><br /><br />%2 + + + Aucune entrée d'historique n'est disponible pour cette sélection... + No hay entradas de historial disponibles para esta selección... + + + Toutes + Todos + + + + main + + Type d'installation : +0 : ShipBase standard, +1 : écran déporté + Tipo de instalación: + 0: Base de envío estándar, + 1: pantalla remota + + + valeur + valor + + + Adresse IPv4 de ShipBase dans le cas d'une installation déportée + ShipBase Dirección IPv4 para instalación remota + + + xxx:xxx:xxx:xxx + xxx:xxx:xxx:xxx + + + Taille de l'écran en pouces : +7, +10 (ShipBase standard), +22 + Tamaño de pantalla en pulgadas: + 7, + 10 (Base de envío estándar), + 22 + + + Original + Original + + + Sombre + Oscuro + + + Métallique + Metálico + + + Triangles + Triángulos + + + Sable + Arena + + + Thème 5 + Tema 5 + + + Thème 6 + Tema 6 + + + Thème 7 + Tema 7 + + + Thème 8 + Tema 8 + + + + page_personnalisee + + <i>--- Circuit non affecté ---</i> + <i>--- Circuito no afectado ---</i> + + + [renfort] + [reforzamiento] + + + <i>--- Aucune batterie affectée ---</i> + <i>--- Ninguna batería afectada ---</i> + + + + parametres + + Paramètres + Parámetros + + + Langue + Idioma + + + Températures + Temperaturas + + + Volumes + Volúmenes + + + Affichage + Mostrar + + + Date et heure + Fecha y hora + + + Protection + Protección + + + Son + Sonido + + + Luminosité + Luminosidad + + + Economiseur d'écran : désactivé + Protector de pantalla: desactivado + + + Economiseur d'écran : normal + Protector de pantalla: normal + + + Flash LEDs : désactivé + LEDs de flash: desactivados + + + Flash LEDs : normal + LEDs intermitentes: normal + + + Nettoyage de l'écran + Limpieza de la pantalla + + + Heure d'été + Horario de verano + + + Heure d'hiver + Invierno + + + Verrouiller le bateau + Cerrar el barco + + + + parametres_avances + + Paramètres avancés + Configuración avanzada + + + Circuits + Circuitos + + + Réservoirs + Tanques + + + Batteries + Pilas + + + Capteurs + Sensores + + + Vos paramètres + Tu configuración + + + Votre installation + Su instalación + + + Système + Sistema + + + Affichage + Mostrar + + + Audio + Audio + + + Ship2net + Ship2net + + + Accès au paramètres + Acceso a los parámetros + + + Configuration ShipRS + Configuración ShipRS + + + Version + Versión + + + Accès réservé Koriolan + Acceso reservado Koriolan + + + Spécifique Suncy + Suncy específico + + + Réseaux + Redes + + + Cette page est actuellement en travaux. <br />Elle sera rendue disponible très rapidement à travers une mise à jour.<br /><br />Merci de votre patience...<br /><br />L'équipe ShipHeart + Esta página está actualmente en construcción. <br /><br />Gracias por su paciencia...<br /><br />El equipo de ShipHeart + + + Evènements + Eventos + + + ShipHeart + ShipHeart + + + Ethernet & Wifi + Ethernet y Wifi + + + One Wire + Un cable + + + NMEA 2000 + NMEA 2000 + + + J1939 + J1939 + + + DMX + DMX + + + Journal de bord + Bitácora + + + Installation + Instalación + + + Menu accueil + Menú de inicio + + + + protection + + Accès protégé + Acceso seguro + + + L'accès aux paramètres avancés est protégé. +Merci d'entrer le code de déverrouillage pour y accéder... + El acceso a la configuración avanzada está protegido. + Por favor ingrese el código de desbloqueo para acceder a él... + + + Mode administrateur validé<br />Entrer votre code dédié + Modo administrador activado<br />Introduzca su código dedicado + + + + reservoir + + [ %1 % ] + [ %1 % ] + + + Aucune donnée n'est disponible pour cette période + No hay datos disponibles para este periodo + + + Le module assurant la supervision de ce réservoir n'est pas accessible !<br /><br />Si des ajouts/suppression/déplacements de modules ont eu lieu récemment, mettez à jour la configuration correspondant dans le menu MODULES de PARAMETRES AVANCES.<br /><br />Dans le cas où aucune modification n'a été effectuée récemment, vérifier les connexions de tous les modules. + <br /><br />Si se han añadido/eliminado/movido módulos recientemente, actualice la configuración correspondiente en el menú MÓDULOS de PARÁMETROS AVANZADOS.<br /><br />Si no se han realizado cambios recientemente, compruebe las conexiones de todos los módulos. + + + Niveau + Nivel + + + La valeur lue sur les electrodes plongées de ce réservoir est incohérente.<br />Vérifier l'ordre de cablage des électrodes sur les entrées auxiliaires à l'arrière de ShipBase. + Compruebe el orden de cableado de los electrodos en las entradas auxiliares de la parte posterior de ShipBase. + + + + shipheart_test_config + + Vitesse de test de l'écran + Velocidad de la prueba de pantalla + + + Nombre de colonnes de test du touchpad + Número de columnas de prueba del panel táctil + + + Nombre de lignes de test du touchpad + Número de líneas de prueba del panel táctil + + + + shipheart_test_home + + Tests matériel + Pruebas de hardware + + + Configuration des tests + Configuración de prueba + + + Test du backlight + Prueba de retroiluminación + + + Test de l'écran + Prueba de pantalla + + + Test du touchpad + Prueba del panel táctil + + + Liste des fonts disponibles + Lista de fuentes disponibles + + + + shipheart_test_liste_fonts + + Liste des fonts disponibles + Lista de fuentes disponibles + + + + test_batterie + + Batteries de servitude + Baterías de servicio + + + Autonomie optimale + Autonomía óptima + + + Autonomie actuelle + Autonomía actual + + + Autonomie<br />maximale + Alcance máximo<br /> + + + dans + en + + + environ + acerca de + + + + test_tri_liste + + TEST DE TRI DE LISTE + TEST DE TRI DE LISTE + + + diff --git a/shipheart_fr_FR.qm b/shipheart_fr_FR.qm new file mode 100755 index 0000000..f57002d Binary files /dev/null and b/shipheart_fr_FR.qm differ diff --git a/shipheart_fr_FR.ts b/shipheart_fr_FR.ts new file mode 100755 index 0000000..41a02fa --- /dev/null +++ b/shipheart_fr_FR.ts @@ -0,0 +1,5477 @@ + + + + + Shipheart_boite_dialogue + + + OK + + + + + Annuler + + + + + Plus tard + + + + + Shipheart_boite_dialogue_action_circuit + + + Action à appliquer au circuit lorsque l'évènement se déclenche : + + + + + Aucune + + + + + Le circuit <b>bascule</b> + + + + + [passe à <b>ON</b> s'il est <b>OFF</b><br /> ou à <b>OFF</b> s'il est <b>ON</b>] + + + + + OFF + + + + + ON + + + + + Annuler + + + + + Shipheart_boite_dialogue_affichage_duree + + + Ok + + + + + Shipheart_boite_dialogue_condition_horaire + + + OK + + + + + Annuler + + + + + Supprimer + + + + + Aube nautique + + + + + Lever du soleil + + + + + Zénith + + + + + Coucher du soleil + + + + + Crépuscule nautique + + + + + Shipheart_boite_dialogue_entrees_aux + + + Entrées Auxiliaires + + + + + Affectation de l'entrée n° %1 du %2 + Affectation de l'entrée n° %1 du %2 + + + + Annuler + + + + + Shipheart_boite_dialogue_entrees_level_sensor + + + Entrées Level Sensor + + + + + Affectation de l'entrée du réservoir + + + + + Annuler + + + + + Shipheart_boite_dialogue_liste_alarmes + + + Ok + + + + + Shipheart_boite_dialogue_minuteur + + + Heures + + + + + Minutes + + + + + Secondes + + + + + Annuler + + + + + Démarrer + + + + + Shipheart_boite_dialogue_nettoyage_ecran + + + Nettoyage de l'écran + + + + + 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. + + + + + Sortie + + + + + Shipheart_boite_dialogue_reveils + + + Annuler + + + + + Enregistrer + Enregistrer + + + + Shipheart_boite_dialogue_validation_securisee + + + OK + OK + + + + Annuler + Annuler + + + + --- + --- + + + + Shipheart_bouton_circuit + + + + + Off + + + + + + On + + + + + batterie + + + + Aucune consommation d'énergie sur cette période... + + + + + Aucune donnée n'est disponible pour cette période + + + + + Le module assurant la supervision de cette batterie n'est pas accessible !<br /><br />Si des ajouts/suppression/déplacements de modules ont eu lieu récemment, mettez à jour la configuration correspondant dans le menu MODULES de PARAMETRES AVANCES.<br /><br />Dans le cas où aucune modification n'a été effectuée récemment, vérifier les connexions de tous les modules. + Le module assurant la supervision de cette batterie n'est pas accessible !<br /><br />Si des ajouts/suppression/déplacements de modules ont eu lieu récemment, mettez à jour la configuration correspondant dans le menu MODULES de PARAMETRES AVANCES.<br /><br />Dans le cas où aucune modification n'a été effectuée récemment, vérifier les connexions de tous les modules. + + + + capteur + + + Max + + + + + Moyen + + + + + Min + + + + + Delta (Max - Min) + Delta (1h) + + + + + Aucune donnée n'est disponible pour cette période + + + + + La sonde One Wire correspondant à ce capteur n'est pas accessible.<br />Vérifier son câblage entre le port One Wire à l'arrière de ShipBase et la sonde. + + + + + Le module assurant la supervision de ce capteur n'est pas accessible !<br /><br />Si des ajouts/suppression/déplacements de modules ont eu lieu récemment, mettez à jour la configuration correspondant dans le menu MODULES de PARAMETRES AVANCES.<br /><br />Dans le cas où aucune modification n'a été effectuée récemment, vérifier les connexions de tous les modules. + + + + + La sonde One Wire du capteur est détectée en défaut.<br />Vérifier son câblage depuis l'arrière de ShipBase. + + + + + Le capteur n'a pas reçu de mise à jour sur le réseau NMEA depuis<br />%1<br />Les données affichées sont donc probablement obsolètes. + Le capteur n'a pas reçu de mise à jour sur le réseau NMEA depuis<br />%1<br />Les données affichées sont donc probablement obsolètes. + + + + circuit + + + + + + Off + + + + + + On + + + + + On +%1% + + + + + Aucune donnée n'est disponible pour cette période + + + + + Aucune consommation d'énergie sur cette période... + + + + + Le module assurant le pilotage de ce circuit n'est pas accessible !<br /><br />Si des ajouts/suppression/déplacements de modules ont eu lieu récemment, mettez à jour la configuration correspondant dans le menu [Réseau ShipHeart] de [Paramètres Avancés].<br /><br />Dans le cas où aucune modification n'a été effectuée récemment, vérifier les connexions de tous les modules. + Le module assurant le pilotage de ce circuit n'est pas accessible !<br /><br />Si des ajouts/suppression/déplacements de modules ont eu lieu récemment, mettez à jour la configuration correspondant dans le menu [Réseau ShipHeart] de [Paramètres Avancés].<br /><br />Dans le cas où aucune modification n'a été effectuée récemment, vérifier les connexions de tous les modules. + + + + Ce circuit est configuré comme <i>Non Affecté</i> et n'est donc pas accessible !<br /><br />Pour accéder à nouveau à ce circuit, merci de l'affecter à un circuit disponible dans le menu [Circuits] de [Paramètres Avancés]. + Ce circuit est configuré comme <i>Non Affecté</i> et n'est donc pas accessible !<br /><br />Pour accéder à nouveau à ce circuit, merci de l'affecter à un circuit disponible dans le menu [Circuits] de [Paramètres Avancés]. + + + + Non défini + Non défini + + + + Le module pilotant ce circuit n'est pas alimentée correctement. + Vérifier l'alimentation correspondante. + + + + + Le module pilotant ce circuit est en mode MANUEL. + Repositionnez le module en mode AUTO pour commander à nouveau ce circuit normalement. + + + + + Le port USB du bas est en défaut. + + + + + Le port USB du milieu est en défaut. + + + + + Les 2 ports USB du milieu et du bas sont en défaut. + + + + + Le port USB du haut est en défaut. + + + + + Les 2 ports USB du haut et du bas sont en défaut. + + + + + Les 2 ports USB du haut et du milieu sont en défaut. + + + + + Les 3 ports USB du haut, du milieu et du bas sont en défaut. + + + + + Le port USB est en défaut. + + + + + L'alimentation du circuit a été coupée + car sa limite de courant (%1 A) + a été dépassée. + + + + + L'alimentation du circuit a été coupée + car les circuits de protection interne ont détecté une anomalie. + + + + + L'alimentation du circuit a été coupée + car le seuil de disjonction du circuit a été dépassé. + + + + + Le circuit est en court-circuit avec le + batterie. + + + + + L'alimentation du circuit a été coupée<br />car la consommation totale du module a dépassé %1 A pendant plus de %2 secondes (limite du module) + + + + + La tension du circuit est anormalement basse. + + + + + La phase et le neutre sont inversés sur ce circuit. + + + + + DANGER : Le neutre n'est pas référencé à la terre sur ce circuit ("absence de terre"). + DANGER : la terre est absente de ce circuit. + DANGER : Le neutre n'est pas référencé à la terre sur ce circuit ("absence de terre"). + + + + La masse est absente du connecteur d'alimentation du module + + + + + Evènements actuellement actifs qui sont susceptibles de commander ce circuit : + + + + + + + Etat inconnu... + + + + + config_acces_parametres + + + Configuration de l'accès aux paramètres avancés + + + + + Durée de maintien de l'accès + + + + + Nouveau code + + + + + Code d'accès + + + + + Répéter le code d'accès + + + + + Enregistrer + + + + + Aucune (saisie du code à chaque accès) + + + + + 1 minute + + + + + 5 minutes + + + + + 15 minutes + + + + + 1 heure + + + + + Infinie (aucune protection des paramètres avancés) + + + + + Les deux valeurs saisies doivent être identiques ! + +De plus, le code doit contenir : +- %1 chiffres au minimum +- %2 chiffres au maximum. + + + + + Le nouveau code doit contenir : +- %1 chiffres au minimum +- %2 chiffres au maximum. + +Le code saisi ne répond pas à ces critères et sa mise à jour n'est donc pas effectuée. + +Merci de saisir un code au format valide si vous souhaitez le modifier. + + + + + config_affichage + + + Configuration de l'affichage + + + + + Nom du bateau + + + + + Fuseau horaire + + + + + Temporisaton économiseur d'écran + + + + + Thème d'affichage + + + + + Enregistrer + + + + + UTC-12 (Yankee) + + + + + UTC-11 (X-Ray) + + + + + UTC-10 (Whisky) + + + + + UTC-9 (Victor) + + + + + UTC-8 (Uniform) + + + + + UTC-7 (Tango) + + + + + UTC-6 (Sierra) + + + + + UTC-5 (Romeo) + + + + + UTC-4 (Quebec) + + + + + UTC-3 (Papa) + + + + + UTC-2 (Oscar) + + + + + UTC-1 (November) + + + + + UTC (Zoulou) + + + + + UTC+1 (Alpha) + + + + + UTC+2 (Bravo) + + + + + UTC+3 (Charlie) + + + + + UTC+4 (Delta) + + + + + UTC+5 (Echo) + + + + + UTC+6 (Foxtrot) + + + + + UTC+7 (Golf) + + + + + UTC+8 (Hotel) + + + + + UTC+9 (India) + + + + + UTC+10 (Kilo) + + + + + UTC+11 (Lima) + + + + + UTC+12 (Mike) + + + + + 15 secondes + + + + + 30 secondes + + + + + 1 minute + + + + + 3 minutes + + + + + 10 minutes + + + + + Aucune limite + + + + + config_audio + + + Configuration audio + + + + + Bips de clic + + + + + Fonctionnement de la sortie Audio + + + + + Enregistrer + + + + + Aucun bip + + + + + Bip par défaut + + + + + Bip 2 + + + + + Bip 3 + + + + + Bip 4 + + + + + Bip 5 + + + + + Bip 6 + + + + + Bip 7 + + + + + Bip 8 + + + + + Bip 9 + + + + + Bip 10 + + + + + Bip 11 + + + + + Bip 12 + + + + + Bip 13 + + + + + Bip 14 + + + + + Le son de ShipBase est coupé. Le son est uniquement diffusé sur la sortie AUDIO + + + + + Le son est diffusé sur ShipBase et sur la sortie AUDIO + + + + + config_batterie + + + Nom de la batterie + + + + + Tension nominale + + + + + Créer la batterie + + + + + Enregistrer + + + + + Supprimer + + + + + + Confirmer + + + + + Etalonner + Etalonnage + + + + + + Non défini + + + + + Création d'un parc de batteries + Création d'un parc de batteries + + + + Configuration du parc de batteries + + + + + Groupe de batteries + + + + + Point de mesure + + + + + Type de batterie(s) + + + + + La modification du <b>type</b> de batterie(s) va nécessiter la remise en <i>configuration usine</i> de certains paramètres.<br /><br />Si vous ne souhaitez pas que cette reconfiguration soit effectuée, notamment si vous avez effectué des réglages spécifiques, cliquez sur ANNULER. <br /><br />Sinon, cliquez sur CONFIRMER pour valider le changement. + + + + + La modification de la <b>tension nominale</b> du parc de batteries va nécessiter la remise en <i>configuration usine</i> de certains paramètres.<br /><br />Si vous ne souhaitez pas que cette reconfiguration soit effectuée, notamment si vous avez effectué des réglages spécifiques, cliquez sur ANNULER. <br /><br />Sinon, cliquez sur CONFIRMER pour valider le changement. + + + + + Capacité + + + + + + Ah + + + + + Masquer les paramètres avancés + + + + + Afficher les paramètres avancés + + + + + Coefficient correcteur d'entrée de tension + + + + + + + + + + Caractéristiques du parc de batteries + + + + + Durée correspondant à la capacité + + + + + + h + + + + + Capacité 2 + + + + + Durée de capacité 2 + + + + + Coefficient de Peukert + + + + + Résistance interne + + + + + mΩ + + + + + Soh actuel + + + + + % + + + + + Paramètres de pleine charge + + + + + Tension mini pleine charge + + + + + + V + + + + + Courant maxi pleine charge + + + + + A + + + + + Temporisation pleine charge + + + + + + s + + + + + Efficacité de charge + + + + + Caractéristiques de charge nulle + + + + + Tension de détection charge nulle + + + + + Temporisation charge nulle + + + + + Alimentation %1 + + + + + 48V + 48V + + + + Cette batterie est utilisée par l'évènement ci-dessous.<br />Vous devez modifier ou supprimer cet évènement pour qu'il ne dépende plus de cette batterie avant de pouvoir la supprimer. + + + + + Cette batterie est utilisée par les %1 évènements ci-dessous.<br />Vous devez modifier ou supprimer ces évènements pour qu'ils ne dépendent plus de cette batterie avant de pouvoir la supprimer. + + + + + Cette batterie est utilisée par le capteur calculé ci-dessous.<br />Vous devez modifier ou supprimer ce capteur calculé pour qu'il ne dépende plus de cette id_batterie avant de pouvoir la supprimer. + + + + + Cette id_batterie est utilisée par les %1 capteurs calculés ci-dessous.<br />Vous devez modifier ou supprimer ces capteurs calculés pour qu'ils ne dépendent plus de cette id_batterie avant de pouvoir la supprimer. + + + + + Ok + + + + + Historique + + + + + Nombre de cycles de charge + + + + + Nombre de décharges complètes + + + + + Forcer Pleine Charge + + + + + Réinitialiser SOH + + + + + Réinitialiser Compteurs + + + + + ShipBS [@ %1] + + + + + Entrée VOLT n° %1 + + + + + Plomb - Acide liquide + + + + + Plomb - AGM / VRLA + + + + + Plomb - Gel + + + + + Plomb - Carbone + + + + + Lithium + + + + + Non définie + + + + + 12V + + + + + 24V + + + + + config_batteries + + + Configuration des batteries + + + + + Aucune batterie n'est encore configurée... + + + + + + + + + + + config_capteur + + + Création d'un capteur + + + + + Configuration du capteur + + + + + Nom du capteur + + + + + Type de capteur + + + + + Module + + + + + Affectation + + + + + %1 : Non définie + %1 : Non définie + + + + %1 : %2 + %1 : %2 + + + + Mode du capteur + + + + + Groupe de capteurs + + + + + Libellé du capteur pour la valeur %1 + Libellé du capteur pour la valeur %1 + + + + + + + Non défini + + + + + Entrées Auxiliaires (AUX INPUTS) + + + + + Entrées Niveau (LEVEL SENSORS) + + + + + Entrées Tension (VOLTAGE INPUTS) + + + + + Capteurs de température (ONE WIRE) + + + + + Entrées NMEA2000 + Entrées NMEA2000 + + + + Capteurs sur modules + + + + + Calculé (conditions logiques) + + + + + + <i>Entrée non utilisée</i> + + + + + Pression Atmosphérique + + + + + + + Température module + + + + + + Tension d'entrée module + + + + + Consommation module + + + + + Consommation ports USB + + + + + Chocs + + + + + Accélération X + + + + + Accélération Y + + + + + Accélération Z + + + + + GNSS - SOG<br />Speed Over Ground + + + + + GNSS - COG<br />Course Over Ground + + + + + GNSS - SIV<br />Satellites In View + + + + + GNSS - HPA<br />Horizontal Precision Accuracy + + + + + GNSS - VPA<br />Vertical Precision Accuracy + + + + + Modem 4G/LTE - RSSI<br />Received Signal Strength Indicator + + + + + Modem 4G/LTE - SINR<br />Signal to Interference & Noise Ratio + + + + + Normal + + + + + Inversé + + + + + Tension 0 - 10 V + + + + + Résistance 0 - 500 Ohms + + + + + Courant 4 - 20 mA + + + + + Défaut d'isolement + + + + + Ce capteur est utilisé par l'évènement ci-dessous.<br />Vous devez modifier ou supprimer cet évènement pour qu'il ne dépende plus de ce capteur avant de pouvoir le supprimer. + + + + + Ce capteur est utilisé par les %1 évènements ci-dessous.<br />Vous devez modifier ou supprimer ces évènements pour qu'ils ne dépendent plus de ce capteur avant de pouvoir le supprimer. + + + + + Ce capteur est utilisé par le capteur calculé ci-dessous.<br />Vous devez modifier ou supprimer ce capteur calculé pour qu'il ne dépende plus de ce capteur avant de pouvoir le supprimer. + + + + + Ce capteur est utilisé par les %1 capteurs calculés ci-dessous.<br />Vous devez modifier ou supprimer ces capteurs calculés pour qu'ils ne dépendent plus de ce capteur avant de pouvoir le supprimer. + + + + + Masquer sur la page Capteurs + + + + + Créer le capteur + + + + + Enregistrer + + + + + Equation + + + + + Supprimer + + + + + Etalonner + + + + + Humidité + + + + + GNSS - Latitude + + + + + GNSS - Longitude + + + + + GNSS - Altitude + + + + + config_capteur_calcule_booleen + + + Equation du capteur calculé [%1] + + + + + Enregistrer + Enregistrer + + + + Supprimer + + + + + Le nombre de conditions par capteur est limité à %1.<br /><br />Vous ne pouvez pas ajouter de groupe ou de nouvelle condition avant d'en avoir supprimé préalablement. + + + + + Des modifications ont été apportées au capteur<br />mais n'ont pas été enregistrées.<br /><br />Cliquer sur ANNULER pour revenir au menu en cours.<br /><br />Cliquer sur Ok pour sortir sans enregistrer. + + + + + est actif + + + + + est inactif + + + + + Ou + + + + + Et + + + + + X-Ou + + + + + config_capteur_calcule_booleen_condition + + + Création d'une condition du capteur [%1] + + + + + Type + + + + + Source + + + + + Variable + + + + + Test + + + + + Seuil + + + + + Créer la condition + + + + + Enregistrer + Enregistrer + + + + + + + Non défini + + + + + Circuit + + + + + Capteur + + + + + Réservoir + + + + + Batterie + + + + + Actif + + + + + Inactif + + + + + &lt; au seuil + + + + + &le; au seuil + + + + + = au seuil + + + + + &ge; au seuil + + + + + &gt; au seuil + + + + + config_capteurs + + + Configuration des capteurs + + + + + Aucun capteur n'est encore configuré... + + + + + + + + + + + config_circuit + + + Configuration du circuit + + + + + Nom du circuit + + + + + Affectation + + + + + Circuit renfort + + + + + Mode de commande + + + + + Vitesse de démarrage/arrêt + + + + + Seuil de disjonction + + + + + Vitesse de disjonction + + + + + Filtrage du courant consommé + + + + + Masquer sur la page d'accueil + + + + + Créer le circuit + + + + + Enregistrer + + + + + L'affectation du circuit vient d'être modifiée alors que le circuit était actif. +Avant d'effectuer ce changement, le circuit a été passé sur OFF. + +Pensez à le réactiver si besoin... + + + + + Supprimer + + + + + Aucun + + + + + ShipPower812 [@ %1] + + + + + ShipPower4AC [@ %1] + + + + + ShipPower8DC [@ %1] + + + + + + Circuit %1 + + + + + Groupe de circuits + Groupe de circuit + + + + + Commande impulsionnelle + + + + + + %1 - %2 + + + + + Non affecté + + + + + On-Off + + + + + On-Off progressif + + + + + Variateur + + + + + Aucun filtrage + + + + + Très faible + + + + + Faible + + + + + Moyen + + + + + Elevé + + + + + Très élevé + + + + + + Très rapide + + + + + + Rapide + + + + + + Moyenne + + + + + + Lente + + + + + + Très lente + + + + + Non + + + + + 1 seconde + + + + + 2 secondes + + + + + 5 secondes + + + + + Ce circuit est utilisé pour la commande du moteur.<br />Vous devez d'abord affecter la commande moteur à un autre circuit avant de pouvoir supprimer celui-ci. + + + + + Ce circuit est utilisé par l'évènement ci-dessous.<br />Vous devez modifier ou supprimer cet évènement pour qu'il ne dépende plus de ce circuit avant de pouvoir le supprimer. + + + + + Ce circuit est utilisé par les %1 évènements ci-dessous.<br />Vous devez modifier ou supprimer ces évènements pour qu'ils ne dépendent plus de ce circuit avant de pouvoir le supprimer. + + + + + Ce circuit est utilisé par le capteur calculé ci-dessous.<br />Vous devez modifier ou supprimer ce capteur calculé pour qu'il ne dépende plus de ce circuit avant de pouvoir le supprimer. + + + + + Ce circuit est utilisé par les %1 capteurs calculés ci-dessous.<br />Vous devez modifier ou supprimer ces capteurs calculés pour qu'ils ne dépendent plus de ce circuit avant de pouvoir le supprimer. + + + + + 15 secondes + + + + + 30 secondes + + + + + 45 secondes + + + + + 1 minute + + + + + 5 minutes + + + + + 15 minutes + + + + + 1 heure + + + + + 4 heures + + + + + L'utilisation d'un circuit de renfort rend l'utilisation du mode de commande [Variateur] impossible.<br /><br />Le mode de commande vient donc d'être ramené à [On-Off Progressif]. + + + + + config_circuits + + + Configuration des circuits + + + + + Pack de batteries : + + + + + Aucun capteur n'est encore configuré... + + + + + Oui + + + + + Non + + + + + Le module n'est affecté à aucune batterie... + + + + + Circuit non utilisé + + + + + Circuits Non Affectés + + + + + Ce circuit est configuré comme renfort du circuit <b>%1</b> et ne peut donc pas être configuré individuellement.<br /><br />Merci de cliquer sur le circuit <b>%1</b> de ce même module pour accéder à leurs paramètres communs<br />(y compris pour supprimer le circuit de renfort actuel). + + + + + Type de carte inconnu... + + + + + Le module <br /><b>%1</b><br /> n'est affecté à aucun pack de batteries. <br /><br />Souhaitez-vous laisser la configuration en l'état ? + + + + + Les modules suivants ne sont affectés à aucun pack de batteries :<br /><b>%1</b><br /><br /><br />Souhaitez-vous laisser la configuration en l'état ? + + + + + config_event + + + Création d'un évènement + + + + + Configuration de l'évènement + + + + + Nom de l'évènement + + + + + Type de la source + + + + + Source + + + + + Variable de la source + + + + + Déclenchement si + + + + + Seuil de déclenchement + + + + + Temporisation de déclenchement + + + + + s + + + + + Masquer sur la page d'accueil + + + + + Conditions horaire + + + + + Le nombre maximal de conditions horaires [%1] est atteint : ajout impossible... + + + + + Aucune condition horaire n'est configurée pour cet évènement... + + + + + Signalisation + + + + + Alarme sonore + + + + + La validation des alarmes sonores a nécessité de valider également l'affichage des messages liés à cet évènement.<br /><br />Cet affichage est en effet nécessaire au fonctionnement des alarmes sonores, afin de pouvoir les acquitter. + + + + + Alarme sur LED + + + + + La validation des alarmes sur LED a nécessité de valider également l'affichage des messages liés à cet évènement.<br /><br />Cet affichage est en effet nécessaire au fonctionnement des alarmes sur LED, afin de pouvoir les acquitter. + + + + + Alarme sur sortie(s) de soutien + + + + + La validation des alarmes sur sortie(s) de soutien a nécessité de valider également l'affichage des messages liés à cet évènement.<br /><br />Cet affichage est en effet nécessaire au fonctionnement des alarmes sur sortie(s) de soutien, afin de pouvoir les acquitter. + + + + + Alarme sur la source + + + + + Affichage message sur ShipBase + + + + + La dévalidation de l'affichage des messages a nécessité de dévalider également :<ul><li>les alarmes sonores,</li><li>les alarmes sur led</li><li>et les alarmes sur sortie(s) de soutien</li></ul><br />L'affichage de message est en effet nécessaire à leur fonctionnement, afin de pouvoir les acquitter. + + + + + Texte du message à afficher + + + + + Emission SMS + + + + + Texte du SMS à envoyer + + + + + Emission Email + + + + + Texte de l'email à envoyer + + + + + Action sur circuits + + + + + Aucune + + + + + Le circuit "bascule" + + + + + Le circuit passe à OFF + + + + + Le circuit passe à ON + + + + + Le nombre de circuits commandés par un évènement est limité à %1.<br /><br />Vous ne pouvez pas ajouter d'action sur un nouveau circuit avant d'en avoir supprimé préalablement. + + + + + Créer l'évènement + + + + + Enregistrer + Enregistrer + + + + Supprimer + + + + + + + + Non défini + + + + + Condition horaire seule + + + + + Circuit + + + + + Capteur + + + + + Réservoir + + + + + Batterie + + + + + Passage à <b>actif</b> + + + + + Passage à <b>inactif</b> + + + + + &lt; au seuil + + + + + &le; au seuil + + + + + = au seuil + + + + + &ge; au seuil + + + + + &gt; au seuil + + + + + config_events + + + Configuration des évènements + + + + + Aucun évènement n'est encore configuré... + + + + + 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. + + + + + Sur circuits + + + + + Sur capteurs + + + + + Sur réservoirs + + + + + Sur batteries + + + + + Horaire seulement + + + + + config_groupe_elements + + + Création d'un groupe + + + + + Modification d'un groupe + + + + + Nom du groupe + + + + + Créer le groupe + + + + + Enregistrer + + + + + Supprimer + + + + + batteries + + + + + capteurs + + + + + circuits + + + + + réservoirs + + + + + 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). + + + + + Ce groupe comprend encore %1 %2.<br /><br />Il est nécessaire d'affecter ces %2 à un autre groupe avant de pouvoir le supprimer. + + + + + 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. + + + + + config_image_accueil + + + Image d'accueil + + + + + Aucune image n'a encore été chargée... + + + + + Sélectionner l'image par défaut + + + + + Sélectionner cette image + + + + + Copier + + + + + Supprimer + + + + + Ejection + + + + + Insérer une clé USB dans le port <u>du bas</u>, à droite + + + + + Vous pouvez retirer la clé en toute sécurité... + + + + + Seuls les fichiers de type '.jpg' ou '.png' de taille inférieure à %1 sont autorisés. + + + + + La clé USB a été <i>éjectée</i> automatiquement.<br />Vous pouvez la retirer dès maintenant en toute sécurité... + + + + + USB Arrière + + + + + Spare + + + + + USB Avant + + + + + Touch pad + + + + + La clé USB a été retirée sans avoir préalablement été <i>éjectée</i> !<br />Cela peut conduire à des pertes de données sur la clé, voire sur ShipHeart.<br /><br />Lors de vos prochaines utilisations, pensez à <i>éjecter</i> la clé avec le bouton en haut de page avant de la retirer... Merci ! + + + + + config_installation + + + Configuration de l'installation + + + + + Raison sociale + + + + + N° & Rue + + + + + Complément d'adresse + + + + + Code postal + + + + + Ville + + + + + Nom du contact + + + + + Téléphone + + + + + Email + + + + + Site web + + + + + Enregistrer + Enregistrer + + + + Rapports + + + + + config_koriolan + + + Accès réservé Koriolan + + + + + Client spécifique + + + + + Mode de mise à jour des firmwares + + + + + Enregistrer + + + + + Tests matériel + + + + + Nombre jours avant suppression historique + + + + + Nombre jours avant suppression mesures + + + + + Période de sauvegarde BDD + + + + + Période de vérification download + + + + + Date de dernier archivage mesures + + + + + Aucune spécificité + + + + + Client Suncy Concept + + + + + Normal (si version installée est antérieure à la version en cours) + + + + + Différente (si version installée est différente de version en cours) + + + + + Toujours (à utiliser avec modération...) + + + + + config_module + + + Modifier + + + + + Localiser le module + + + + + Paramètres du module [%1] + + + + + Paramètres du module [%1] à l'adresse [%2] + + + + + N° de série + + + + + Nom du firmware + + + + + Version du firmware + + + + + Version matérielle + Version matérielle + + + + Résistance de terminaison + + + + + Oui + + + + + Non + + + + + CRC du firmware + + + + + Courant de masses sur réseau + Courant de masses sur réseau + + + + <i>--- Circuit non affecté ---</i> + <i>--- Circuit non affecté ---</i> + + + + [renfort] + [renfort] + + + + Affectations + Affectations + + + + <i>--- Aucune batterie affectée ---</i> + <i>--- Aucune batterie affectée ---</i> + + + + Affectation + Affectation + + + + Version processeur + + + + + Emplacement du module à bord + Emplacement du module à bord + + + + Commentaires + Commentaires + + + + config_module_modification + + + Configuration du module [%1] à l'adresse [%2] + Configuration du module [%1] à l'adresse [%2] + + + + Emplacement du module à bord + Emplacement du module à bord + + + + Commentaires + Commentaires + + + + Courant de masses max. sur réseau + Courant de masses max. sur réseau + + + + A + A + + + + Enregistrer + Enregistrer + + + + config_ordre_elements + + + 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... + + + + + Aucun groupe n'est actuellement configuré... + + + + + Aucun élément n'est actuellement configuré... + + + + + Aucun groupe de batteries n'est actuellement configuré... + + + + + Aucune batterie n'est actuellement affectée à ce groupe... + + + + + Affichage des batteries sur la page d'accueil + + + + + Aucun capteur n'est actuellement affecté ce groupe... + + + + + Affichage des capteurs sur la page d'accueil + + + + + Aucun circuit n'est actuellement affecté à ce groupe... + + + + + Affichage des circuits sur la page d'accueil + + + + + Aucun groupe de réservoirs n'est actuellement configuré... + + + + + Aucun réservoir n'est actuellement affecté à ce groupe... + + + + + Affichage des réservoirs sur la page d'accueil + + + + + Aucun groupe de capteurs n'est actuellement configuré... + + + + + Aucun groupe de circuits n'est actuellement configuré... + + + + + config_page + + + Création d'une page + + + + + Configuration de la page + + + + + Nom de la page + + + + + Opacité de la silhouette + + + + + Fichier de silhouette + + + + + Créer la page + + + + + Enregistrer + Enregistrer + + + + Silhouette + + + + + Supprimer + Supprimer + + + + + Aucun + + + + + config_page_edition + + + Edition de la page [%1] + + + + + Aucun équipement n'est configuré sur cette page pour le moment... + + + + + Page + + + + + Enregistrer + Enregistrer + + + + 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. + + + + + config_page_point + + + Création d'un point + + + + + Configuration du point + + + + + Type de la source + + + + + Source + + + + + Type de point + + + + + Taille du point + + + + + Enregistrer + Enregistrer + + + + Créer le point + + + + + Supprimer + Supprimer + + + + + Non défini + Non défini + + + + Capteur + + + + + Circuit + + + + + Réservoir + + + + + Batterie + + + + + Modules + Modules + + + + config_page_silhouette + + + Silhouette de la page + + + + + Aucune image n'a encore été chargée... + + + + + Aucune image + + + + + Sélectionner cette image + + + + + Copier + + + + + Supprimer + Supprimer + + + + Ejection + + + + + Insérer une clé USB dans le port <u>du bas</u>, à droite + + + + + Vous pouvez retirer la clé en toute sécurité... + + + + + Seuls les fichiers de type '.jpg' ou '.png' de taille inférieure à %1 sont autorisés. + + + + + La clé USB a été <i>éjectée</i> automatiquement.<br />Vous pouvez la retirer dès maintenant en toute sécurité... + + + + + USB Arrière + + + + + Spare + + + + + USB Avant + + + + + Touch pad + + + + + La clé USB a été retirée sans avoir préalablement été <i>éjectée</i> !<br />Cela peut conduire à des pertes de données sur la clé, voire sur ShipHeart.<br /><br />Lors de vos prochaines utilisations, pensez à <i>éjecter</i> la clé avec le bouton en haut de page avant de la retirer... Merci ! + + + + + config_pages + + + Configuration des pages + + + + + Aucune page n'est encore configurée... + + + + + Image accueil + Image accueil + + + + + + + + + + config_pdf + + + Ship2net + + + + + Enregistrer + Enregistrer + + + + config_rapports + + + Rapports d'installation + + + + + Aucun rapport d'installation n'est encore disponible... + + + + + Nouveau rapport d'installation + + + + + Copier + + + + + Déplacer + + + + + Supprimer + + + + + Ejection + + + + + Insérer une clé USB dans le port <u>du bas</u>, à droite + + + + + Vous pouvez retirer la clé en toute sécurité... + + + + + La clé USB a été <i>éjectée</i> automatiquement.<br />Vous pouvez la retirer dès maintenant en toute sécurité... + + + + + USB Arrière + + + + + Spare + + + + + USB Avant + + + + + Touch pad + + + + + La clé USB a été retirée sans avoir préalablement été <i>éjectée</i> !<br />Cela peut conduire à des pertes de données sur la clé, voire sur ShipHeart.<br /><br />Lors de vos prochaines utilisations, pensez à <i>éjecter</i> la clé avec le bouton en haut de page avant de la retirer... Merci ! + + + + + Le rapport d'installation<br /><br /><b>%1</b><br /><br />a été généré. + + + + + config_reseau_ethernet_wifi + + + Réseau Ethernet & Wifi + + + + + + Modifier + + + + + Ethernet + + + + + + + Adresse IP + + + + + + + Non connecté + + + + + Connexion à un réseau existant + + + + + + Etat + + + + + + On + + + + + + Off + + + + + + Nom du réseau [SSID] + + + + + Génération d'un réseau spécifique + + + + + Canal + + + + + config_reseau_k_bus + + + Réseau ShipHeart + Réseau ShipHeart + + + + Modules physiquement présents + Modules physiquement présents + + + + %1 - %2 + %1 - %2 + + + + Modules utilisés par la configuration actuelle + Modules utilisés par la configuration actuelle + + + + [@ %1] : %2 + + + + + La configuration actuelle ne fait appel à aucun autre module que ShipBase... + La configuration actuelle ne fait appel à aucun autre module que ShipBase... + + + + Module non utilisé en configuration + + + + + [renfort] + [renfort] + + + + Enregistrer + Enregistrer + + + + Retour + Retour + + + + Quitter + Quitter + + + + Aucune modification n'a été apportée à la configuration actuelle.<br />Celle-ci contient toujours des anomalies !<br /><br /><br />Souhaitez-vous :<br />Poursuivre les modifications [%1]<br />Quitter ce menu sans enregistrer les modifications [%2] + Aucune modification n'a été apportée à la configuration actuelle.<br />Celle-ci contient toujours des anomalies !<br /><br /><br />Souhaitez-vous :<br />Poursuivre les modifications [%1]<br />Quitter ce menu sans enregistrer les modifications [%2] + + + + La configuration actuelle contient toujours des anomalies !<br /><br /><br />Souhaitez-vous :<br />Enregistrer cette nouvelle configuration et quitter ce menu [%1]<br />Poursuivre les modifications [%2]<br />Quitter ce menu sans enregistrer les modifications [%3] + La configuration actuelle contient toujours des anomalies !<br /><br /><br />Souhaitez-vous :<br />Enregistrer cette nouvelle configuration et quitter ce menu [%1]<br />Poursuivre les modifications [%2]<br />Quitter ce menu sans enregistrer les modifications [%3] + + + + La configuration actuelle est correcte <br />mais n'a pas encore été enregistrée.<br /><br /><br />Souhaitez-vous :<br />Enregistrer cette nouvelle configuration et quitter ce menu [%1]<br />Poursuivre les modifications [%2]<br />Quitter ce menu sans enregistrer les modifications [%3] + La configuration actuelle est correcte <br />mais n'a pas encore été enregistrée.<br /><br /><br />Souhaitez-vous :<br />Enregistrer cette nouvelle configuration et quitter ce menu [%1]<br />Poursuivre les modifications [%2]<br />Quitter ce menu sans enregistrer les modifications [%3] + + + + config_reseau_nmea + + + Réseau NMEA2000 + Réseau NMEA2000 + + + + Aucun PGN n'a encore été détecté sur le réseau NMEA2000... + Aucun PGN n'a encore été détecté sur le réseau NMEA2000... + + + + PGN non affecté + PGN non affecté + + + + config_reseau_one_wire + + + Réseau One Wire + + + + + Aucune sonde n'est encore installée... + + + + + 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. + + + + + Type inconnu + + + + + Sonde non affectée + + + + + config_reseau_one_wire_modification + + + Configuration de la sonde [%1] + + + + + Emplacement de la sonde + + + + + Enregistrer + Enregistrer + + + + config_reseau_wifi_ap + + + Configuration Wifi en mode AP + + + + + Etat + + + + + Nom du réseau (SSID) + + + + + Mot de passe d'accès au réseau + + + + + Canal + + + + + Adresse IP + + + + + Non connecté + + + + + Enregistrer + Enregistrer + + + + Off + + + + + On + + + + + Canal %1 - [%2GHz] + + + + + Le nom du réseau (SSID) doit comprendre entre 1 et 32 caractères. <br />Merci d'entrer un nom valide. + + + + + 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. + + + + + 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. + + + + + 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. + + + + + config_reseau_wifi_sta + + + Configuration Wifi en mode STA + + + + + Etat + + + + + Réseau + + + + + Mot de passe d'accès au réseau + + + + + Enregistrer + Enregistrer + + + + Réseaux connus + + + + + Off + + + + + On + + + + + Aucun réseau... + + + + + config_reseau_wifi_sta_liste + + + Liste des réseaux Wifi connus + + + + + Aucun réseau n'a été détecté... + + + + + Oublier tous les réseaux + + + + + Oublier ce réseau + + + + + config_reservoir + + + Création d'un réservoir + + + + + Configuration du réservoir + + + + + Nom du réservoir + + + + + Famille de réservoirs + + + + + Type de capteur de niveau + + + + + %1 : Non définie + + + + + %1 : %2 + + + + + Sonde la plus basse dans le réservoir + + + + + Non définie + + + + + Logique d'alarme + + + + + Filtrage des mesures + + + + + Créer le réservoir + + + + + Enregistrer + + + + + Supprimer + + + + + Etalonnage + + + + + + AUX INPUT %1 + + + + + + LEVEL SENSOR %1 + + + + + Confirmer + + + + + Capacité du réservoir + + + + + litres + + + + + Logique des entrées inversée + + + + + La modification du <b>type de capteur</b> va nécessiter la remise en <i>configuration usine</i> de tous les paramètres du réservoir.<br /><br />Si vous ne souhaitez pas que cette reconfiguration soit effectuée, cliquez sur ANNULER. <br /><br />Sinon, cliquez sur CONFIRMER pour valider le changement. + + + + + Non défini + + + + + Electrodes plongées ou contacts secs + + + + + Résistif 0 - 190Ω + + + + + Résistif 240 - 30Ω + + + + + Résistif 0 - 700Ω + Résistif 0 - 700Ω + + + + Boucle de courant 4 - 20mA + + + + + Tension 0 - 10V + + + + + Aucun filtrage + + + + + Très faible + + + + + Faible + + + + + Moyen + + + + + Elevé + + + + + Très élevé + + + + + Ce réservoir est utilisé par l'évènement ci-dessous.<br />Vous devez modifier ou supprimer cet évènement pour qu'il ne dépende plus de ce réservoir avant de pouvoir le supprimer. + + + + + Ce réservoir est utilisé par les %1 évènements ci-dessous.<br />Vous devez modifier ou supprimer ces évènements pour qu'ils ne dépendent plus de ce réservoir avant de pouvoir le supprimer. + + + + + Ce réservoir est utilisé par le capteur calculé ci-dessous.<br />Vous devez modifier ou supprimer ce capteur calculé pour qu'il ne dépende plus de ce réservoir avant de pouvoir le supprimer. + + + + + Ce réservoir est utilisé par les %1 capteurs calculés ci-dessous.<br />Vous devez modifier ou supprimer ces capteurs calculés pour qu'ils ne dépendent plus de ce réservoir avant de pouvoir le supprimer. + + + + + Alerte sur niveau faible + + + + + Alerte sur niveau élevé + + + + + config_reservoirs + + + Configuration des réservoirs + + + + + Aucun réservoir n'est encore configuré... + + + + + + + + + + + config_ship2net + + + Ship2net + + + + + Période des sauvegardes + + + + + Période de connexion à Ship2net + Période de connexion à Ship2net + + + + Mode de validation des mises à jour + + + + + Accès distant WebGL #1 + Accès distant WebGL #1 + + + + Accès distant WebGL #2 + Accès distant WebGL #2 + + + + Accès distant WebGL #3 + Accès distant WebGL #3 + + + + Enregistrer + + + + + + Jamais + + + + + + 2 minutes + 2 minutes + + + + + 30 minutes + + + + + + 1 heure + + + + + 2 heures + + + + + + 4 heures + + + + + + 12 heures + + + + + + 24 heures + + + + + + + Dévalidé + + + + + + + Valide [port %1] + Valide [port %1] + + + + + 10 minutes + 10 minutes + + + + Aucune mise à jour + + + + + Validation manuelle des mises à jour reçues + + + + + Validation automatique des mises à jour reçues + + + + + config_specifique_client_suncy + + + Configuration spécifique à Suncy Concept + + + + + Circuit d'activation moteur + + + + + Nouveau code + + + + + Code d'accès au bateau + + + + + Répéter le code d'accès + + + + + Enregistrer + + + + + Aucune + + + + + [module %1 - circuit %2] %3 + + + + + Les deux valeurs saisies doivent être identiques ! + +De plus, le code doit contenir : +- %1 chiffres au minimum +- %2 chiffres au maximum. + + + + + Le nouveau code doit contenir : +- %1 chiffres au minimum +- %2 chiffres au maximum. + +Le code saisi ne répond pas à ces critères et sa mise à jour n'est donc pas effectuée. + +Merci de saisir un code au format valide si vous souhaitez le modifier. + + + + + config_valeurs_niveaux + + + Aucun point de conversion n'est configuré pour le moment... + + + + + Le nombre maximal de points d'étalonnage a été atteint (%1 points)<br />Vous ne pouvez pas en ajouter sans en avoir prélablement supprimé. + Le nombre maximal de points d'étalonnage a été atteint (%1 points)<br />Vous ne pouvez pas en ajouter sans en avoir prélablement supprimé. + + + + Courbe usine + + + + + Enregistrer + + + + + La valeur lue sur les electrodes plongées de ce réservoir est incohérente.<br />Vérifier l'ordre de cablage des électrodes sur les entrées auxiliaires à l'arrière de ShipBase. + La valeur lue sur les electrodes plongées de ce réservoir est incohérente.<br />Vérifier l'ordre de cablage des électrodes sur les entrées auxiliaires à l'arrière de ShipBase. + + + + Aucune donnée n'est disponible... + + + + + 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. + + + + + Aucun point n'est actuellement configuré pour cette batterie... + + + + + + Courbe de conversion de [%1] + + + + + Aucun réservoir n'est actuellement configuré... + + + + + Aucun point n'est actuellement configuré pour cet élément... + + + + + Courbe de conversion de type INCONNU + + + + + config_version + + + Version + + + + + %1 : %2 + + + + + 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 : + + + + + La version <b>%1</b> est disponible.<br /><br />Souhaitez-vous : + + + + + + L'installer +maintenant + + + + + L'installer au prochain démarrage de ShipHeart + + + + + + Ne jamais l'installer + + + + + Supprimer + Supprimer + + + + Si vous confirmez, cette mise à jour sera définitivement supprimée.<br />Cliquez sur Annuler pour revenir en arrière et la conserver. + Si vous confirmez, cette mise à jour sera définitivement supprimée.<br />Cliquez sur Annuler pour revenir en arrière et la conserver. + + + + Installer + Installer + + + + 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 la conserver pour une installation ultérieure. + 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 la conserver pour une installation ultérieure. + + + + 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 'shipheart.tech' ou de nous contacter à l'adresse 'contact@shipheart.tech'. + 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 'shipheart.tech' ou de nous contacter à l'adresser 'contact@shipheart.tech'. + + + + + Version du package logiciel + + + + + Version de l'application + + + + + Version de l'interface graphique + + + + + Version du firmware du modem + + + + + Numéro d'IMEI + + + + + Numéro d'ICCID + + + + + Numéro d'IMSI + + + + + ephemeride + + + Ephéméride + + + + + Heure d'hiver + + + + + Heure d'été + + + + + Aube nautique + + + + + Lever du soleil + + + + + Zénith + + + + + Coucher du soleil + + + + + Crépuscule nautique + + + + + Lune + + + + + Latitude + + + + + Longitude + + + + + etalonnage_capteur + + + Etalonnage du capteur [%1] + + + + + Valeur brute actuelle + + + + + Valeur corrigée actuelle (%1) + + + + + Correction + + + + + Enregistrer + + + + + etalonnage_carte + + + Etalonnage du module [%1 - #%2] + + + + + Point 1 + + + + + Point 2 + + + + + Courant de décharge + + + + + Courant différentiel + + + + + + Recalculer ce point + + + + + + Mémoriser ce point + + + + + Off + + + + + On + + + + + On (%1 %%) + + + + + Enregistrer + + + + + Aide + + + + + 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 /> + + + + + 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. + + + + + fonctions + + + Modèle inconnu + Modèle inconnu + + + + Circuit + + + + + Capteur + + + + + Réservoir + + + + + Batterie + + + + + Type inconnu + + + + + Consigne + + + + + + + Tension + + + + + Courant + + + + + Fréquence + + + + + + Puissance + + + + + + Energie + + + + + Température + + + + + Courant différentiel + + + + + Courant de charge + + + + + Courant de décharge + + + + + SOH (state Of Health) + + + + + SOC (State Of Charge) + + + + + Autonomie + + + + + fonctions_date_heure + + + 1 heure + + + + + 24 heures + + + + + 7 jours + + + + + 30 jours + + + + + Fin de nuit + + + + + Aube nautique + + + + + Aube + + + + + Lever du soleil + + + + + Zénith + + + + + Coucher du soleil + + + + + Crépuscule + + + + + Crépuscule nautique + + + + + Début de nuit + + + + + %1h + + + + + Dimanche + + + + + Lundi + + + + + Mardi + + + + + Mercredi + + + + + Jeudi + + + + + Vendredi + + + + + Samedi + + + + + Tous les jours + + + + + janvier + + + + + février + + + + + mars + + + + + avril + + + + + mai + + + + + juin + + + + + juillet + + + + + août + + + + + septembre + + + + + octobre + + + + + novembre + + + + + décembre + + + + + fonctions_historique + + + Commande 'OFF' du circuit %1 + + + + + Commande 'ON' du circuit %1 + + + + + Commande à %1 % du circuit %2 + + + + + Le circuit %1 est revenu à son état de fonctionnement normal + + + + + L'alimentation du circuit %1 a été coupée car sa limite de courant (%2 A) a été dépassée + + + + + L'alimentation du circuit %1 a été coupée car les circuits de protection interne ont détecté une anomalie + + + + + L'alimentation du circuit %1 a été coupée car le seuil de disjonction a été dépassé + + + + + Le circuit %1 est en court-circuit avec le + batterie + + + + + L'alimentation du circuit %1 a été coupée car la consommation totale du module a été dépassé + + + + + Le circuit %1 a été créé + + + + + La configuration du circuit %1 a été modifiée + + + + + Le circuit %1 a été supprimé + + + + + La configuration du circuit %1 est invalide car le module sur lequel le circuit est configuré n'est pas présent + + + + + Le circuit %1 a fonctionné trop longtemps (> %2 secondes). Il a donc été désactivé automatiquement. + + + + + Evénement de type CIRCUITS avec code de sous-type inconnu [%1] + + + + + Le capteur %1 est repassé à l'état normal + + + + + Le capteur %1 est passé à l'état ALERTE + + + + + Le capteur %1 est passé à l'état ALARME + + + + + Evénement de type CAPTEURS avec code de sous-type inconnu [%1] + + + + + Le niveau de charge de la batterie %1 est repassé au niveau normal + + + + + Le niveau de charge de la batterie %1 est passé en dessous du niveau d'alerte + + + + + Le niveau de charge de la batterie %1 est passé au-dessus du niveau d'alarme (il est maintenant au niveau d'alerte uniquement) + + + + + Le niveau de charge de la batterie %1 est passé en-dessous du niveau d'alarme + + + + + Evénement de type BATTERIES avec code de sous-type inconnu [%1] + + + + + Le niveau du réservoir %1 est repassé au niveau normal + + + + + Le niveau du réservoir %1 est passé en dessous du niveau d'alerte + + + + + Le niveau du réservoir %1 est passé au-dessus du niveau d'alarme (il est maintenant au niveau d'alerte uniquement) + + + + + Le niveau du réservoir %1 est passé en-dessous du niveau d'alarme + + + + + Evénement de type RESERVOIRS avec code de sous-type inconnu [%1] + + + + + La consigne des ports USB est passée à %1 + + + + + L'état des ports USB est redevenu normal + + + + + Défaut détecté sur les ports USB + + + + + Evénement de type USB avec code de sous-type inconnu [%1] + + + + + Evénement de type INCONNU (avec code de sous-type [%1] + + + + + home + + + Aucun circuit n'est configuré pour ce groupe...<br /><br />Si ce groupe n'a pas d'utilité, vous pouvez le supprimer dans le menu [Circuits] des Paramètres Avancés. + + + + + Aucun capteur n'est configuré pour ce groupe...<br /><br />Si ce groupe n'a pas d'utilité, vous pouvez le supprimer dans le menu [Capteurs] des Paramètres Avancés. + + + + + Aucun réservoir n'est configuré pour ce groupe...<br /><br />Si ce groupe n'a pas d'utilité, vous pouvez le supprimer dans le menu [Réservoirs] des Paramètres Avancés. + + + + + Aucun parc de batterie n'est configuré pour ce groupe...<br /><br />Si ce groupe n'a pas d'utilité, vous pouvez le supprimer dans le menu [Batteries] des Paramètres Avancés. + + + + + Cette page est actuellement en travaux. <br />Elle sera rendue disponible très rapidement à travers une mise à jour.<br /><br />Merci de votre patience...<br /><br />L'équipe ShipHeart + + + + + + + Déconnecté + + + + + Nombre de satellites visibles + + + + + + Connecté + + + + + + OFF + + + + + + ON + + + + + Niveau + + + + + Actif + + + + + Inactif + + + + + + + <b>%1</b> + + + + + Démarrage + + + + + Firmware de <b>ShipBase</b> + + + + + Firmware du <b>ShipPower812</b> à l'adresse <b>%1</b> + + + + + Firmware du <b>ShipBS</b> à l'adresse <b>%1</b> + + + + + Firmware du <b>ShipPower4AC</b> à l'adresse <b>%1</b> + + + + + Firmware du <b>ShipPower8DC</b> à l'adresse <b>%1</b> + + + + + Firmware du module à l'adresse <b>%1</b> + + + + + Merci de patienter et de ne rien débrancher<br />avant la fin de la mise à jour. + + + + + Chargement des mises à jour effectué avec succès !<br /><br />L'activation des nouvelles version est en cours sur tous les modules concernés.<br /><br />Merci de patienter encore quelques secondes... + + + + + ShipHeart va redémarrer pour effectuer une mise à jour.<br /><br />Cette opération va prendre quelques minutes au maximum.<br />Merci de patienter et de ne rien débrancher jusqu'au redémarrage final... + + + + + Votre système ShipHeart est dorénavant équipé de la version<br /><br /><b>%1</b><br /><br />(la version précédente était la %2) + + + + + Le nombre de modules détectés sur le réseau ShipHeart est insuffisant par rapport à la configuration du bateau.<br /><br />Vérifiez les connexions entre le module <b>%1</b> à la <b>position @%2</b> %3 et le module <b>%4</b> suivant%5<br /><br />Vous pouvez visualiser l'état complet du réseau ShipHeart et les anomalies détectées dans le menu 'Réseau > ShipHeart' dans les Paramètres Avancés + + + + + Le modules détecté en <b>position @%1</b> est un <b>%2</b>. Cela ne correspond pas à la configuration actuelle du bateau (<b>%3</b>).<br /><br />Cela peut provenir de l'ajout, de la suppression ou d'un déplacement de module.<br /><br />Vous pouvez visualiser toutes les anomalies détectées et les corriger dans le menu 'Réseau > ShipHeart' dans les Paramètres Avancés + + + + + Code inconnu + + + + + home_accueil + + + Bienvenue à bord de + + + + + home_suncy + + + L'accès au bateau est protégé. +Merci d'entrer votre code de déverrouillage pour y accéder... + + + + + journal_de_bord + + + + + + Tous + + + + + Batteries + + + + + Capteurs + + + + + Circuits + + + + + Réservoirs + + + + + Système + + + + + Ports USB + + + + + Journal de bord + + + + + Aucun type n'est configuré... + + + + + %1<br /><br /><br />%2 + + + + + Aucune entrée d'historique n'est disponible pour cette sélection... + + + + + Toutes + + + + + main + + + Type d'installation : +0 : ShipBase standard, +1 : écran déporté + + + + + + valeur + + + + + Adresse IPv4 de ShipBase dans le cas d'une installation déportée + + + + + xxx:xxx:xxx:xxx + + + + + Taille de l'écran en pouces : +7, +10 (ShipBase standard), +22 + + + + + Original + + + + + Sombre + + + + + Métallique + + + + + Triangles + + + + + Sable + + + + + Thème 5 + + + + + Thème 6 + + + + + Thème 7 + + + + + Thème 8 + + + + + page_personnalisee + + + <i>--- Circuit non affecté ---</i> + <i>--- Circuit non affecté ---</i> + + + + [renfort] + [renfort] + + + + <i>--- Aucune batterie affectée ---</i> + <i>--- Aucune batterie affectée ---</i> + + + + parametres + + + Paramètres + + + + + Langue + + + + + Températures + + + + + Volumes + + + + + Affichage + + + + + Date et heure + + + + + Protection + + + + + Son + + + + + Luminosité + + + + + Economiseur d'écran : désactivé + + + + + Economiseur d'écran : normal + + + + + Flash LEDs : désactivé + + + + + Flash LEDs : normal + + + + + Nettoyage de l'écran + + + + + Heure d'été + + + + + Heure d'hiver + + + + + Verrouiller le bateau + + + + + parametres_avances + + + Paramètres avancés + + + + + Réseaux + + + + + Cette page est actuellement en travaux. <br />Elle sera rendue disponible très rapidement à travers une mise à jour.<br /><br />Merci de votre patience...<br /><br />L'équipe ShipHeart + + + + + Circuits + + + + + Réservoirs + + + + + Batteries + + + + + Capteurs + + + + + Menu accueil + + + + + Evènements + + + + + ShipHeart + + + + + Ethernet & Wifi + + + + + One Wire + + + + + NMEA 2000 + + + + + J1939 + + + + + DMX + + + + + Journal de bord + + + + + Vos paramètres + + + + + Votre installation + + + + + Système + + + + + Affichage + + + + + Audio + + + + + Ship2net + + + + + Accès au paramètres + + + + + Configuration ShipRS + + + + + Installation + + + + + Version + + + + + Accès réservé Koriolan + + + + + Spécifique Suncy + + + + + protection + + + Accès protégé + + + + + L'accès aux paramètres avancés est protégé. +Merci d'entrer le code de déverrouillage pour y accéder... + + + + + Mode administrateur validé<br />Entrer votre code dédié + + + + + reservoir + + + [ %1 % ] + + + + + Le module assurant la supervision de ce réservoir n'est pas accessible !<br /><br />Si des ajouts/suppression/déplacements de modules ont eu lieu récemment, mettez à jour la configuration correspondant dans le menu MODULES de PARAMETRES AVANCES.<br /><br />Dans le cas où aucune modification n'a été effectuée récemment, vérifier les connexions de tous les modules. + + + + + Niveau + + + + + La valeur lue sur les electrodes plongées de ce réservoir est incohérente.<br />Vérifier l'ordre de cablage des électrodes sur les entrées auxiliaires à l'arrière de ShipBase. + + + + + Aucune donnée n'est disponible pour cette période + + + + + shipheart_test_config + + + Vitesse de test de l'écran + + + + + Nombre de colonnes de test du touchpad + + + + + Nombre de lignes de test du touchpad + + + + + shipheart_test_home + + + Tests matériel + + + + + Configuration des tests + + + + + Test du backlight + + + + + Test de l'écran + + + + + Test du touchpad + + + + + Liste des fonts disponibles + Liste des fonts disponibles + + + + shipheart_test_liste_fonts + + + Liste des fonts disponibles + Liste des fonts disponibles + + + + test_batterie + + + Batteries de servitude + + + + + Autonomie optimale + + + + + Autonomie actuelle + + + + + Autonomie<br />maximale + + + + + dans + + + + + environ + + + + + test_tri_liste + + + TEST DE TRI DE LISTE + TEST DE TRI DE LISTE + + + diff --git a/shipheart_it_IT.qm b/shipheart_it_IT.qm new file mode 100755 index 0000000..d2bb380 Binary files /dev/null and b/shipheart_it_IT.qm differ diff --git a/shipheart_it_IT.ts b/shipheart_it_IT.ts new file mode 100755 index 0000000..b0660cc --- /dev/null +++ b/shipheart_it_IT.ts @@ -0,0 +1,4409 @@ + + + + + Shipheart_boite_dialogue + + OK + OK + + + Annuler + Annullamento + + + Plus tard + In seguito + + + + Shipheart_boite_dialogue_action_circuit + + Action à appliquer au circuit lorsque l'évènement se déclenche : + Azione da applicare al circuito quando l'evento viene attivato : + + + Aucune + No + + + Le circuit <b>bascule</b> + Il circuito <b>toggle</b> + + + [passe à <b>ON</b> s'il est <b>OFF</b><br /> ou à <b>OFF</b> s'il est <b>ON</b>] + [passa a <b>ON</b> se è <b>OFF</b><br /> o <b>OFF</b> se è <b>ON</b>] + + + OFF + OFF + + + ON + ON + + + Annuler + Annullamento + + + + Shipheart_boite_dialogue_affichage_duree + + Ok + OK + + + + Shipheart_boite_dialogue_condition_horaire + + OK + OK + + + Annuler + Annullamento + + + Supprimer + Cancellare + + + Aube nautique + Alba nautica + + + Lever du soleil + Alba + + + Zénith + Zenith + + + Coucher du soleil + Tramonto + + + Crépuscule nautique + Crepuscolo nautico + + + + Shipheart_boite_dialogue_entrees_aux + + Entrées Auxiliaires + Ingressi ausiliari + + + Annuler + Annullamento + + + Affectation de l'entrée n° %1 du %2 + Assegnazione del numero di voce %1 di %2 + + + + Shipheart_boite_dialogue_entrees_level_sensor + + Entrées Level Sensor + Ingressi del sensore di livello + + + Affectation de l'entrée du réservoir + Assegnazione dell'ingresso del serbatoio + + + Annuler + Annullamento + + + + Shipheart_boite_dialogue_liste_alarmes + + Ok + OK + + + + Shipheart_boite_dialogue_minuteur + + Heures + Orario + + + Minutes + Verbale + + + Secondes + Secondi + + + Annuler + Annullamento + + + Démarrer + Inizio + + + + Shipheart_boite_dialogue_nettoyage_ecran + + Nettoyage de l'écran + Pulizia dello schermo + + + 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. + Lo schermo è attualmente congelato per consentire di pulirlo senza il rischio di attivare azioni indesiderate.<br /><br />Tenere premuto il pulsante sottostante per più di %1 secondi per uscire da questa modalità. + + + Sortie + Uscita + + + + Shipheart_boite_dialogue_reveils + + Annuler + Annullamento + + + Enregistrer + Registro + + + + Shipheart_boite_dialogue_validation_securisee + + OK + OK + + + Annuler + Annullamento + + + --- + --- + + + + Shipheart_bouton_circuit + + Off + OFF + + + On + ON + + + + batterie + + Aucune donnée n'est disponible pour cette période + Non sono disponibili dati per questo periodo + + + Le module assurant la supervision de cette batterie n'est pas accessible !<br /><br />Si des ajouts/suppression/déplacements de modules ont eu lieu récemment, mettez à jour la configuration correspondant dans le menu MODULES de PARAMETRES AVANCES.<br /><br />Dans le cas où aucune modification n'a été effectuée récemment, vérifier les connexions de tous les modules. + Il modulo che monitora questa batteria non è accessibile!<br /><br />Se dei moduli sono stati aggiunti/eliminati/spostati di recente, aggiornare la configurazione corrispondente nel menu MODULI di PARAMETRI AVANZATI. <br /><br />Nel caso non sono state apportate modifiche recentemente, verificare i collegamenti di tutti i moduli. + + + Aucune consommation d'énergie sur cette période... + Nessun consumo di energia durante questo periodo... + + + + capteur + + Max + Massimo + + + Moyen + Medio + + + Min + Min + + + Delta (Max - Min) + Delta (Max - Min) + + + Aucune donnée n'est disponible pour cette période + Non sono disponibili dati per questo periodo + + + La sonde One Wire correspondant à ce capteur n'est pas accessible.<br />Vérifier son câblage entre le port One Wire à l'arrière de ShipBase et la sonde. + La sonda One Wire corrispondente a questo sensore non è accessibile.<br />Controllare il cablaggio tra la porta One Wire sul retro di ShipBase e la sonda. + + + Le module assurant la supervision de ce capteur n'est pas accessible !<br /><br />Si des ajouts/suppression/déplacements de modules ont eu lieu récemment, mettez à jour la configuration correspondant dans le menu MODULES de PARAMETRES AVANCES.<br /><br />Dans le cas où aucune modification n'a été effectuée récemment, vérifier les connexions de tous les modules. + Il modulo che monitora questo sensore non è accessibile! <br /><br />Se i moduli sono stati aggiunti/cancellati/sposti di recente, aggiornare la configurazione corrispondente nel menu MODULI di PARAMETRI AVANZATI.<br /><br />Se non sono state apportate modifiche di recente, controllare i collegamenti di tutti i moduli. + + + La sonde One Wire du capteur est détectée en défaut.<br />Vérifier son câblage depuis l'arrière de ShipBase. + La sonda One Wire del sensore viene rilevata come difettosa <br />Controllare il cablaggio dal retro di ShipBase. + + + Le capteur n'a pas reçu de mise à jour sur le réseau NMEA depuis<br />%1<br />Les données affichées sont donc probablement obsolètes. + Il sensore non ha ricevuto alcun aggiornamento sulla rete NMEA da<br />%1<br />I dati visualizzati sono quindi probabilmente obsoleti. + + + + circuit + + Off + OFF + + + On + ON + + + On +%1% + Su +%1% + + + Aucune donnée n'est disponible pour cette période + Non sono disponibili dati per questo periodo + + + L'alimentation du circuit a été coupée + car sa limite de courant (%1 A) + a été dépassée. + L'alimentazione del circuito è stata interrotta + perché il suo limite di corrente (%1 A) + è stato superato. + + + L'alimentation du circuit a été coupée + car les circuits de protection interne ont détecté une anomalie. + L'alimentazione al circuito è stata interrotta + perché i circuiti di protezione interni hanno rilevato un'anomalia. + + + L'alimentation du circuit a été coupée + car le seuil de disjonction du circuit a été dépassé. + L'alimentazione del circuito è stata interrotta + perché è stata superata la soglia di disconnessione del circuito. + + + Le circuit est en court-circuit avec le + batterie. + Il circuito è cortocircuitato con il + della batteria. + + + L'alimentation du circuit a été coupée<br />car la consommation totale du module a dépassé %1 A pendant plus de %2 secondes (limite du module) + L'alimentazione del circuito è stata interrotta<br />perché il consumo totale del modulo ha superato %1 A per più di %2 secondi (limite del modulo) + + + La tension du circuit est anormalement basse. + La tensione del circuito è anormalmente bassa. + + + La phase et le neutre sont inversés sur ce circuit. + In questo circuito la fase e il neutro sono invertiti. + + + Etat inconnu... + Stato sconosciuto... + + + Le module assurant le pilotage de ce circuit n'est pas accessible !<br /><br />Si des ajouts/suppression/déplacements de modules ont eu lieu récemment, mettez à jour la configuration correspondant dans le menu [Réseau ShipHeart] de [Paramètres Avancés].<br /><br />Dans le cas où aucune modification n'a été effectuée récemment, vérifier les connexions de tous les modules. + Il modulo che controlla questo circuito non è accessibile!<br /><br />Se i moduli sono stati aggiunti/eliminati/spostati di recente, aggiorna la configurazione corrispondente nel menu [Rete ShipHeart] di [Impostazioni avanzate].<br />< br />Nel caso in cui non siano state apportate modifiche recentemente, controllare le connessioni di tutti i moduli. + + + Ce circuit est configuré comme <i>Non Affecté</i> et n'est donc pas accessible !<br /><br />Pour accéder à nouveau à ce circuit, merci de l'affecter à un circuit disponible dans le menu [Circuits] de [Paramètres Avancés]. + Questo circuito è configurato come <i>Non assegnato</i> e pertanto non è accessibile!<br /><br />Per accedere nuovamente a questo circuito, assegnarlo a un circuito disponibile nel menu [Circuiti] di [Impostazioni avanzate ]. + + + Aucune consommation d'énergie sur cette période... + Nessun consumo di energia durante questo periodo... + + + Le module pilotant ce circuit n'est pas alimentée correctement. + Vérifier l'alimentation correspondante. + Il modulo che pilota questo circuito non è alimentato correttamente. + Controllare l'alimentazione corrispondente. + + + Le module pilotant ce circuit est en mode MANUEL. + Repositionnez le module en mode AUTO pour commander à nouveau ce circuit normalement. + Il modulo che controlla questo circuito è in modalità MANUALE. + Riportare il modulo in modalità AUTO per controllare normalmente questo circuito. + + + Le port USB du bas est en défaut. + La porta USB inferiore è difettosa. + + + Le port USB du milieu est en défaut. + La porta USB centrale è difettosa. + + + Les 2 ports USB du milieu et du bas sont en défaut. + Le 2 porte USB al centro e in basso sono difettose. + + + Le port USB du haut est en défaut. + La porta USB superiore è difettosa. + + + Les 2 ports USB du haut et du bas sont en défaut. + Le 2 porte USB in alto e in basso sono difettose. + + + Les 2 ports USB du haut et du milieu sont en défaut. + Le 2 porte USB in alto e al centro sono difettose. + + + Les 3 ports USB du haut, du milieu et du bas sont en défaut. + Le 3 porte USB in alto, al centro e in basso sono difettose. + + + Le port USB est en défaut. + La porta USB è difettosa. + + + La masse est absente du connecteur d'alimentation du module + Manca la messa a terra dal connettore di alimentazione del modulo + + + Evènements actuellement actifs qui sont susceptibles de commander ce circuit : + Eventi attualmente attivi che possono controllare questo circuito: + + + Non défini + Non definito + + + DANGER : Le neutre n'est pas référencé à la terre sur ce circuit ("absence de terre"). + PERICOLO: il neutro non è riferito a terra su questo circuito ("nessuna terra"). + + + + config_acces_parametres + + Configuration de l'accès aux paramètres avancés + Configurazione dell'accesso alle impostazioni avanzate + + + Durée de maintien de l'accès + Durata dell'accesso + + + Nouveau code + Nuovo codice + + + Code d'accès + Codice di accesso + + + Répéter le code d'accès + Ripetere il codice di accesso + + + Enregistrer + Registro + + + Aucune (saisie du code à chaque accès) + Nessuno (codice inserito ogni volta che si concede l'accesso) + + + 1 minute + 1 minuto + + + 5 minutes + 5 minuti + + + 15 minutes + 15 minuti + + + 1 heure + 1 ora + + + Infinie (aucune protection des paramètres avancés) + Infinito (nessuna protezione delle impostazioni avanzate) + + + Les deux valeurs saisies doivent être identiques ! + +De plus, le code doit contenir : +- %1 chiffres au minimum +- %2 chiffres au maximum. + I due valori inseriti devono essere identici! + +Inoltre, il codice deve contenere : +- %1 cifre minimo +- %2 cifre massimo. + + + Le nouveau code doit contenir : +- %1 chiffres au minimum +- %2 chiffres au maximum. + +Le code saisi ne répond pas à ces critères et sa mise à jour n'est donc pas effectuée. + +Merci de saisir un code au format valide si vous souhaitez le modifier. + Il nuovo codice deve contenere : +- %1 cifre minimo +- %2 cifre massimo. + +Il codice inserito non soddisfa questi criteri e non verrà aggiornato. + +Inserire un codice valido se si desidera modificarlo. + + + + config_affichage + + Configuration de l'affichage + Configurazione del display + + + Temporisaton économiseur d'écran + Timer salvaschermo + + + Enregistrer + Registro + + + 15 secondes + 15 secondi + + + 30 secondes + 30 secondi + + + 1 minute + 1 minuto + + + 3 minutes + 3 minuti + + + 10 minutes + 10 minuti + + + Aucune limite + Nessun limite + + + Nom du bateau + Nome della barca + + + Fuseau horaire + Fuso orario + + + Thème d'affichage + Tema di visualizzazione + + + UTC-12 (Yankee) + UTC-12 (Yankee) + + + UTC-11 (X-Ray) + UTC-11 (raggi X) + + + UTC-10 (Whisky) + UTC-10 (Whisky) + + + UTC-9 (Victor) + UTC-9 (Victor) + + + UTC-8 (Uniform) + UTC-8 (uniforme) + + + UTC-7 (Tango) + UTC-7 (Tango) + + + UTC-6 (Sierra) + UTC-6 (Sierra) + + + UTC-5 (Romeo) + UTC-5 (Romeo) + + + UTC-4 (Quebec) + UTC-4 (Quebec) + + + UTC-3 (Papa) + UTC-3 (papà) + + + UTC-2 (Oscar) + UTC-2 (Oscar) + + + UTC-1 (November) + UTC-1 (novembre) + + + UTC (Zoulou) + UTC (Zulu) + + + UTC+1 (Alpha) + UTC+1 (Alfa) + + + UTC+2 (Bravo) + UTC+2 (Bravo) + + + UTC+3 (Charlie) + UTC+3 (Charlie) + + + UTC+4 (Delta) + UTC+4 (Delta) + + + UTC+5 (Echo) + UTC+5 (Eco) + + + UTC+6 (Foxtrot) + UTC+6 (Foxtrot) + + + UTC+7 (Golf) + UTC+7 (Golf) + + + UTC+8 (Hotel) + UTC+8 (Hotel) + + + UTC+9 (India) + UTC+9 (India) + + + UTC+10 (Kilo) + UTC+10 (Kilo) + + + UTC+11 (Lima) + UTC+11 (Lima) + + + UTC+12 (Mike) + UTC+12 (Mike) + + + + config_audio + + Bips de clic + Segnali acustici a scatto + + + Fonctionnement de la sortie Audio + Funzionamento dell'uscita audio + + + Enregistrer + Registro + + + Aucun bip + Nessun segnale acustico + + + Bip par défaut + Segnale acustico predefinito + + + Bip 2 + Bip 2 + + + Bip 3 + Bip 3 + + + Bip 4 + Bip 4 + + + Bip 5 + Bip 5 + + + Bip 6 + Bip 6 + + + Bip 7 + Bip 7 + + + Bip 8 + Bip 8 + + + Bip 9 + Bip 9 + + + Bip 10 + Bip 10 + + + Bip 11 + Bip 11 + + + Bip 12 + Bip 12 + + + Bip 13 + Bip 13 + + + Bip 14 + Bip 14 + + + Configuration audio + Configurazione audio + + + Le son de ShipBase est coupé. Le son est uniquement diffusé sur la sortie AUDIO + Il suono di ShipBase è disattivato. Il suono viene emesso solo sull'uscita AUDIO + + + Le son est diffusé sur ShipBase et sur la sortie AUDIO + Il suono viene trasmesso su ShipBase e sull'uscita AUDIO + + + + config_batterie + + Nom de la batterie + Nome della batteria + + + Tension nominale + Tensione nominale + + + Créer la batterie + Creare la batteria + + + Enregistrer + Registro + + + Supprimer + Cancellare + + + Confirmer + Confermare + + + Etalonner + Calibrare + + + Non défini + Non definito + + + ShipBS [@ %1] + ShipBS [@ %1] + + + Entrée VOLT n° %1 + Ingresso VOLT n° %1 + + + Plomb - Acide liquide + Piombo - Acido liquido + + + Plomb - AGM / VRLA + Piombo - AGM / VRLA + + + Plomb - Gel + Piombo - Gel + + + Plomb - Carbone + Piombo - Carbonio + + + Lithium + Litio + + + 12V + 12V + + + 24V + 24V + + + Création d'un parc de batteries + Creazione di un banco di batterie + + + Configuration du parc de batteries + Configurazione del banco batterie + + + Point de mesure + Punto di misurazione + + + Type de batterie(s) + Tipo/i di batteria + + + La modification du <b>type</b> de batterie(s) va nécessiter la remise en <i>configuration usine</i> de certains paramètres.<br /><br />Si vous ne souhaitez pas que cette reconfiguration soit effectuée, notamment si vous avez effectué des réglages spécifiques, cliquez sur ANNULER. <br /><br />Sinon, cliquez sur CONFIRMER pour valider le changement. + La modifica del <b>tipo</b> delle batterie richiederà il ripristino di alcuni parametri alla <i>configurazione di fabbrica</i>.<br /><br />Se non si desidera che venga eseguita questa riconfigurazione, soprattutto se hai effettuato impostazioni specifiche, clicca su ANNULLA. <br /><br />In caso contrario, fare clic su CONFERMA per convalidare la modifica. + + + La modification de la <b>tension nominale</b> du parc de batteries va nécessiter la remise en <i>configuration usine</i> de certains paramètres.<br /><br />Si vous ne souhaitez pas que cette reconfiguration soit effectuée, notamment si vous avez effectué des réglages spécifiques, cliquez sur ANNULER. <br /><br />Sinon, cliquez sur CONFIRMER pour valider le changement. + La modifica della <b>tensione nominale</b> del banco batterie richiederà il ripristino di alcuni parametri alla <i>configurazione di fabbrica</i>.<br /><br />Se non si desidera che venga eseguita questa riconfigurazione, soprattutto se hai effettuato impostazioni specifiche, clicca su ANNULLA. <br /><br />In caso contrario, fare clic su CONFERMA per convalidare la modifica. + + + Capacité + Capacità + + + Ah + Ah + + + Masquer les paramètres avancés + Nascondi le impostazioni avanzate + + + Afficher les paramètres avancés + mostra impostazioni avanzate + + + Coefficient correcteur d'entrée de tension + Coefficiente di correzione dell'ingresso di tensione + + + + + + + Caractéristiques du parc de batteries + Caratteristiche del banco batterie + + + Durée correspondant à la capacité + Durata corrispondente alla capacità + + + h + h + + + Capacité 2 + Capacità 2 + + + Durée de capacité 2 + Durata della capacità 2 + + + Coefficient de Peukert + Coefficiente di Peukert + + + Résistance interne + Resistenza interna + + + mΩ + mΩ + + + Soh actuel + Soh attuale + + + % + % + + + Paramètres de pleine charge + Impostazioni di caricamento completo + + + Tension mini pleine charge + Tensione minima a pieno carico + + + V + V + + + Courant maxi pleine charge + Maximum full load current + + + A + A + + + Temporisation pleine charge + Ritardo a pieno carico + + + s + s + + + Efficacité de charge + Efficienza di ricarica + + + Caractéristiques de charge nulle + Caratteristiche di carico zero + + + Tension de détection charge nulle + Tensione di rilevamento del carico zero + + + Temporisation charge nulle + Ritardo di carico zero + + + Historique + Storico + + + Nombre de cycles de charge + Numero di cicli di carica + + + Nombre de décharges complètes + Numero di scariche complete + + + Forcer Pleine Charge + Forza pieno carico + + + Réinitialiser SOH + Reimposta SOH + + + Réinitialiser Compteurs + Reimposta contatori + + + Non définie + Non definito + + + Groupe de batteries + Pacco batteria + + + Alimentation %1 + Alimentazione %1 + + + Cette batterie est utilisée par l'évènement ci-dessous.<br />Vous devez modifier ou supprimer cet évènement pour qu'il ne dépende plus de cette batterie avant de pouvoir la supprimer. + Questa batteria è utilizzata dall'evento sottostante.<br />Prima di poterlo eliminare, è necessario modificare o eliminare questo evento in modo che non dipenda più da questa batteria. + + + Cette batterie est utilisée par les %1 évènements ci-dessous.<br />Vous devez modifier ou supprimer ces évènements pour qu'ils ne dépendent plus de cette batterie avant de pouvoir la supprimer. + Questa batteria è utilizzata dagli eventi %1 che seguono.<br />Prima di poterla eliminare, è necessario modificare o eliminare questi eventi in modo che non dipendano più da questa batteria. + + + Cette batterie est utilisée par le capteur calculé ci-dessous.<br />Vous devez modifier ou supprimer ce capteur calculé pour qu'il ne dépende plus de cette id_batterie avant de pouvoir la supprimer. + Questa batteria è utilizzata dal sensore calcolato sottostante.<br />Prima di poterla eliminare, è necessario modificare o eliminare questo sensore calcolato in modo che non dipenda più da questo id batteria. + + + Cette id_batterie est utilisée par les %1 capteurs calculés ci-dessous.<br />Vous devez modifier ou supprimer ces capteurs calculés pour qu'ils ne dépendent plus de cette id_batterie avant de pouvoir la supprimer. + Questo id batteria è utilizzato dai sensori %1 calcolati di seguito.<br />Prima di poterlo eliminare, è necessario modificare o eliminare questi sensori calcolati in modo che non dipendano più da questo id batteria. + + + Ok + OK + + + 48V + 48V + + + + config_batteries + + Configuration des batteries + Configurazione della batteria + + + Aucune batterie n'est encore configurée... + La batteria non è ancora configurata... + + + + + + + + + + config_capteur + + Création d'un capteur + Creazione di un sensore + + + Configuration du capteur + Configurazione del sensore + + + Nom du capteur + Nome del sensore + + + Affectation + Assegnazione + + + Masquer sur la page Capteurs + Nascondi nella pagina Sensori + + + Créer le capteur + Creare il sensore + + + Enregistrer + Registro + + + Supprimer + Cancellare + + + Etalonner + Calibrare + + + Humidité + Umidità + + + GNSS - Latitude + GNSS - Latitudine + + + GNSS - Longitude + GNSS - Longitudine + + + GNSS - Altitude + GNSS - Altitudine + + + Type de capteur + Tipo di sensore + + + Module + Modulo + + + Mode du capteur + Modalità sensore + + + Groupe de capteurs + Gruppo di sensori + + + Equation + Equazione + + + Non défini + Non definito + + + Entrées Auxiliaires (AUX INPUTS) + Ingressi ausiliari (AUX INPUTS) + + + Entrées Niveau (LEVEL SENSORS) + Ingressi di livello (SENSORI DI LIVELLO) + + + Entrées Tension (VOLTAGE INPUTS) + INGRESSI DI TENSIONE + + + Capteurs de température (ONE WIRE) + Sensori di temperatura (UN FILO) + + + Capteurs sur modules + Sensori sui moduli + + + Calculé (conditions logiques) + Calcolato (condizioni logiche) + + + <i>Entrée non utilisée</i> + <i>Ingresso non utilizzato</i> + + + Pression Atmosphérique + Pressione atmosferica + + + Température module + Temperatura del modulo + + + Tension d'entrée module + Tensione d'ingresso del modulo + + + Consommation module + Consumo del modulo + + + Consommation ports USB + Consumo della porta USB + + + Chocs + Ammortizzatori + + + Accélération X + X accelerazione + + + Accélération Y + Accelerazione Y + + + Accélération Z + Accelerazione Z + + + GNSS - SOG<br />Speed Over Ground + GNSS - SOG<br />Velocità sul terreno + + + GNSS - COG<br />Course Over Ground + GNSS - COG<br />Corso sul terreno + + + GNSS - SIV<br />Satellites In View + GNSS - SIV<br />Satelliti in vista + + + GNSS - HPA<br />Horizontal Precision Accuracy + GNSS - HPA<br />Accuratezza di precisione orizzontale + + + GNSS - VPA<br />Vertical Precision Accuracy + GNSS - VPA<br />Accuratezza di precisione verticale + + + Modem 4G/LTE - RSSI<br />Received Signal Strength Indicator + Modem 4G/LTE - RSSI<br />Indicatore di potenza del segnale ricevuto + + + Modem 4G/LTE - SINR<br />Signal to Interference & Noise Ratio + Modem 4G/LTE - SINR<br />Rapporto segnale/interferenza e rumore + + + Normal + Normale + + + Inversé + Invertito + + + Tension 0 - 10 V + Tensione 0 - 10 V + + + Résistance 0 - 500 Ohms + Resistenza 0 - 500 Ohm + + + Courant 4 - 20 mA + Corrente 4 - 20 mA + + + Défaut d'isolement + Guasto di isolamento + + + Ce capteur est utilisé par l'évènement ci-dessous.<br />Vous devez modifier ou supprimer cet évènement pour qu'il ne dépende plus de ce capteur avant de pouvoir le supprimer. + Questo sensore è utilizzato dall'evento sottostante.<br />Prima di poterlo eliminare, è necessario modificare o eliminare questo evento in modo che non dipenda più da questo sensore. + + + Ce capteur est utilisé par les %1 évènements ci-dessous.<br />Vous devez modifier ou supprimer ces évènements pour qu'ils ne dépendent plus de ce capteur avant de pouvoir le supprimer. + Questo sensore è utilizzato dagli eventi %1 riportati di seguito.<br />Prima di poterlo eliminare, è necessario modificare o eliminare questi eventi in modo che non dipendano più da questo sensore. + + + Ce capteur est utilisé par le capteur calculé ci-dessous.<br />Vous devez modifier ou supprimer ce capteur calculé pour qu'il ne dépende plus de ce capteur avant de pouvoir le supprimer. + Questo sensore è utilizzato dal sensore calcolato sottostante.<br />Prima di poterlo eliminare, è necessario modificare o eliminare questo sensore calcolato in modo che non dipenda più da questo sensore. + + + Ce capteur est utilisé par les %1 capteurs calculés ci-dessous.<br />Vous devez modifier ou supprimer ces capteurs calculés pour qu'ils ne dépendent plus de ce capteur avant de pouvoir le supprimer. + Questo sensore è utilizzato dai sensori %1 calcolati di seguito.<br />Prima di poterlo eliminare, è necessario modificare o eliminare questi sensori calcolati in modo che non dipendano più da questo sensore. + + + %1 : Non définie + %1 : Non definito + + + %1 : %2 + %1 : %2 + + + Libellé du capteur pour la valeur %1 + Etichetta del sensore per il valore %1 + + + Entrées NMEA2000 + voci NMEA2000 + + + + config_capteur_calcule_booleen + + Equation du capteur calculé [%1] + Equazione del sensore calcolata [%1] + + + Enregistrer + Registro + + + Supprimer + Cancellare + + + Le nombre de conditions par capteur est limité à %1.<br /><br />Vous ne pouvez pas ajouter de groupe ou de nouvelle condition avant d'en avoir supprimé préalablement. + Il numero di condizioni per sensore è limitato a %1.<br /><br />Non è possibile aggiungere un gruppo o una nuova condizione se prima non se ne è cancellata una. + + + Des modifications ont été apportées au capteur<br />mais n'ont pas été enregistrées.<br /><br />Cliquer sur ANNULER pour revenir au menu en cours.<br /><br />Cliquer sur Ok pour sortir sans enregistrer. + Sono state apportate modifiche al sensore<br />ma non sono state salvate.<br /><br />Cliccare su ANNULLA per tornare al menu corrente.<br /><br />Cliccare su OK per uscire senza salvare. + + + est actif + è attivo + + + est inactif + è inattivo + + + Ou + Oppure + + + Et + E + + + X-Ou + X-Ou + + + + config_capteur_calcule_booleen_condition + + Création d'une condition du capteur [%1] + Creazione di una condizione del sensore [%1] + + + Type + Tipo + + + Source + Fonte + + + Variable + Variabile + + + Test + Test + + + Seuil + Soglia + + + Créer la condition + Creare la condizione + + + Enregistrer + Registro + + + Non défini + Non definito + + + Circuit + Circuito + + + Capteur + Sensore + + + Réservoir + Serbatoio + + + Batterie + Batteria + + + Actif + Attività + + + Inactif + Inattivo + + + &lt; au seuil + alla soglia + + + &le; au seuil + sulla soglia + + + = au seuil + = alla soglia + + + &ge; au seuil + alla soglia + + + &gt; au seuil + sulla soglia + + + + config_capteurs + + Configuration des capteurs + Configurazione del sensore + + + Aucun capteur n'est encore configuré... + Non è ancora stato configurato alcun sensore... + + + + + + + + + + config_circuit + + Configuration du circuit + Configurazione del circuito + + + Nom du circuit + Nome del circuito + + + Affectation + Assegnazione + + + Circuit renfort + Circuito di rinforzo + + + Mode de commande + Modalità di controllo + + + Vitesse de démarrage/arrêt + Velocità di avvio/arresto + + + Seuil de disjonction + Soglia di intervento + + + Vitesse de disjonction + Velocità di disconnessione + + + Filtrage du courant consommé + Filtraggio attuale + + + Masquer sur la page d'accueil + Nascondi nella pagina iniziale + + + Créer le circuit + Creare il circuito + + + Enregistrer + Registro + + + L'affectation du circuit vient d'être modifiée alors que le circuit était actif. +Avant d'effectuer ce changement, le circuit a été passé sur OFF. + +Pensez à le réactiver si besoin... + L'assegnazione del circuito è stata appena modificata mentre il circuito era attivo. +Prima di effettuare questa modifica, il circuito è stato disattivato. + +Ricordarsi di riattivarlo se necessario... + + + Supprimer + Cancellare + + + Aucun + No + + + ShipPower812 [@ %1] + ShipPower812 [@ %1] + + + ShipPower4AC [@ %1] + ShipPower4AC [@ %1] + + + ShipPower8DC [@ %1] + ShipPower8DC [@ %1] + + + Circuit %1 + Circuito %1 + + + Groupe de circuits + Gruppo di circuiti + + + %1 - %2 + %1 - %2 + + + Non affecté + Non allocato + + + On-Off + On-Off + + + On-Off progressif + Progressivo on-off + + + Variateur + Interruttore dimmer + + + Aucun filtrage + Nessun filtraggio + + + Très faible + Molto basso + + + Faible + Basso + + + Moyen + Medio + + + Elevé + Alto + + + Très élevé + Molto alto + + + Très rapide + Molto veloce + + + Rapide + Veloce + + + Moyenne + Media + + + Lente + Lento + + + Très lente + Molto lento + + + 15 secondes + 15 secondi + + + 1 minute + 1 minuto + + + 5 minutes + 5 minuti + + + 15 minutes + 15 minuti + + + 1 heure + 1 ora + + + 4 heures + 4 ore + + + L'utilisation d'un circuit de renfort rend l'utilisation du mode de commande [Variateur] impossible.<br /><br />Le mode de commande vient donc d'être ramené à [On-Off Progressif]. + L'utilizzo di un circuito di rinforzo rende impossibile l'uso della modalità di controllo [Dimmer].<br /><br />La modalità di controllo è quindi appena tornata a [On-Off progressivo]. + + + Commande impulsionnelle + Controllo degli impulsi + + + Non + No + + + 1 seconde + 1 secondo + + + 2 secondes + 15 secondi {2 ?} + + + 5 secondes + 15 secondi {5 ?} + + + 30 secondes + 30 secondi + + + 45 secondes + 15 secondi {45 ?} + + + Ce circuit est utilisé pour la commande du moteur.<br />Vous devez d'abord affecter la commande moteur à un autre circuit avant de pouvoir supprimer celui-ci. + Questo circuito viene utilizzato per controllare il motore.<br />Prima di poterlo eliminare, è necessario assegnare il controllo del motore a un altro circuito. + + + Ce circuit est utilisé par l'évènement ci-dessous.<br />Vous devez modifier ou supprimer cet évènement pour qu'il ne dépende plus de ce circuit avant de pouvoir le supprimer. + Questo circuito è utilizzato dall'evento sottostante.<br />Prima di poterlo eliminare, è necessario modificare o eliminare questo evento in modo che non dipenda più da questo circuito. + + + Ce circuit est utilisé par les %1 évènements ci-dessous.<br />Vous devez modifier ou supprimer ces évènements pour qu'ils ne dépendent plus de ce circuit avant de pouvoir le supprimer. + Questo circuito è utilizzato dagli eventi %1 che seguono.<br />Prima di poterlo eliminare, è necessario modificare o eliminare questi eventi in modo che non dipendano più da questo circuito. + + + Ce circuit est utilisé par le capteur calculé ci-dessous.<br />Vous devez modifier ou supprimer ce capteur calculé pour qu'il ne dépende plus de ce circuit avant de pouvoir le supprimer. + Questo circuito è utilizzato dal sensore calcolato sottostante.<br />Prima di poterlo eliminare, è necessario modificare o eliminare questo sensore calcolato in modo che non dipenda più da questo circuito. + + + Ce circuit est utilisé par les %1 capteurs calculés ci-dessous.<br />Vous devez modifier ou supprimer ces capteurs calculés pour qu'ils ne dépendent plus de ce circuit avant de pouvoir le supprimer. + Questo circuito è utilizzato dai sensori %1 calcolati di seguito.<br />Prima di poterlo eliminare, è necessario modificare o eliminare questi sensori calcolati in modo che non dipendano più da questo circuito. + + + + config_circuits + + Configuration des circuits + Configurazione del circuito + + + Pack de batteries : + Batteria : + + + Aucun capteur n'est encore configuré... + Non è ancora stato configurato alcun sensore... + + + Oui + + + + Non + No + + + Le module n'est affecté à aucune batterie... + Il modulo non è assegnato a nessuna batteria... + + + Circuit non utilisé + Circuito non utilizzato + + + Circuits Non Affectés + Circuiti non interessati + + + Ce circuit est configuré comme renfort du circuit <b>%1</b> et ne peut donc pas être configuré individuellement.<br /><br />Merci de cliquer sur le circuit <b>%1</b> de ce même module pour accéder à leurs paramètres communs<br />(y compris pour supprimer le circuit de renfort actuel). + Questo circuito è configurato come back-up per il circuito <b>%1</b> e non può quindi essere configurato individualmente.<br /><br />Cliccare sul circuito <b>%1</b> in questo stesso modulo per accedere ai parametri comuni<br />(compresa la cancellazione dell'attuale circuito di back-up). + + + Type de carte inconnu... + Tipo di carta sconosciuto... + + + Le module <br /><b>%1</b><br /> n'est affecté à aucun pack de batteries. <br /><br />Souhaitez-vous laisser la configuration en l'état ? + Il modulo <br /><b>%1</b><br /> non è assegnato a nessun pacco batteria. <br /><br />Si vuole lasciare la configurazione così com'è? + + + Les modules suivants ne sont affectés à aucun pack de batteries :<br /><b>%1</b><br /><br /><br />Souhaitez-vous laisser la configuration en l'état ? + I seguenti moduli non sono assegnati a nessun pacco batteria:<br /><b>%1</b><br /><br /><br /> Si desidera lasciare la configurazione così com'è? + + + + config_event + + Création d'un évènement + Creare un evento + + + Configuration de l'évènement + Configurazione dell'evento + + + Nom de l'évènement + Nome dell'evento + + + Type de la source + Tipo di fonte + + + Source + Fonte + + + Variable de la source + Variabile di fonte + + + Déclenchement si + Attivato se + + + Seuil de déclenchement + Soglia di attivazione + + + Temporisation de déclenchement + Ritardo di attivazione + + + s + s + + + Masquer sur la page d'accueil + Nascondi nella pagina iniziale + + + Conditions horaire + Condizioni orarie + + + Le nombre maximal de conditions horaires [%1] est atteint : ajout impossible... + È stato raggiunto il numero massimo di condizioni temporali [%1]: non è possibile aggiungere... + + + Aucune condition horaire n'est configurée pour cet évènement... + Non sono state fissate condizioni temporali per questo evento... + + + Signalisation + Segnaletica + + + Alarme sonore + Allarme acustico + + + La validation des alarmes sonores a nécessité de valider également l'affichage des messages liés à cet évènement.<br /><br />Cet affichage est en effet nécessaire au fonctionnement des alarmes sonores, afin de pouvoir les acquitter. + Convalidare gli allarmi acustici significa anche convalidare la visualizzazione dei messaggi relativi a questo evento.<br /><br />Questa visualizzazione è necessaria per il funzionamento degli allarmi acustici, in modo che possano essere riconosciuti. + + + Alarme sur LED + Allarme a LED + + + La validation des alarmes sur LED a nécessité de valider également l'affichage des messages liés à cet évènement.<br /><br />Cet affichage est en effet nécessaire au fonctionnement des alarmes sur LED, afin de pouvoir les acquitter. + Per convalidare gli allarmi LED, abbiamo dovuto convalidare anche la visualizzazione dei messaggi relativi a questo evento.<br /><br />Questa visualizzazione è necessaria per il funzionamento degli allarmi LED, in modo che possano essere riconosciuti. + + + Alarme sur sortie(s) de soutien + Allarme su uscita/i di supporto + + + La validation des alarmes sur sortie(s) de soutien a nécessité de valider également l'affichage des messages liés à cet évènement.<br /><br />Cet affichage est en effet nécessaire au fonctionnement des alarmes sur sortie(s) de soutien, afin de pouvoir les acquitter. + Per convalidare gli allarmi sulle uscite di supporto, è stato necessario convalidare anche la visualizzazione dei messaggi relativi a questo evento.<br /><br />Questa visualizzazione è infatti necessaria per il funzionamento degli allarmi sulle uscite di supporto, al fine di poterli riconoscere. + + + Alarme sur la source + Allarme sorgente + + + Affichage message sur ShipBase + Visualizzazione dei messaggi su ShipBase + + + La dévalidation de l'affichage des messages a nécessité de dévalider également :<ul><li>les alarmes sonores,</li><li>les alarmes sur led</li><li>et les alarmes sur sortie(s) de soutien</li></ul><br />L'affichage de message est en effet nécessaire à leur fonctionnement, afin de pouvoir les acquitter. + La disattivazione della visualizzazione dei messaggi richiede anche la disattivazione di:<ul><li>allarmi sonori,</li><li>allarmi luminosi</li><li>e allarmi su uscite di supporto <li/li></ul><br />La visualizzazione dei messaggi è infatti necessaria per il loro funzionamento, al fine di poterli riconoscere. + + + Texte du message à afficher + Testo del messaggio da visualizzare + + + Emission SMS + Trasmissione di SMS + + + Texte du SMS à envoyer + Testo dell'SMS da inviare + + + Emission Email + Trasmissione e-mail + + + Texte de l'email à envoyer + Testo dell'e-mail da inviare + + + Action sur circuits + Azione sui circuiti + + + Aucune + No + + + Le circuit "bascule" + Il circuito "flip-flop + + + Le circuit passe à OFF + Il circuito passa a OFF + + + Le circuit passe à ON + Il circuito passa a ON + + + Le nombre de circuits commandés par un évènement est limité à %1.<br /><br />Vous ne pouvez pas ajouter d'action sur un nouveau circuit avant d'en avoir supprimé préalablement. + Il numero di circuiti controllati da un evento è limitato a %1.<br /><br />Non è possibile aggiungere un'azione a un nuovo circuito se prima non se ne è cancellato uno. + + + Créer l'évènement + Creare l'evento + + + Enregistrer + Registro + + + Supprimer + Cancellare + + + Non défini + Non definito + + + Condition horaire seule + Condizione di solo tempo + + + Circuit + Circuito + + + Capteur + Sensore + + + Réservoir + Serbatoio + + + Batterie + Batteria + + + Passage à <b>actif</b> + Passare a <b>attivo</b> + + + Passage à <b>inactif</b> + Passare a <b>inattivo</b> + + + &lt; au seuil + &lt; alla soglia + + + &le; au seuil + &le; sulla soglia + + + = au seuil + = alla soglia + + + &ge; au seuil + &ge; alla soglia + + + &gt; au seuil + &gt; sulla soglia + + + + config_events + + Configuration des évènements + Configurazione dell'evento + + + Aucun évènement n'est encore configuré... + Non è ancora stato configurato alcun evento... + + + 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. + Il numero totale di eventi è limitato a %1.<br /><br />Non è possibile aggiungere un nuovo evento prima di averne cancellato uno. + + + Sur circuits + Sui circuiti + + + Sur capteurs + Sui sensori + + + Sur réservoirs + Sui serbatoi + + + Sur batteries + Sulle batterie + + + Horaire seulement + Solo programma + + + + config_groupe_elements + + Création d'un groupe + Creare un gruppo + + + Modification d'un groupe + Modifica di un gruppo + + + Nom du groupe + Nome del gruppo + + + Créer le groupe + Creare un gruppo + + + Enregistrer + Registro + + + Supprimer + Cancellare + + + capteurs + sensori + + + circuits + circuiti + + + 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). + Questo gruppo è l'ultimo ancora valido.<br /><br />È possibile eliminarlo solo dopo aver creato almeno un altro gruppo (non è possibile operare senza alcun gruppo %1). + + + Ce groupe comprend encore %1 %2.<br /><br />Il est nécessaire d'affecter ces %2 à un autre groupe avant de pouvoir le supprimer. + Questo gruppo include ancora %1 %2.<br /><br />Questo %2 deve essere assegnato a un altro gruppo prima di poter essere cancellato. + + + 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. + Questo gruppo include ancora %1 %2,<br />incluso %3 configurato come "nascosto".<br /><br />Questo %2 deve essere assegnato a un altro gruppo prima di poter essere cancellato. + + + batteries + batterie + + + réservoirs + serbatoi + + + + config_image_accueil + + Image d'accueil + Immagine della casa + + + Aucune image n'a encore été chargée... + Non sono state ancora caricate immagini... + + + Sélectionner l'image par défaut + Selezionare l'immagine predefinita + + + Sélectionner cette image + Selezionare questa immagine + + + Copier + Copia + + + Supprimer + Cancellare + + + Ejection + Espulsione + + + Insérer une clé USB dans le port <u>du bas</u>, à droite + Inserire una chiavetta USB nella porta <u>in basso</u> a destra + + + Vous pouvez retirer la clé en toute sécurité... + È possibile rimuovere la chiave in modo sicuro... + + + Seuls les fichiers de type '.jpg' ou '.png' de taille inférieure à %1 sont autorisés. + Sono autorizzati solo i file '.jpg' o '.png' di dimensioni inferiori a %1. + + + La clé USB a été <i>éjectée</i> automatiquement.<br />Vous pouvez la retirer dès maintenant en toute sécurité... + La chiave USB è stata <i>espulsa automaticamente</i>.<br /> Ora è possibile rimuoverla con sicurezza... + + + USB Arrière + USB posteriore + + + Spare + Ricambio + + + USB Avant + Fronte USB + + + Touch pad + Touch pad + + + La clé USB a été retirée sans avoir préalablement été <i>éjectée</i> !<br />Cela peut conduire à des pertes de données sur la clé, voire sur ShipHeart.<br /><br />Lors de vos prochaines utilisations, pensez à <i>éjecter</i> la clé avec le bouton en haut de page avant de la retirer... Merci ! + La chiave USB è stata rimossa senza averla prima <i>espulsa</i>! <br />Questo può causare la perdita di dati sulla chiave e persino su ShipHeart.<br /><br />La prossima volta che si utilizza la chiave, ricordarsi di <i>espellerla</i> utilizzando il pulsante in cima alla pagina prima di rimuoverla... Grazie mille! + + + + config_installation + + Configuration de l'installation + Configurazione dell'installazione + + + Raison sociale + Nome della società + + + N° & Rue + Numero e via + + + Complément d'adresse + Indirizzo aggiuntivo + + + Code postal + Codice postale + + + Ville + Città + + + Nom du contact + Nome del contatto + + + Téléphone + Telefono + + + Email + Email + + + Site web + Sito web + + + Enregistrer + Registro + + + Rapports + Rapporti + + + + config_koriolan + + Accès réservé Koriolan + Accesso riservato Koriolan + + + Client spécifique + Cliente specifico + + + Enregistrer + Registro + + + Nombre jours avant suppression historique + Numero di giorni prima che la cronologia venga cancellata + + + Nombre jours avant suppression mesures + Numero di giorni prima delle misure di rimozione + + + Période de sauvegarde BDD + Periodo di backup del DB + + + Période de vérification download + Download del periodo di verifica + + + Date de dernier archivage mesures + Data dell'ultima archiviazione delle misure + + + Aucune spécificité + Nessuna specificità + + + Client Suncy Concept + Cliente Suncy Concept + + + Mode de mise à jour des firmwares + Modalità di aggiornamento del firmware + + + Tests matériel + Test dell'hardware + + + Normal (si version installée est antérieure à la version en cours) + Normale (se la versione installata è precedente a quella attuale) + + + Différente (si version installée est différente de version en cours) + Diverso (se la versione installata è diversa da quella attuale) + + + Toujours (à utiliser avec modération...) + Sempre (da usare con moderazione...) + + + + config_module + + Emplacement du module à bord + Posizione del modulo a bordo + + + Commentaires + Commenti + + + Modifier + Modificare + + + Localiser le module + Individuare il modulo + + + Paramètres du module [%1] + Parametri del modulo [%1] + + + Paramètres du module [%1] à l'adresse [%2] + Parametri del modulo [%1] all'indirizzo [%2] + + + N° de série + Numero di serie + + + Nom du firmware + Nome del firmware + + + Version du firmware + Versione del firmware + + + Version matérielle + Versione dell'hardware + + + Résistance de terminaison + Resistenza di terminazione + + + Oui + + + + Non + No + + + CRC du firmware + CRC del firmware + + + <i>--- Circuit non affecté ---</i> + <i>--- Circuito non interessato ---</i> + + + [renfort] + [rinforzo] + + + Affectations + Assegnazione + + + <i>--- Aucune batterie affectée ---</i> + <i>--- Nessuna batteria interessata ---</i> + + + Affectation + Assegnazione + + + Version processeur + Versione del processore + + + Courant de masses sur réseau + Corrente di massa sulla rete + + + + config_module_modification + + Configuration du module [%1] à l'adresse [%2] + Configurazione del modulo [%1] all'indirizzo [%2] + + + Emplacement du module à bord + Posizione del modulo a bordo + + + Commentaires + Commenti + + + Enregistrer + Registro + + + Courant de masses max. sur réseau + Corrente massima di massa sulla rete + + + A + A + + + + config_ordre_elements + + 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... + Per spostare un gruppo, tenere premuto il pulsante del mouse e trascinarlo.<br />Per modificare o eliminare un gruppo, fare doppio clic sul gruppo.<br />Per aggiungere un gruppo, fare clic su '+'.<br /><br />Nota: se c'è un solo gruppo, nella pagina interessata non viene visualizzata alcuna scheda... + + + Aucun groupe n'est actuellement configuré... + Non ci sono gruppi attualmente configurati... + + + Aucun élément n'est actuellement configuré... + Non ci sono elementi attualmente configurati... + + + Aucun groupe de capteurs n'est actuellement configuré... + Non sono stati configurati gruppi di sensori... + + + Aucun groupe de circuits n'est actuellement configuré... + Al momento non sono configurati gruppi di circuiti... + + + Aucun groupe de batteries n'est actuellement configuré... + Al momento non sono configurati gruppi di batterie... + + + Aucune batterie n'est actuellement affectée à ce groupe... + Nessuna batteria è attualmente assegnata a questo gruppo... + + + Affichage des batteries sur la page d'accueil + Visualizzazione della batteria nella pagina iniziale + + + Aucun capteur n'est actuellement affecté ce groupe... + Al momento non ci sono sensori assegnati a questo gruppo... + + + Affichage des capteurs sur la page d'accueil + Visualizzazione dei sensori sulla home page + + + Aucun circuit n'est actuellement affecté à ce groupe... + Nessun circuito è attualmente assegnato a questo gruppo... + + + Affichage des circuits sur la page d'accueil + Visite visualizzate sulla home page + + + Aucun groupe de réservoirs n'est actuellement configuré... + Al momento non sono configurati gruppi di serbatoi... + + + Aucun réservoir n'est actuellement affecté à ce groupe... + Al momento non ci sono serbatoi assegnati a questo gruppo... + + + Affichage des réservoirs sur la page d'accueil + Visualizzazione dei serbatoi nella pagina iniziale + + + + config_page + + Création d'une page + Creazione di una pagina + + + Configuration de la page + Impostazione della pagina + + + Nom de la page + Nome della pagina + + + Opacité de la silhouette + Opacità della sagoma + + + Fichier de silhouette + Archivio di sagoma + + + Créer la page + Crea la pagina + + + Enregistrer + Registro + + + Silhouette + Silhouette + + + Supprimer + Cancellare + + + Aucun + No + + + + config_page_edition + + Edition de la page [%1] + Modifica della pagina [%1] + + + Aucun équipement n'est configuré sur cette page pour le moment... + Nessuna apparecchiatura è configurata in questa pagina al momento... + + + Page + Pagina + + + Enregistrer + Registro + + + 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. + Sono state apportate modifiche che non sono state salvate<br />Fare clic su Annulla per tornare indietro e salvarle.<br />Fare clic su OK per uscire senza salvare. + + + + config_page_point + + Création d'un point + Creare un punto + + + Configuration du point + Configurazione dei punti + + + Type de la source + Tipo di fonte + + + Source + Fonte + + + Type de point + Tipo di punto + + + Taille du point + Dimensione del punto + + + Enregistrer + Registro + + + Créer le point + Crea il punto + + + Supprimer + Cancellare + + + Non défini + Non definito + + + Capteur + Sensore + + + Circuit + Circuito + + + Réservoir + Serbatoio + + + Batterie + Batteria + + + Modules + Moduli + + + + config_page_silhouette + + Silhouette de la page + Sagoma della pagina + + + Aucune image n'a encore été chargée... + Non sono state ancora caricate immagini... + + + Aucune image + Nessuna foto + + + Sélectionner cette image + Selezionare questa immagine + + + Copier + Copia + + + Supprimer + Cancellare + + + Ejection + Espulsione + + + Insérer une clé USB dans le port <u>du bas</u>, à droite + Inserire una chiavetta USB nella porta <u>in basso</u> a destra + + + Vous pouvez retirer la clé en toute sécurité... + È possibile rimuovere la chiave in modo sicuro... + + + Seuls les fichiers de type '.jpg' ou '.png' de taille inférieure à %1 sont autorisés. + Sono autorizzati solo i file '.jpg' o '.png' di dimensioni inferiori a %1. + + + La clé USB a été <i>éjectée</i> automatiquement.<br />Vous pouvez la retirer dès maintenant en toute sécurité... + La chiave USB è stata <i>espulsa automaticamente</i>.<br /> Ora è possibile rimuoverla con sicurezza... + + + USB Arrière + USB posteriore + + + Spare + Ricambio + + + USB Avant + Fronte USB + + + Touch pad + Touch pad + + + La clé USB a été retirée sans avoir préalablement été <i>éjectée</i> !<br />Cela peut conduire à des pertes de données sur la clé, voire sur ShipHeart.<br /><br />Lors de vos prochaines utilisations, pensez à <i>éjecter</i> la clé avec le bouton en haut de page avant de la retirer... Merci ! + La chiave USB è stata rimossa senza averla prima <i>espulsa</i>! <br />Questo può causare la perdita di dati sulla chiave e persino su ShipHeart.<br /><br />La prossima volta che si utilizza la chiave, ricordarsi di <i>espellerla</i> utilizzando il pulsante in cima alla pagina prima di rimuoverla... Grazie mille! + + + + config_pages + + Configuration des pages + Impostazione della pagina + + + Aucune page n'est encore configurée... + Nessuna pagina è ancora configurata... + + + + + + + + + Image accueil + Immagine di benvenuto + + + + config_pdf + + Ship2net + Nave2net + + + Enregistrer + Registro + + + + config_rapports + + Rapports d'installation + Rapporti di installazione + + + Aucun rapport d'installation n'est encore disponible... + Non è ancora disponibile un rapporto di installazione... + + + Nouveau rapport d'installation + Rapporto sulla nuova installazione + + + Copier + Copia + + + Déplacer + Muoversi + + + Supprimer + Cancellare + + + Ejection + Espulsione + + + Insérer une clé USB dans le port <u>du bas</u>, à droite + Inserire una chiavetta USB nella porta <u>in basso</u> a destra + + + Vous pouvez retirer la clé en toute sécurité... + È possibile rimuovere la chiave in modo sicuro... + + + La clé USB a été <i>éjectée</i> automatiquement.<br />Vous pouvez la retirer dès maintenant en toute sécurité... + La chiave USB è stata <i>espulsa automaticamente</i>.<br /> Ora è possibile rimuoverla con sicurezza... + + + USB Arrière + USB posteriore + + + Spare + Ricambio + + + USB Avant + Fronte USB + + + Touch pad + Touch pad + + + La clé USB a été retirée sans avoir préalablement été <i>éjectée</i> !<br />Cela peut conduire à des pertes de données sur la clé, voire sur ShipHeart.<br /><br />Lors de vos prochaines utilisations, pensez à <i>éjecter</i> la clé avec le bouton en haut de page avant de la retirer... Merci ! + La chiave USB è stata rimossa senza averla prima <i>espulsa</i>! <br />Questo può causare la perdita di dati sulla chiave e persino su ShipHeart.<br /><br />La prossima volta che si utilizza la chiave, ricordarsi di <i>espellerla</i> utilizzando il pulsante in cima alla pagina prima di rimuoverla... Grazie mille! + + + Le rapport d'installation<br /><br /><b>%1</b><br /><br />a été généré. + Il rapporto di installazione<br /><br /><b>%1</b><br /><br />è stato generato. + + + + config_reseau_ethernet_wifi + + Réseau Ethernet & Wifi + Rete Ethernet e Wifi + + + Modifier + Modificare + + + Ethernet + Ethernet + + + Adresse IP + Indirizzo IP + + + Non connecté + Non collegato + + + Connexion à un réseau existant + Connessione a una rete esistente + + + Etat + Stato + + + On + ON + + + Off + OFF + + + Nom du réseau [SSID] + Nome della rete [SSID] + + + Génération d'un réseau spécifique + Generazione di una rete specifica + + + Canal + Canale + + + + config_reseau_k_bus + + Réseau ShipHeart + Rete ShipHeart + + + Modules physiquement présents + Moduli fisicamente presenti + + + %1 - %2 + %1 - %2 + + + Modules utilisés par la configuration actuelle + Moduli utilizzati dalla configurazione corrente + + + [@ %1] : %2 + [@ %1] : %2 + + + La configuration actuelle ne fait appel à aucun autre module que ShipBase... + La configurazione attuale non utilizza nessun altro modulo oltre a ShipBase... + + + Module non utilisé en configuration + Modulo non utilizzato nella configurazione + + + [renfort] + [rinforzo] + + + Enregistrer + Registro + + + Retour + Indietro + + + Quitter + Lasciare + + + Aucune modification n'a été apportée à la configuration actuelle.<br />Celle-ci contient toujours des anomalies !<br /><br /><br />Souhaitez-vous :<br />Poursuivre les modifications [%1]<br />Quitter ce menu sans enregistrer les modifications [%2] + Non è stata apportata alcuna modifica alla configurazione corrente.<br />Contiene ancora anomalie!<br /><br /><br />Vorresti:<br />Continuare ad apportare modifiche [%1]<br / >Esci da questo menu senza salvare le modifiche [%2] + + + La configuration actuelle contient toujours des anomalies !<br /><br /><br />Souhaitez-vous :<br />Enregistrer cette nouvelle configuration et quitter ce menu [%1]<br />Poursuivre les modifications [%2]<br />Quitter ce menu sans enregistrer les modifications [%3] + La configurazione attuale contiene ancora delle anomalie!<br /><br /><br />Vuoi:<br />Salvare questa nuova configurazione e uscire da questo menu [%1]<br />Continuare con le modifiche [%2 ]<br />Esci da questo menu senza salvare le modifiche [%3] + + + La configuration actuelle est correcte <br />mais n'a pas encore été enregistrée.<br /><br /><br />Souhaitez-vous :<br />Enregistrer cette nouvelle configuration et quitter ce menu [%1]<br />Poursuivre les modifications [%2]<br />Quitter ce menu sans enregistrer les modifications [%3] + La configurazione corrente è corretta <br />ma non è stata ancora salvata.<br /><br /><br />Vorresti:<br />Salvare questa nuova configurazione e uscire da questo menu [%1] < br />Continua le modifiche [%2]<br />Esci da questo menu senza salvare le modifiche [%3] + + + + config_reseau_nmea + + Réseau NMEA2000 + Rete NMEA2000 + + + Aucun PGN n'a encore été détecté sur le réseau NMEA2000... + Non è stato ancora rilevato alcun PGN sulla rete NMEA2000... + + + PGN non affecté + PGN non assegnato + + + + config_reseau_one_wire + + Réseau One Wire + Rete One Wire + + + Aucune sonde n'est encore installée... + Non è ancora stata installata alcuna sonda... + + + 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. + Il bus One Wire è attualmente rilevato come cortocircuitato. <br />Questa condizione non rappresenta un pericolo, ma ne impedisce il funzionamento. <br /><br />Controllare il cablaggio corrispondente finché il messaggio non scompare. + + + Type inconnu + Tipo sconosciuto + + + Sonde non affectée + Sonda non assegnata + + + + config_reseau_one_wire_modification + + Configuration de la sonde [%1] + Configurazione del sensore [%1] + + + Emplacement de la sonde + Posizione della sonda + + + Enregistrer + Registro + + + + config_reseau_wifi_ap + + Configuration Wifi en mode AP + Configurazione Wifi in modalità AP + + + Etat + Stato + + + Nom du réseau (SSID) + Nome della rete (SSID) + + + Mot de passe d'accès au réseau + Password di accesso alla rete + + + Canal + Canale + + + Adresse IP + Indirizzo IP + + + Non connecté + Non collegato + + + Enregistrer + Registro + + + Off + OFF + + + On + ON + + + Canal %1 - [%2GHz] + Canale %1 - [%2GHz] + + + Le nom du réseau (SSID) doit comprendre entre 1 et 32 caractères. <br />Merci d'entrer un nom valide. + Il nome della rete (SSID) deve avere una lunghezza compresa tra 1 e 32 caratteri. <br />Inserire un nome valido. + + + 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. + La password di accesso alla rete deve avere una lunghezza compresa tra 8 e 63 caratteri. <br />Inserire una password valida. + + + 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. + Il nome della rete (SSID) deve includere solo:<br />- lettere maiuscole [A - Z],<br />- lettere minuscole [a - z],<br />- cifre [0 - 9]<br />- caratteri speciali [%1].<br /><br />Inserire un nome valido. + + + 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. + La password di accesso alla rete deve contenere solo:<br />- lettere maiuscole [A - Z],<br />- lettere minuscole [a - z],<br />- numeri [0 - 9]<br />- caratteri speciali [%1].<br /><br />Inserire un nome valido. + + + + config_reseau_wifi_sta + + Configuration Wifi en mode STA + Configurazione Wifi in modalità STA + + + Etat + Stato + + + Réseau + Rete + + + Mot de passe d'accès au réseau + Password di accesso alla rete + + + Enregistrer + Registro + + + Réseaux connus + Reti conosciute + + + Off + OFF + + + On + ON + + + Aucun réseau... + Nessuna rete... + + + + config_reseau_wifi_sta_liste + + Liste des réseaux Wifi connus + Elenco delle reti Wifi conosciute + + + Aucun réseau n'a été détecté... + Non è stata rilevata alcuna rete... + + + Oublier tous les réseaux + Dimenticate tutte le reti + + + Oublier ce réseau + Dimenticate questa rete + + + + config_reservoir + + Création d'un réservoir + Creazione di un serbatoio + + + Configuration du réservoir + Configurazione del serbatoio + + + Nom du réservoir + Nome del serbatoio + + + Famille de réservoirs + Famiglia di serbatoi + + + Type de capteur de niveau + Tipo di sensore di livello + + + %1 : Non définie + %1 : Non definito + + + %1 : %2 + %1 : %2 + + + Sonde la plus basse dans le réservoir + Sonda più bassa nel serbatoio + + + Non définie + Non definito + + + Logique d'alarme + Logica di allarme + + + Filtrage des mesures + Filtraggio delle misure + + + Créer le réservoir + Creazione del serbatoio + + + Enregistrer + Registro + + + Supprimer + Cancellare + + + Etalonnage + Calibrazione + + + AUX INPUT %1 + INGRESSO AUX %1 + + + LEVEL SENSOR %1 + SENSORE DI LIVELLO %1 + + + Confirmer + Confermare + + + Non défini + Non definito + + + Electrodes plongées ou contacts secs + Elettrodi immersi o contatti a secco + + + Résistif 0 - 190Ω + Resistivo 0 - 190Ω + + + Résistif 240 - 30Ω + Resistivo 240 - 30Ω + + + Boucle de courant 4 - 20mA + Anello di corrente 4 - 20mA + + + Tension 0 - 10V + Tensione 0 - 10V + + + Aucun filtrage + Nessun filtraggio + + + Très faible + Molto basso + + + Faible + Basso + + + Moyen + Medio + + + Elevé + Alto + + + Très élevé + Molto alto + + + Alerte sur niveau faible + Allarme di basso livello + + + Alerte sur niveau élevé + Allarme di alto livello + + + Capacité du réservoir + Capacità del serbatoio + + + litres + litri + + + Logique des entrées inversée + Logica di ingresso inversa + + + La modification du <b>type de capteur</b> va nécessiter la remise en <i>configuration usine</i> de tous les paramètres du réservoir.<br /><br />Si vous ne souhaitez pas que cette reconfiguration soit effectuée, cliquez sur ANNULER. <br /><br />Sinon, cliquez sur CONFIRMER pour valider le changement. + La modifica del <b>tipo di sensore</b> richiederà il ripristino di tutte le impostazioni del serbatoio alla <i>configurazione di fabbrica</i>.<br /><br /> Se non si desidera effettuare questa riconfigurazione, fare clic su ANNULLA. <br /><br />In caso contrario, fare clic su CONFERMA per confermare la modifica. + + + Ce réservoir est utilisé par l'évènement ci-dessous.<br />Vous devez modifier ou supprimer cet évènement pour qu'il ne dépende plus de ce réservoir avant de pouvoir le supprimer. + Questo serbatoio è utilizzato dall'evento sottostante.<br />Prima di poterlo eliminare, è necessario modificare o eliminare questo evento in modo che non dipenda più da questo serbatoio. + + + Ce réservoir est utilisé par les %1 évènements ci-dessous.<br />Vous devez modifier ou supprimer ces évènements pour qu'ils ne dépendent plus de ce réservoir avant de pouvoir le supprimer. + Questo serbatoio è utilizzato dagli eventi %1 che seguono.<br />Prima di poterlo eliminare, è necessario modificare o eliminare questi eventi in modo che non dipendano più da questo serbatoio. + + + Ce réservoir est utilisé par le capteur calculé ci-dessous.<br />Vous devez modifier ou supprimer ce capteur calculé pour qu'il ne dépende plus de ce réservoir avant de pouvoir le supprimer. + Questo serbatoio è utilizzato dal sensore calcolato sottostante.<br />Prima di poterlo cancellare, è necessario modificare o cancellare questo sensore calcolato in modo che non dipenda più da questo serbatoio. + + + Ce réservoir est utilisé par les %1 capteurs calculés ci-dessous.<br />Vous devez modifier ou supprimer ces capteurs calculés pour qu'ils ne dépendent plus de ce réservoir avant de pouvoir le supprimer. + Questo serbatoio è utilizzato dai sensori %1 calcolati di seguito.<br />Prima di poterlo cancellare, è necessario modificare o cancellare questi sensori calcolati in modo che non dipendano più da questo serbatoio. + + + Résistif 0 - 700Ω + Resistivo 0 - 700Ω + + + + config_reservoirs + + Configuration des réservoirs + Configurazione del serbatoio + + + Aucun réservoir n'est encore configuré... + Nessun serbatoio è stato ancora configurato... + + + + + + + + + + config_ship2net + + Ship2net + Nave2net + + + Période des sauvegardes + Periodo di backup + + + Mode de validation des mises à jour + Aggiornamento della modalità di convalida + + + Enregistrer + Registro + + + Jamais + Mai + + + 30 minutes + 30 minuti + + + 1 heure + 1 ora + + + 2 heures + 2 ore + + + 4 heures + 4 ore + + + 12 heures + 12 ore + + + 24 heures + 24 ore + + + Aucune mise à jour + Nessun aggiornamento + + + Validation manuelle des mises à jour reçues + Convalida manuale degli aggiornamenti ricevuti + + + Validation automatique des mises à jour reçues + Convalida automatica degli aggiornamenti ricevuti + + + Période de connexion à Ship2net + Periodo di connessione Ship2net + + + 10 minutes + 10 minuti + + + Accès distant WebGL #1 + Accesso remoto WebGL n. 1 + + + Accès distant WebGL #2 + Accesso remoto WebGL n. 2 + + + Accès distant WebGL #3 + Accesso remoto WebGL n. 3 + + + 2 minutes + 10 minuti + + + Dévalidé + Svalidato + + + Valide [port %1] + Valido [porta %1] + + + + config_specifique_client_suncy + + Configuration spécifique à Suncy Concept + Configurazione specifica per Suncy Concept + + + Circuit d'activation moteur + Circuito di attivazione del motore + + + Nouveau code + Nuovo codice + + + Code d'accès au bateau + Codice di accesso alla barca + + + Répéter le code d'accès + Ripetere il codice di accesso + + + Enregistrer + Registro + + + Aucune + No + + + [module %1 - circuit %2] %3 + [modulo %1 - circuito %2] %3 + + + Les deux valeurs saisies doivent être identiques ! + +De plus, le code doit contenir : +- %1 chiffres au minimum +- %2 chiffres au maximum. + I due valori inseriti devono essere identici! + +Inoltre, il codice deve contenere : +- %1 cifre minimo +- %2 cifre massimo. + + + Le nouveau code doit contenir : +- %1 chiffres au minimum +- %2 chiffres au maximum. + +Le code saisi ne répond pas à ces critères et sa mise à jour n'est donc pas effectuée. + +Merci de saisir un code au format valide si vous souhaitez le modifier. + Il nuovo codice deve contenere : +- %1 cifre minimo +- %2 cifre massimo. + +Il codice inserito non soddisfa questi criteri e non verrà aggiornato. + +Inserire un codice valido se si desidera modificarlo. + + + + config_valeurs_niveaux + + Aucun point de conversion n'est configuré pour le moment... + Non sono ancora stati configurati punti di conversione... + + + Courbe usine + Curva di fabbrica + + + Enregistrer + Registro + + + Aucune donnée n'est disponible... + Nessun dato disponibile... + + + 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. + Sono state apportate modifiche che non sono state salvate<br />Fare clic su Annulla per tornare indietro e salvarle.<br />Fare clic su OK per uscire senza salvare. + + + Aucun point n'est actuellement configuré pour cette batterie... + Al momento non ci sono punti configurati per questa batteria... + + + Courbe de conversion de [%1] + Curva di conversione per [%1] + + + Aucun réservoir n'est actuellement configuré... + Al momento non è configurato alcun serbatoio... + + + Aucun point n'est actuellement configuré pour cet élément... + Non ci sono punti attualmente configurati per questo elemento... + + + Courbe de conversion de type INCONNU + Tipo curva di conversione UNKNOWN + + + La valeur lue sur les electrodes plongées de ce réservoir est incohérente.<br />Vérifier l'ordre de cablage des électrodes sur les entrées auxiliaires à l'arrière de ShipBase. + Il valore letto sugli elettrodi immersi in questo serbatoio è incoerente.<br />Verificare l'ordine di cablaggio degli elettrodi sugli ingressi ausiliari sul retro di ShipBase. + + + Le nombre maximal de points d'étalonnage a été atteint (%1 points)<br />Vous ne pouvez pas en ajouter sans en avoir prélablement supprimé. + È stato raggiunto il numero massimo di punti di calibrazione (%1 punti)<br />Non è possibile aggiungerne senza prima eliminarne alcuni. + + + + config_version + + Version + Versione + + + %1 : %2 + %1 : %2 + + + 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 : + La versione <b>%1</b> è disponibile.<br /><br />Verrà installata automaticamente al successivo avvio di ShipHeart.<br />A meno che non si scelga una delle opzioni seguenti: + + + La version <b>%1</b> est disponible.<br /><br />Souhaitez-vous : + La versione <b>%1</b> è disponibile.<br /><br />Si desidera : + + + L'installer +maintenant + Installare +ora + + + L'installer au prochain démarrage de ShipHeart + Installatelo al prossimo avvio di ShipHeart + + + Ne jamais l'installer + Non installarlo mai + + + 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 'shipheart.tech' ou de nous contacter à l'adresse 'contact@shipheart.tech'. + Questo prodotto è progettato e realizzato dalla società Koriolan, che detiene tutte le licenze e i diritti di sfruttamento delle immagini, del software e dei brevetti utilizzati sia per la progettazione che per il funzionamento. ShipHeart™, Ship2net™ e Koriolan™ sono marchi registrati di Koriolan. Per qualsiasi domanda su questo prodotto, visitate il sito "shipheart.tech" o contattateci all'indirizzo "contact@shipheart.tech". + + + Version du package logiciel + Versione del pacchetto software + + + Version de l'application + Versione dell'applicazione + + + Version de l'interface graphique + Versione dell'interfaccia grafica + + + Version du firmware du modem + Versione firmware del modem + + + Numéro d'IMEI + Numero IMEI + + + Numéro d'ICCID + Numero ICCID + + + Numéro d'IMSI + Numero IMSI + + + Supprimer + Cancellare + + + Si vous confirmez, cette mise à jour sera définitivement supprimée.<br />Cliquez sur Annuler pour revenir en arrière et la conserver. + Se confermi, questo aggiornamento verrà eliminato definitivamente.<br />Fai clic su Annulla per tornare indietro e mantenerlo. + + + Installer + Installare + + + 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 la conserver pour une installation ultérieure. + Se confermi, questo aggiornamento potrebbe richiedere <u>alcuni minuti</u> durante i quali <b>il tuo sistema ShipHeart non sarà accessibile</b>.<br /><br />Non è necessario confermare installazione solo se vi trovate in una situazione sicura (in porto, all'ancora, ecc.) e la perdita di controllo dei vostri sistemi di bordo durante questo periodo di tempo è senza alcun pericolo!<br /><br />Clicca su Annulla per tornare indietro e salvarlo per un'installazione successiva. + + + + ephemeride + + Ephéméride + Effemeridi + + + Heure d'hiver + Inverno + + + Heure d'été + Ora legale + + + Aube nautique + Alba nautica + + + Lever du soleil + Alba + + + Zénith + Zenith + + + Coucher du soleil + Tramonto + + + Crépuscule nautique + Crepuscolo nautico + + + Lune + Luna + + + Latitude + Latitudine + + + Longitude + Longitudine + + + + etalonnage_capteur + + Etalonnage du capteur [%1] + Calibrazione del sensore [%1] + + + Valeur brute actuelle + Valore lordo attuale + + + Valeur corrigée actuelle (%1) + Valore attuale corretto (%1) + + + Correction + Correzione + + + Enregistrer + Registro + + + + etalonnage_carte + + Etalonnage du module [%1 - #%2] + Calibrazione del modulo [%1 - #%2] + + + Point 1 + Punto 1 + + + Point 2 + Punto 2 + + + Courant de décharge + Corrente di scarica + + + Courant différentiel + Corrente differenziale + + + Recalculer ce point + Ricalcolare questo punto + + + Mémoriser ce point + Ricordate questo punto + + + Off + OFF + + + On + ON + + + On (%1 %%) + Su (%1 %%) + + + Enregistrer + Registro + + + Aide + Aiuto + + + 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 /> + Non è possibile eseguire la calibrazione con due punti identici.<br /><br /> + Cercare di modificare almeno uno dei due punti di riferimento utilizzando i controlli del circuito sotto riportati.<br /> + + + 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. + Il principio della calibrazione consiste nel confrontare, in <u>2 punti diversi</u>, il valore della corrente differenziale misurata da ShipBS da un lato e la corrente di scarica misurata dal sistema ShipHeart dall'altro. la corrente di scarica misurata dal sistema ShipHeart.<br /> Ad esempio, sottoponendo lo ShipBS durante la calibrazione a un consumo energetico basso o nullo (primo punto) quindi azionando uno o più dispositivi per ottenere un consumo di diversi ampere, se possibile (secondo punto).<br /> <br /><u><b>Molto importante</b>: durante la fase di calibrazione non deve essere applicata alcuna corrente di <b>carico</b> a ShipBS!</u> È quindi essenziale scollegare dal sistema tutti i caricabatterie, i regolatori solari, ecc. durante la calibrazione. In caso contrario, i valori di calibrazione non saranno corretti...<br /><br /> Note :<br /> - tutti i consumi devono passare attraverso il sistema ShipHeart! Pertanto, è necessario assicurarsi che nessun carico sia collegato direttamente al alla batteria.<br /> - i valori di corrente non sono importanti.<br /> - la corrente al punto 2 può essere più bassa o più alta di quella al punto 1 (ma il più lontano possibile).<br /> - È consigliabile scegliere carichi il cui consumo sia relativamente stabile o, per lo meno, cambi poco nell'arco di pochi secondi. + + + + fonctions + + Modèle inconnu + Modello sconosciuto + + + Circuit + Circuito + + + Capteur + Sensore + + + Réservoir + Serbatoio + + + Batterie + Batteria + + + Type inconnu + Tipo sconosciuto + + + Consigne + Istruzioni + + + Tension + Tensione + + + Courant + Attuale + + + Fréquence + Frequenza + + + Puissance + Potenza + + + Energie + Energia + + + Température + Temperatura + + + Courant différentiel + Corrente differenziale + + + Courant de charge + Corrente di carico + + + Courant de décharge + Corrente di scarica + + + SOH (state Of Health) + SOH (Stato di salute) + + + SOC (State Of Charge) + SOC (Stato di carica) + + + Autonomie + Autonomia + + + + fonctions_date_heure + + Dimanche + Domenica + + + Lundi + Lunedì + + + Mardi + Martedì + + + Mercredi + Mercoledì + + + Jeudi + Giovedì + + + Vendredi + Venerdì + + + Samedi + Sabato + + + janvier + Gennaio + + + février + Febbraio + + + mars + Marzo + + + avril + Aprile + + + mai + Maggio + + + juin + Giugno + + + juillet + Luglio + + + août + Agosto + + + septembre + Settembre + + + octobre + Ottobre + + + novembre + Novembre + + + décembre + Dicembre + + + 1 heure + 1 ora + + + 24 heures + 24 ore + + + 7 jours + 7 giorni + + + 30 jours + 30 giorni + + + Fin de nuit + Fine della serata + + + Aube nautique + Alba nautica + + + Aube + Aube + + + Lever du soleil + Alba + + + Zénith + Zenith + + + Coucher du soleil + Tramonto + + + Crépuscule + Crepuscolo + + + Crépuscule nautique + Crepuscolo nautico + + + Début de nuit + Notte presto + + + %1h + %1h + + + Tous les jours + Ogni giorno + + + + fonctions_historique + + Commande 'OFF' du circuit %1 + comando "OFF" per il circuito %1 + + + Commande 'ON' du circuit %1 + comando "ON" per il circuito %1 + + + Commande à %1 % du circuit %2 + Controllo %1% del circuito %2 + + + Le circuit %1 est revenu à son état de fonctionnement normal + Il circuito %1 è tornato al suo stato di funzionamento normale + + + L'alimentation du circuit %1 a été coupée car sa limite de courant (%2 A) a été dépassée + L'alimentazione del circuito %1 è stata interrotta perché il suo limite di corrente (%2 A) è stato superato + + + L'alimentation du circuit %1 a été coupée car les circuits de protection interne ont détecté une anomalie + L'alimentazione del circuito %1 è stata interrotta perché i circuiti di protezione interni hanno rilevato un'anomalia + + + L'alimentation du circuit %1 a été coupée car le seuil de disjonction a été dépassé + L'alimentazione del circuito %1 è stata interrotta a causa del superamento della soglia di intervento + + + Le circuit %1 est en court-circuit avec le + batterie + Il circuito %1 è in cortocircuito con il + della batteria + + + L'alimentation du circuit %1 a été coupée car la consommation totale du module a été dépassé + L'alimentazione del circuito %1 è stata interrotta perché è stato superato il consumo totale del modulo + + + Le circuit %1 a été créé + Il circuito %1 è stato creato + + + La configuration du circuit %1 a été modifiée + La configurazione del circuito %1 è stata modificata + + + Le circuit %1 a été supprimé + Il circuito %1 è stato cancellato + + + La configuration du circuit %1 est invalide car le module sur lequel le circuit est configuré n'est pas présent + La configurazione del circuito %1 non è valida perché il modulo su cui è configurato il circuito non è presente + + + Le circuit %1 a fonctionné trop longtemps (> %2 secondes). Il a donc été désactivé automatiquement. + Il circuito %1 è rimasto in funzione per troppo tempo (> %2 secondi). Pertanto, è stato disattivato automaticamente. + + + Evénement de type CIRCUITS avec code de sous-type inconnu [%1] + Evento CIRCUITI con codice sottotipo sconosciuto [%1] + + + Le capteur %1 est repassé à l'état normal + Il sensore %1 è tornato allo stato normale + + + Le capteur %1 est passé à l'état ALERTE + Il sensore %1 è passato allo stato di ALERT + + + Le capteur %1 est passé à l'état ALARME + Il sensore %1 è passato allo stato di ALLARME + + + Evénement de type CAPTEURS avec code de sous-type inconnu [%1] + Evento CAPTORS con codice di sottotipo sconosciuto [%1] + + + Le niveau de charge de la batterie %1 est repassé au niveau normal + Il livello di carica della batteria %1 è tornato al livello normale + + + Le niveau de charge de la batterie %1 est passé en dessous du niveau d'alerte + Il livello di carica della batteria %1 è sceso al di sotto del livello di allarme + + + Le niveau de charge de la batterie %1 est passé au-dessus du niveau d'alarme (il est maintenant au niveau d'alerte uniquement) + Il livello di carica della batteria %1 è salito oltre il livello di allarme (ora è solo al livello di allerta) + + + Le niveau de charge de la batterie %1 est passé en-dessous du niveau d'alarme + Il livello di carica della batteria %1 è sceso sotto il livello di allarme + + + Evénement de type BATTERIES avec code de sous-type inconnu [%1] + Evento BATTERIE con codice sottotipo sconosciuto [%1] + + + Le niveau du réservoir %1 est repassé au niveau normal + Il livello del serbatoio %1 è tornato al livello normale + + + Le niveau du réservoir %1 est passé en dessous du niveau d'alerte + Il livello del serbatoio %1 è sceso sotto il livello di allarme + + + Le niveau du réservoir %1 est passé au-dessus du niveau d'alarme (il est maintenant au niveau d'alerte uniquement) + Il livello del serbatoio %1 è salito oltre il livello di allarme (ora è solo al livello di allerta) + + + Le niveau du réservoir %1 est passé en-dessous du niveau d'alarme + Il livello del serbatoio %1 è sceso sotto il livello di allarme + + + Evénement de type RESERVOIRS avec code de sous-type inconnu [%1] + Evento RESERVOIRS con codice di sottotipo sconosciuto [%1] + + + La consigne des ports USB est passée à %1 + Il valore nominale della porta USB è stato modificato in %1 + + + L'état des ports USB est redevenu normal + Lo stato delle porte USB è tornato normale + + + Défaut détecté sur les ports USB + Rilevato errore della porta USB + + + Evénement de type USB avec code de sous-type inconnu [%1] + Evento USB con codice di sottotipo sconosciuto [%1] + + + Evénement de type INCONNU (avec code de sous-type [%1] + Evento UNKNOWN (con codice di sottotipo [%1]) + + + + home + + Démarrage + Inizio + + + Code inconnu + Codice sconosciuto + + + Aucun circuit n'est configuré pour ce groupe...<br /><br />Si ce groupe n'a pas d'utilité, vous pouvez le supprimer dans le menu [Circuits] des Paramètres Avancés. + Per questo gruppo non è configurato alcun circuito...<br /><br />Se questo gruppo non è utilizzato, è possibile eliminarlo nel menu [Circuiti] di Impostazioni avanzate. + + + Aucun capteur n'est configuré pour ce groupe...<br /><br />Si ce groupe n'a pas d'utilité, vous pouvez le supprimer dans le menu [Capteurs] des Paramètres Avancés. + Non ci sono sensori configurati per questo gruppo...<br /><br />Se questo gruppo non è necessario, è possibile eliminarlo nel menu [Sensori] di Impostazioni avanzate. + + + Aucun réservoir n'est configuré pour ce groupe...<br /><br />Si ce groupe n'a pas d'utilité, vous pouvez le supprimer dans le menu [Réservoirs] des Paramètres Avancés. + Nessun serbatoio è configurato per questo gruppo...<br /><br />Se questo gruppo non è utilizzato, è possibile eliminarlo dal menu [Serbatoi] delle Impostazioni avanzate. + + + Aucun parc de batterie n'est configuré pour ce groupe...<br /><br />Si ce groupe n'a pas d'utilité, vous pouvez le supprimer dans le menu [Batteries] des Paramètres Avancés. + Per questo gruppo non è configurato alcun parco batterie...<br /><br />Se questo gruppo non è utilizzato, è possibile eliminarlo nel menu [Batterie] di Impostazioni avanzate. + + + Cette page est actuellement en travaux. <br />Elle sera rendue disponible très rapidement à travers une mise à jour.<br /><br />Merci de votre patience...<br /><br />L'équipe ShipHeart + Questa pagina è attualmente in costruzione. <br /><br />Grazie per la vostra pazienza...<br /><br />Il team ShipHeart + + + Déconnecté + Disconnesso + + + Nombre de satellites visibles + Numero di satelliti visibili + + + Connecté + In linea + + + OFF + OFF + + + ON + ON + + + Niveau + Livello + + + Actif + Attività + + + Inactif + Inattivo + + + <b>%1</b> + <1%1</b> + + + Firmware de <b>ShipBase</b> + Firmware per <b>ShipBase</b> + + + Firmware du <b>ShipPower812</b> à l'adresse <b>%1</b> + Firmware per la <b>ShipPower812</b> al <b>%1</b> + + + Firmware du <b>ShipBS</b> à l'adresse <b>%1</b> + Firmware per <b>ShipBS</b> a <b>%1</b> + + + Firmware du <b>ShipPower4AC</b> à l'adresse <b>%1</b> + Firmware per <b>ShipPower4AC</b> a <b>%1</b> + + + Firmware du <b>ShipPower8DC</b> à l'adresse <b>%1</b> + Firmware per <b>ShipPower8DC</b> a <b>%1</b> + + + Firmware du module à l'adresse <b>%1</b> + Firmware del modulo a <b>%1</b> + + + Merci de patienter et de ne rien débrancher<br />avant la fin de la mise à jour. + Si prega di avere pazienza e di non scollegare nulla fino al completamento dell'aggiornamento. + + + Chargement des mises à jour effectué avec succès !<br /><br />L'activation des nouvelles version est en cours sur tous les modules concernés.<br /><br />Merci de patienter encore quelques secondes... + Gli aggiornamenti sono stati caricati con successo! <br /><br />Le nuove versioni sono state attivate su tutti i moduli interessati.<br /><br />Per favore aspettate ancora qualche secondo... + + + ShipHeart va redémarrer pour effectuer une mise à jour.<br /><br />Cette opération va prendre quelques minutes au maximum.<br />Merci de patienter et de ne rien débrancher jusqu'au redémarrage final... + ShipHeart si riavvierà per eseguire l'aggiornamento.<br /><br />Questa operazione richiederà al massimo qualche minuto.<br />Si prega di essere pazienti e di non scollegare nulla fino al riavvio finale... + + + Votre système ShipHeart est dorénavant équipé de la version<br /><br /><b>%1</b><br /><br />(la version précédente était la %2) + Il vostro sistema ShipHeart è ora dotato della versione<br /><br /><b>%1</b><br /><br /> (la versione precedente era %2) + + + Le nombre de modules détectés sur le réseau ShipHeart est insuffisant par rapport à la configuration du bateau.<br /><br />Vérifiez les connexions entre le module <b>%1</b> à la <b>position @%2</b> %3 et le module <b>%4</b> suivant%5<br /><br />Vous pouvez visualiser l'état complet du réseau ShipHeart et les anomalies détectées dans le menu 'Réseau > ShipHeart' dans les Paramètres Avancés + Il numero di moduli rilevati sulla rete ShipHeart è insufficiente per la configurazione della nave.<br /><br />Controllare le connessioni tra il modulo <b>%1</b> nella <b>posizione @%2</b> %3 e il successivo <b>%4</b> modulo%5<br /><br />.br />È possibile visualizzare lo stato completo della rete ShipHeart e le eventuali anomalie rilevate nel menu "Rete > ShipHeart" delle Impostazioni avanzate + + + Le modules détecté en <b>position @%1</b> est un <b>%2</b>. Cela ne correspond pas à la configuration actuelle du bateau (<b>%3</b>).<br /><br />Cela peut provenir de l'ajout, de la suppression ou d'un déplacement de module.<br /><br />Vous pouvez visualiser toutes les anomalies détectées et les corriger dans le menu 'Réseau > ShipHeart' dans les Paramètres Avancés + Il modulo rilevato nella <b>posizione @%1</b> è un <b>%2</b>. Non corrisponde alla configurazione attuale della nave (<b>%3</b>).<br /><br /> Ciò può essere dovuto all'aggiunta, alla cancellazione o allo spostamento di un modulo.<br /><br />È possibile visualizzare tutte le anomalie rilevate e correggerle nel menu "Rete > ShipHeart" delle Impostazioni avanzate + + + + home_accueil + + Bienvenue à bord de + Benvenuti a bordo + + + + home_suncy + + L'accès au bateau est protégé. +Merci d'entrer votre code de déverrouillage pour y accéder... + L'accesso alla barca è protetto. +Inserisci il tuo codice di sblocco per accedere... + + + + journal_de_bord + + Tous + Tutti + + + Batteries + Batterie + + + Capteurs + Sensori + + + Circuits + Circuiti + + + Réservoirs + Serbatoi + + + Système + Sistema + + + Ports USB + Porte USB + + + Journal de bord + Diario di bordo + + + Aucun type n'est configuré... + Non è configurato alcun tipo... + + + %1<br /><br /><br />%2 + %1<br /><br /><br />%2 + + + Aucune entrée d'historique n'est disponible pour cette sélection... + Non sono disponibili voci di cronologia per questa selezione... + + + Toutes + Tutti + + + + main + + Type d'installation : +0 : ShipBase standard, +1 : écran déporté + Tipo di installazione : +0: base navale standard, +1: schermo remoto + + + valeur + valore + + + Adresse IPv4 de ShipBase dans le cas d'une installation déportée + Indirizzo IPv4 di ShipBase per installazione remota + + + xxx:xxx:xxx:xxx + xxx:xxx:xxx:xxx + + + Taille de l'écran en pouces : +7, +10 (ShipBase standard), +22 + Dimensioni dello schermo in pollici : +7, +10 (standard ShipBase), +22 + + + Original + Originale + + + Sombre + Scuro + + + Métallique + Metallico + + + Triangles + Triangoli + + + Sable + Sabbia + + + Thème 5 + Tema 5 + + + Thème 6 + Tema 6 + + + Thème 7 + Tema 7 + + + Thème 8 + Tema 8 + + + + page_personnalisee + + <i>--- Circuit non affecté ---</i> + <i>--- Circuito non interessato ---</i> + + + [renfort] + [rinforzo] + + + <i>--- Aucune batterie affectée ---</i> + <i>--- Nessuna batteria interessata ---</i> + + + + parametres + + Paramètres + Parametri + + + Langue + Lingua + + + Températures + Temperature + + + Volumes + Volumi + + + Affichage + Display + + + Date et heure + Data e ora + + + Protection + Protezione + + + Son + Suono + + + Luminosité + Luminosità + + + Economiseur d'écran : désactivé + Screen saver: disabilitato + + + Economiseur d'écran : normal + Screen saver: normale + + + Flash LEDs : désactivé + Flash LED: disattivato + + + Flash LEDs : normal + LED lampeggiante: normale + + + Nettoyage de l'écran + Pulizia dello schermo + + + Heure d'été + Ora legale + + + Heure d'hiver + Inverno + + + Verrouiller le bateau + Bloccare la barca + + + + parametres_avances + + Paramètres avancés + Impostazioni avanzate + + + Circuits + Circuiti + + + Réservoirs + Serbatoi + + + Batteries + Batterie + + + Capteurs + Sensori + + + Vos paramètres + Le vostre impostazioni + + + Votre installation + L'installazione + + + Système + Sistema + + + Affichage + Display + + + Audio + Audio + + + Ship2net + Nave2net + + + Accès au paramètres + Accesso ai parametri + + + Configuration ShipRS + Configurazione di ShipRS + + + Version + Versione + + + Accès réservé Koriolan + Accesso riservato Koriolan + + + Spécifique Suncy + Specifico di Suncy + + + Réseaux + Reti + + + Cette page est actuellement en travaux. <br />Elle sera rendue disponible très rapidement à travers une mise à jour.<br /><br />Merci de votre patience...<br /><br />L'équipe ShipHeart + Questa pagina è attualmente in costruzione. <br /><br />Grazie per la vostra pazienza...<br /><br />Il team ShipHeart + + + Evènements + Eventi + + + ShipHeart + ShipHeart + + + Ethernet & Wifi + Ethernet e Wifi + + + One Wire + Un filo + + + NMEA 2000 + NMEA 2000 + + + J1939 + J1939 + + + DMX + DMX + + + Journal de bord + Diario di bordo + + + Installation + Installazione + + + Menu accueil + Menù di casa + + + + protection + + Accès protégé + Accesso sicuro + + + L'accès aux paramètres avancés est protégé. +Merci d'entrer le code de déverrouillage pour y accéder... + L'accesso alle impostazioni avanzate è protetto. +Inserire il codice di sblocco per accedere... + + + Mode administrateur validé<br />Entrer votre code dédié + Modalità amministratore abilitata<br />Inserire il codice dedicato + + + + reservoir + + [ %1 % ] + [ %1 % ] + + + Aucune donnée n'est disponible pour cette période + Non sono disponibili dati per questo periodo + + + Le module assurant la supervision de ce réservoir n'est pas accessible !<br /><br />Si des ajouts/suppression/déplacements de modules ont eu lieu récemment, mettez à jour la configuration correspondant dans le menu MODULES de PARAMETRES AVANCES.<br /><br />Dans le cas où aucune modification n'a été effectuée récemment, vérifier les connexions de tous les modules. + Il modulo di supervisione di questo serbatoio non è accessibile! <br /><br />Se i moduli sono stati aggiunti/eliminati/sposti di recente, aggiornare la configurazione corrispondente nel menu MODULI di PARAMETRI AVANZATI.<br /><br />Se non sono state apportate modifiche di recente, controllare i collegamenti di tutti i moduli. + + + Niveau + Livello + + + La valeur lue sur les electrodes plongées de ce réservoir est incohérente.<br />Vérifier l'ordre de cablage des électrodes sur les entrées auxiliaires à l'arrière de ShipBase. + Controllare l'ordine di cablaggio degli elettrodi sugli ingressi ausiliari sul retro di ShipBase. + + + + shipheart_test_config + + Vitesse de test de l'écran + Velocità del test dello schermo + + + Nombre de colonnes de test du touchpad + Numero di colonne di test del touchpad + + + Nombre de lignes de test du touchpad + Numero di linee di test del touchpad + + + + shipheart_test_home + + Tests matériel + Test dell'hardware + + + Configuration des tests + Configurazione del test + + + Test du backlight + Test della retroilluminazione + + + Test de l'écran + Test dello schermo + + + Test du touchpad + Test del touchpad + + + Liste des fonts disponibles + Elenco delle fonti disponibili + + + + shipheart_test_liste_fonts + + Liste des fonts disponibles + Elenco delle fonti disponibili + + + + test_batterie + + Batteries de servitude + Batterie di servizio + + + Autonomie optimale + Autonomia ottimale + + + Autonomie actuelle + Autonomia attuale + + + Autonomie<br />maximale + Portata massima<br /> + + + dans + in + + + environ + circa + + + + test_tri_liste + + TEST DE TRI DE LISTE + TEST DE TRI DE LISTE + + + diff --git a/shipheart_lv_LV.qm b/shipheart_lv_LV.qm new file mode 100755 index 0000000..3809b30 Binary files /dev/null and b/shipheart_lv_LV.qm differ diff --git a/shipheart_lv_LV.ts b/shipheart_lv_LV.ts new file mode 100755 index 0000000..20c11f0 --- /dev/null +++ b/shipheart_lv_LV.ts @@ -0,0 +1,4421 @@ + + + + + Shipheart_boite_dialogue + + OK + OK + + + Annuler + Atcelt + + + Plus tard + Vēlāk + + + + Shipheart_boite_dialogue_action_circuit + + Action à appliquer au circuit lorsque l'évènement se déclenche : + Darbība, kas attiecas uz ķēdi, kad notikums tiek aktivizēts: + + + Aucune + Nav + + + Le circuit <b>bascule</b> + Ķēdes <b>slēdži</b> + + + [passe à <b>ON</b> s'il est <b>OFF</b><br /> ou à <b>OFF</b> s'il est <b>ON</b>] + [ <b>Ieslēgts</b> , ja <b>IZSLĒGTS</b><br /> vai uz <b>OFF</b> , ja tas ir <b>IESLĒGTS</b> ] + + + OFF + OFF + + + ON + ON + + + Annuler + Atcelt + + + + Shipheart_boite_dialogue_affichage_duree + + Ok + OK + + + + Shipheart_boite_dialogue_condition_horaire + + OK + OK + + + Annuler + Atcelt + + + Supprimer + DZĒST + + + Aube nautique + Jūras rītausma + + + Lever du soleil + Saullēkts + + + Zénith + Zenīts + + + Coucher du soleil + Saulriets + + + Crépuscule nautique + Jūras krēsla + + + + Shipheart_boite_dialogue_entrees_aux + + Entrées Auxiliaires + Papildu ieejas + + + Annuler + Atcelt + + + Affectation de l'entrée n° %1 du %2 + Ieraksta numura %1 no %2 piešķiršana + + + + Shipheart_boite_dialogue_entrees_level_sensor + + Entrées Level Sensor + Līmeņa sensora ieejas + + + Affectation de l'entrée du réservoir + Tvertnes ieplūdes uzdevums + + + Annuler + Atcelt + + + + Shipheart_boite_dialogue_liste_alarmes + + Ok + OK + + + + Shipheart_boite_dialogue_minuteur + + Heures + Stundas + + + Minutes + Minūtes + + + Secondes + Sekundes + + + Annuler + Atcelt + + + Démarrer + Lai palaistu + + + + Shipheart_boite_dialogue_nettoyage_ecran + + Nettoyage de l'écran + Ekrāna tīrīšana + + + 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. + Ekrāns pašlaik ir iesaldēts, lai jūs varētu to notīrīt, neriskējot izraisīt nevēlamas darbības.<br /><br /> Lai izietu no šī režīma, turiet zemāk esošo pogu ilgāk par %1 sekundi. + + + Sortie + Izeja + + + + Shipheart_boite_dialogue_reveils + + Annuler + Atcelt + + + Enregistrer + Saglabāt + + + + Shipheart_boite_dialogue_validation_securisee + + OK + OK + + + Annuler + Atcelt + + + --- + --- + + + + Shipheart_bouton_circuit + + Off + OFF + + + On + ON + + + + batterie + + Aucune donnée n'est disponible pour cette période + Par šo periodu dati nav pieejami + + + Le module assurant la supervision de cette batterie n'est pas accessible !<br /><br />Si des ajouts/suppression/déplacements de modules ont eu lieu récemment, mettez à jour la configuration correspondant dans le menu MODULES de PARAMETRES AVANCES.<br /><br />Dans le cas où aucune modification n'a été effectuée récemment, vérifier les connexions de tous les modules. + Modulis, kas nodrošina šī akumulatora uzraudzību, nav pieejams!<br /><br /> Ja moduļi ir pievienoti/dzēsti/pārvietoti nesen, atjauniniet atbilstošo konfigurāciju PAPILDUS IESTATĪJUMU izvēlnē MODUĻI.<br /><br /> Ja pēdējā laikā nav veiktas nekādas izmaiņas, pārbaudiet visu moduļu savienojumus. + + + Aucune consommation d'énergie sur cette période... + Šajā periodā nav enerģijas patēriņa... + + + + capteur + + Max + Maks + + + Moyen + VIDĒJS + + + Min + Min + + + Delta (Max - Min) + Delta (maks.–min.) + + + Aucune donnée n'est disponible pour cette période + Par šo periodu dati nav pieejami + + + La sonde One Wire correspondant à ce capteur n'est pas accessible.<br />Vérifier son câblage entre le port One Wire à l'arrière de ShipBase et la sonde. + Šim sensoram atbilstošā One Wire zonde nav pieejama.<br /> Pārbaudiet tā vadu starp One Wire portu ShipBase aizmugurē un zondi. + + + Le module assurant la supervision de ce capteur n'est pas accessible !<br /><br />Si des ajouts/suppression/déplacements de modules ont eu lieu récemment, mettez à jour la configuration correspondant dans le menu MODULES de PARAMETRES AVANCES.<br /><br />Dans le cas où aucune modification n'a été effectuée récemment, vérifier les connexions de tous les modules. + Modulis, kas uzrauga šo sensoru, nav pieejams!<br /><br /> Ja moduļi ir pievienoti/dzēsti/pārvietoti nesen, atjauniniet atbilstošo konfigurāciju PAPILDUS IESTATĪJUMU izvēlnē MODUĻI.<br /><br /> Ja pēdējā laikā nav veiktas nekādas izmaiņas, pārbaudiet visu moduļu savienojumus. + + + La sonde One Wire du capteur est détectée en défaut.<br />Vérifier son câblage depuis l'arrière de ShipBase. + Sensora One Wire zonde ir konstatēta kā bojāta.<br /> Pārbaudiet tā kabeļus no ShipBase aizmugures. + + + Le capteur n'a pas reçu de mise à jour sur le réseau NMEA depuis<br />%1<br />Les données affichées sont donc probablement obsolètes. + Sensors nav saņēmis atjauninājumu NMEA tīklā kopš<br />%1<br />Tāpēc parādītie dati, iespējams, ir novecojuši. + + + + circuit + + Off + OFF + + + On + ON + + + On +%1% + Mēs + %1% + + + Aucune donnée n'est disponible pour cette période + Par šo periodu dati nav pieejami + + + L'alimentation du circuit a été coupée + car sa limite de courant (%1 A) + a été dépassée. + Strāvas padeve ķēdei ir pārtraukta + jo tā pašreizējā robeža (%1 A) + tika pārsniegts. + + + L'alimentation du circuit a été coupée + car les circuits de protection interne ont détecté une anomalie. + Strāvas padeve ķēdei ir pārtraukta + jo iekšējās aizsardzības shēmas ir konstatējušas anomāliju. + + + L'alimentation du circuit a été coupée + car le seuil de disjonction du circuit a été dépassé. + Strāvas padeve ķēdei ir pārtraukta + jo ir pārsniegts ķēdes izslēgšanas slieksnis. + + + Le circuit est en court-circuit avec le + batterie. + Ķēde ir īssavienojums ar akumulatoru +. + + + L'alimentation du circuit a été coupée<br />car la consommation totale du module a dépassé %1 A pendant plus de %2 secondes (limite du module) + Strāvas padeve ķēdei ir pārtraukta<br /> jo kopējais moduļa patēriņš pārsniedza %1 A vairāk nekā %2 sekundes (moduļa ierobežojums) + + + La tension du circuit est anormalement basse. + Ķēdes spriegums ir neparasti zems. + + + La phase et le neutre sont inversés sur ce circuit. + Šajā ķēdē fāze un neitrāls ir apgrieztas. + + + Etat inconnu... + Nezināms stāvoklis... + + + Le module assurant le pilotage de ce circuit n'est pas accessible !<br /><br />Si des ajouts/suppression/déplacements de modules ont eu lieu récemment, mettez à jour la configuration correspondant dans le menu [Réseau ShipHeart] de [Paramètres Avancés].<br /><br />Dans le cas où aucune modification n'a été effectuée récemment, vérifier les connexions de tous les modules. + Modulis, kas kontrolē šo ķēdi, nav pieejams!<br /><br /> Ja moduļi ir pievienoti/noņemti/pārvietoti nesen, atjauniniet atbilstošo konfigurāciju [Advanced Settings] izvēlnē [ShipHeart Network].<br /><br /> Ja pēdējā laikā nav veiktas nekādas izmaiņas, pārbaudiet visu moduļu savienojumus. + + + Ce circuit est configuré comme <i>Non Affecté</i> et n'est donc pas accessible !<br /><br />Pour accéder à nouveau à ce circuit, merci de l'affecter à un circuit disponible dans le menu [Circuits] de [Paramètres Avancés]. + Šī ķēde ir konfigurēta kā <i>Nepiešķirta</i> un tāpēc nav pieejama!<br /><br /> Lai vēlreiz piekļūtu šai shēmai, lūdzu, piešķiriet to ķēdei, kas pieejama [Papildu iestatījumi] izvēlnē [Circuits]. + + + Aucune consommation d'énergie sur cette période... + Šajā periodā nav enerģijas patēriņa... + + + Le module pilotant ce circuit n'est pas alimentée correctement. + Vérifier l'alimentation correspondante. + Modulis, kas kontrolē šo ķēdi, netiek pareizi barots. + Pārbaudiet atbilstošo barošanas avotu. + + + Le module pilotant ce circuit est en mode MANUEL. + Repositionnez le module en mode AUTO pour commander à nouveau ce circuit normalement. + Modulis, kas kontrolē šo ķēdi, ir MANUĀLĀ režīmā. + Atgrieziet moduli AUTO režīmā, lai atkal normāli vadītu šo ķēdi. + + + Le port USB du bas est en défaut. + Apakšējais USB ports ir bojāts. + + + Le port USB du milieu est en défaut. + Vidējais USB ports ir bojāts. + + + Les 2 ports USB du milieu et du bas sont en défaut. + Divi vidējie un apakšējie USB porti ir bojāti. + + + Le port USB du haut est en défaut. + Augšējais USB ports ir bojāts. + + + Les 2 ports USB du haut et du bas sont en défaut. + Divi USB porti augšpusē un apakšā ir bojāti. + + + Les 2 ports USB du haut et du milieu sont en défaut. + Divi augšējie un vidējie USB porti ir bojāti. + + + Les 3 ports USB du haut, du milieu et du bas sont en défaut. + Augšējais, vidējais un apakšējais 3 USB porti ir bojāti. + + + Le port USB est en défaut. + USB ports ir bojāts. + + + La masse est absente du connecteur d'alimentation du module + Moduļa strāvas savienotājam trūkst zemes + + + Evènements actuellement actifs qui sont susceptibles de commander ce circuit : + Pašlaik aktīvie notikumi, kas varētu kontrolēt šo ķēdi: + + + Non défini + Nav definēts + + + DANGER : Le neutre n'est pas référencé à la terre sur ce circuit ("absence de terre"). + APDRAUDĒJUMS: neitrāls šajā ķēdē nav saistīts ar zemējumu ("bez zemējuma"). + + + + config_acces_parametres + + Configuration de l'accès aux paramètres avancés + Piekļuves konfigurēšana papildu iestatījumiem + + + Durée de maintien de l'accès + Piekļuves uzturēšanas ilgums + + + Nouveau code + Jauns kods + + + Code d'accès + Pieejas kods + + + Répéter le code d'accès + Atkārtojiet piekļuves kodu + + + Enregistrer + Saglabāt + + + Aucune (saisie du code à chaque accès) + Nav (koda ievade katru reizi, kad piekļūstat) + + + 1 minute + 1 minūte + + + 5 minutes + 5 minūtes + + + 15 minutes + 15 minūtes + + + 1 heure + 1 stunda + + + Infinie (aucune protection des paramètres avancés) + Bezgalīgs (bez papildu iestatījumu aizsardzības) + + + Les deux valeurs saisies doivent être identiques ! + +De plus, le code doit contenir : +- %1 chiffres au minimum +- %2 chiffres au maximum. + Abām ievadītajām vērtībām jābūt identiskām! + + Turklāt kodā jāiekļauj: + - Vismaz %1 cipars + - %2 cipari maksimums. + + + Le nouveau code doit contenir : +- %1 chiffres au minimum +- %2 chiffres au maximum. + +Le code saisi ne répond pas à ces critères et sa mise à jour n'est donc pas effectuée. + +Merci de saisir un code au format valide si vous souhaitez le modifier. + Jaunajā kodā jāiekļauj: + - Vismaz %1 cipars + - %2 cipari maksimums. + + Ievadītais kods neatbilst šiem kritērijiem un tāpēc netiek atjaunināts. + + Lūdzu, ievadiet kodu derīgā formātā, ja vēlaties to modificēt. + + + + config_affichage + + Configuration de l'affichage + Displeja iestatīšana + + + Temporisaton économiseur d'écran + Ekrānsaudzētāja taimauts + + + Enregistrer + Saglabāt + + + 15 secondes + 15 sekundes + + + 30 secondes + 30 sekundes + + + 1 minute + 1 minūte + + + 3 minutes + 3 minūtes + + + 10 minutes + 10 minūtes + + + Aucune limite + Nav ierobežojumu + + + Nom du bateau + Laivas nosaukums + + + Fuseau horaire + Laika zona + + + Thème d'affichage + Displeja tēma + + + UTC-12 (Yankee) + UTC-12 (Yankee) + + + UTC-11 (X-Ray) + UTC-11 (rentgena starojums) + + + UTC-10 (Whisky) + UTC-10 (viskijs) + + + UTC-9 (Victor) + UTC-9 (Victor) + + + UTC-8 (Uniform) + UTC-8 (vienotā) + + + UTC-7 (Tango) + UTC-7 (Tango) + + + UTC-6 (Sierra) + UTC-6 (Sierra) + + + UTC-5 (Romeo) + UTC-5 (Romeo) + + + UTC-4 (Quebec) + UTC-4 (Kvebeka) + + + UTC-3 (Papa) + UTC-3 (tētis) + + + UTC-2 (Oscar) + UTC-2 (Oskars) + + + UTC-1 (November) + UTC-1 (novembris) + + + UTC (Zoulou) + UTC (zulu) + + + UTC+1 (Alpha) + UTC+1 (alfa) + + + UTC+2 (Bravo) + UTC+2 (labi darīts) + + + UTC+3 (Charlie) + UTC+3 (Čārlijs) + + + UTC+4 (Delta) + UTC+4 (delta) + + + UTC+5 (Echo) + UTC+5 (atbalss) + + + UTC+6 (Foxtrot) + UTC+6 (fokstrots) + + + UTC+7 (Golf) + UTC+7 (golfs) + + + UTC+8 (Hotel) + UTC+8 (viesnīca) + + + UTC+9 (India) + UTC+9 (Indija) + + + UTC+10 (Kilo) + UTC+10 (kilos) + + + UTC+11 (Lima) + UTC+11 (Lima) + + + UTC+12 (Mike) + UTC+12 (Maiks) + + + + config_audio + + Bips de clic + Noklikšķiniet uz skaņas signāliem + + + Fonctionnement de la sortie Audio + Audio izvades darbība + + + Enregistrer + Saglabāt + + + Aucun bip + Nav pīkstiena + + + Bip par défaut + Noklusējuma pīkstiens + + + Bip 2 + Pīkstiens 2 + + + Bip 3 + Pīkstiens 3 + + + Bip 4 + Pīkstiens 4 + + + Bip 5 + Pīkstiens 5 + + + Bip 6 + Pīkstiens 6 + + + Bip 7 + Pīkstiens 7 + + + Bip 8 + Pīkstiens 8 + + + Bip 9 + Pīkstiens 9 + + + Bip 10 + Pīkstiens 10 + + + Bip 11 + Pīkstiens 11 + + + Bip 12 + Pīkstiens 12 + + + Bip 13 + Pīkstiens 13 + + + Bip 14 + Pīkstiens 14 + + + Configuration audio + Audio iestatīšana + + + Le son de ShipBase est coupé. Le son est uniquement diffusé sur la sortie AUDIO + ShipBase audio ir izslēgts. Skaņa tiek izvadīta tikai no AUDIO izejas + + + Le son est diffusé sur ShipBase et sur la sortie AUDIO + Audio tiek straumēts uz ShipBase un AUDIO izvadi + + + + config_batterie + + Nom de la batterie + Akumulatora nosaukums + + + Tension nominale + Nominālais spriegums + + + Créer la batterie + Izveidojiet akumulatoru + + + Enregistrer + Saglabāt + + + Supprimer + DZĒST + + + Confirmer + Apstiprināt + + + Etalonner + Kalibrēt + + + Non défini + Nav definēts + + + ShipBS [@ %1] + Piegāde[@%1] + + + Entrée VOLT n° %1 + VOLT ieeja Nr %1 + + + Plomb - Acide liquide + Svins - Šķidra skābe + + + Plomb - AGM / VRLA + Svins - AGM / VRLA + + + Plomb - Gel + Svins - želeja + + + Plomb - Carbone + Svins – ogleklis + + + Lithium + Litijs + + + 12V + 12V + + + 24V + 24V + + + Création d'un parc de batteries + Akumulatoru bankas izveide + + + Configuration du parc de batteries + Akumulatora bankas konfigurācija + + + Point de mesure + Mērīšanas punkts + + + Type de batterie(s) + Akumulatora veids(-i) + + + La modification du <b>type</b> de batterie(s) va nécessiter la remise en <i>configuration usine</i> de certains paramètres.<br /><br />Si vous ne souhaitez pas que cette reconfiguration soit effectuée, notamment si vous avez effectué des réglages spécifiques, cliquez sur ANNULER. <br /><br />Sinon, cliquez sur CONFIRMER pour valider le changement. + Mainot akumulatora(-u) <b>veidu</b> , noteikti parametri būs jāatjauno uz <i>rūpnīcas iestatījumiem</i> .<br /><br /> Ja nevēlaties, lai šī pārkonfigurācija tiktu veikta, it īpaši, ja esat veicis īpašus iestatījumus, noklikšķiniet uz CANCEL.<br /><br /> Pretējā gadījumā noklikšķiniet uz APSTIPRINĀT, lai apstiprinātu izmaiņas. + + + La modification de la <b>tension nominale</b> du parc de batteries va nécessiter la remise en <i>configuration usine</i> de certains paramètres.<br /><br />Si vous ne souhaitez pas que cette reconfiguration soit effectuée, notamment si vous avez effectué des réglages spécifiques, cliquez sur ANNULER. <br /><br />Sinon, cliquez sur CONFIRMER pour valider le changement. + Mainot akumulatora <b>nominālo spriegumu,</b> noteikti parametri būs jāatjauno uz <i>rūpnīcas iestatījumiem</i> .<br /><br /> Ja nevēlaties, lai šī pārkonfigurācija tiktu veikta, it īpaši, ja esat veicis īpašus iestatījumus, noklikšķiniet uz CANCEL.<br /><br /> Pretējā gadījumā noklikšķiniet uz APSTIPRINĀT, lai apstiprinātu izmaiņas. + + + Capacité + Spēja + + + Ah + Ak + + + Masquer les paramètres avancés + Slēpt papildu iestatījumus + + + Afficher les paramètres avancés + Rādīt papildu iestatījumus + + + Coefficient correcteur d'entrée de tension + Sprieguma ievades korekcijas koeficients + + + + + + + Caractéristiques du parc de batteries + Akumulatoru bankas īpašības + + + Durée correspondant à la capacité + Ilgums atbilst jaudai + + + h + h + + + Capacité 2 + Jauda 2 + + + Durée de capacité 2 + Jaudas ilgums 2 + + + Coefficient de Peukert + Peukerta koeficients + + + Résistance interne + Iekšējā pretestība + + + mΩ + + + + Soh actuel + Pašreizējais Soh + + + % + % + + + Paramètres de pleine charge + Pilnas slodzes iestatījumi + + + Tension mini pleine charge + Minimālais pilnas slodzes spriegums + + + V + V + + + Courant maxi pleine charge + Maksimālā pilnas slodzes strāva + + + A + IR + + + Temporisation pleine charge + Pilnas slodzes aizkave + + + s + s + + + Efficacité de charge + Uzlādes efektivitāte + + + Caractéristiques de charge nulle + Nulles slodzes raksturlielumi + + + Tension de détection charge nulle + Nulles slodzes noteikšanas spriegums + + + Temporisation charge nulle + Nulles slodzes aizkave + + + Historique + Vēsturisks + + + Nombre de cycles de charge + Uzlādes ciklu skaits + + + Nombre de décharges complètes + Pilnīgu izlādi skaits + + + Forcer Pleine Charge + Piespiedu pilna slodze + + + Réinitialiser SOH + Atiestatīt SOH + + + Réinitialiser Compteurs + Atiestatīt skaitītājus + + + Non définie + Nav definēts + + + Groupe de batteries + Akumulatoru grupa + + + Alimentation %1 + Barošanas avots %1 + + + Cette batterie est utilisée par l'évènement ci-dessous.<br />Vous devez modifier ou supprimer cet évènement pour qu'il ne dépende plus de cette batterie avant de pouvoir la supprimer. + Šis akumulators tiek izmantots tālāk norādītajam notikumam.<br /> Lai to varētu dzēst, jums ir jāmaina vai jāizdzēš šis notikums, lai tas vairs nebūtu atkarīgs no šī akumulatora. + + + Cette batterie est utilisée par les %1 évènements ci-dessous.<br />Vous devez modifier ou supprimer ces évènements pour qu'ils ne dépendent plus de cette batterie avant de pouvoir la supprimer. + Šo akumulatoru izmanto tālāk norādītie %1 notikumi.<br /> Lai tos varētu dzēst, jums ir jāpārveido vai jāizdzēš šie notikumi, lai tie vairs nebūtu atkarīgi no šīs fermas. + + + Cette batterie est utilisée par le capteur calculé ci-dessous.<br />Vous devez modifier ou supprimer ce capteur calculé pour qu'il ne dépende plus de cette id_batterie avant de pouvoir la supprimer. + Šo akumulatoru izmanto tālāk aprēķinātais sensors.<br /> Lai to varētu dzēst, jums ir jāpārveido vai jādzēš šis aprēķinātais sensors, lai tas vairs nebūtu atkarīgs no šī akumulatora ID. + + + Cette id_batterie est utilisée par les %1 capteurs calculés ci-dessous.<br />Vous devez modifier ou supprimer ces capteurs calculés pour qu'ils ne dépendent plus de cette id_batterie avant de pouvoir la supprimer. + Šo akumulatora_id izmanto %1 sensori, kas aprēķināti tālāk.<br /> Jums ir jāpārveido vai jādzēš šie aprēķinātie sensori, lai tie vairs nebūtu atkarīgi no šī akumulatora id, pirms varat to dzēst. + + + Ok + OK + + + 48V + 48V + + + + config_batteries + + Configuration des batteries + Akumulatora konfigurācija + + + Aucune batterie n'est encore configurée... + Vēl nav konfigurēts neviens akumulators... + + + + + + + + + + config_capteur + + Création d'un capteur + Sensora izveide + + + Configuration du capteur + Sensora konfigurācija + + + Nom du capteur + Sensora nosaukums + + + Affectation + Piešķiršana + + + Masquer sur la page Capteurs + Paslēpt lapā Sensori + + + Créer le capteur + Izveidojiet sensoru + + + Enregistrer + Saglabāt + + + Supprimer + DZĒST + + + Etalonner + Kalibrēt + + + Humidité + Mitrums + + + GNSS - Latitude + GNSS — platums + + + GNSS - Longitude + GNSS — garums + + + GNSS - Altitude + GNSS — augstums virs jūras līmeņa + + + Type de capteur + Sensora tips + + + Module + Modulis + + + Mode du capteur + Sensora režīms + + + Groupe de capteurs + Sensoru grupa + + + Equation + Vienādojums + + + Non défini + Nav definēts + + + Entrées Auxiliaires (AUX INPUTS) + Papildu ieejas (AUX INPUT) + + + Entrées Niveau (LEVEL SENSORS) + Līmeņa ieejas (LEVEL SENSORS) + + + Entrées Tension (VOLTAGE INPUTS) + Sprieguma ieejas (VOLTAGE INPUTS) + + + Capteurs de température (ONE WIRE) + Temperatūras sensori (VIENS VADS) + + + Capteurs sur modules + Sensori uz moduļiem + + + Calculé (conditions logiques) + Aprēķināts (loģiskie nosacījumi) + + + <i>Entrée non utilisée</i> + <i>Ievade nav izmantota</i> + + + Pression Atmosphérique + Atmosfēras spiediens + + + Température module + Moduļa temperatūra + + + Tension d'entrée module + Moduļa ieejas spriegums + + + Consommation module + Moduļa patēriņš + + + Consommation ports USB + USB porta patēriņš + + + Chocs + Šoki + + + Accélération X + Paātrinājums + + + Accélération Y + Paātrinājums Y + + + Accélération Z + Z paātrinājums + + + GNSS - SOG<br />Speed Over Ground + GNSS — SOG<br /> Ātrums virs zemes + + + GNSS - COG<br />Course Over Ground + GNSS — COG<br /> Virszemes sacīkstes + + + GNSS - SIV<br />Satellites In View + GNSS — SIV<br /> Satelīti skatā + + + GNSS - HPA<br />Horizontal Precision Accuracy + GNSS — HPA<br /> Horizontālā precizitāte + + + GNSS - VPA<br />Vertical Precision Accuracy + GNSS — VPA<br /> Vertikālā precizitāte + + + Modem 4G/LTE - RSSI<br />Received Signal Strength Indicator + 4G/LTE modems — RSSI<br /> Saņemtā signāla stipruma indikators + + + Modem 4G/LTE - SINR<br />Signal to Interference & Noise Ratio + 4G/LTE modems - SINR<br /> Signāla un traucējumu un trokšņu attiecība + + + Normal + Normāls + + + Inversé + Reverss + + + Tension 0 - 10 V + Spriegums 0 - 10 V + + + Résistance 0 - 500 Ohms + Pretestība 0 - 500 omi + + + Courant 4 - 20 mA + Strāva 4 - 20 mA + + + Défaut d'isolement + Izolācijas defekts + + + Ce capteur est utilisé par l'évènement ci-dessous.<br />Vous devez modifier ou supprimer cet évènement pour qu'il ne dépende plus de ce capteur avant de pouvoir le supprimer. + Šis sensors tiek izmantots tālāk norādītajam notikumam.<br /> Pirms varat to dzēst, šis notikums ir jāmaina vai jāizdzēš, lai tas vairs nebūtu atkarīgs no šī sensora. + + + Ce capteur est utilisé par les %1 évènements ci-dessous.<br />Vous devez modifier ou supprimer ces évènements pour qu'ils ne dépendent plus de ce capteur avant de pouvoir le supprimer. + Šo sensoru izmanto tālāk norādītie %1 notikumi.<br /> Jums ir jāpārveido vai jāizdzēš šie notikumi, lai tie vairs nebūtu atkarīgi no šī sensora, pirms varat to dzēst. + + + Ce capteur est utilisé par le capteur calculé ci-dessous.<br />Vous devez modifier ou supprimer ce capteur calculé pour qu'il ne dépende plus de ce capteur avant de pouvoir le supprimer. + Šo sensoru izmanto tālāk aprēķinātais sensors.<br /> Šis aprēķinātais sensors ir jāpārveido vai jāizdzēš, lai tas vairs nebūtu atkarīgs no šī sensora, pirms to varat dzēst. + + + Ce capteur est utilisé par les %1 capteurs calculés ci-dessous.<br />Vous devez modifier ou supprimer ces capteurs calculés pour qu'ils ne dépendent plus de ce capteur avant de pouvoir le supprimer. + Šo sensoru izmanto %1 sensori, kas aprēķināti tālāk.<br /> Jums ir jāpārveido vai jādzēš šie aprēķinātie sensori, lai tie vairs nebūtu atkarīgi no šī sensora, pirms varat to dzēst. + + + %1 : Non définie + %1: nav definēts + + + %1 : %2 + %1 : %2 + + + Libellé du capteur pour la valeur %1 + Sensora etiķete vērtībai %1 + + + Entrées NMEA2000 + NMEA2000 ieraksti + + + + config_capteur_calcule_booleen + + Equation du capteur calculé [%1] + Aprēķinātais sensora vienādojums [%1] + + + Enregistrer + Saglabāt + + + Supprimer + DZĒST + + + Le nombre de conditions par capteur est limité à %1.<br /><br />Vous ne pouvez pas ajouter de groupe ou de nouvelle condition avant d'en avoir supprimé préalablement. + Nosacījumu skaits vienam sensoram ir ierobežots līdz %1.<br /><br /> Jūs nevarat pievienot grupu vai jaunu nosacījumu, kamēr neesat to izdzēsis. + + + Des modifications ont été apportées au capteur<br />mais n'ont pas été enregistrées.<br /><br />Cliquer sur ANNULER pour revenir au menu en cours.<br /><br />Cliquer sur Ok pour sortir sans enregistrer. + Sensorā ir veiktas izmaiņas<br /> bet netika ierakstīti.<br /><br /> Noklikšķiniet uz ATCELT, lai atgrieztos pašreizējā izvēlnē.<br /><br /> Noklikšķiniet uz Labi, lai izietu, nesaglabājot. + + + est actif + ir aktīvs + + + est inactif + ir neaktīvs + + + Ou + Or + + + Et + Un + + + X-Ou + X-Or + + + + config_capteur_calcule_booleen_condition + + Création d'une condition du capteur [%1] + Sensora nosacījuma izveide [%1] + + + Type + Laipni + + + Source + Avots + + + Variable + Mainīgs + + + Test + Pārbaude + + + Seuil + Slieksnis + + + Créer la condition + Izveidojiet nosacījumu + + + Enregistrer + Saglabāt + + + Non défini + Nav definēts + + + Circuit + Ķēde + + + Capteur + Sensors + + + Réservoir + Rezervuārs + + + Batterie + Akumulators + + + Actif + Aktīvs + + + Inactif + Neaktīvs + + + &lt; au seuil + < slieksnis + + + &le; au seuil + ≤ pie sliekšņa + + + = au seuil + = pie sliekšņa + + + &ge; au seuil + ≥ pie sliekšņa + + + &gt; au seuil + > pie sliekšņa + + + + config_capteurs + + Configuration des capteurs + Sensoru konfigurēšana + + + Aucun capteur n'est encore configuré... + Neviens sensors vēl nav konfigurēts... + + + + + + + + + + config_circuit + + Configuration du circuit + Ķēdes konfigurācija + + + Nom du circuit + Tūres nosaukums + + + Affectation + Piešķiršana + + + Circuit renfort + Armatūras ķēde + + + Mode de commande + Pasūtīšanas metode + + + Vitesse de démarrage/arrêt + Start/stop ātrums + + + Seuil de disjonction + Disjunkcijas slieksnis + + + Vitesse de disjonction + Disjunkcijas ātrums + + + Filtrage du courant consommé + Patērētās strāvas filtrēšana + + + Masquer sur la page d'accueil + Slēpt mājaslapā + + + Créer le circuit + Izveidojiet ķēdi + + + Enregistrer + Saglabāt + + + L'affectation du circuit vient d'être modifiée alors que le circuit était actif. +Avant d'effectuer ce changement, le circuit a été passé sur OFF. + +Pensez à le réactiver si besoin... + Ķēdes piešķiršana tikko tika mainīta, kamēr ķēde bija aktīva. + Pirms šo izmaiņu veikšanas ķēde tika IZSLĒGTA. + + Atcerieties to atkārtoti aktivizēt, ja nepieciešams... + + + Supprimer + DZĒST + + + Aucun + Nav + + + ShipPower812 [@ %1] + ShipPower812 [@%1] + + + ShipPower4AC [@ %1] + ShipPower4AC [@%1] + + + ShipPower8DC [@ %1] + ShipPower8DC [@%1] + + + Circuit %1 + Ķēde %1 + + + Groupe de circuits + Ķēžu grupa + + + %1 - %2 + %1 - %2 + + + Non affecté + Neietekmē + + + On-Off + Ieslēgts Izslēgts + + + On-Off progressif + Progresīvā ieslēgšana-izslēgšana + + + Variateur + Dimmer + + + Aucun filtrage + Nav filtrēšanas + + + Très faible + Ļoti vāja + + + Faible + Vāja + + + Moyen + VIDĒJS + + + Elevé + Skolēns + + + Très élevé + Ļoti augstu + + + Très rapide + Ļoti ātri + + + Rapide + Ātri + + + Moyenne + Vidēji + + + Lente + Lēns + + + Très lente + Ļoti lēni + + + 15 secondes + 15 sekundes + + + 1 minute + 1 minūte + + + 5 minutes + 5 minūtes + + + 15 minutes + 15 minūtes + + + 1 heure + 1 stunda + + + 4 heures + 4 stundas + + + L'utilisation d'un circuit de renfort rend l'utilisation du mode de commande [Variateur] impossible.<br /><br />Le mode de commande vient donc d'être ramené à [On-Off Progressif]. + Izmantojot pastiprinātāja ķēdi, nav iespējams izmantot [Dimmer] vadības režīmu.<br /><br /> Tāpēc vadības režīms ir tikko atgriezts uz [Progressive On-Off]. + + + Commande impulsionnelle + Impulsu kontrole + + + Non + + + + 1 seconde + 1 sekunde + + + 2 secondes + 2 sekundes + + + 5 secondes + 5 sekundes + + + 30 secondes + 30 sekundes + + + 45 secondes + 45 sekundes + + + Ce circuit est utilisé pour la commande du moteur.<br />Vous devez d'abord affecter la commande moteur à un autre circuit avant de pouvoir supprimer celui-ci. + Šo shēmu izmanto motora vadībai.<br /> Pirms šīs ķēdes dzēšanas vispirms jāpiešķir motora vadība citai ķēdei. + + + Ce circuit est utilisé par l'évènement ci-dessous.<br />Vous devez modifier ou supprimer cet évènement pour qu'il ne dépende plus de ce circuit avant de pouvoir le supprimer. + Šo ķēdi izmanto tālāk norādītais notikums.<br /> Lai to varētu dzēst, jums ir jāmaina vai jāizdzēš šis notikums, lai tas vairs nebūtu atkarīgs no šīs shēmas. + + + Ce circuit est utilisé par les %1 évènements ci-dessous.<br />Vous devez modifier ou supprimer ces évènements pour qu'ils ne dépendent plus de ce circuit avant de pouvoir le supprimer. + Šo ķēdi izmanto tālāk norādītie %1 notikumi.<br /> Jums ir jāmaina vai jāizdzēš šie notikumi, lai tie vairs nebūtu atkarīgi no šīs ķēdes, pirms varat to dzēst. + + + Ce circuit est utilisé par le capteur calculé ci-dessous.<br />Vous devez modifier ou supprimer ce capteur calculé pour qu'il ne dépende plus de ce circuit avant de pouvoir le supprimer. + Šo ķēdi izmanto tālāk aprēķinātais sensors.<br /> Šis aprēķinātais sensors ir jāpārveido vai jānoņem, lai tas vairs nebūtu atkarīgs no šīs ķēdes, pirms varat to dzēst. + + + Ce circuit est utilisé par les %1 capteurs calculés ci-dessous.<br />Vous devez modifier ou supprimer ces capteurs calculés pour qu'ils ne dépendent plus de ce circuit avant de pouvoir le supprimer. + Šo ķēdi izmanto %1 sensori, kas aprēķināti tālāk.<br /> Jums ir jāpārveido vai jānoņem šie aprēķinātie sensori, lai tie vairs nebūtu atkarīgi no šīs ķēdes, pirms varat to dzēst. + + + + config_circuits + + Configuration des circuits + Ķēdes konfigurācija + + + Pack de batteries : + Baterijas paka: + + + Aucun capteur n'est encore configuré... + Neviens sensors vēl nav konfigurēts... + + + Oui + + + + Non + + + + Le module n'est affecté à aucune batterie... + Modulis nav piešķirts nevienam akumulatoram... + + + Circuit non utilisé + Ķēde nav izmantota + + + Circuits Non Affectés + Neietekmētas ķēdes + + + Ce circuit est configuré comme renfort du circuit <b>%1</b> et ne peut donc pas être configuré individuellement.<br /><br />Merci de cliquer sur le circuit <b>%1</b> de ce même module pour accéder à leurs paramètres communs<br />(y compris pour supprimer le circuit de renfort actuel). + Šī shēma ir konfigurēta kā rezerves shēma ķēdei <b>%1</b> , tāpēc to nevar konfigurēt atsevišķi.<br /><br /> Lūdzu, noklikšķiniet uz šī paša moduļa ķēdes <b>%1</b> , lai piekļūtu to kopējiem parametriem<br /> (tostarp, lai noņemtu pašreizējo stiegrojuma ķēdi). + + + Type de carte inconnu... + Nezināms kartes veids... + + + Le module <br /><b>%1</b><br /> n'est affecté à aucun pack de batteries. <br /><br />Souhaitez-vous laisser la configuration en l'état ? + Modulis<br /> <b>%1</b><br /> nav piešķirts nevienam akumulatora blokam. <br /><br />Vai vēlaties atstāt konfigurāciju tādu, kāda tā ir? + + + Les modules suivants ne sont affectés à aucun pack de batteries :<br /><b>%1</b><br /><br /><br />Souhaitez-vous laisser la configuration en l'état ? + Šie moduļi nav piešķirti nevienam akumulatora blokam:<br /> <b>%1</b><br /><br /><br /> Vai vēlaties atstāt konfigurāciju tādu, kāda tā ir? + + + + config_event + + Création d'un évènement + Pasākuma izveide + + + Configuration de l'évènement + Pasākuma konfigurācija + + + Nom de l'évènement + Pasākuma nosaukums + + + Type de la source + Avota veids + + + Source + Avots + + + Variable de la source + Avota mainīgais + + + Déclenchement si + Iedarbināts, ja + + + Seuil de déclenchement + Sprūda punkts + + + Temporisation de déclenchement + Sprūda aizkave + + + s + s + + + Masquer sur la page d'accueil + Slēpt mājaslapā + + + Conditions horaire + Laika apstākļi + + + Le nombre maximal de conditions horaires [%1] est atteint : ajout impossible... + Ir sasniegts maksimālais laika nosacījumu skaits [%1]: nav iespējams pievienot... + + + Aucune condition horaire n'est configurée pour cet évènement... + Šim notikumam nav konfigurēti laika apstākļi... + + + Signalisation + Signalizēšana + + + Alarme sonore + Skaņas signalizācija + + + La validation des alarmes sonores a nécessité de valider également l'affichage des messages liés à cet évènement.<br /><br />Cet affichage est en effet nécessaire au fonctionnement des alarmes sonores, afin de pouvoir les acquitter. + Lai apstiprinātu skaņas signālus, bija arī jāapstiprina ar šo notikumu saistīto ziņojumu parādīšana.<br /><br /> Šis displejs patiesībā ir nepieciešams skaņas signālu darbībai, lai varētu tos apstiprināt. + + + Alarme sur LED + Signalizācija iedegas LED + + + La validation des alarmes sur LED a nécessité de valider également l'affichage des messages liés à cet évènement.<br /><br />Cet affichage est en effet nécessaire au fonctionnement des alarmes sur LED, afin de pouvoir les acquitter. + Lai apstiprinātu LED trauksmi, bija arī jāapstiprina ar šo notikumu saistīto ziņojumu displejs.<br /><br /> Šis displejs patiesībā ir nepieciešams, lai LED trauksmes signāli darbotos, lai varētu tos apstiprināt. + + + Alarme sur sortie(s) de soutien + Trauksme par atbalsta izvadi(-ēm) + + + La validation des alarmes sur sortie(s) de soutien a nécessité de valider également l'affichage des messages liés à cet évènement.<br /><br />Cet affichage est en effet nécessaire au fonctionnement des alarmes sur sortie(s) de soutien, afin de pouvoir les acquitter. + Lai apstiprinātu trauksmes signālus atbalsta izvadē(-s), bija arī jāapstiprina ar šo notikumu saistīto ziņojumu parādīšana.<br /><br /> Šis displejs patiesībā ir nepieciešams trauksmes signālu darbībai atbalsta izvadē(-s), lai varētu tās apstiprināt. + + + Alarme sur la source + Trauksme avotā + + + Affichage message sur ShipBase + Ziņojumu parādīšana ShipBase + + + La dévalidation de l'affichage des messages a nécessité de dévalider également :<ul><li>les alarmes sonores,</li><li>les alarmes sur led</li><li>et les alarmes sur sortie(s) de soutien</li></ul><br />L'affichage de message est en effet nécessaire à leur fonctionnement, afin de pouvoir les acquitter. + Lai atspējotu ziņojumu rādīšanu, bija jāveic arī:<ul><li> skaņas trauksmes signāli,</li><li> LED signalizācijas</li><li> un trauksmes uz atbalsta izvadi(-ēm)</li></ul><br /> Ziņojumu displejs patiesībā ir nepieciešams to darbībai, lai tos varētu apstiprināt. + + + Texte du message à afficher + Parādāmās ziņas teksts + + + Emission SMS + SMS pārraide + + + Texte du SMS à envoyer + Nosūtāmās SMS teksts + + + Emission Email + E-pasta pārsūtīšana + + + Texte de l'email à envoyer + Nosūtāmā e-pasta teksts + + + Action sur circuits + Darbība uz ķēdēm + + + Aucune + Nav + + + Le circuit "bascule" + "Pārslēgšanas" ķēde + + + Le circuit passe à OFF + Ķēde izslēdzas + + + Le circuit passe à ON + Ķēde IESLĒGTS + + + Le nombre de circuits commandés par un évènement est limité à %1.<br /><br />Vous ne pouvez pas ajouter d'action sur un nouveau circuit avant d'en avoir supprimé préalablement. + Notikuma kontrolēto ķēžu skaits ir ierobežots līdz %1.<br /><br /> Jūs nevarat pievienot darbību jaunai shēmai, pirms tā nav izdzēsta. + + + Créer l'évènement + Izveidojiet notikumu + + + Enregistrer + Saglabāt + + + Supprimer + DZĒST + + + Non défini + Nav definēts + + + Condition horaire seule + Tikai laika nosacījums + + + Circuit + Ķēde + + + Capteur + Sensors + + + Réservoir + Rezervuārs + + + Batterie + Akumulators + + + Passage à <b>actif</b> + Pārslēdzieties uz <b>aktīvo</b> + + + Passage à <b>inactif</b> + Pārslēgšanās uz <b>neaktīvu</b> + + + &lt; au seuil + &lt; slieksnis + + + &le; au seuil + &le; pie sliekšņa + + + = au seuil + = pie sliekšņa + + + &ge; au seuil + &ge; pie sliekšņa + + + &gt; au seuil + &gt; pie sliekšņa + + + + config_events + + Configuration des évènements + Notikumu konfigurēšana + + + Aucun évènement n'est encore configuré... + Vēl nav konfigurēts neviens pasākums... + + + 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. + Kopējais notikumu skaits ir ierobežots līdz %1.<br /><br /> Jūs nevarat pievienot jaunu notikumu, pirms tas nav izdzēsts. + + + Sur circuits + Uz ķēdēm + + + Sur capteurs + Uz sensoriem + + + Sur réservoirs + Uz tankiem + + + Sur batteries + Uz baterijām + + + Horaire seulement + Tikai grafiks + + + + config_groupe_elements + + Création d'un groupe + Grupas izveide + + + Modification d'un groupe + Grupas rediģēšana + + + Nom du groupe + Grupas nosaukums + + + Créer le groupe + Izveidojiet grupu + + + Enregistrer + Saglabāt + + + Supprimer + DZĒST + + + capteurs + sensori + + + circuits + ķēdēm + + + 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). + Šī grupa ir pēdējā, kas joprojām ir spēkā.<br /><br /> Jūs to varēsiet dzēst tikai pēc tam, kad būsit iepriekš izveidojis vismaz vienu citu (nav iespējams darboties bez %1 grupas). + + + Ce groupe comprend encore %1 %2.<br /><br />Il est nécessaire d'affecter ces %2 à un autre groupe avant de pouvoir le supprimer. + Šajā grupā joprojām ietilpst %1 %2.<br /><br /> Šie %2 ir jāpiešķir citai grupai, lai to varētu izdzēst. + + + 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. + Šajā grupā joprojām ietilpst %1 %2,<br /> tostarp %3 konfigurēts kā "slēpts".<br /><br /> Šie %2 ir jāpiešķir citai grupai, lai to varētu izdzēst. + + + batteries + baterijas + + + réservoirs + tvertnes + + + + config_image_accueil + + Image d'accueil + Mājas attēls + + + Aucune image n'a encore été chargée... + Vēl nav ielādēts neviens attēls... + + + Sélectionner l'image par défaut + Izvēlieties noklusējuma attēlu + + + Sélectionner cette image + Izvēlieties šo attēlu + + + Copier + Lai kopētu + + + Supprimer + DZĒST + + + Ejection + Izgrūšana + + + Insérer une clé USB dans le port <u>du bas</u>, à droite + Ievietojiet USB atslēgu <u>apakšējā</u> labajā portā + + + Vous pouvez retirer la clé en toute sécurité... + Atslēgu var droši izņemt... + + + Seuls les fichiers de type '.jpg' ou '.png' de taille inférieure à %1 sont autorisés. + Ir atļauti tikai '.jpg' vai '.png' tipa faili, kuru izmērs ir mazāks par %1. + + + La clé USB a été <i>éjectée</i> automatiquement.<br />Vous pouvez la retirer dès maintenant en toute sécurité... + USB disks tika automātiski <i>izņemts</i> .<br /> Tagad varat to droši noņemt... + + + USB Arrière + USB aizmugure + + + Spare + Rezerves + + + USB Avant + USB priekšpuse + + + Touch pad + Skārienpaliktnis + + + La clé USB a été retirée sans avoir préalablement été <i>éjectée</i> !<br />Cela peut conduire à des pertes de données sur la clé, voire sur ShipHeart.<br /><br />Lors de vos prochaines utilisations, pensez à <i>éjecter</i> la clé avec le bouton en haut de page avant de la retirer... Merci ! + USB zibatmiņa tika izņemta, iepriekš <i>neizņemot</i> !<br /> Tas var izraisīt datu zudumu atslēgā vai pat ShipHeart.<br /><br /> Nākamajā reizē, kad to izmantosit, atcerieties <i>izņemt</i> atslēgu, izmantojot pogu lapas augšpusē, pirms to izņemat... PALDIES ! + + + + config_installation + + Configuration de l'installation + Instalācijas konfigurācija + + + Raison sociale + Sociālais iemesls + + + N° & Rue + Nr. un iela + + + Complément d'adresse + Papildu adrese + + + Code postal + Pasta indekss + + + Ville + Pilsēta + + + Nom du contact + Kontakta vārds + + + Téléphone + Tālrunis + + + Email + E-pasts + + + Site web + Tīmekļa vietne + + + Enregistrer + Saglabāt + + + Rapports + Pārskati + + + + config_koriolan + + Accès réservé Koriolan + Rezervēta piekļuve Koriolan + + + Client spécifique + Konkrēts klients + + + Enregistrer + Saglabāt + + + Nombre jours avant suppression historique + Dienu skaits pirms vēsturiskās dzēšanas + + + Nombre jours avant suppression mesures + Dienu skaits pirms mērījumu dzēšanas + + + Période de sauvegarde BDD + BDD rezerves periods + + + Période de vérification download + Lejupielādes verifikācijas periods + + + Date de dernier archivage mesures + Pēdējā mērījuma arhivēšanas datums + + + Aucune spécificité + Nav konkrētības + + + Client Suncy Concept + Klients Sunny Concept + + + Mode de mise à jour des firmwares + Programmaparatūras atjaunināšanas režīms + + + Tests matériel + Aparatūras testi + + + Normal (si version installée est antérieure à la version en cours) + Normāls (ja instalētā versija ir vecāka par pašreizējo versiju) + + + Différente (si version installée est différente de version en cours) + Atšķiras (ja instalētā versija atšķiras no pašreizējās versijas) + + + Toujours (à utiliser avec modération...) + Vienmēr (lietot ar mēru...) + + + + config_module + + Emplacement du module à bord + Moduļa atrašanās vieta uz kuģa + + + Commentaires + komentāri + + + Modifier + Lai modificētu + + + Localiser le module + Atrodiet moduli + + + Paramètres du module [%1] + Moduļa iestatījumi [%1] + + + Paramètres du module [%1] à l'adresse [%2] + Moduļa [%1] parametri adresē [%2] + + + N° de série + Sērijas Nr + + + Nom du firmware + Programmaparatūras nosaukums + + + Version du firmware + Programmaparatūras versija + + + Version matérielle + Aparatūras versija + + + Résistance de terminaison + Izbeigšanas rezistors + + + Oui + + + + Non + + + + CRC du firmware + Programmaparatūra CRC + + + <i>--- Circuit non affecté ---</i> + <i>--- ķēde nav ietekmēta ---</i> + + + [renfort] + [pastiprinājums] + + + Affectations + Uzdevumi + + + <i>--- Aucune batterie affectée ---</i> + <i>--- Nav ietekmēts akumulators ---</i> + + + Affectation + Piešķiršana + + + Version processeur + Procesora versija + + + Courant de masses sur réseau + Masu plūsma tīklā + + + + config_module_modification + + Configuration du module [%1] à l'adresse [%2] + Moduļa [%1] konfigurācija adresē [%2] + + + Emplacement du module à bord + Moduļa atrašanās vieta uz kuģa + + + Commentaires + komentāri + + + Enregistrer + Saglabāt + + + Courant de masses max. sur réseau + Maksimālais masu plūsmas stiprums tīklā + + + A + A + + + + config_ordre_elements + + 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... + Lai pārvietotu grupu, turiet to nospiestu un velciet to.<br /> Lai rediģētu vai dzēstu grupu, veiciet dubultklikšķi uz grupas.<br /> Lai pievienotu grupu, noklikšķiniet uz '+'.<br /><br /> Piezīme: ja tikai viena grupa, attiecīgajā lapā netiek parādīta neviena cilne... + + + Aucun groupe n'est actuellement configuré... + Pašlaik nav konfigurēta neviena grupa... + + + Aucun élément n'est actuellement configuré... + Pašlaik nekas nav konfigurēts... + + + Aucun groupe de capteurs n'est actuellement configuré... + Pašlaik nav konfigurēta neviena sensoru grupa... + + + Aucun groupe de circuits n'est actuellement configuré... + Pašlaik nav konfigurēta neviena ķēdes grupa... + + + Aucun groupe de batteries n'est actuellement configuré... + Pašlaik nav konfigurēta neviena akumulatora banka... + + + Aucune batterie n'est actuellement affectée à ce groupe... + Šai grupai pašlaik nav piešķirts neviens akumulators... + + + Affichage des batteries sur la page d'accueil + Akumulatoru parādīšana mājaslapā + + + Aucun capteur n'est actuellement affecté ce groupe... + Šai grupai pašlaik nav piešķirts neviens sensors... + + + Affichage des capteurs sur la page d'accueil + Sensoru attēlojums mājaslapā + + + Aucun circuit n'est actuellement affecté à ce groupe... + Šai grupai pašlaik nav piešķirtas ķēdes... + + + Affichage des circuits sur la page d'accueil + Ķēžu attēlojums mājaslapā + + + Aucun groupe de réservoirs n'est actuellement configuré... + Pašlaik nav konfigurēta neviena tanku grupa... + + + Aucun réservoir n'est actuellement affecté à ce groupe... + Šai grupai pašlaik nav piešķirts neviens tanks... + + + Affichage des réservoirs sur la page d'accueil + Mājas lapā tiek rādītas tvertnes + + + + config_page + + Création d'une page + Lapas izveide + + + Configuration de la page + Lapas iestatīšana + + + Nom de la page + Lapas nosaukums + + + Opacité de la silhouette + Silueta necaurredzamība + + + Fichier de silhouette + Silueta fails + + + Créer la page + Izveidojiet lapu + + + Enregistrer + Saglabāt + + + Silhouette + Siluets + + + Supprimer + DZĒST + + + Aucun + Nav + + + + config_page_edition + + Edition de la page [%1] + Rediģē lapu [%1] + + + Aucun équipement n'est configuré sur cette page pour le moment... + Šajā lapā šobrīd nav konfigurēts neviens aprīkojums... + + + Page + Lapa + + + Enregistrer + Saglabāt + + + 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. + Jūs esat veicis izmaiņas, kas nav saglabātas<br /> Noklikšķiniet uz Atcelt, lai atgrieztos un saglabātu tos.<br /> Noklikšķiniet uz Labi, lai izietu bez saglabāšanas. + + + + config_page_point + + Création d'un point + Punkta izveide + + + Configuration du point + Punktu konfigurācija + + + Type de la source + Avota veids + + + Source + Avots + + + Type de point + Dūriena veids + + + Taille du point + Punkta izmērs + + + Enregistrer + Saglabāt + + + Créer le point + Izveidojiet punktu + + + Supprimer + DZĒST + + + Non défini + Nav definēts + + + Capteur + Sensors + + + Circuit + Ķēde + + + Réservoir + Rezervuārs + + + Batterie + Akumulators + + + Modules + Moduļi + + + + config_page_silhouette + + Silhouette de la page + Lapas siluets + + + Aucune image n'a encore été chargée... + Vēl nav ielādēts neviens attēls... + + + Aucune image + Nav attēlu + + + Sélectionner cette image + Izvēlieties šo attēlu + + + Copier + Lai kopētu + + + Supprimer + DZĒST + + + Ejection + Izgrūšana + + + Insérer une clé USB dans le port <u>du bas</u>, à droite + Ievietojiet USB atslēgu <u>apakšējā</u> labajā portā + + + Vous pouvez retirer la clé en toute sécurité... + Atslēgu var droši izņemt... + + + Seuls les fichiers de type '.jpg' ou '.png' de taille inférieure à %1 sont autorisés. + Ir atļauti tikai '.jpg' vai '.png' tipa faili, kuru izmērs ir mazāks par %1. + + + La clé USB a été <i>éjectée</i> automatiquement.<br />Vous pouvez la retirer dès maintenant en toute sécurité... + USB disks tika automātiski <i>izņemts</i> .<br /> Tagad varat to droši noņemt... + + + USB Arrière + USB aizmugure + + + Spare + Rezerves + + + USB Avant + USB priekšpuse + + + Touch pad + Skārienpaliktnis + + + La clé USB a été retirée sans avoir préalablement été <i>éjectée</i> !<br />Cela peut conduire à des pertes de données sur la clé, voire sur ShipHeart.<br /><br />Lors de vos prochaines utilisations, pensez à <i>éjecter</i> la clé avec le bouton en haut de page avant de la retirer... Merci ! + + + + + config_pages + + Configuration des pages + Lapas iestatīšana + + + Aucune page n'est encore configurée... + Vēl neviena lapa nav konfigurēta... + + + + + + + + + Image accueil + Sākuma attēls + + + + config_pdf + + Ship2net + Ship2net + + + Enregistrer + Saglabāt + + + + config_rapports + + Rapports d'installation + Instalācijas atskaites + + + Aucun rapport d'installation n'est encore disponible... + Instalācijas pārskats vēl nav pieejams... + + + Nouveau rapport d'installation + Jauns uzstādīšanas ziņojums + + + Copier + Lai kopētu + + + Déplacer + Kustēties + + + Supprimer + DZĒST + + + Ejection + Izgrūšana + + + Insérer une clé USB dans le port <u>du bas</u>, à droite + Ievietojiet USB atslēgu <u>apakšējā</u> labajā portā + + + Vous pouvez retirer la clé en toute sécurité... + Atslēgu var droši izņemt... + + + La clé USB a été <i>éjectée</i> automatiquement.<br />Vous pouvez la retirer dès maintenant en toute sécurité... + USB disks tika automātiski <i>izņemts</i> .<br /> Tagad varat to droši noņemt... + + + USB Arrière + USB aizmugure + + + Spare + Rezerves + + + USB Avant + USB priekšpuse + + + Touch pad + Skārienpaliktnis + + + La clé USB a été retirée sans avoir préalablement été <i>éjectée</i> !<br />Cela peut conduire à des pertes de données sur la clé, voire sur ShipHeart.<br /><br />Lors de vos prochaines utilisations, pensez à <i>éjecter</i> la clé avec le bouton en haut de page avant de la retirer... Merci ! + USB zibatmiņa tika izņemta, iepriekš <i>neizņemot</i> !<br /> Tas var izraisīt datu zudumu atslēgā vai pat ShipHeart.<br /><br /> Nākamajā reizē, kad to izmantojat, atcerieties <i>izņemt</i> atslēgu, izmantojot pogu lapas augšpusē, pirms to izņemat... PALDIES ! + + + Le rapport d'installation<br /><br /><b>%1</b><br /><br />a été généré. + Instalācijas ziņojums<br /><br /> <b>%1</b><br /><br /> tika ģenerēts. + + + + config_reseau_ethernet_wifi + + Réseau Ethernet & Wifi + Ethernet un Wifi tīkls + + + Modifier + Lai modificētu + + + Ethernet + Ethernet + + + Adresse IP + IP adrese + + + Non connecté + Nav savienots + + + Connexion à un réseau existant + Savienojuma izveide ar esošu tīklu + + + Etat + Valsts + + + On + ON + + + Off + OFF + + + Nom du réseau [SSID] + Tīkla nosaukums [SSID] + + + Génération d'un réseau spécifique + Konkrēta tīkla ģenerēšana + + + Canal + Kanāls + + + + config_reseau_k_bus + + Réseau ShipHeart + ShipHeart tīkls + + + Modules physiquement présents + Moduļi ir fiziski klāt + + + %1 - %2 + %1 - %2 + + + Modules utilisés par la configuration actuelle + Pašreizējā konfigurācijā izmantotie moduļi + + + [@ %1] : %2 + [@ %1] : %2 + + + La configuration actuelle ne fait appel à aucun autre module que ShipBase... + Pašreizējā konfigurācijā netiek izmantots neviens cits modulis, izņemot ShipBase... + + + Module non utilisé en configuration + Modulis konfigurācijā netiek izmantots + + + [renfort] + [pastiprinājums] + + + Enregistrer + Saglabāt + + + Retour + Atpakaļ + + + Quitter + Aiziet + + + Aucune modification n'a été apportée à la configuration actuelle.<br />Celle-ci contient toujours des anomalies !<br /><br /><br />Souhaitez-vous :<br />Poursuivre les modifications [%1]<br />Quitter ce menu sans enregistrer les modifications [%2] + Pašreizējā konfigurācijā izmaiņas nav veiktas.<br /> Tas vienmēr satur anomālijas!<br /><br /><br /> Vai tu gribētu:<br /> Turpināt rediģēt [%1]<br /> Iziet no šīs izvēlnes, nesaglabājot izmaiņas [%2] + + + La configuration actuelle contient toujours des anomalies !<br /><br /><br />Souhaitez-vous :<br />Enregistrer cette nouvelle configuration et quitter ce menu [%1]<br />Poursuivre les modifications [%2]<br />Quitter ce menu sans enregistrer les modifications [%3] + Pašreizējā konfigurācijā joprojām ir anomālijas!<br /><br /><br /> Vai tu gribētu:<br /> Saglabāt šo jauno konfigurāciju un iziet no šīs izvēlnes [%1]<br /> Turpināt rediģēt [%2]<br /> Iziet no šīs izvēlnes, nesaglabājot izmaiņas [%3] + + + La configuration actuelle est correcte <br />mais n'a pas encore été enregistrée.<br /><br /><br />Souhaitez-vous :<br />Enregistrer cette nouvelle configuration et quitter ce menu [%1]<br />Poursuivre les modifications [%2]<br />Quitter ce menu sans enregistrer les modifications [%3] + Pašreizējā konfigurācija ir pareiza<br /> bet vēl nav ierakstīts.<br /><br /><br /> Vai tu gribētu:<br /> Saglabāt šo jauno konfigurāciju un iziet no šīs izvēlnes [%1]<br /> Turpināt rediģēt [%2]<br /> Iziet no šīs izvēlnes, nesaglabājot izmaiņas [%3] + + + + config_reseau_nmea + + Réseau NMEA2000 + NMEA2000 tīkls + + + Aucun PGN n'a encore été détecté sur le réseau NMEA2000... + NMEA2000 tīklā vēl nav konstatēts PGN... + + + PGN non affecté + PGN nav piešķirts + + + + config_reseau_one_wire + + Réseau One Wire + Viens vadu tīkls + + + Aucune sonde n'est encore installée... + Neviena zonde vēl nav uzstādīta... + + + 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. + One Wire kopne pašlaik ir konstatēta īssavienojums. <br />Šis stāvoklis nerada nekādas briesmas, bet neļauj tam darboties. <br /><br />Pārbaudiet atbilstošo vadu, līdz šis ziņojums pazūd. + + + Type inconnu + Nezināms veids + + + Sonde non affectée + Zonde nav piešķirta + + + + config_reseau_one_wire_modification + + Configuration de la sonde [%1] + Zondes konfigurācija [%1] + + + Emplacement de la sonde + Zondes atrašanās vieta + + + Enregistrer + Saglabāt + + + + config_reseau_wifi_ap + + Configuration Wifi en mode AP + Wifi konfigurācija AP režīmā + + + Etat + Valsts + + + Nom du réseau (SSID) + Tīkla nosaukums (SSID) + + + Mot de passe d'accès au réseau + Tīkla piekļuves parole + + + Canal + Kanāls + + + Adresse IP + IP adrese + + + Non connecté + Nav savienots + + + Enregistrer + Saglabāt + + + Off + OFF + + + On + ON + + + Canal %1 - [%2GHz] + Kanāls %1 — [%2GHz] + + + Le nom du réseau (SSID) doit comprendre entre 1 et 32 caractères. <br />Merci d'entrer un nom valide. + Tīkla nosaukumam (SSID) ir jābūt no 1 līdz 32 rakstzīmēm.<br /> Lūdzu, ievadiet derīgu vārdu. + + + 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. + Tīkla piekļuves parolei ir jābūt no 8 līdz 63 rakstzīmēm.<br /> Lūdzu, ievadiet derīgu paroli. + + + 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. + Tīkla nosaukumā (SSID) ir jāietver tikai:<br /> - lielie burti [A–Z],<br /> - mazie burti [a - z],<br /> - cipari [0-9]<br /> - īpašās rakstzīmes [%1].<br /><br /> Lūdzu, ievadiet derīgu vārdu. + + + 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. + Tīkla piekļuves parolē jāiekļauj tikai:<br /> - lielie burti [A–Z],<br /> - mazie burti [a - z],<br /> - cipari [0-9]<br /> - speciālās rakstzīmes [%1].<br /><br /> Lūdzu, ievadiet derīgu vārdu. + + + + config_reseau_wifi_sta + + Configuration Wifi en mode STA + Wifi konfigurācija STA režīmā + + + Etat + Valsts + + + Réseau + Tīkls + + + Mot de passe d'accès au réseau + Tīkla piekļuves parole + + + Enregistrer + Saglabāt + + + Réseaux connus + Zināmi tīkli + + + Off + OFF + + + On + ON + + + Aucun réseau... + Nav tīkla... + + + + config_reseau_wifi_sta_liste + + Liste des réseaux Wifi connus + Zināmo WiFi tīklu saraksts + + + Aucun réseau n'a été détecté... + Tīkls nav atklāts... + + + Oublier tous les réseaux + Aizmirstiet visus tīklus + + + Oublier ce réseau + Aizmirstiet šo tīklu + + + + config_reservoir + + Création d'un réservoir + Rezervuāra izveidošana + + + Configuration du réservoir + Tvertnes konfigurācija + + + Nom du réservoir + Rezervuāra nosaukums + + + Famille de réservoirs + Tanku ģimene + + + Type de capteur de niveau + Līmeņa sensora tips + + + %1 : Non définie + %1: nav definēts + + + %1 : %2 + %1 : %2 + + + Sonde la plus basse dans le réservoir + Zemākā zonde tvertnē + + + Non définie + Nav definēts + + + Logique d'alarme + Trauksmes loģika + + + Filtrage des mesures + Filtrēšanas mērījumi + + + Créer le réservoir + Izveidojiet tvertni + + + Enregistrer + Saglabāt + + + Supprimer + DZĒST + + + Etalonnage + Kalibrēšana + + + AUX INPUT %1 + AUX IEEJA %1 + + + LEVEL SENSOR %1 + LĪMEŅA SENSORS %1 + + + Confirmer + Apstiprināt + + + Non défini + Nav definēts + + + Electrodes plongées ou contacts secs + Iegremdēti elektrodi vai sausie kontakti + + + Résistif 0 - 190Ω + Pretestība 0 - 190Ω + + + Résistif 240 - 30Ω + Pretestība 240 - 30Ω + + + Boucle de courant 4 - 20mA + Strāvas cilpa 4 - 20mA + + + Tension 0 - 10V + Spriegums 0 - 10V + + + Aucun filtrage + Nav filtrēšanas + + + Très faible + Ļoti vāja + + + Faible + Vāja + + + Moyen + VIDĒJS + + + Elevé + Skolēns + + + Très élevé + Ļoti augstu + + + Alerte sur niveau faible + Zema līmeņa brīdinājums + + + Alerte sur niveau élevé + Augsta līmeņa brīdinājums + + + Capacité du réservoir + Tvertnes ietilpība + + + litres + litri + + + Logique des entrées inversée + Apgrieztā ievades loģika + + + La modification du <b>type de capteur</b> va nécessiter la remise en <i>configuration usine</i> de tous les paramètres du réservoir.<br /><br />Si vous ne souhaitez pas que cette reconfiguration soit effectuée, cliquez sur ANNULER. <br /><br />Sinon, cliquez sur CONFIRMER pour valider le changement. + Mainot <b>sensora veidu,</b> būs jāatjauno visi tvertnes parametri uz <i>rūpnīcas iestatījumiem</i> .<br /><br /> Ja nevēlaties, lai šī pārkonfigurācija tiktu veikta, noklikšķiniet uz CANCEL. <br /><br />Pretējā gadījumā noklikšķiniet uz APSTIPRINĀT, lai apstiprinātu izmaiņas. + + + Ce réservoir est utilisé par l'évènement ci-dessous.<br />Vous devez modifier ou supprimer cet évènement pour qu'il ne dépende plus de ce réservoir avant de pouvoir le supprimer. + Šo tvertni izmanto tālāk norādītais notikums.<br /> Jums ir jāmaina vai jāizdzēš šis notikums, lai tas vairs nebūtu atkarīgs no šīs tvertnes, pirms varat to dzēst. + + + Ce réservoir est utilisé par les %1 évènements ci-dessous.<br />Vous devez modifier ou supprimer ces évènements pour qu'ils ne dépendent plus de ce réservoir avant de pouvoir le supprimer. + Šo rezervuāru izmanto tālāk norādītie %1 notikumi.<br /> Jums ir jāpārveido vai jāizdzēš šie notikumi, lai tie vairs nebūtu atkarīgi no šīs tvertnes, pirms varat to dzēst. + + + Ce réservoir est utilisé par le capteur calculé ci-dessous.<br />Vous devez modifier ou supprimer ce capteur calculé pour qu'il ne dépende plus de ce réservoir avant de pouvoir le supprimer. + Šo tvertni izmanto tālāk aprēķinātais sensors.<br /> Šis aprēķinātais sensors ir jāpārveido vai jāizdzēš, lai tas vairs nebūtu atkarīgs no šīs tvertnes, pirms varat to dzēst. + + + Ce réservoir est utilisé par les %1 capteurs calculés ci-dessous.<br />Vous devez modifier ou supprimer ces capteurs calculés pour qu'ils ne dépendent plus de ce réservoir avant de pouvoir le supprimer. + Šo tvertni izmanto %1 sensori, kas aprēķināti tālāk.<br /> Jums ir jāmaina vai jādzēš šie aprēķinātie sensori, lai tie vairs nebūtu atkarīgi no šīs tvertnes, pirms varat to dzēst. + + + Résistif 0 - 700Ω + Pretestība 0 - 700Ω + + + + config_reservoirs + + Configuration des réservoirs + Tvertnes konfigurācija + + + Aucun réservoir n'est encore configuré... + Neviena tvertne vēl nav konfigurēta... + + + + + + + + + + config_ship2net + + Ship2net + Ship2net + + + Période des sauvegardes + Rezerves periods + + + Mode de validation des mises à jour + Atjaunināt validācijas režīmu + + + Enregistrer + Saglabāt + + + Jamais + Nekad + + + 30 minutes + 30 minūtes + + + 1 heure + 1 stunda + + + 2 heures + 2 stundas + + + 4 heures + 4 stundas + + + 12 heures + 12 stundas + + + 24 heures + 24 stundas + + + Aucune mise à jour + Nav atjauninājumu + + + Validation manuelle des mises à jour reçues + Saņemto atjauninājumu manuāla validācija + + + Validation automatique des mises à jour reçues + Automātiska saņemto atjauninājumu apstiprināšana + + + Période de connexion à Ship2net + Ship2net savienojuma periods + + + 10 minutes + 10 minūtes + + + Accès distant WebGL #1 + WebGL attālā piekļuve Nr. 1 + + + Accès distant WebGL #2 + WebGL attālā piekļuve Nr. 2 + + + Accès distant WebGL #3 + WebGL attālā piekļuve Nr. 3 + + + 2 minutes + 2 minūtes + + + Dévalidé + Disvalidēts + + + Valide [port %1] + Derīgs [ports %1] + + + + config_specifique_client_suncy + + Configuration spécifique à Suncy Concept + Konfigurācija, kas raksturīga Sunny Concept + + + Circuit d'activation moteur + Motora iedarbināšanas ķēde + + + Nouveau code + Jauns kods + + + Code d'accès au bateau + Laivas piekļuves kods + + + Répéter le code d'accès + Atkārtojiet piekļuves kodu + + + Enregistrer + Saglabāt + + + Aucune + Nav + + + [module %1 - circuit %2] %3 + [modulis %1 — ķēde %2] %3 + + + Les deux valeurs saisies doivent être identiques ! + +De plus, le code doit contenir : +- %1 chiffres au minimum +- %2 chiffres au maximum. + Abām ievadītajām vērtībām jābūt identiskām! + + Turklāt kodā jāiekļauj: + - Vismaz %1 cipars + - %2 cipari maksimums. + + + Le nouveau code doit contenir : +- %1 chiffres au minimum +- %2 chiffres au maximum. + +Le code saisi ne répond pas à ces critères et sa mise à jour n'est donc pas effectuée. + +Merci de saisir un code au format valide si vous souhaitez le modifier. + Jaunajā kodā jāiekļauj: + - Vismaz %1 cipars + - %2 cipari maksimums. + + Ievadītais kods neatbilst šiem kritērijiem un tāpēc netiek atjaunināts. + + Lūdzu, ievadiet kodu derīgā formātā, ja vēlaties to modificēt. + + + + config_valeurs_niveaux + + Aucun point de conversion n'est configuré pour le moment... + Pašlaik nav konfigurēts neviens konversijas punkts... + + + Courbe usine + Rūpnīcas līkne + + + Enregistrer + Saglabāt + + + Aucune donnée n'est disponible... + Dati nav pieejami... + + + 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. + Jūs esat veicis izmaiņas, kas nav saglabātas<br /> Noklikšķiniet uz Atcelt, lai atgrieztos un saglabātu tos.<br /> Noklikšķiniet uz Labi, lai izietu bez saglabāšanas. + + + Aucun point n'est actuellement configuré pour cette batterie... + Šim akumulatoram pašlaik nav konfigurēts neviens punkts... + + + Courbe de conversion de [%1] + [%1] konversijas līkne + + + Aucun réservoir n'est actuellement configuré... + Pašlaik nav konfigurēta neviena tvertne... + + + Aucun point n'est actuellement configuré pour cet élément... + Šim vienumam pašlaik nav konfigurēts neviens punkts... + + + Courbe de conversion de type INCONNU + NEZINĀMA tipa konversijas līkne + + + La valeur lue sur les electrodes plongées de ce réservoir est incohérente.<br />Vérifier l'ordre de cablage des électrodes sur les entrées auxiliaires à l'arrière de ShipBase. + Šī rezervuāra iegremdēto elektrodu rādījumi ir nekonsekventi. <br />Pārbaudiet elektrodu vadu savienojumu secību palīgierīču ieejās ShipBase aizmugurē. + + + Le nombre maximal de points d'étalonnage a été atteint (%1 points)<br />Vous ne pouvez pas en ajouter sans en avoir prélablement supprimé. + Ir sasniegts maksimālais kalibrēšanas punktu skaits (%1 punkti).<br />Nevar pievienot nevienu, vispirms neizdzēšot dažus. + + + + config_version + + Version + Versija + + + %1 : %2 + %1 : %2 + + + 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 : + Ir pieejama versija <b>%1</b> .<br /><br /> Tas tiks automātiski instalēts nākamreiz, kad startēsit ShipHeart.<br /> Ja vien neizvēlaties kādu no tālāk norādītajām opcijām: + + + La version <b>%1</b> est disponible.<br /><br />Souhaitez-vous : + Ir pieejama versija <b>%1</b> .<br /><br /> Vai tu gribētu: + + + L'installer +maintenant + Instalējiet to + TAGAD + + + L'installer au prochain démarrage de ShipHeart + Instalējiet to nākamreiz startējot ShipHeart + + + Ne jamais l'installer + Nekad neinstalējiet to + + + 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 'shipheart.tech' ou de nous contacter à l'adresse 'contact@shipheart.tech'. + Šo produktu izstrādā un ražo uzņēmums Koriolan, kuram ir visas licences un izmantošanas tiesības uz attēliem, programmatūru un patentiem, kas tiek izmantoti gan tā projektēšanai, gan darbībai. ShipHeart™, Ship2net™ un Koriolan™ ir Koriolan uzņēmuma reģistrētas preču zīmes. Ja jums ir kādi jautājumi par šo produktu, lūdzu, apmeklējiet vietni "shipheart.tech" vai sazinieties ar mums pa e-pastu "contact@shipheart.tech". + + + Version du package logiciel + Programmatūras pakotnes versija + + + Version de l'application + Lietotnes versija + + + Version de l'interface graphique + GUI versija + + + Version du firmware du modem + Modema programmaparatūras versija + + + Numéro d'IMEI + IMEI numurs + + + Numéro d'ICCID + ICCID numurs + + + Numéro d'IMSI + IMSI numurs + + + Supprimer + DZĒST + + + Si vous confirmez, cette mise à jour sera définitivement supprimée.<br />Cliquez sur Annuler pour revenir en arrière et la conserver. + Ja apstiprināsit, šis atjauninājums tiks neatgriezeniski dzēsts.<br />Noklikšķiniet uz Atcelt, lai atgrieztos un saglabātu to. + + + Installer + Uzstādīt + + + 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 la conserver pour une installation ultérieure. + Ja apstiprināsit, šis atjauninājums var ilgt <u>dažas minūtes</u>, kuru laikā <b>jūsu ShipHeart sistēma nebūs pieejama</b>.<br /><br />Jums nav jāapstiprina uzstādīšanu tikai tad, ja atrodaties drošā situācijā (ostā, noenkurojoties utt.) un kontroles zaudēšana pār jūsu borta sistēmām šajā laika periodā nav bīstama!<br /><br />Noklikšķiniet uz Atceliet, lai atgrieztos un saglabātu to vēlākai instalēšanai. + + + + ephemeride + + Ephéméride + Ephemeris + + + Heure d'hiver + Ziemas stunda + + + Heure d'été + Vasaras laiks + + + Aube nautique + Jūras rītausma + + + Lever du soleil + Saullēkts + + + Zénith + Zenīts + + + Coucher du soleil + Saulriets + + + Crépuscule nautique + Jūras krēsla + + + Lune + Mēness + + + Latitude + Platums + + + Longitude + Garums + + + + etalonnage_capteur + + Etalonnage du capteur [%1] + Sensora kalibrēšana [%1] + + + Valeur brute actuelle + Pašreizējā bruto vērtība + + + Valeur corrigée actuelle (%1) + Pašreizējā labotā vērtība (%1) + + + Correction + Labojums + + + Enregistrer + Saglabāt + + + + etalonnage_carte + + Etalonnage du module [%1 - #%2] + Moduļa kalibrēšana [%1 - #%2] + + + Point 1 + 1. punkts + + + Point 2 + 2. punkts + + + Courant de décharge + Izlādes strāva + + + Courant différentiel + Diferenciālā strāva + + + Recalculer ce point + Pārrēķiniet šo punktu + + + Mémoriser ce point + Iegaumējiet šo punktu + + + Off + OFF + + + On + ON + + + On (%1 %%) + mēs (%1 %%) + + + Enregistrer + Saglabāt + + + Aide + Palīdzība + + + 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 /> + Kalibrēšanu nevar veikt ar diviem identiskiem punktiem.<br /><br /> + Mēģiniet modificēt vismaz vienu no diviem atskaites punktiem, pielāgojot tālāk norādītās ķēdes vadības ierīces.<br /> + + + 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. + Kalibrēšanas princips ir salīdzināt 2 dažādos punktos diferenciālo strāvas vērtību, ko mēra ShipBS, no vienas puses, un + no otras puses, izlādes strāva, ko mēra ShipHeart sistēma. + Piemēram, pakļaut ShipBS, kas tiek kalibrēts, zemai jaudai vai bez jaudas (pirmais punkts) + pēc tam ieslēdzot vienu vai vairākas ierīces, lai, ja iespējams, iegūtu vairāku ampēru patēriņu (otrais punkts). + Ļoti svarīgi : visas kalibrēšanas fāzes laikā ShipBS nedrīkst pievadīt lādēšanas strāvu! + Tāpēc kalibrēšanas laikā ir svarīgi no sistēmas atvienot visus lādētājus, saules enerģijas regulatorus utt. + Pretējā gadījumā kalibrēšanas vērtības būs nepareizas... + Piezīmes: + - visam patēriņam jāiet caur ShipHeart sistēmu! Tāpēc ir jānodrošina, lai slodze nebūtu tieši savienota + akumulatoru bankā. + - pašreizējām vērtībām nav nozīmes. + - strāva 2. punktā var būt zemāka vai lielāka nekā 1. punktā (bet pēc iespējas "tālāk" viena no otras). + - vēlams izvēlēties slodzes, kuru patēriņš ir samērā stabils vai, kā minimums, nedaudz mainās dažu sekunžu laikā. + + + + fonctions + + Modèle inconnu + Nezināms modelis + + + Circuit + Ķēde + + + Capteur + Sensors + + + Réservoir + Rezervuārs + + + Batterie + Akumulators + + + Type inconnu + Nezināms veids + + + Consigne + Pasūtiet + + + Tension + Spriedze + + + Courant + Brīvi + + + Fréquence + Biežums + + + Puissance + Jauda + + + Energie + Enerģija + + + Température + Temperatūra + + + Courant différentiel + Diferenciālā strāva + + + Courant de charge + Uzlādes strāva + + + Courant de décharge + Izlādes strāva + + + SOH (state Of Health) + SOH (veselības stāvoklis) + + + SOC (State Of Charge) + SOC (state of Charge) + + + Autonomie + Autonomija + + + + fonctions_date_heure + + Dimanche + svētdiena + + + Lundi + pirmdiena + + + Mardi + otrdiena + + + Mercredi + trešdiena + + + Jeudi + CETURTDIENA + + + Vendredi + piektdiena + + + Samedi + SESTDIENA + + + janvier + janvārī + + + février + FEBRUĀRIS + + + mars + marts + + + avril + aprīlis + + + mai + var + + + juin + jūnijs + + + juillet + jūlijā + + + août + augusts + + + septembre + septembris + + + octobre + oktobris + + + novembre + novembris + + + décembre + decembris + + + 1 heure + 1 stunda + + + 24 heures + 24 stundas + + + 7 jours + 7 dienas + + + 30 jours + 30 dienas + + + Fin de nuit + Nakts beigas + + + Aube nautique + Jūras rītausma + + + Aube + Rītausma + + + Lever du soleil + Saullēkts + + + Zénith + Zenīts + + + Coucher du soleil + Saulriets + + + Crépuscule + Krēsla + + + Crépuscule nautique + Jūras krēsla + + + Début de nuit + Agra nakts + + + %1h + %1h + + + Tous les jours + Katru dienu + + + + fonctions_historique + + Commande 'OFF' du circuit %1 + 'OFF' komanda ķēdei %1 + + + Commande 'ON' du circuit %1 + 'ON' komanda ķēdei %1 + + + Commande à %1 % du circuit %2 + Vadība pie %1% no ķēdes %2 + + + Le circuit %1 est revenu à son état de fonctionnement normal + Ķēde %1 ir atgriezusies normālā darba stāvoklī + + + L'alimentation du circuit %1 a été coupée car sa limite de courant (%2 A) a été dépassée + Strāvas padeve ķēdei %1 tika pārtraukta, jo tika pārsniegts tās strāvas ierobežojums (%2 A) + + + L'alimentation du circuit %1 a été coupée car les circuits de protection interne ont détecté une anomalie + Strāvas padeve ķēdei %1 tika pārtraukta, jo iekšējās aizsardzības shēmas atklāja anomāliju + + + L'alimentation du circuit %1 a été coupée car le seuil de disjonction a été dépassé + Strāvas padeve ķēdei %1 tika pārtraukta, jo tika pārsniegts izslēgšanas slieksnis + + + Le circuit %1 est en court-circuit avec le + batterie + Ķēde %1 ir īssavienota ar + akumulatoru + + + L'alimentation du circuit %1 a été coupée car la consommation totale du module a été dépassé + Strāvas padeve ķēdei %1 tika pārtraukta, jo tika pārsniegts moduļa kopējais patēriņš + + + Le circuit %1 a été créé + Ir izveidota ķēde %1 + + + La configuration du circuit %1 a été modifiée + Ķēdes %1 konfigurācija ir mainīta + + + Le circuit %1 a été supprimé + Ķēde %1 ir izdzēsta + + + La configuration du circuit %1 est invalide car le module sur lequel le circuit est configuré n'est pas présent + Ķēdes %1 konfigurācija nav derīga, jo nav moduļa, kurā ķēde ir konfigurēta + + + Le circuit %1 a fonctionné trop longtemps (> %2 secondes). Il a donc été désactivé automatiquement. + Ķēde %1 darbojas pārāk ilgi (> %2 sekundes). Tāpēc tas tika automātiski deaktivizēts. + + + Evénement de type CIRCUITS avec code de sous-type inconnu [%1] + CIRCUITS tipa notikums ar nezināmu apakštipa kodu [%1] + + + Le capteur %1 est repassé à l'état normal + Sensors %1 ir atgriezies normālā stāvoklī + + + Le capteur %1 est passé à l'état ALERTE + Sensors %1 pārgāja uz BRĪDINĀJUMA stāvokli + + + Le capteur %1 est passé à l'état ALARME + Sensors %1 pārgāja stāvoklī ALARM + + + Evénement de type CAPTEURS avec code de sous-type inconnu [%1] + SENSORS tipa notikums ar nezināmu apakštipa kodu [%1] + + + Le niveau de charge de la batterie %1 est repassé au niveau normal + Akumulatora uzlādes līmenis %1 ir atgriezies normālā līmenī + + + Le niveau de charge de la batterie %1 est passé en dessous du niveau d'alerte + Akumulatora uzlādes līmenis %1 ir nokrities zem brīdinājuma līmeņa + + + Le niveau de charge de la batterie %1 est passé au-dessus du niveau d'alarme (il est maintenant au niveau d'alerte uniquement) + Akumulatora uzlādes līmenis %1 ir pieaudzis virs trauksmes līmeņa (tagad ir tikai trauksmes līmenī) + + + Le niveau de charge de la batterie %1 est passé en-dessous du niveau d'alarme + Akumulatora uzlādes līmenis %1 ir nokrities zem trauksmes līmeņa + + + Evénement de type BATTERIES avec code de sous-type inconnu [%1] + BATTERIES tipa notikums ar nezināmu apakštipa kodu [%1] + + + Le niveau du réservoir %1 est repassé au niveau normal + Tvertnes līmenis %1 ir atgriezies normālā līmenī + + + Le niveau du réservoir %1 est passé en dessous du niveau d'alerte + Rezervuāra līmenis %1 ir nokrities zem brīdinājuma līmeņa + + + Le niveau du réservoir %1 est passé au-dessus du niveau d'alarme (il est maintenant au niveau d'alerte uniquement) + Tvertnes līmenis %1 ir palielinājies virs trauksmes līmeņa (tagad ir tikai trauksmes līmenī) + + + Le niveau du réservoir %1 est passé en-dessous du niveau d'alarme + Tvertnes līmenis %1 ir nokrities zem trauksmes līmeņa + + + Evénement de type RESERVOIRS avec code de sous-type inconnu [%1] + TANKS tipa notikums ar nezināmu apakštipa kodu [%1] + + + La consigne des ports USB est passée à %1 + USB portu iestatītā vērtība ir mainīta uz %1 + + + L'état des ports USB est redevenu normal + USB portu statuss ir atgriezies normālā stāvoklī + + + Défaut détecté sur les ports USB + USB portos konstatēta kļūme + + + Evénement de type USB avec code de sous-type inconnu [%1] + USB tipa notikums ar nezināmu apakštipa kodu [%1] + + + Evénement de type INCONNU (avec code de sous-type [%1] + Notikums, kura tips ir NEZINĀMS (ar apakštipa kodu [%1] + + + + home + + Démarrage + Uzsākt + + + Code inconnu + Nezināms kods + + + Aucun circuit n'est configuré pour ce groupe...<br /><br />Si ce groupe n'a pas d'utilité, vous pouvez le supprimer dans le menu [Circuits] des Paramètres Avancés. + Šai grupai nav konfigurēta neviena ķēde...<br /><br /> Ja šī grupa nav nepieciešama, varat to izdzēst papildu iestatījumu izvēlnē [Circuits]. + + + Aucun capteur n'est configuré pour ce groupe...<br /><br />Si ce groupe n'a pas d'utilité, vous pouvez le supprimer dans le menu [Capteurs] des Paramètres Avancés. + Šai grupai nav konfigurēts neviens sensors...<br /><br /> Ja šī grupa nav nepieciešama, varat to izdzēst papildu iestatījumu izvēlnē [Sensori]. + + + Aucun réservoir n'est configuré pour ce groupe...<br /><br />Si ce groupe n'a pas d'utilité, vous pouvez le supprimer dans le menu [Réservoirs] des Paramètres Avancés. + Šai grupai nav konfigurēta neviena tvertne...<br /><br /> Ja šī grupa nav nepieciešama, varat to izdzēst papildu iestatījumu izvēlnē [Tanks]. + + + Aucun parc de batterie n'est configuré pour ce groupe...<br /><br />Si ce groupe n'a pas d'utilité, vous pouvez le supprimer dans le menu [Batteries] des Paramètres Avancés. + Šai grupai nav konfigurēta neviena akumulatora banka...<br /><br /> Ja šī grupa nav nepieciešama, varat to izdzēst papildu iestatījumu izvēlnē [Batteries]. + + + Cette page est actuellement en travaux. <br />Elle sera rendue disponible très rapidement à travers une mise à jour.<br /><br />Merci de votre patience...<br /><br />L'équipe ShipHeart + Šī lapa pašlaik ir izstrādes stadijā. <br />Tas būs pieejams ļoti ātri, izmantojot atjauninājumu.<br /><br /> Paldies par pacietību...<br /><br /> ShipHeart komanda + + + Déconnecté + Atvienots + + + Nombre de satellites visibles + Redzamo satelītu skaits + + + Connecté + Savienots + + + OFF + OFF + + + ON + ON + + + Niveau + Līmenis + + + Actif + Aktīvs + + + Inactif + Neaktīvs + + + <b>%1</b> + <b>%1</b> + + + Firmware de <b>ShipBase</b> + <b>ShipBase</b> programmaparatūra + + + Firmware du <b>ShipPower812</b> à l'adresse <b>%1</b> + <b>ShipPower812</b> programmaparatūra adresē <b>%1</b> + + + Firmware du <b>ShipBS</b> à l'adresse <b>%1</b> + <b>ShipBS</b> programmaparatūra adresē <b>%1</b> + + + Firmware du <b>ShipPower4AC</b> à l'adresse <b>%1</b> + <b>ShipPower4AC</b> programmaparatūra adresē <b>%1</b> + + + Firmware du <b>ShipPower8DC</b> à l'adresse <b>%1</b> + <b>ShipPower8DC</b> programmaparatūra adresē <b>%1</b> + + + Firmware du module à l'adresse <b>%1</b> + Moduļa programmaparatūra adresē <b>%1</b> + + + Merci de patienter et de ne rien débrancher<br />avant la fin de la mise à jour. + Lūdzu, esiet pacietīgs un neko neatvienojiet.<br /> pirms atjaunināšanas pabeigšanas. + + + Chargement des mises à jour effectué avec succès !<br /><br />L'activation des nouvelles version est en cours sur tous les modules concernés.<br /><br />Merci de patienter encore quelques secondes... + Atjauninājumi ir veiksmīgi ielādēti!<br /><br /> Notiek jauno versiju aktivizēšana visos attiecīgajos moduļos.<br /><br /> Lūdzu, uzgaidiet vēl dažas sekundes... + + + ShipHeart va redémarrer pour effectuer une mise à jour.<br /><br />Cette opération va prendre quelques minutes au maximum.<br />Merci de patienter et de ne rien débrancher jusqu'au redémarrage final... + ShipHeart tiks restartēts, lai veiktu atjaunināšanu.<br /><br /> Šī darbība ilgs ne vairāk kā dažas minūtes.<br /> Lūdzu, uzgaidiet un neko neatvienojiet līdz pēdējai atsāknēšanai... + + + Votre système ShipHeart est dorénavant équipé de la version<br /><br /><b>%1</b><br /><br />(la version précédente était la %2) + Jūsu ShipHeart sistēma tagad ir aprīkota ar versiju<br /><br /> <b>%1</b><br /><br /> (iepriekšējā versija bija %2) + + + Le nombre de modules détectés sur le réseau ShipHeart est insuffisant par rapport à la configuration du bateau.<br /><br />Vérifiez les connexions entre le module <b>%1</b> à la <b>position @%2</b> %3 et le module <b>%4</b> suivant%5<br /><br />Vous pouvez visualiser l'état complet du réseau ShipHeart et les anomalies détectées dans le menu 'Réseau > ShipHeart' dans les Paramètres Avancés + ShipHeart tīklā konstatēto moduļu skaits ir nepietiekams, salīdzinot ar laivas konfigurāciju.<br /><br /> Pārbaudiet savienojumus starp moduli <b>%1</b> <b>pozīcijā @%2</b> %3 un moduli <b>%4</b> blakus %5<br /><br /> Pilnu ShipHeart tīkla statusu un konstatētās novirzes varat skatīt papildu iestatījumu izvēlnē Tīkls > ShipHeart + + + Le modules détecté en <b>position @%1</b> est un <b>%2</b>. Cela ne correspond pas à la configuration actuelle du bateau (<b>%3</b>).<br /><br />Cela peut provenir de l'ajout, de la suppression ou d'un déplacement de module.<br /><br />Vous pouvez visualiser toutes les anomalies détectées et les corriger dans le menu 'Réseau > ShipHeart' dans les Paramètres Avancés + <b>Pozīcijā @%1</b> konstatētais modulis ir <b>%2</b> . Tas neatbilst pašreizējai laivas konfigurācijai ( <b>%3</b> ).<br /><br /> Tas var rasties, pievienojot, noņemot vai pārvietojot moduli.<br /><br /> Visas atklātās anomālijas varat apskatīt un labot papildu iestatījumu izvēlnē Tīkls > ShipHeart + + + + home_accueil + + Bienvenue à bord de + Laipni lūgti uz borta + + + + home_suncy + + L'accès au bateau est protégé. +Merci d'entrer votre code de déverrouillage pour y accéder... + Piekļuve laivai ir aizsargāta. + Lūdzu, ievadiet savu atbloķēšanas kodu, lai tam piekļūtu... + + + + journal_de_bord + + Tous + Visi + + + Batteries + Baterijas + + + Capteurs + Sensori + + + Circuits + Ekskursijas + + + Réservoirs + Tanki + + + Système + Sistēma + + + Ports USB + USB porti + + + Journal de bord + Žurnāls + + + Aucun type n'est configuré... + Nav konfigurēts neviens veids... + + + %1<br /><br /><br />%2 + %1<br /><br /><br /> %2 + + + Aucune entrée d'historique n'est disponible pour cette sélection... + Šai atlasei nav pieejams vēstures ieraksts... + + + Toutes + Visi + + + + main + + Type d'installation : +0 : ShipBase standard, +1 : écran déporté + Uzstādīšanas veids: + 0: standarta kuģu bāze, + 1: attālais ekrāns + + + valeur + vērtību + + + Adresse IPv4 de ShipBase dans le cas d'une installation déportée + ShipBase IPv4 adrese attālās instalācijas gadījumā + + + xxx:xxx:xxx:xxx + xxx:xxx:xxx:xxx + + + Taille de l'écran en pouces : +7, +10 (ShipBase standard), +22 + Ekrāna izmērs collās: + 7, + 10 (standarta ShipBase), + 22 + + + Original + Oriģināls + + + Sombre + Tumšs + + + Métallique + Metālisks + + + Triangles + Trīsstūri + + + Sable + Smiltis + + + Thème 5 + 5. tēma + + + Thème 6 + 6. tēma + + + Thème 7 + 7. tēma + + + Thème 8 + 8. tēma + + + + page_personnalisee + + <i>--- Circuit non affecté ---</i> + <i>--- ķēde nav ietekmēta ---</i> + + + [renfort] + [pastiprinājums] + + + <i>--- Aucune batterie affectée ---</i> + <i>--- Nav ietekmēts akumulators ---</i> + + + + parametres + + Paramètres + Iestatījumi + + + Langue + Valoda + + + Températures + Temperatūras + + + Volumes + Apjomi + + + Affichage + Displejs + + + Date et heure + Datums un stunda + + + Protection + Aizsardzība + + + Son + Viņa + + + Luminosité + Spilgtums + + + Economiseur d'écran : désactivé + Ekrānsaudzētājs: atspējots + + + Economiseur d'écran : normal + Ekrānsaudzētājs: normāls + + + Flash LEDs : désactivé + LED zibspuldze: atspējota + + + Flash LEDs : normal + LED zibspuldze: normāla + + + Nettoyage de l'écran + Ekrāna tīrīšana + + + Heure d'été + Vasaras laiks + + + Heure d'hiver + Ziemas stunda + + + Verrouiller le bateau + Aizslēdziet laivu + + + + parametres_avances + + Paramètres avancés + papildu iestatījumi + + + Circuits + Ekskursijas + + + Réservoirs + Tanki + + + Batteries + Baterijas + + + Capteurs + Sensori + + + Vos paramètres + Jūsu iestatījumi + + + Votre installation + Jūsu instalācija + + + Système + Sistēma + + + Affichage + Displejs + + + Audio + Audio + + + Ship2net + Ship2net + + + Accès au paramètres + Piekļuve iestatījumiem + + + Configuration ShipRS + ShipRS iestatīšana + + + Version + Versija + + + Accès réservé Koriolan + Rezervēta piekļuve Koriolan + + + Spécifique Suncy + Konkrētā Sunsija + + + Réseaux + Tīkli + + + Cette page est actuellement en travaux. <br />Elle sera rendue disponible très rapidement à travers une mise à jour.<br /><br />Merci de votre patience...<br /><br />L'équipe ShipHeart + Šī lapa šobrīd ir izstrādes stadijā. <br />Tas būs pieejams ļoti ātri, izmantojot atjauninājumu.<br /><br /> Paldies par pacietību...<br /><br /> ShipHeart komanda + + + Evènements + Pasākumi + + + ShipHeart + ShipHeart + + + Ethernet & Wifi + Ethernet un Wifi + + + One Wire + Viens vads + + + NMEA 2000 + NMEA 2000 + + + J1939 + J1939 + + + DMX + DMX + + + Journal de bord + Žurnāls + + + Installation + Iekārta + + + Menu accueil + Sākuma izvēlne + + + + protection + + Accès protégé + Aizsargāta piekļuve + + + L'accès aux paramètres avancés est protégé. +Merci d'entrer le code de déverrouillage pour y accéder... + Piekļuve papildu iestatījumiem ir aizsargāta. + Lūdzu, ievadiet atbloķēšanas kodu, lai tam piekļūtu... + + + Mode administrateur validé<br />Entrer votre code dédié + Administratora režīms apstiprināts<br /> Ievadiet savu īpašo kodu + + + + reservoir + + [ %1 % ] + [ %1 % ] + + + Aucune donnée n'est disponible pour cette période + Par šo periodu dati nav pieejami + + + Le module assurant la supervision de ce réservoir n'est pas accessible !<br /><br />Si des ajouts/suppression/déplacements de modules ont eu lieu récemment, mettez à jour la configuration correspondant dans le menu MODULES de PARAMETRES AVANCES.<br /><br />Dans le cas où aucune modification n'a été effectuée récemment, vérifier les connexions de tous les modules. + Modulis, kas nodrošina šīs tvertnes uzraudzību, nav pieejams!<br /><br /> Ja moduļi ir pievienoti/dzēsti/pārvietoti nesen, atjauniniet atbilstošo konfigurāciju PAPILDUS IESTATĪJUMU izvēlnē MODUĻI.<br /><br /> Ja pēdējā laikā nav veiktas nekādas izmaiņas, pārbaudiet visu moduļu savienojumus. + + + Niveau + Līmenis + + + La valeur lue sur les electrodes plongées de ce réservoir est incohérente.<br />Vérifier l'ordre de cablage des électrodes sur les entrées auxiliaires à l'arrière de ShipBase. + Vērtība, kas nolasīta uz šajā tvertnē iegremdētajiem elektrodiem, ir pretrunīga.<br /> Pārbaudiet elektrodu vadu secību ShipBase aizmugurē esošajās papildu ieejās. + + + + shipheart_test_config + + Vitesse de test de l'écran + Ekrāna pārbaudes ātrums + + + Nombre de colonnes de test du touchpad + Skārienpaliktņa testa kolonnu skaits + + + Nombre de lignes de test du touchpad + Skārienpaliktņa pārbaudes līniju skaits + + + + shipheart_test_home + + Tests matériel + Aparatūras testi + + + Configuration des tests + Testa iestatīšana + + + Test du backlight + Fona apgaismojuma pārbaude + + + Test de l'écran + Ekrāna pārbaude + + + Test du touchpad + Skārienpaliktņa pārbaude + + + Liste des fonts disponibles + Pieejamo fontu saraksts + + + + shipheart_test_liste_fonts + + Liste des fonts disponibles + Pieejamo fontu saraksts + + + + test_batterie + + Batteries de servitude + Servisa akumulatori + + + Autonomie optimale + Optimāla autonomija + + + Autonomie actuelle + Pašreizējā autonomija + + + Autonomie<br />maximale + Autonomija<br /> maksimums + + + dans + In + + + environ + aptuveni + + + + test_tri_liste + + TEST DE TRI DE LISTE + SARAKSTA KĀRTOŠANAS PĀRBAUDE + + + diff --git a/shipheart_nl_NL.qm b/shipheart_nl_NL.qm new file mode 100755 index 0000000..dca81eb Binary files /dev/null and b/shipheart_nl_NL.qm differ diff --git a/shipheart_nl_NL.ts b/shipheart_nl_NL.ts new file mode 100755 index 0000000..56b72da --- /dev/null +++ b/shipheart_nl_NL.ts @@ -0,0 +1,4409 @@ + + + + + Shipheart_boite_dialogue + + OK + OK + + + Annuler + Annuleren + + + Plus tard + Later + + + + Shipheart_boite_dialogue_action_circuit + + Action à appliquer au circuit lorsque l'évènement se déclenche : + Actie die op het circuit moet worden toegepast wanneer de gebeurtenis wordt geactiveerd: + + + Aucune + Geen + + + Le circuit <b>bascule</b> + Het circuit <b>schakelt</b> + + + [passe à <b>ON</b> s'il est <b>OFF</b><br /> ou à <b>OFF</b> s'il est <b>ON</b>] + [gaat <b>AAN</b> indien <b>UIT</b><br /> of naar <b>UIT</b> als deze <b>AAN</b> is] + + + OFF + OFF + + + ON + ON + + + Annuler + Annuleren + + + + Shipheart_boite_dialogue_affichage_duree + + Ok + OK + + + + Shipheart_boite_dialogue_condition_horaire + + OK + OK + + + Annuler + Annuleren + + + Supprimer + Verwijder + + + Aube nautique + Nautische dageraad + + + Lever du soleil + Zonsopgang + + + Zénith + Zenith + + + Coucher du soleil + Zonsondergang + + + Crépuscule nautique + Nautische schemering + + + + Shipheart_boite_dialogue_entrees_aux + + Entrées Auxiliaires + Hulpingangen + + + Annuler + Annuleren + + + Affectation de l'entrée n° %1 du %2 + Toewijzing van invoernummer %1 van %2 + + + + Shipheart_boite_dialogue_entrees_level_sensor + + Entrées Level Sensor + Niveausensor ingangen + + + Affectation de l'entrée du réservoir + Toewijzing reservoirinlaat + + + Annuler + Annuleren + + + + Shipheart_boite_dialogue_liste_alarmes + + Ok + OK + + + + Shipheart_boite_dialogue_minuteur + + Heures + Uur + + + Minutes + Minuten + + + Secondes + Seconden + + + Annuler + Annuleren + + + Démarrer + Beginnen + + + + Shipheart_boite_dialogue_nettoyage_ecran + + Nettoyage de l'écran + Het scherm schoonmaken + + + 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. + Het scherm is momenteel bevroren zodat je het kunt schoonmaken zonder het risico te lopen ongewenste acties te activeren.<br /><br />Houd de onderstaande knop langer dan %1 seconden ingedrukt om deze modus te verlaten. + + + Sortie + Uitgang + + + + Shipheart_boite_dialogue_reveils + + Annuler + Annuleren + + + Enregistrer + Opnemen + + + + Shipheart_boite_dialogue_validation_securisee + + OK + OK + + + Annuler + Annuleren + + + --- + --- + + + + Shipheart_bouton_circuit + + Off + OFF + + + On + ON + + + + batterie + + Aucune donnée n'est disponible pour cette période + Geen gegevens beschikbaar voor deze periode + + + Le module assurant la supervision de cette batterie n'est pas accessible !<br /><br />Si des ajouts/suppression/déplacements de modules ont eu lieu récemment, mettez à jour la configuration correspondant dans le menu MODULES de PARAMETRES AVANCES.<br /><br />Dans le cas où aucune modification n'a été effectuée récemment, vérifier les connexions de tous les modules. + De module die deze batterij bewaakt, is niet toegankelijk!<br /><br />Als modules onlangs zijn toegevoegd/verwijderd/verplaatst, update dan de overeenkomstige configuratie in het MODULES-menu van GEAVANCEERDE PARAMETERS. <br /><br />In het geval dat er zijn recentelijk geen wijzigingen aangebracht, controleer de aansluitingen van alle modules. + + + Aucune consommation d'énergie sur cette période... + Geen energieverbruik tijdens deze periode... + + + + capteur + + Max + Max + + + Moyen + Medium + + + Min + Min + + + Delta (Max - Min) + Delta (Max - Min) + + + Aucune donnée n'est disponible pour cette période + Geen gegevens beschikbaar voor deze periode + + + La sonde One Wire correspondant à ce capteur n'est pas accessible.<br />Vérifier son câblage entre le port One Wire à l'arrière de ShipBase et la sonde. + De One Wire-sonde die bij deze sensor hoort, is niet toegankelijk.<br /> Controleer de bedrading tussen de One Wire-poort aan de achterkant van ShipBase en de sonde. + + + Le module assurant la supervision de ce capteur n'est pas accessible !<br /><br />Si des ajouts/suppression/déplacements de modules ont eu lieu récemment, mettez à jour la configuration correspondant dans le menu MODULES de PARAMETRES AVANCES.<br /><br />Dans le cas où aucune modification n'a été effectuée récemment, vérifier les connexions de tous les modules. + De module die deze sensor bewaakt is niet toegankelijk!<br /><br /> Als er onlangs modules zijn toegevoegd/verwijderd/verplaatst, update dan de overeenkomstige configuratie in het menu MODULES van GEAVANCEERDE INSTELLINGEN.<br /><br /> Indien er recentelijk geen wijzigingen zijn aangebracht, controleer dan de aansluitingen van alle modules. + + + La sonde One Wire du capteur est détectée en défaut.<br />Vérifier son câblage depuis l'arrière de ShipBase. + De One Wire-sonde van de sensor wordt als defect gedetecteerd.<br /> Controleer de bekabeling vanaf de achterkant van ShipBase. + + + Le capteur n'a pas reçu de mise à jour sur le réseau NMEA depuis<br />%1<br />Les données affichées sont donc probablement obsolètes. + De sensor heeft sinds<br />%1 geen update meer ontvangen op het NMEA-netwerk. De weergegeven gegevens zijn daarom waarschijnlijk verouderd. + + + + circuit + + Off + OFF + + + On + ON + + + On +%1% + Wij + %1% + + + Aucune donnée n'est disponible pour cette période + Geen gegevens beschikbaar voor deze periode + + + L'alimentation du circuit a été coupée + car sa limite de courant (%1 A) + a été dépassée. + De stroom naar het circuit is uitgeschakeld + omdat de huidige limiet (%1 A) + werd overschreden. + + + L'alimentation du circuit a été coupée + car les circuits de protection interne ont détecté une anomalie. + De stroom naar het circuit is uitgeschakeld + omdat de interne beveiligingscircuits een anomalie hebben gedetecteerd. + + + L'alimentation du circuit a été coupée + car le seuil de disjonction du circuit a été dépassé. + De stroom naar het circuit is uitgeschakeld + omdat de uitschakeldrempel van het circuit is overschreden. + + + Le circuit est en court-circuit avec le + batterie. + Het circuit is kortgesloten met de + batterij. + + + L'alimentation du circuit a été coupée<br />car la consommation totale du module a dépassé %1 A pendant plus de %2 secondes (limite du module) + De voeding van het circuit is onderbroken op<br />omdat het totale verbruik van de module %1 A overschreden heeft gedurende meer dan %2 seconden (modulegrens) + + + La tension du circuit est anormalement basse. + De circuitspanning is abnormaal laag. + + + La phase et le neutre sont inversés sur ce circuit. + Fase en nul zijn omgekeerd op dit circuit. + + + Etat inconnu... + Status onbekend... + + + Le module assurant le pilotage de ce circuit n'est pas accessible !<br /><br />Si des ajouts/suppression/déplacements de modules ont eu lieu récemment, mettez à jour la configuration correspondant dans le menu [Réseau ShipHeart] de [Paramètres Avancés].<br /><br />Dans le cas où aucune modification n'a été effectuée récemment, vérifier les connexions de tous les modules. + De module die dit circuit bestuurt, is niet toegankelijk!<br /><br />Als er onlangs modules zijn toegevoegd/verwijderd/verplaatst, update dan de overeenkomstige configuratie in het menu [ShipHeart Network] van [Geavanceerde instellingen].<br />< br />Als er onlangs geen wijzigingen zijn aangebracht, controleer dan de aansluitingen van alle modules. + + + Ce circuit est configuré comme <i>Non Affecté</i> et n'est donc pas accessible !<br /><br />Pour accéder à nouveau à ce circuit, merci de l'affecter à un circuit disponible dans le menu [Circuits] de [Paramètres Avancés]. + Dit circuit is geconfigureerd als <i>Niet toegewezen</i> en is daarom niet toegankelijk!<br /><br />Om opnieuw toegang te krijgen tot dit circuit, wijst u het toe aan een circuit dat beschikbaar is in het menu [Circuits] van [Geavanceerde instellingen ]. + + + Aucune consommation d'énergie sur cette période... + Geen energieverbruik tijdens deze periode... + + + Le module pilotant ce circuit n'est pas alimentée correctement. + Vérifier l'alimentation correspondante. + De module die dit circuit bestuurt, wordt niet correct gevoed. + Controleer de bijbehorende voeding. + + + Le module pilotant ce circuit est en mode MANUEL. + Repositionnez le module en mode AUTO pour commander à nouveau ce circuit normalement. + De module die dit circuit bestuurt, bevindt zich in de HANDMATIGE modus. + Zet de module terug naar de AUTO-modus om dit circuit weer normaal te besturen. + + + Le port USB du bas est en défaut. + De onderste USB-poort is defect. + + + Le port USB du milieu est en défaut. + De middelste USB-poort is defect. + + + Les 2 ports USB du milieu et du bas sont en défaut. + De 2 middelste en onderste USB-poorten zijn defect. + + + Le port USB du haut est en défaut. + De bovenste USB-poort is defect. + + + Les 2 ports USB du haut et du bas sont en défaut. + De 2 USB-poorten aan de boven- en onderkant zijn defect. + + + Les 2 ports USB du haut et du milieu sont en défaut. + De 2 bovenste en middelste USB-poorten zijn defect. + + + Les 3 ports USB du haut, du milieu et du bas sont en défaut. + De bovenste, middelste en onderste 3 USB-poorten zijn defect. + + + Le port USB est en défaut. + De USB-poort is defect. + + + La masse est absente du connecteur d'alimentation du module + Er ontbreekt aarde op de voedingsconnector van de module + + + Evènements actuellement actifs qui sont susceptibles de commander ce circuit : + Momenteel actieve gebeurtenissen die dit circuit waarschijnlijk zullen besturen: + + + Non défini + Niet gedefinieerd + + + DANGER : Le neutre n'est pas référencé à la terre sur ce circuit ("absence de terre"). + GEVAAR: De nulleider heeft op dit circuit geen verbinding met aarde ("geen aarde"). + + + + config_acces_parametres + + Configuration de l'accès aux paramètres avancés + Toegang tot geavanceerde instellingen configureren + + + Durée de maintien de l'accès + Duur van de toegang + + + Nouveau code + Nieuwe code + + + Code d'accès + Toegangscode + + + Répéter le code d'accès + Toegangscode herhalen + + + Enregistrer + Registreer + + + Aucune (saisie du code à chaque accès) + Geen (code ingevoerd telkens wanneer toegang wordt verleend) + + + 1 minute + 1 minuut + + + 5 minutes + 5 minuten + + + 15 minutes + 15 minuten + + + 1 heure + 1 uur + + + Infinie (aucune protection des paramètres avancés) + Oneindig (geen bescherming voor geavanceerde instellingen) + + + Les deux valeurs saisies doivent être identiques ! + +De plus, le code doit contenir : +- %1 chiffres au minimum +- %2 chiffres au maximum. + De twee ingevoerde waarden moeten identiek zijn! + + Bovendien moet de code het volgende bevatten: + - %1 cijfer minimaal + - %2 cijfers maximaal. + + + Le nouveau code doit contenir : +- %1 chiffres au minimum +- %2 chiffres au maximum. + +Le code saisi ne répond pas à ces critères et sa mise à jour n'est donc pas effectuée. + +Merci de saisir un code au format valide si vous souhaitez le modifier. + De nieuwe code moet het volgende bevatten: + - %1 cijfer minimaal + - %2 cijfers maximaal. + + De ingevoerde code voldoet niet aan deze criteria en wordt daarom niet bijgewerkt. + + Voer een code in een geldig formaat in als u deze wilt wijzigen. + + + + config_affichage + + Configuration de l'affichage + Weergaveconfiguratie + + + Temporisaton économiseur d'écran + Timer voor schermbeveiliging + + + Enregistrer + Registreer + + + 15 secondes + 15 seconden + + + 30 secondes + 30 seconden + + + 1 minute + 1 minuut + + + 3 minutes + 3 minuten + + + 10 minutes + 10 minuten + + + Aucune limite + Geen limiet + + + Nom du bateau + Naam van de boot + + + Fuseau horaire + Tijdzone + + + Thème d'affichage + Weergavethema + + + UTC-12 (Yankee) + UTC-12 (Yankee) + + + UTC-11 (X-Ray) + UTC-11 (röntgen) + + + UTC-10 (Whisky) + UTC-10 (Whisky) + + + UTC-9 (Victor) + UTC-9 (Victor) + + + UTC-8 (Uniform) + UTC-8 (Uniform) + + + UTC-7 (Tango) + UTC-7 (Tango) + + + UTC-6 (Sierra) + UTC-6 (Sierra) + + + UTC-5 (Romeo) + UTC-5 (Romeo) + + + UTC-4 (Quebec) + UTC-4 (Quebec) + + + UTC-3 (Papa) + UTC-3 (vader) + + + UTC-2 (Oscar) + UTC-2 (Oscar) + + + UTC-1 (November) + UTC-1 (november) + + + UTC (Zoulou) + UTC (Zoeloe) + + + UTC+1 (Alpha) + UTC+1 (Alfa) + + + UTC+2 (Bravo) + UTC+2 (Bravo) + + + UTC+3 (Charlie) + UTC+3 (Charlie) + + + UTC+4 (Delta) + UTC+4 (Delta) + + + UTC+5 (Echo) + UTC+5 (Echo) + + + UTC+6 (Foxtrot) + UTC+6 (Foxtrot) + + + UTC+7 (Golf) + UTC+7 (Golf) + + + UTC+8 (Hotel) + UTC+8 (hotel) + + + UTC+9 (India) + UTC+9 (India) + + + UTC+10 (Kilo) + UTC+10 (Kilo) + + + UTC+11 (Lima) + UTC+11 (Lima) + + + UTC+12 (Mike) + UTC+12 (Mike) + + + + config_audio + + Bips de clic + Klik pieptonen + + + Fonctionnement de la sortie Audio + Audio-uitgang + + + Enregistrer + Registreer + + + Aucun bip + Geen pieptoon + + + Bip par défaut + Standaard pieptoon + + + Bip 2 + Piep 2 + + + Bip 3 + Piep 3 + + + Bip 4 + Piep 4 + + + Bip 5 + Piep 5 + + + Bip 6 + Piep 6 + + + Bip 7 + Piep 7 + + + Bip 8 + Piep 8 + + + Bip 9 + Piep 9 + + + Bip 10 + Piep 10 + + + Bip 11 + Piep 11 + + + Bip 12 + Piep 12 + + + Bip 13 + Bip 13 + + + Bip 14 + Piep 14 + + + Configuration audio + Audio-installatie + + + Le son de ShipBase est coupé. Le son est uniquement diffusé sur la sortie AUDIO + ShipBase-audio is gedempt. Er wordt alleen geluid weergegeven via de AUDIO-uitgang + + + Le son est diffusé sur ShipBase et sur la sortie AUDIO + Audio wordt gestreamd naar ShipBase en AUDIO-uitvoer + + + + config_batterie + + Nom de la batterie + Naam batterij + + + Tension nominale + Nominale spanning + + + Créer la batterie + De batterij maken + + + Enregistrer + Registreer + + + Supprimer + Verwijder + + + Confirmer + Bevestig + + + Etalonner + Kalibreer + + + Non défini + Niet gedefinieerd + + + ShipBS [@ %1] + ShipBS [@ %1] + + + Entrée VOLT n° %1 + VOLT ingang nr. %1 + + + Plomb - Acide liquide + Lood - Vloeibaar zuur + + + Plomb - AGM / VRLA + Lood - AGM / VRLA + + + Plomb - Gel + Lood - Gel + + + Plomb - Carbone + Lood - Koolstof + + + Lithium + Lithium + + + 12V + 12V + + + 24V + 24V + + + Création d'un parc de batteries + Oprichting van een batterijbank + + + Configuration du parc de batteries + Configuratie van de batterijbank + + + Point de mesure + Meetpunt + + + Type de batterie(s) + Batterijtype(s) + + + La modification du <b>type</b> de batterie(s) va nécessiter la remise en <i>configuration usine</i> de certains paramètres.<br /><br />Si vous ne souhaitez pas que cette reconfiguration soit effectuée, notamment si vous avez effectué des réglages spécifiques, cliquez sur ANNULER. <br /><br />Sinon, cliquez sur CONFIRMER pour valider le changement. + Als u het <b>type</b> batterij(en) wilt wijzigen, moeten bepaalde parameters worden teruggezet naar de <i>fabrieksconfiguratie</i>.<br /><br />Als u niet wilt dat deze herconfiguratie wordt uitgevoerd, vooral als u specifieke instellingen heeft gemaakt, klikt u op ANNULEREN. <br /><br />Klik anders op BEVESTIGEN om de wijziging te valideren. + + + La modification de la <b>tension nominale</b> du parc de batteries va nécessiter la remise en <i>configuration usine</i> de certains paramètres.<br /><br />Si vous ne souhaitez pas que cette reconfiguration soit effectuée, notamment si vous avez effectué des réglages spécifiques, cliquez sur ANNULER. <br /><br />Sinon, cliquez sur CONFIRMER pour valider le changement. + Als u de <b>nominale spanning</b> van de accubank wijzigt, moeten bepaalde parameters worden teruggezet naar de <i>fabrieksconfiguratie</i>.<br /><br />Als u niet wilt dat deze herconfiguratie wordt uitgevoerd, vooral als u specifieke instellingen heeft gemaakt, klikt u op ANNULEREN. <br /><br />Klik anders op BEVESTIGEN om de wijziging te valideren. + + + Capacité + Vaardigheid + + + Ah + Ah + + + Masquer les paramètres avancés + Geavanceerde instellingen verbergen + + + Afficher les paramètres avancés + Toon geavanceerde instellingen + + + Coefficient correcteur d'entrée de tension + Correctiecoëfficiënt voor spanningsingang + + + + + + + Caractéristiques du parc de batteries + Kenmerken van de batterijbank + + + Durée correspondant à la capacité + Duur overeenkomstig de capaciteit + + + h + uur + + + Capacité 2 + Vaardigheid 2 + + + Durée de capacité 2 + Capaciteitsduur 2 + + + Coefficient de Peukert + Peukert-coëfficiënt + + + Résistance interne + Interne weerstand + + + mΩ + mΩ + + + Soh actuel + Huidige Soh + + + % + % + + + Paramètres de pleine charge + Instellingen voor volledige belasting + + + Tension mini pleine charge + Minimale vollastspanning + + + V + V + + + Courant maxi pleine charge + Maximale stroom bij volledige belasting + + + A + A + + + Temporisation pleine charge + Vertraging bij volledige belasting + + + s + s + + + Efficacité de charge + Oplaadefficiëntie + + + Caractéristiques de charge nulle + Kenmerken van nullast + + + Tension de détection charge nulle + Detectiespanning nullast + + + Temporisation charge nulle + Vertraging nullast + + + Historique + Historisch + + + Nombre de cycles de charge + Aantal oplaadcycli + + + Nombre de décharges complètes + Aantal volledige lozingen + + + Forcer Pleine Charge + Forceer volledige belasting + + + Réinitialiser SOH + SOH opnieuw instellen + + + Réinitialiser Compteurs + Tellers opnieuw instellen + + + Non définie + Niet gedefinieerd + + + Groupe de batteries + Batterij groep + + + Alimentation %1 + Voeding %1 + + + Cette batterie est utilisée par l'évènement ci-dessous.<br />Vous devez modifier ou supprimer cet évènement pour qu'il ne dépende plus de cette batterie avant de pouvoir la supprimer. + Deze batterij wordt gebruikt bij onderstaand evenement.<br /> U moet deze gebeurtenis wijzigen of verwijderen, zodat deze niet langer afhankelijk is van deze batterij, voordat u deze kunt verwijderen. + + + Cette batterie est utilisée par les %1 évènements ci-dessous.<br />Vous devez modifier ou supprimer ces évènements pour qu'ils ne dépendent plus de cette batterie avant de pouvoir la supprimer. + Deze batterij wordt gebruikt door de %1 onderstaande gebeurtenissen.<br /> U moet deze gebeurtenissen wijzigen of verwijderen, zodat ze niet langer afhankelijk zijn van deze boerderij voordat u deze kunt verwijderen. + + + Cette batterie est utilisée par le capteur calculé ci-dessous.<br />Vous devez modifier ou supprimer ce capteur calculé pour qu'il ne dépende plus de cette id_batterie avant de pouvoir la supprimer. + Deze batterij wordt gebruikt door de hieronder berekende sensor.<br /> U moet deze berekende sensor wijzigen of verwijderen, zodat deze niet langer afhankelijk is van deze batterij_id voordat u deze kunt verwijderen. + + + Cette id_batterie est utilisée par les %1 capteurs calculés ci-dessous.<br />Vous devez modifier ou supprimer ces capteurs calculés pour qu'ils ne dépendent plus de cette id_batterie avant de pouvoir la supprimer. + Deze batterij_id wordt gebruikt door de %1 hieronder berekende sensoren.<br /> U moet deze berekende sensoren wijzigen of verwijderen, zodat ze niet langer afhankelijk zijn van deze batterij_id voordat u deze kunt verwijderen. + + + Ok + OK + + + 48V + 48V + + + + config_batteries + + Configuration des batteries + Batterijconfiguratie + + + Aucune batterie n'est encore configurée... + Er is nog geen batterij geconfigureerd... + + + + + + + + + + config_capteur + + Création d'un capteur + Een sensor maken + + + Configuration du capteur + Sensorconfiguratie + + + Nom du capteur + Naam sensor + + + Affectation + Opdracht + + + Masquer sur la page Capteurs + Verberg op de Sensorpagina + + + Créer le capteur + Maak de sensor + + + Enregistrer + Registreer + + + Supprimer + Verwijder + + + Etalonner + Kalibreer + + + Humidité + Vochtigheid + + + GNSS - Latitude + GNSS - Breedtegraad + + + GNSS - Longitude + GNSS - Lengtegraad + + + GNSS - Altitude + GNSS - Hoogte + + + Type de capteur + Sensortype + + + Module + Module + + + Mode du capteur + Sensormodus + + + Groupe de capteurs + Sensorgroep + + + Equation + Vergelijking + + + Non défini + Niet gedefinieerd + + + Entrées Auxiliaires (AUX INPUTS) + Hulpingangen (AUX-INGANGEN) + + + Entrées Niveau (LEVEL SENSORS) + Niveau-ingangen (LEVEL SENSORS) + + + Entrées Tension (VOLTAGE INPUTS) + Spanningsingangen (SPANNINGINGANGEN) + + + Capteurs de température (ONE WIRE) + Temperatuursensoren (ÉÉN DRAAD) + + + Capteurs sur modules + Sensoren op modules + + + Calculé (conditions logiques) + Berekend (logische voorwaarden) + + + <i>Entrée non utilisée</i> + <i>Ingang niet gebruikt</i> + + + Pression Atmosphérique + Luchtdruk + + + Température module + Moduletemperatuur + + + Tension d'entrée module + Module-ingangsspanning + + + Consommation module + Moduleverbruik + + + Consommation ports USB + Verbruik van USB-poort + + + Chocs + Schokken + + + Accélération X + Versnelling + + + Accélération Y + Versnelling Y + + + Accélération Z + Z-versnelling + + + GNSS - SOG<br />Speed Over Ground + GNSS-SOG<br /> Snelheid over de grond + + + GNSS - COG<br />Course Over Ground + GNSS-COG<br /> Over grondrace + + + GNSS - SIV<br />Satellites In View + GNSS-SIV<br /> Satellieten in zicht + + + GNSS - HPA<br />Horizontal Precision Accuracy + GNSS-HPA<br /> Horizontale precisienauwkeurigheid + + + GNSS - VPA<br />Vertical Precision Accuracy + GNSS-VPA<br /> Verticale precisienauwkeurigheid + + + Modem 4G/LTE - RSSI<br />Received Signal Strength Indicator + 4G/LTE-modem - RSSI<br /> Ontvangen signaalsterkte-indicator + + + Modem 4G/LTE - SINR<br />Signal to Interference & Noise Ratio + 4G/LTE-modem - SINR<br /> Signaal-interferentie- en ruisverhouding + + + Normal + Normaal + + + Inversé + Achteruit + + + Tension 0 - 10 V + Spanning 0 - 10 V + + + Résistance 0 - 500 Ohms + Weerstand 0 - 500 Ohm + + + Courant 4 - 20 mA + Stroom 4 - 20 mA + + + Défaut d'isolement + Isolatiefout + + + Ce capteur est utilisé par l'évènement ci-dessous.<br />Vous devez modifier ou supprimer cet évènement pour qu'il ne dépende plus de ce capteur avant de pouvoir le supprimer. + Deze sensor wordt gebruikt bij het onderstaande evenement.<br /> U moet deze gebeurtenis wijzigen of verwijderen, zodat deze niet langer afhankelijk is van deze sensor, voordat u deze kunt verwijderen. + + + Ce capteur est utilisé par les %1 évènements ci-dessous.<br />Vous devez modifier ou supprimer ces évènements pour qu'ils ne dépendent plus de ce capteur avant de pouvoir le supprimer. + Deze sensor wordt gebruikt door de %1 onderstaande gebeurtenissen.<br /> U moet deze gebeurtenissen wijzigen of verwijderen, zodat ze niet langer afhankelijk zijn van deze sensor voordat u deze kunt verwijderen. + + + Ce capteur est utilisé par le capteur calculé ci-dessous.<br />Vous devez modifier ou supprimer ce capteur calculé pour qu'il ne dépende plus de ce capteur avant de pouvoir le supprimer. + Deze sensor wordt gebruikt door de hieronder berekende sensor.<br /> U moet deze berekende sensor wijzigen of verwijderen, zodat deze niet langer afhankelijk is van deze sensor voordat u deze kunt verwijderen. + + + Ce capteur est utilisé par les %1 capteurs calculés ci-dessous.<br />Vous devez modifier ou supprimer ces capteurs calculés pour qu'ils ne dépendent plus de ce capteur avant de pouvoir le supprimer. + Deze sensor wordt gebruikt door de hieronder berekende %1 sensoren.<br /> U moet deze berekende sensoren wijzigen of verwijderen, zodat ze niet langer afhankelijk zijn van deze sensor voordat u deze kunt verwijderen. + + + %1 : Non définie + %1 : Niet gedefinieerd + + + %1 : %2 + %1 : %2 + + + Libellé du capteur pour la valeur %1 + Sensorlabel voor waarde %1 + + + Entrées NMEA2000 + NMEA2000-vermeldingen + + + + config_capteur_calcule_booleen + + Equation du capteur calculé [%1] + Berekende sensorvergelijking [%1] + + + Enregistrer + Opnemen + + + Supprimer + Verwijder + + + Le nombre de conditions par capteur est limité à %1.<br /><br />Vous ne pouvez pas ajouter de groupe ou de nouvelle condition avant d'en avoir supprimé préalablement. + Het aantal condities per sensor is beperkt tot %1.<br /><br /> U kunt pas een groep of een nieuwe voorwaarde toevoegen nadat u er eerst een heeft verwijderd. + + + Des modifications ont été apportées au capteur<br />mais n'ont pas été enregistrées.<br /><br />Cliquer sur ANNULER pour revenir au menu en cours.<br /><br />Cliquer sur Ok pour sortir sans enregistrer. + Er zijn wijzigingen aangebracht aan de sensor<br /> maar werden niet opgenomen.<br /><br /> Klik op ANNULEREN om terug te keren naar het huidige menu.<br /><br /> Klik op Ok om af te sluiten zonder op te slaan. + + + est actif + is actief + + + est inactif + is inactief + + + Ou + Of + + + Et + En + + + X-Ou + X-Of + + + + config_capteur_calcule_booleen_condition + + Création d'une condition du capteur [%1] + Een sensorvoorwaarde creëren [%1] + + + Type + Vriendelijk + + + Source + Bron + + + Variable + Variabel + + + Test + Test + + + Seuil + Drempelwaarde + + + Créer la condition + Conditie creëren + + + Enregistrer + Opnemen + + + Non défini + Niet gedefinieerd + + + Circuit + Circuit + + + Capteur + Sensor + + + Réservoir + Reservoir + + + Batterie + Accu + + + Actif + Actief + + + Inactif + Inactief + + + &lt; au seuil + <drempel + + + &le; au seuil + ≤ bij drempel + + + = au seuil + = op de drempel + + + &ge; au seuil + ≥ bij drempel + + + &gt; au seuil + > op de drempel + + + + config_capteurs + + Configuration des capteurs + Sensorconfiguratie + + + Aucun capteur n'est encore configuré... + Er is nog geen sensor geconfigureerd... + + + + + + + + + + config_circuit + + Configuration du circuit + Circuitconfiguratie + + + Nom du circuit + Naam circuit + + + Affectation + Opdracht + + + Circuit renfort + Versterkingscircuit + + + Mode de commande + Besturingsmodus + + + Vitesse de démarrage/arrêt + Start-/stopsnelheid + + + Seuil de disjonction + Uitschakeldrempel + + + Vitesse de disjonction + Ontkoppelingssnelheid + + + Filtrage du courant consommé + Huidige filtering + + + Masquer sur la page d'accueil + Verbergen op startpagina + + + Créer le circuit + Het circuit maken + + + Enregistrer + Registreer + + + L'affectation du circuit vient d'être modifiée alors que le circuit était actif. +Avant d'effectuer ce changement, le circuit a été passé sur OFF. + +Pensez à le réactiver si besoin... + De circuittoewijzing is zojuist gewijzigd terwijl het circuit actief was. + Voordat deze wijziging werd aangebracht, was het circuit UITGESCHAKELD. + + Vergeet niet om het indien nodig opnieuw te activeren... + + + Supprimer + Verwijder + + + Aucun + Geen + + + ShipPower812 [@ %1] + ShipPower812 [@ %1] + + + ShipPower4AC [@ %1] + ShipPower4AC [@ %1] + + + ShipPower8DC [@ %1] + ShipPower8DC [@ %1] + + + Circuit %1 + Circuit %1 + + + Groupe de circuits + Circuitgroep + + + %1 - %2 + %1 - %2 + + + Non affecté + Niet-toegewezen + + + On-Off + Aan-uit + + + On-Off progressif + Progressief aan-uit + + + Variateur + Dimschakelaar + + + Aucun filtrage + Geen filtering + + + Très faible + Zeer laag + + + Faible + Laag + + + Moyen + Medium + + + Elevé + Hoog + + + Très élevé + Zeer hoog + + + Très rapide + Zeer snel + + + Rapide + Snel + + + Moyenne + Gemiddeld + + + Lente + Langzaam + + + Très lente + Zeer langzaam + + + 15 secondes + 15 seconden + + + 1 minute + 1 minuut + + + 5 minutes + 5 minuten + + + 15 minutes + 15 minuten + + + 1 heure + 1 uur + + + 4 heures + 4 uur + + + L'utilisation d'un circuit de renfort rend l'utilisation du mode de commande [Variateur] impossible.<br /><br />Le mode de commande vient donc d'être ramené à [On-Off Progressif]. + Het gebruik van een versterkingscircuit maakt het onmogelijk om de regelmodus [Dimmer] te gebruiken.<br /><br />De regelmodus is daarom zojuist teruggezet naar [Progressive On-Off]. + + + Commande impulsionnelle + Impuls controle + + + Non + Geen + + + 1 seconde + 1 seconde + + + 2 secondes + 15 seconden {2 ?} + + + 5 secondes + 15 seconden {5 ?} + + + 30 secondes + 30 seconden + + + 45 secondes + 15 seconden {45 ?} + + + Ce circuit est utilisé pour la commande du moteur.<br />Vous devez d'abord affecter la commande moteur à un autre circuit avant de pouvoir supprimer celui-ci. + Dit circuit wordt gebruikt voor motorbesturing.<br /> Voordat u dit circuit kunt verwijderen, moet u de motorbesturing eerst aan een ander circuit toewijzen. + + + Ce circuit est utilisé par l'évènement ci-dessous.<br />Vous devez modifier ou supprimer cet évènement pour qu'il ne dépende plus de ce circuit avant de pouvoir le supprimer. + Dit circuit wordt gebruikt door het onderstaande evenement.<br /> U moet deze gebeurtenis wijzigen of verwijderen, zodat deze niet langer afhankelijk is van dit circuit, voordat u deze kunt verwijderen. + + + Ce circuit est utilisé par les %1 évènements ci-dessous.<br />Vous devez modifier ou supprimer ces évènements pour qu'ils ne dépendent plus de ce circuit avant de pouvoir le supprimer. + Dit circuit wordt gebruikt door de %1 onderstaande gebeurtenissen.<br /> U moet deze gebeurtenissen wijzigen of verwijderen, zodat ze niet langer afhankelijk zijn van dit circuit voordat u deze kunt verwijderen. + + + Ce circuit est utilisé par le capteur calculé ci-dessous.<br />Vous devez modifier ou supprimer ce capteur calculé pour qu'il ne dépende plus de ce circuit avant de pouvoir le supprimer. + Dit circuit wordt gebruikt door de hieronder berekende sensor.<br /> U moet deze berekende sensor wijzigen of verwijderen, zodat deze niet langer afhankelijk is van dit circuit, voordat u deze kunt verwijderen. + + + Ce circuit est utilisé par les %1 capteurs calculés ci-dessous.<br />Vous devez modifier ou supprimer ces capteurs calculés pour qu'ils ne dépendent plus de ce circuit avant de pouvoir le supprimer. + Dit circuit wordt gebruikt door de hieronder berekende %1-sensoren.<br /> Voordat u deze kunt verwijderen, moet u deze berekende sensoren wijzigen of verwijderen, zodat ze niet langer afhankelijk zijn van dit circuit. + + + + config_circuits + + Configuration des circuits + Circuitconfiguratie + + + Pack de batteries : + Batterij : + + + Aucun capteur n'est encore configuré... + Er is nog geen sensor geconfigureerd... + + + Oui + Ja + + + Non + Geen + + + Le module n'est affecté à aucune batterie... + De module is niet toegewezen aan een batterij... + + + Circuit non utilisé + Circuit niet gebruikt + + + Circuits Non Affectés + Onaangetaste circuits + + + Ce circuit est configuré comme renfort du circuit <b>%1</b> et ne peut donc pas être configuré individuellement.<br /><br />Merci de cliquer sur le circuit <b>%1</b> de ce même module pour accéder à leurs paramètres communs<br />(y compris pour supprimer le circuit de renfort actuel). + Dit circuit is geconfigureerd als back-up voor circuit <b>%1</b> en kan daarom niet afzonderlijk worden geconfigureerd.<br /><br />Klik op circuit <b>%1</b> in deze zelfde module om toegang te krijgen tot hun gemeenschappelijke parameters<br />(inclusief het verwijderen van het huidige back-up circuit). + + + Type de carte inconnu... + Onbekend kaarttype... + + + Le module <br /><b>%1</b><br /> n'est affecté à aucun pack de batteries. <br /><br />Souhaitez-vous laisser la configuration en l'état ? + De module<br /> <b>%1</b><br /> is aan geen enkel accupakket toegewezen. <br /><br />Wilt u de configuratie ongewijzigd laten? + + + Les modules suivants ne sont affectés à aucun pack de batteries :<br /><b>%1</b><br /><br /><br />Souhaitez-vous laisser la configuration en l'état ? + De volgende modules zijn aan geen enkel accupakket toegewezen:<br /> <b>%1</b><br /><br /><br /> Wilt u de configuratie ongewijzigd laten? + + + + config_event + + Création d'un évènement + Een evenement maken + + + Configuration de l'évènement + Configuratie van evenementen + + + Nom de l'évènement + Evenement naam + + + Type de la source + Bron Type + + + Source + Bron + + + Variable de la source + Bronvariabele + + + Déclenchement si + Geactiveerd als + + + Seuil de déclenchement + Triggerpunt + + + Temporisation de déclenchement + Vertraging activeren + + + s + s + + + Masquer sur la page d'accueil + Verbergen op startpagina + + + Conditions horaire + Tijdsomstandigheden + + + Le nombre maximal de conditions horaires [%1] est atteint : ajout impossible... + Het maximale aantal tijdsvoorwaarden [%1] is bereikt: optelling onmogelijk... + + + Aucune condition horaire n'est configurée pour cet évènement... + Er zijn geen tijdsomstandigheden geconfigureerd voor deze gebeurtenis... + + + Signalisation + Signalering + + + Alarme sonore + Hoorbaar alarm + + + La validation des alarmes sonores a nécessité de valider également l'affichage des messages liés à cet évènement.<br /><br />Cet affichage est en effet nécessaire au fonctionnement des alarmes sonores, afin de pouvoir les acquitter. + Voor het valideren van de hoorbare alarmen moest ook de weergave van berichten met betrekking tot deze gebeurtenis worden gevalideerd.<br /><br /> Deze weergave is namelijk noodzakelijk voor de werking van de akoestische alarmen, om deze te kunnen bevestigen. + + + Alarme sur LED + Alarm op LED + + + La validation des alarmes sur LED a nécessité de valider également l'affichage des messages liés à cet évènement.<br /><br />Cet affichage est en effet nécessaire au fonctionnement des alarmes sur LED, afin de pouvoir les acquitter. + Voor het valideren van alarmen op LED was ook het valideren van de weergave van berichten met betrekking tot deze gebeurtenis vereist.<br /><br /> Deze weergave is namelijk noodzakelijk voor het functioneren van de LED-alarmen, om deze te kunnen bevestigen. + + + Alarme sur sortie(s) de soutien + Alarm op ondersteuningsuitgang(en) + + + La validation des alarmes sur sortie(s) de soutien a nécessité de valider également l'affichage des messages liés à cet évènement.<br /><br />Cet affichage est en effet nécessaire au fonctionnement des alarmes sur sortie(s) de soutien, afin de pouvoir les acquitter. + Voor het valideren van alarmen op ondersteuningsuitgang(en) was ook het valideren van de weergave van aan deze gebeurtenis gekoppelde berichten vereist.<br /><br /> Deze weergave is namelijk noodzakelijk voor het in werking stellen van alarmen op steunuitgang(en), om deze te kunnen bevestigen. + + + Alarme sur la source + Alarm op bron + + + Affichage message sur ShipBase + Berichtenweergave op ShipBase + + + La dévalidation de l'affichage des messages a nécessité de dévalider également :<ul><li>les alarmes sonores,</li><li>les alarmes sur led</li><li>et les alarmes sur sortie(s) de soutien</li></ul><br />L'affichage de message est en effet nécessaire à leur fonctionnement, afin de pouvoir les acquitter. + Als u de weergave van berichten uitschakelt, moet u ook devalideren:<ul><li> hoorbare alarmen,</li><li> LED-alarmen</li><li> en alarmen op ondersteuningsuitgang(en)</li></ul><br /> De berichtenweergave is namelijk noodzakelijk voor de werking ervan, om ze te kunnen bevestigen. + + + Texte du message à afficher + Berichttekst om weer te geven + + + Emission SMS + SMS-transmissie + + + Texte du SMS à envoyer + Tekst van de te verzenden sms + + + Emission Email + E-mailverzending + + + Texte de l'email à envoyer + Tekst van de te verzenden e-mail + + + Action sur circuits + Actie op circuits + + + Aucune + Geen + + + Le circuit "bascule" + Het “toggle”-circuit + + + Le circuit passe à OFF + Het circuit gaat UIT + + + Le circuit passe à ON + Het circuit gaat AAN + + + Le nombre de circuits commandés par un évènement est limité à %1.<br /><br />Vous ne pouvez pas ajouter d'action sur un nouveau circuit avant d'en avoir supprimé préalablement. + Het aantal circuits dat door een gebeurtenis wordt bestuurd, is beperkt tot %1.<br /><br /> U kunt geen actie aan een nieuw circuit toevoegen voordat u er eerder een hebt verwijderd. + + + Créer l'évènement + Maak de gebeurtenis aan + + + Enregistrer + Opnemen + + + Supprimer + Verwijder + + + Non défini + Niet gedefinieerd + + + Condition horaire seule + Alleen tijdsvoorwaarde + + + Circuit + Circuit + + + Capteur + Sensor + + + Réservoir + Reservoir + + + Batterie + Accu + + + Passage à <b>actif</b> + Schakel over naar <b>actief</b> + + + Passage à <b>inactif</b> + Overschakelen naar <b>inactief</b> + + + &lt; au seuil + &lt; bij drempel + + + &le; au seuil + &le; bij drempel + + + = au seuil + = op de drempel + + + &ge; au seuil + &ge; bij drempel + + + &gt; au seuil + &gt; bij drempel + + + + config_events + + Configuration des évènements + Gebeurtenissen configureren + + + Aucun évènement n'est encore configuré... + Er zijn nog geen evenementen geconfigureerd... + + + 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. + Het totale aantal gebeurtenissen is beperkt tot %1.<br /><br /> Je kunt geen nieuwe gebeurtenis toevoegen voordat je er eerder een hebt verwijderd. + + + Sur circuits + Op circuits + + + Sur capteurs + Op sensoren + + + Sur réservoirs + Op tanks + + + Sur batteries + Op batterijen + + + Horaire seulement + Alleen schema + + + + config_groupe_elements + + Création d'un groupe + Een groep maken + + + Modification d'un groupe + Een groep wijzigen + + + Nom du groupe + Naam groep + + + Créer le groupe + Een groep maken + + + Enregistrer + Registreer + + + Supprimer + Verwijder + + + capteurs + sensoren + + + circuits + circuits + + + 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). + Deze groep is de laatste die nog geldig is.<br /><br />Je kunt deze alleen verwijderen nadat je minstens één andere groep hebt gemaakt (het is niet mogelijk om zonder %1 groepen te werken). + + + Ce groupe comprend encore %1 %2.<br /><br />Il est nécessaire d'affecter ces %2 à un autre groupe avant de pouvoir le supprimer. + Deze groep bevat nog %1 %2.<br /><br />Deze %2 moet worden toegewezen aan een andere groep voordat hij kan worden verwijderd. + + + 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. + Deze groep bevat nog %1 %2,<br />inclusief %3 geconfigureerd als "verborgen".<br /><br />Deze %2 moet worden toegewezen aan een andere groep voordat deze kan worden verwijderd. + + + batteries + batterijen + + + réservoirs + tanks + + + + config_image_accueil + + Image d'accueil + Thuis afbeelding + + + Aucune image n'a encore été chargée... + Er zijn nog geen afbeeldingen geladen... + + + Sélectionner l'image par défaut + Selecteer standaardafbeelding + + + Sélectionner cette image + Selecteer deze afbeelding + + + Copier + Kopiëren + + + Supprimer + Verwijder + + + Ejection + Uitwerpen + + + Insérer une clé USB dans le port <u>du bas</u>, à droite + Plaats een USB-stick in de poort <u>rechtsonder</u> + + + Vous pouvez retirer la clé en toute sécurité... + U kunt de sleutel veilig verwijderen... + + + Seuls les fichiers de type '.jpg' ou '.png' de taille inférieure à %1 sont autorisés. + Alleen bestanden van het type '.jpg' of '.png' met een grootte kleiner dan %1 zijn toegestaan. + + + La clé USB a été <i>éjectée</i> automatiquement.<br />Vous pouvez la retirer dès maintenant en toute sécurité... + Het USB-station werd automatisch <i>uitgeworpen</i> .<br /> Je kunt het nu veilig verwijderen... + + + USB Arrière + USB-achterkant + + + Spare + Reserve + + + USB Avant + USB-voorzijde + + + Touch pad + Touchpad + + + La clé USB a été retirée sans avoir préalablement été <i>éjectée</i> !<br />Cela peut conduire à des pertes de données sur la clé, voire sur ShipHeart.<br /><br />Lors de vos prochaines utilisations, pensez à <i>éjecter</i> la clé avec le bouton en haut de page avant de la retirer... Merci ! + De USB-stick is verwijderd zonder eerst te zijn <i>uitgeworpen</i> !<br /> Dit kan leiden tot gegevensverlies op de sleutel of zelfs op ShipHeart.<br /><br /> De volgende keer dat u de sleutel gebruikt, vergeet dan niet om de sleutel <i>uit te werpen</i> met de knop bovenaan de pagina voordat u deze verwijdert... Dankjewel ! + + + + config_installation + + Configuration de l'installation + Installatie configuratie + + + Raison sociale + Sociale reden + + + N° & Rue + Nr. & Straat + + + Complément d'adresse + Extra adres + + + Code postal + Postcode + + + Ville + Stad + + + Nom du contact + contactnaam + + + Téléphone + Telefoon + + + Email + E-mail + + + Site web + Website + + + Enregistrer + Opnemen + + + Rapports + Rapporten + + + + config_koriolan + + Accès réservé Koriolan + Gereserveerde toegang Koriolan + + + Client spécifique + Specifieke klant + + + Enregistrer + Registreer + + + Nombre jours avant suppression historique + Aantal dagen voordat de geschiedenis wordt verwijderd + + + Nombre jours avant suppression mesures + Aantal dagen voor verwijderingsmaatregelen + + + Période de sauvegarde BDD + DB back-up periode + + + Période de vérification download + Verificatieperiode downloaden + + + Date de dernier archivage mesures + Datum laatste archivering van metingen + + + Aucune spécificité + Geen specificiteit + + + Client Suncy Concept + Suncy Concept klant + + + Mode de mise à jour des firmwares + Firmware-updatemodus + + + Tests matériel + Hardwaretests + + + Normal (si version installée est antérieure à la version en cours) + Normaal (als de geïnstalleerde versie ouder is dan de huidige versie) + + + Différente (si version installée est différente de version en cours) + Anders (als de geïnstalleerde versie anders is dan de huidige versie) + + + Toujours (à utiliser avec modération...) + Altijd (gebruik met mate...) + + + + config_module + + Emplacement du module à bord + Modulelocatie aan boord + + + Commentaires + Opmerkingen + + + Modifier + Bewerken + + + Localiser le module + Zoek de module + + + Paramètres du module [%1] + Module-instellingen [%1] + + + Paramètres du module [%1] à l'adresse [%2] + Parameters van module [%1] op adres [%2] + + + N° de série + Serienummer + + + Nom du firmware + Firmware naam + + + Version du firmware + Firmwareversie + + + Version matérielle + Hardware Versie + + + Résistance de terminaison + Afsluitweerstand + + + Oui + Ja + + + Non + Geen + + + CRC du firmware + Firmware CRC + + + <i>--- Circuit non affecté ---</i> + <i>--- Circuit niet beïnvloed ---</i> + + + [renfort] + [versterking] + + + Affectations + Opdrachten + + + <i>--- Aucune batterie affectée ---</i> + <i>--- Geen batterij aangetast ---</i> + + + Affectation + Opdracht + + + Version processeur + Processorversie + + + Courant de masses sur réseau + Massastroom op het netwerk + + + + config_module_modification + + Configuration du module [%1] à l'adresse [%2] + Configuratie van module [%1] op adres [%2] + + + Emplacement du module à bord + Modulelocatie aan boord + + + Commentaires + Opmerkingen + + + Enregistrer + Opnemen + + + Courant de masses max. sur réseau + Max. massastroom op het netwerk + + + A + A + + + + config_ordre_elements + + 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... + Als u een groep wilt verplaatsen, houdt u de muisknop ingedrukt en sleept u de groep.<br />Als u een groep wilt wijzigen of verwijderen, dubbelklikt u op de groep.<br />Als u een groep wilt toevoegen, klikt u op '+'.<br /><br />Opmerking: als er maar één groep is, wordt er geen tabblad weergegeven op de betreffende pagina... + + + Aucun groupe n'est actuellement configuré... + Er zijn momenteel geen groepen geconfigureerd... + + + Aucun élément n'est actuellement configuré... + Er zijn momenteel geen items geconfigureerd... + + + Aucun groupe de capteurs n'est actuellement configuré... + Er zijn momenteel geen sensorgroepen geconfigureerd... + + + Aucun groupe de circuits n'est actuellement configuré... + Er zijn momenteel geen circuitgroepen geconfigureerd... + + + Aucun groupe de batteries n'est actuellement configuré... + Er zijn momenteel geen batterijbanken geconfigureerd... + + + Aucune batterie n'est actuellement affectée à ce groupe... + Er zijn momenteel geen batterijen toegewezen aan deze groep... + + + Affichage des batteries sur la page d'accueil + Batterijen weergeven op de startpagina + + + Aucun capteur n'est actuellement affecté ce groupe... + Er zijn momenteel geen sensoren toegewezen aan deze groep... + + + Affichage des capteurs sur la page d'accueil + Weergave van sensoren op de startpagina + + + Aucun circuit n'est actuellement affecté à ce groupe... + Er zijn momenteel geen circuits toegewezen aan deze groep... + + + Affichage des circuits sur la page d'accueil + Weergave van circuits op de startpagina + + + Aucun groupe de réservoirs n'est actuellement configuré... + Er zijn momenteel geen tankgroepen geconfigureerd... + + + Aucun réservoir n'est actuellement affecté à ce groupe... + Er zijn momenteel geen tanks toegewezen aan deze groep... + + + Affichage des réservoirs sur la page d'accueil + Tanks weergeven op de startpagina + + + + config_page + + Création d'une page + Een pagina maken + + + Configuration de la page + Pagina-instelling + + + Nom de la page + Paginanaam + + + Opacité de la silhouette + Silhouet dekking + + + Fichier de silhouette + Silhouet bestand + + + Créer la page + Maak de pagina + + + Enregistrer + Opslaan + + + Silhouette + Silhouet + + + Supprimer + Verwijder + + + Aucun + Geen + + + + config_page_edition + + Edition de la page [%1] + De pagina bewerken [%1] + + + Aucun équipement n'est configuré sur cette page pour le moment... + Er is momenteel geen apparatuur geconfigureerd op deze pagina... + + + Page + Pagina + + + Enregistrer + Opslaan + + + 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. + U hebt wijzigingen aangebracht die niet zijn opgeslagen<br />Klik op Annuleren om terug te gaan en ze op te slaan.<br />Klik op OK om af te sluiten zonder op te slaan. + + + + config_page_point + + Création d'un point + Een punt creëren + + + Configuration du point + Puntconfiguratie + + + Type de la source + Bron Type + + + Source + Bron + + + Type de point + Steektype + + + Taille du point + Puntgrootte + + + Enregistrer + Opslaan + + + Créer le point + Creëer het punt + + + Supprimer + Verwijder + + + Non défini + Niet gedefinieerd + + + Capteur + Sensor + + + Circuit + Circuit + + + Réservoir + Reservoir + + + Batterie + Accu + + + Modules + Modules + + + + config_page_silhouette + + Silhouette de la page + Paginasilhouet + + + Aucune image n'a encore été chargée... + Er zijn nog geen afbeeldingen geladen... + + + Aucune image + Geen foto's + + + Sélectionner cette image + Selecteer deze afbeelding + + + Copier + Kopiëren + + + Supprimer + Verwijder + + + Ejection + Uitwerpen + + + Insérer une clé USB dans le port <u>du bas</u>, à droite + Plaats een USB-sleutel in de poort <u>rechtsonder</u> + + + Vous pouvez retirer la clé en toute sécurité... + U kunt de sleutel veilig verwijderen... + + + Seuls les fichiers de type '.jpg' ou '.png' de taille inférieure à %1 sont autorisés. + Alleen bestanden van het type '.jpg' of '.png' met een grootte kleiner dan %1 zijn toegestaan. + + + La clé USB a été <i>éjectée</i> automatiquement.<br />Vous pouvez la retirer dès maintenant en toute sécurité... + Het USB-station werd automatisch <i>uitgeworpen</i> .<br /> Je kunt het nu veilig verwijderen... + + + USB Arrière + USB-achterkant + + + Spare + Reserve + + + USB Avant + USB-voorzijde + + + Touch pad + Touchpad + + + La clé USB a été retirée sans avoir préalablement été <i>éjectée</i> !<br />Cela peut conduire à des pertes de données sur la clé, voire sur ShipHeart.<br /><br />Lors de vos prochaines utilisations, pensez à <i>éjecter</i> la clé avec le bouton en haut de page avant de la retirer... Merci ! + De USB-stick is verwijderd zonder eerst te zijn <i>uitgeworpen</i> !<br /> Dit kan leiden tot gegevensverlies op de sleutel of zelfs op ShipHeart.<br /><br /> De volgende keer dat u de sleutel gebruikt, vergeet dan niet om de sleutel <i>uit te werpen</i> met de knop bovenaan de pagina voordat u deze verwijdert... Dankjewel ! + + + + config_pages + + Configuration des pages + Pagina-instelling + + + Aucune page n'est encore configurée... + Er is nog geen pagina geconfigureerd... + + + + + + + + + Image accueil + Homepage afbeelding + + + + config_pdf + + Ship2net + Ship2net + + + Enregistrer + Opnemen + + + + config_rapports + + Rapports d'installation + Installatierapporten + + + Aucun rapport d'installation n'est encore disponible... + Er is nog geen installatierapport beschikbaar... + + + Nouveau rapport d'installation + Nieuw installatierapport + + + Copier + Kopiëren + + + Déplacer + Verplaatsen, verschuiven + + + Supprimer + Verwijder + + + Ejection + Uitwerpen + + + Insérer une clé USB dans le port <u>du bas</u>, à droite + Plaats een USB-sleutel in de poort <u>rechtsonder</u> + + + Vous pouvez retirer la clé en toute sécurité... + U kunt de sleutel veilig verwijderen... + + + La clé USB a été <i>éjectée</i> automatiquement.<br />Vous pouvez la retirer dès maintenant en toute sécurité... + Het USB-station werd automatisch <i>uitgeworpen</i> .<br /> Je kunt het nu veilig verwijderen... + + + USB Arrière + USB-achterkant + + + Spare + Reserve + + + USB Avant + USB-voorkant + + + Touch pad + Touchpad + + + La clé USB a été retirée sans avoir préalablement été <i>éjectée</i> !<br />Cela peut conduire à des pertes de données sur la clé, voire sur ShipHeart.<br /><br />Lors de vos prochaines utilisations, pensez à <i>éjecter</i> la clé avec le bouton en haut de page avant de la retirer... Merci ! + De USB-stick is verwijderd zonder eerst te zijn <i>uitgeworpen</i> !<br /> Dit kan leiden tot gegevensverlies op de sleutel of zelfs op ShipHeart.<br /><br /> De volgende keer dat u de sleutel gebruikt, vergeet dan niet om de sleutel <i>uit te werpen</i> met de knop bovenaan de pagina voordat u deze verwijdert... Dankjewel ! + + + Le rapport d'installation<br /><br /><b>%1</b><br /><br />a été généré. + Het installatierapport<br /><br /> <b>%1</b><br /><br /> werd gegenereerd. + + + + config_reseau_ethernet_wifi + + Réseau Ethernet & Wifi + Ethernet- en wifi-netwerk + + + Modifier + Bewerken + + + Ethernet + Ethernet + + + Adresse IP + IP adres + + + Non connecté + Niet aangesloten + + + Connexion à un réseau existant + Verbinding maken met een bestaand netwerk + + + Etat + Status + + + On + ON + + + Off + OFF + + + Nom du réseau [SSID] + Netwerk naam (SSID] + + + Génération d'un réseau spécifique + Genereren van een specifiek netwerk + + + Canal + Kanaal + + + + config_reseau_k_bus + + Réseau ShipHeart + ShipHeart-netwerk + + + Modules physiquement présents + Modules fysiek aanwezig + + + %1 - %2 + %1 - %2 + + + Modules utilisés par la configuration actuelle + Modules die worden gebruikt door de huidige configuratie + + + [@ %1] : %2 + [@ %1] : %2 + + + La configuration actuelle ne fait appel à aucun autre module que ShipBase... + De huidige configuratie gebruikt geen andere module dan ShipBase... + + + Module non utilisé en configuration + Module niet gebruikt in configuratie + + + [renfort] + [versterking] + + + Enregistrer + Opnemen + + + Retour + Rug + + + Quitter + Verlaten + + + Aucune modification n'a été apportée à la configuration actuelle.<br />Celle-ci contient toujours des anomalies !<br /><br /><br />Souhaitez-vous :<br />Poursuivre les modifications [%1]<br />Quitter ce menu sans enregistrer les modifications [%2] + Er zijn geen wijzigingen aangebracht in de huidige configuratie.<br />Deze bevat nog steeds afwijkingen!<br /><br /><br />Wilt u het volgende doen:<br />Doorgaan met het aanbrengen van wijzigingen [%1 ]<br / >Dit menu verlaten zonder de wijzigingen op te slaan [%2] + + + La configuration actuelle contient toujours des anomalies !<br /><br /><br />Souhaitez-vous :<br />Enregistrer cette nouvelle configuration et quitter ce menu [%1]<br />Poursuivre les modifications [%2]<br />Quitter ce menu sans enregistrer les modifications [%3] + De huidige configuratie bevat nog steeds afwijkingen!<br /><br /><br />Wilt u:<br />Deze nieuwe configuratie opslaan en dit menu afsluiten [%1]<br />Doorgaan met wijzigingen [%2 ]<br />Dit menu verlaten zonder de wijzigingen op te slaan [%3] + + + La configuration actuelle est correcte <br />mais n'a pas encore été enregistrée.<br /><br /><br />Souhaitez-vous :<br />Enregistrer cette nouvelle configuration et quitter ce menu [%1]<br />Poursuivre les modifications [%2]<br />Quitter ce menu sans enregistrer les modifications [%3] + De huidige configuratie is correct<br />maar is nog niet opgeslagen.<br /><br /><br />Wilt u:<br />Deze nieuwe configuratie opslaan en dit menu verlaten [%1] < br />Doorgaan met wijzigingen [%2]<br />Dit menu verlaten zonder wijzigingen op te slaan [%3] + + + + config_reseau_nmea + + Réseau NMEA2000 + NMEA2000-netwerk + + + Aucun PGN n'a encore été détecté sur le réseau NMEA2000... + Er is nog geen PGN gedetecteerd op het NMEA2000-netwerk... + + + PGN non affecté + PGN niet toegewezen + + + + config_reseau_one_wire + + Réseau One Wire + Eén draadnetwerk + + + Aucune sonde n'est encore installée... + Er is nog geen sonde geïnstalleerd... + + + 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. + Er is momenteel kortsluiting gedetecteerd in de One Wire-bus. <br />Deze toestand brengt geen enkel gevaar met zich mee, maar verhindert het functioneren ervan. <br /><br />Controleer de betreffende bedrading totdat deze melding verdwijnt. + + + Type inconnu + Onbekend type + + + Sonde non affectée + Sonde niet toegewezen + + + + config_reseau_one_wire_modification + + Configuration de la sonde [%1] + Sondeconfiguratie [%1] + + + Emplacement de la sonde + Locatie van de sonde + + + Enregistrer + Opnemen + + + + config_reseau_wifi_ap + + Configuration Wifi en mode AP + Wifi-configuratie in AP-modus + + + Etat + Status + + + Nom du réseau (SSID) + Netwerknaam (SSID) + + + Mot de passe d'accès au réseau + Wachtwoord voor netwerktoegang + + + Canal + Kanaal + + + Adresse IP + IP adres + + + Non connecté + Niet aangesloten + + + Enregistrer + Opnemen + + + Off + OFF + + + On + ON + + + Canal %1 - [%2GHz] + Kanaal %1 - [%2GHz] + + + Le nom du réseau (SSID) doit comprendre entre 1 et 32 caractères. <br />Merci d'entrer un nom valide. + De netwerknaam (SSID) moet tussen 1 en 32 tekens lang zijn. <br />Voer een geldige naam in. + + + 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. + Het wachtwoord voor netwerktoegang moet tussen 8 en 63 tekens lang zijn. <br />Voer een geldig wachtwoord in. + + + 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. + De netwerknaam (SSID) mag alleen bestaan uit:<br />- hoofdletters [A - Z],<br />- kleine letters [a - z],<br />- cijfers [0 - 9]<br />- speciale tekens [%1].<br /><br />Voer een geldige naam in. + + + 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. + Het wachtwoord voor netwerktoegang mag alleen bestaan uit:<br />- hoofdletters [A - Z],<br />- kleine letters [a - z],<br />- cijfers [0 - 9]<br />- speciale tekens [%1].<br /><br />Voer een geldige naam in. + + + + config_reseau_wifi_sta + + Configuration Wifi en mode STA + Wifi-configuratie in STA-modus + + + Etat + Status + + + Réseau + Netwerk + + + Mot de passe d'accès au réseau + Wachtwoord voor netwerktoegang + + + Enregistrer + Opnemen + + + Réseaux connus + Bekende netwerken + + + Off + OFF + + + On + ON + + + Aucun réseau... + Geen netwerk... + + + + config_reseau_wifi_sta_liste + + Liste des réseaux Wifi connus + Lijst met bekende WiFi-netwerken + + + Aucun réseau n'a été détecté... + Geen netwerk gedetecteerd... + + + Oublier tous les réseaux + Vergeet alle netwerken + + + Oublier ce réseau + Vergeet dit netwerk + + + + config_reservoir + + Création d'un réservoir + Aanleg van een reservoir + + + Configuration du réservoir + Tankconfiguratie + + + Nom du réservoir + Naam reservoir + + + Famille de réservoirs + Familie van tanks + + + Type de capteur de niveau + Type niveausensor + + + %1 : Non définie + %1 : Niet gedefinieerd + + + %1 : %2 + %1 : %2 + + + Sonde la plus basse dans le réservoir + Laagste sonde in de tank + + + Non définie + Niet gedefinieerd + + + Logique d'alarme + Alarmlogica + + + Filtrage des mesures + Meting filteren + + + Créer le réservoir + De tank maken + + + Enregistrer + Registreer + + + Supprimer + Verwijder + + + Etalonnage + Kalibratie + + + AUX INPUT %1 + AUX-INVOER %1 + + + LEVEL SENSOR %1 + NIVEAUSENSOR %1 + + + Confirmer + Bevestig + + + Non défini + Niet gedefinieerd + + + Electrodes plongées ou contacts secs + Ondergedompelde elektroden of droge contacten + + + Résistif 0 - 190Ω + Weerstand 0 - 190Ω + + + Résistif 240 - 30Ω + Weerstand 240 - 30Ω + + + Boucle de courant 4 - 20mA + Stroomlus 4 - 20mA + + + Tension 0 - 10V + Spanning 0 - 10V + + + Aucun filtrage + Geen filtering + + + Très faible + Zeer laag + + + Faible + Laag + + + Moyen + Medium + + + Elevé + Hoog + + + Très élevé + Zeer hoog + + + Alerte sur niveau faible + Waarschuwing op laag niveau + + + Alerte sur niveau élevé + Waarschuwing op hoog niveau + + + Capacité du réservoir + Tankinhoud + + + litres + liter + + + Logique des entrées inversée + Omgekeerde ingangslogica + + + La modification du <b>type de capteur</b> va nécessiter la remise en <i>configuration usine</i> de tous les paramètres du réservoir.<br /><br />Si vous ne souhaitez pas que cette reconfiguration soit effectuée, cliquez sur ANNULER. <br /><br />Sinon, cliquez sur CONFIRMER pour valider le changement. + Als u het <b>sensortype</b> wijzigt, moeten alle tankparameters worden teruggezet naar <i>de fabrieksinstellingen</i> .<br /><br /> Als u niet wilt dat deze herconfiguratie wordt uitgevoerd, klikt u op ANNULEREN. <br /><br />Klik anders op BEVESTIGEN om de wijziging te valideren. + + + Ce réservoir est utilisé par l'évènement ci-dessous.<br />Vous devez modifier ou supprimer cet évènement pour qu'il ne dépende plus de ce réservoir avant de pouvoir le supprimer. + Deze tank wordt gebruikt bij het onderstaande evenement.<br /> U moet deze gebeurtenis wijzigen of verwijderen, zodat deze niet langer afhankelijk is van deze tank, voordat u deze kunt verwijderen. + + + Ce réservoir est utilisé par les %1 évènements ci-dessous.<br />Vous devez modifier ou supprimer ces évènements pour qu'ils ne dépendent plus de ce réservoir avant de pouvoir le supprimer. + Dit reservoir wordt gebruikt door de %1 onderstaande gebeurtenissen.<br /> Je moet deze gebeurtenissen wijzigen of verwijderen, zodat ze niet langer afhankelijk zijn van deze tank voordat je deze kunt verwijderen. + + + Ce réservoir est utilisé par le capteur calculé ci-dessous.<br />Vous devez modifier ou supprimer ce capteur calculé pour qu'il ne dépende plus de ce réservoir avant de pouvoir le supprimer. + Deze tank wordt gebruikt door de hieronder berekende sensor.<br /> U moet deze berekende sensor wijzigen of verwijderen, zodat deze niet langer afhankelijk is van deze tank, voordat u deze kunt verwijderen. + + + Ce réservoir est utilisé par les %1 capteurs calculés ci-dessous.<br />Vous devez modifier ou supprimer ces capteurs calculés pour qu'ils ne dépendent plus de ce réservoir avant de pouvoir le supprimer. + Deze tank wordt gebruikt door de hieronder berekende %1 sensoren.<br /> U moet deze berekende sensoren wijzigen of verwijderen, zodat ze niet langer afhankelijk zijn van deze tank voordat u deze kunt verwijderen. + + + Résistif 0 - 700Ω + Weerstand 0 - 700Ω + + + + config_reservoirs + + Configuration des réservoirs + Tankconfiguratie + + + Aucun réservoir n'est encore configuré... + Er is nog geen tank geconfigureerd... + + + + + + + + + + config_ship2net + + Ship2net + Ship2net + + + Période des sauvegardes + Back-up periode + + + Mode de validation des mises à jour + Validatiemodus bijwerken + + + Enregistrer + Registreer + + + Jamais + Nooit + + + 30 minutes + 30 minuten + + + 1 heure + 1 uur + + + 2 heures + 2 uur + + + 4 heures + 4 uur + + + 12 heures + 12 uur + + + 24 heures + 24 uur + + + Aucune mise à jour + Geen updates + + + Validation manuelle des mises à jour reçues + Handmatige validatie van ontvangen updates + + + Validation automatique des mises à jour reçues + Automatische validatie van ontvangen updates + + + Période de connexion à Ship2net + Ship2net verbindingsperiode + + + 10 minutes + 10 minuten + + + Accès distant WebGL #1 + WebGL-toegang op afstand #1 + + + Accès distant WebGL #2 + WebGL-toegang op afstand #2 + + + Accès distant WebGL #3 + WebGL-toegang op afstand #3 + + + 2 minutes + 2 minuten + + + Dévalidé + Ongeldig verklaard + + + Valide [port %1] + Geldig [poort %1] + + + + config_specifique_client_suncy + + Configuration spécifique à Suncy Concept + Configuratie specifiek voor Suncy Concept + + + Circuit d'activation moteur + Motor activeringscircuit + + + Nouveau code + Nieuwe code + + + Code d'accès au bateau + Toegangscode boot + + + Répéter le code d'accès + Toegangscode herhalen + + + Enregistrer + Registreer + + + Aucune + Geen + + + [module %1 - circuit %2] %3 + [module %1 - circuit %2] %3 + + + Les deux valeurs saisies doivent être identiques ! + +De plus, le code doit contenir : +- %1 chiffres au minimum +- %2 chiffres au maximum. + De twee ingevoerde waarden moeten identiek zijn! + + Bovendien moet de code het volgende bevatten: + - %1 cijfer minimaal + - %2 cijfers maximaal. + + + Le nouveau code doit contenir : +- %1 chiffres au minimum +- %2 chiffres au maximum. + +Le code saisi ne répond pas à ces critères et sa mise à jour n'est donc pas effectuée. + +Merci de saisir un code au format valide si vous souhaitez le modifier. + De nieuwe code moet het volgende bevatten: + - %1 cijfer minimaal + - %2 cijfers maximaal. + + De ingevoerde code voldoet niet aan deze criteria en wordt daarom niet bijgewerkt. + + Voer een code in een geldig formaat in als u deze wilt wijzigen. + + + + config_valeurs_niveaux + + Aucun point de conversion n'est configuré pour le moment... + Er zijn nog geen conversiepunten geconfigureerd... + + + Courbe usine + Fabriekscurve + + + Enregistrer + Registreer + + + Aucune donnée n'est disponible... + Geen gegevens beschikbaar... + + + 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. + U hebt wijzigingen aangebracht die niet zijn opgeslagen<br />Klik op Annuleren om terug te gaan en ze op te slaan.<br />Klik op OK om af te sluiten zonder op te slaan. + + + Aucun point n'est actuellement configuré pour cette batterie... + Er zijn momenteel geen punten geconfigureerd voor deze batterij... + + + Courbe de conversion de [%1] + Conversiecurve voor [%1] + + + Aucun réservoir n'est actuellement configuré... + Er is momenteel geen tank geconfigureerd... + + + Aucun point n'est actuellement configuré pour cet élément... + Er zijn momenteel geen punten geconfigureerd voor dit element... + + + Courbe de conversion de type INCONNU + Type UNKNOWN conversiecurve + + + La valeur lue sur les electrodes plongées de ce réservoir est incohérente.<br />Vérifier l'ordre de cablage des électrodes sur les entrées auxiliaires à l'arrière de ShipBase. + De waarde die wordt afgelezen op de ondergedompelde elektroden van dit reservoir is inconsistent.<br />Controleer de bedradingsvolgorde van de elektroden op de hulpingangen aan de achterzijde van ShipBase. + + + Le nombre maximal de points d'étalonnage a été atteint (%1 points)<br />Vous ne pouvez pas en ajouter sans en avoir prélablement supprimé. + Het maximale aantal kalibratiepunten is bereikt (%1 punten)<br />U kunt geen kalibratiepunten toevoegen zonder eerst een aantal punten te verwijderen. + + + + config_version + + Version + Versie + + + %1 : %2 + %1 : %2 + + + 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 : + Versie <b>%1</b> is beschikbaar.<br /><br />Het zal automatisch worden geïnstalleerd de volgende keer dat ShipHeart wordt gestart.<br />Tenzij je een van de onderstaande opties kiest: + + + La version <b>%1</b> est disponible.<br /><br />Souhaitez-vous : + Versie <b>%1</b> is beschikbaar.<br /><br />Wilt u : + + + L'installer +maintenant + Installeer het + NU + + + L'installer au prochain démarrage de ShipHeart + Installeer het de volgende keer dat je ShipHeart start + + + Ne jamais l'installer + Installeer het nooit + + + 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 'shipheart.tech' ou de nous contacter à l'adresse 'contact@shipheart.tech'. + Dit product is ontworpen en geproduceerd door Koriolan, dat alle licenties en exploitatierechten heeft op de afbeeldingen, software en patenten die gebruikt zijn voor zowel het ontwerp als de werking. ShipHeart™, Ship2net™ en Koriolan™ zijn geregistreerde handelsmerken van Koriolan. Als u vragen heeft over dit product, bezoek dan 'shipheart.tech' of neem contact met ons op via 'contact@shipheart.tech'. + + + Version du package logiciel + Versie softwarepakket + + + Version de l'application + Toepassingsversie + + + Version de l'interface graphique + Versie grafische interface + + + Version du firmware du modem + Versie modemfirmware + + + Numéro d'IMEI + IMEI-nummer + + + Numéro d'ICCID + ICCID-nummer + + + Numéro d'IMSI + IMSI-nummer + + + Supprimer + Verwijder + + + Si vous confirmez, cette mise à jour sera définitivement supprimée.<br />Cliquez sur Annuler pour revenir en arrière et la conserver. + Als u bevestigt, wordt deze update permanent verwijderd.<br />Klik op Annuleren om terug te gaan en de update te behouden. + + + Installer + Installeren + + + 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 la conserver pour une installation ultérieure. + Als u bevestigt, kan deze update <u>enkele minuten</u> duren, gedurende welke <b>uw ShipHeart-systeem niet toegankelijk zal zijn</b>.<br /><br />U hoeft de update niet te bevestigen installatie alleen als u zich in een veilige situatie bevindt (in de haven, voor anker, etc.) en het verlies van controle over uw boordsystemen gedurende deze periode zonder gevaar is!<br /><br />Klik op Annuleer om terug te gaan en het op te slaan voor latere installatie. + + + + ephemeride + + Ephéméride + Ephemeris + + + Heure d'hiver + Wintertijd + + + Heure d'été + Zomertijd + + + Aube nautique + Nautische dageraad + + + Lever du soleil + Zonsopgang + + + Zénith + Zenith + + + Coucher du soleil + Zonsondergang + + + Crépuscule nautique + Nautische schemering + + + Lune + Maan + + + Latitude + Breedte + + + Longitude + Lengte + + + + etalonnage_capteur + + Etalonnage du capteur [%1] + Sensorkalibratie [%1] + + + Valeur brute actuelle + Huidige brutowaarde + + + Valeur corrigée actuelle (%1) + Huidige gecorrigeerde waarde (%1) + + + Correction + Correctie + + + Enregistrer + Registreer + + + + etalonnage_carte + + Etalonnage du module [%1 - #%2] + Kalibratie van de module [%1 - #%2] + + + Point 1 + Punt 1 + + + Point 2 + Punt 2 + + + Courant de décharge + Ontlaadstroom + + + Courant différentiel + Differentiële stroom + + + Recalculer ce point + Herbereken dit punt + + + Mémoriser ce point + Onthoud dit punt + + + Off + OFF + + + On + ON + + + On (%1 %%) + Op (%1 %%) + + + Enregistrer + Registreer + + + Aide + Help + + + 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 /> + Kalibratie kan niet worden uitgevoerd met twee identieke punten.<br /><br /> + Probeer ten minste één van de twee referentiepunten te wijzigen door de onderstaande circuitregelaars aan te passen.<br /> + + + 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. + Het principe van kalibratie is het vergelijken, op <u>2 verschillende punten</u>, van de differentiële stroomwaarde gemeten door het ShipBS enerzijds en de ontlaadstroom gemeten door het ShipHeart systeem anderzijds. de ontlaadstroom gemeten door het ShipHeart-systeem.<br /> Bijvoorbeeld door het ShipBS tijdens de kalibratie te onderwerpen aan een laag of nulverbruik van stroom (eerste punt) vervolgens een of meer apparaten te bedienen om een verbruik van enkele ampères te verkrijgen indien mogelijk (tweede punt).<br /> <br /><u><b>Zeer belangrijk</b>: er mag geen <b>laadstroom</b> worden toegepast op de ShipBS tijdens de kalibratiefase!</u> Het is daarom essentieel om alle laders, zonneregelaars, enz. los te koppelen van het systeem tijdens de kalibratie. Als je dit niet doet, resulteert dit in onjuiste kalibratiewaarden...<br /><br /> Opmerkingen :<br /> - Alle verbruik moet door het ShipHeart systeem! Je moet er dus voor zorgen dat er geen verbruikers rechtstreeks zijn aangesloten op de op de accubank.<br /> - de stroomwaarden zijn niet belangrijk.<br /> - de stroom op punt 2 mag lager of hoger zijn dan die op punt 1 (maar zo ver mogelijk uit elkaar).<br /> - Het is raadzaam om belastingen te kiezen waarvan het verbruik relatief stabiel is of op zijn minst weinig verandert over een periode van een paar seconden. + + + + fonctions + + Modèle inconnu + Onbekend model + + + Circuit + Circuit + + + Capteur + Sensor + + + Réservoir + Reservoir + + + Batterie + Accu + + + Type inconnu + Onbekend type + + + Consigne + Volgorde + + + Tension + Spanning + + + Courant + Vloeiend + + + Fréquence + Frequentie + + + Puissance + Kracht + + + Energie + Energie + + + Température + Temperatuur + + + Courant différentiel + Differentiële stroom + + + Courant de charge + Belastingsstroom + + + Courant de décharge + Ontlaadstroom + + + SOH (state Of Health) + SOH (gezondheidstoestand) + + + SOC (State Of Charge) + SOC (laadstatus) + + + Autonomie + Autonomie + + + + fonctions_date_heure + + Dimanche + Zondag + + + Lundi + Maandag + + + Mardi + Dinsdag + + + Mercredi + Woensdag + + + Jeudi + Donderdag + + + Vendredi + Vrijdag + + + Samedi + Zaterdag + + + janvier + Januari + + + février + Februari + + + mars + Maart + + + avril + April + + + mai + Mei + + + juin + Juni + + + juillet + Juli + + + août + Augustus + + + septembre + September + + + octobre + Oktober + + + novembre + November + + + décembre + December + + + 1 heure + 1 uur + + + 24 heures + 24 uur + + + 7 jours + 7 dagen + + + 30 jours + 30 dagen + + + Fin de nuit + Einde van de nacht + + + Aube nautique + Nautische dageraad + + + Aube + Ochtendgloren + + + Lever du soleil + Zonsopgang + + + Zénith + Zenith + + + Coucher du soleil + Zonsondergang + + + Crépuscule + Schemering + + + Crépuscule nautique + Nautische schemering + + + Début de nuit + Vroege nacht + + + %1h + %1h + + + Tous les jours + Elke dag + + + + fonctions_historique + + Commande 'OFF' du circuit %1 + OFF' commando voor circuit %1 + + + Commande 'ON' du circuit %1 + AAN'-commando voor circuit %1 + + + Commande à %1 % du circuit %2 + Controle %1% van circuit %2 + + + Le circuit %1 est revenu à son état de fonctionnement normal + Circuit %1 is teruggekeerd naar de normale bedrijfstoestand + + + L'alimentation du circuit %1 a été coupée car sa limite de courant (%2 A) a été dépassée + De voeding van circuit %1 is onderbroken omdat de stroomlimiet (%2 A) is overschreden + + + L'alimentation du circuit %1 a été coupée car les circuits de protection interne ont détecté une anomalie + De stroomtoevoer naar circuit %1 is onderbroken omdat de interne beveiligingscircuits een afwijking hebben gedetecteerd + + + L'alimentation du circuit %1 a été coupée car le seuil de disjonction a été dépassé + De stroomtoevoer naar circuit %1 is onderbroken omdat de uitschakeldrempel is overschreden + + + Le circuit %1 est en court-circuit avec le + batterie + Circuit %1 is kortgesloten met de + batterij + + + L'alimentation du circuit %1 a été coupée car la consommation totale du module a été dépassé + De voeding van circuit %1 is onderbroken omdat het totale verbruik van de module overschreden is + + + Le circuit %1 a été créé + Het circuit %1 is aangemaakt + + + La configuration du circuit %1 a été modifiée + De configuratie van circuit %1 is gewijzigd + + + Le circuit %1 a été supprimé + Circuit %1 is verwijderd + + + La configuration du circuit %1 est invalide car le module sur lequel le circuit est configuré n'est pas présent + De configuratie van circuit %1 is ongeldig omdat de module waarop het circuit is geconfigureerd niet aanwezig is + + + Le circuit %1 a fonctionné trop longtemps (> %2 secondes). Il a donc été désactivé automatiquement. + Circuit %1 heeft te lang gewerkt (> %2 seconden). Het is daarom automatisch gedeactiveerd. + + + Evénement de type CIRCUITS avec code de sous-type inconnu [%1] + CIRCUITS-gebeurtenis met onbekende subtypecode [%1] + + + Le capteur %1 est repassé à l'état normal + Sensor %1 is teruggekeerd naar normale status + + + Le capteur %1 est passé à l'état ALERTE + Sensor %1 is in ALERT-status gegaan + + + Le capteur %1 est passé à l'état ALARME + Sensor %1 is in ALARM gegaan + + + Evénement de type CAPTEURS avec code de sous-type inconnu [%1] + CAPTORS-gebeurtenis met onbekende subtypecode [%1] + + + Le niveau de charge de la batterie %1 est repassé au niveau normal + Laadniveau van batterij %1 is terug op normaal niveau + + + Le niveau de charge de la batterie %1 est passé en dessous du niveau d'alerte + Laadniveau van batterij %1 is gedaald tot onder het waarschuwingsniveau + + + Le niveau de charge de la batterie %1 est passé au-dessus du niveau d'alarme (il est maintenant au niveau d'alerte uniquement) + Laadniveau van batterij %1 is gestegen tot boven het alarmniveau (het is nu alleen op het waarschuwingsniveau) + + + Le niveau de charge de la batterie %1 est passé en-dessous du niveau d'alarme + Laadniveau %1 van de batterij is onder het alarmniveau gedaald + + + Evénement de type BATTERIES avec code de sous-type inconnu [%1] + Gebeurtenis BATTERIJEN met onbekende subtypecode [%1] + + + Le niveau du réservoir %1 est repassé au niveau normal + Tankniveau %1 is terug op normaal niveau + + + Le niveau du réservoir %1 est passé en dessous du niveau d'alerte + Tankniveau %1 is onder het waarschuwingsniveau gezakt + + + Le niveau du réservoir %1 est passé au-dessus du niveau d'alarme (il est maintenant au niveau d'alerte uniquement) + Tankniveau %1 is boven het alarmniveau gestegen (het is nu alleen op het waarschuwingsniveau) + + + Le niveau du réservoir %1 est passé en-dessous du niveau d'alarme + Tankniveau %1 is onder het alarmniveau gezakt + + + Evénement de type RESERVOIRS avec code de sous-type inconnu [%1] + RESERVOIRS voorval met onbekende subtype code [%1] + + + La consigne des ports USB est passée à %1 + Het instelpunt van de USB-poort is gewijzigd in %1 + + + L'état des ports USB est redevenu normal + De status van de USB-poorten is weer normaal + + + Défaut détecté sur les ports USB + Fout in USB-poort gedetecteerd + + + Evénement de type USB avec code de sous-type inconnu [%1] + USB-gebeurtenis met onbekende subtypecode [%1] + + + Evénement de type INCONNU (avec code de sous-type [%1] + UNKNOWN voorval (met subtypecode [%1]) + + + + home + + Démarrage + Start + + + Code inconnu + Onbekende code + + + Aucun circuit n'est configuré pour ce groupe...<br /><br />Si ce groupe n'a pas d'utilité, vous pouvez le supprimer dans le menu [Circuits] des Paramètres Avancés. + Er is geen circuit geconfigureerd voor deze groep...<br /><br /> Als deze groep niet nodig is, kunt u deze verwijderen in het menu [Circuits] van Geavanceerde instellingen. + + + Aucun capteur n'est configuré pour ce groupe...<br /><br />Si ce groupe n'a pas d'utilité, vous pouvez le supprimer dans le menu [Capteurs] des Paramètres Avancés. + Er zijn geen sensoren geconfigureerd voor deze groep...<br /><br /> Als deze groep niet nodig is, kunt u deze verwijderen in het menu [Sensoren] van Geavanceerde instellingen. + + + Aucun réservoir n'est configuré pour ce groupe...<br /><br />Si ce groupe n'a pas d'utilité, vous pouvez le supprimer dans le menu [Réservoirs] des Paramètres Avancés. + Er is geen tank geconfigureerd voor deze groep...<br /><br /> Als deze groep niet nodig is, kunt u deze verwijderen in het menu [Tanks] van Geavanceerde instellingen. + + + Aucun parc de batterie n'est configuré pour ce groupe...<br /><br />Si ce groupe n'a pas d'utilité, vous pouvez le supprimer dans le menu [Batteries] des Paramètres Avancés. + Er is geen batterijbank geconfigureerd voor deze groep...<br /><br /> Als deze groep niet nodig is, kunt u deze verwijderen in het menu [Batterijen] van Geavanceerde instellingen. + + + Cette page est actuellement en travaux. <br />Elle sera rendue disponible très rapidement à travers une mise à jour.<br /><br />Merci de votre patience...<br /><br />L'équipe ShipHeart + Deze pagina is momenteel in aanbouw. <br />Het zal zeer snel beschikbaar worden gemaakt via een update.<br /><br /> Bedankt voor uw geduld...<br /><br /> Het ShipHeart-team + + + Déconnecté + Losgekoppeld + + + Nombre de satellites visibles + Aantal zichtbare satellieten + + + Connecté + Verbonden + + + OFF + OFF + + + ON + ON + + + Niveau + Niveau + + + Actif + Actief + + + Inactif + Inactief + + + <b>%1</b> + <b>%1</b> + + + Firmware de <b>ShipBase</b> + <b>ShipBase-</b> firmware + + + Firmware du <b>ShipPower812</b> à l'adresse <b>%1</b> + <b>ShipPower812</b> -firmware op adres <b>%1</b> + + + Firmware du <b>ShipBS</b> à l'adresse <b>%1</b> + <b>ShipBS</b> -firmware op adres <b>%1</b> + + + Firmware du <b>ShipPower4AC</b> à l'adresse <b>%1</b> + <b>ShipPower4AC</b> -firmware op adres <b>%1</b> + + + Firmware du <b>ShipPower8DC</b> à l'adresse <b>%1</b> + <b>ShipPower8DC</b> -firmware op adres <b>%1</b> + + + Firmware du module à l'adresse <b>%1</b> + Modulefirmware op adres <b>%1</b> + + + Merci de patienter et de ne rien débrancher<br />avant la fin de la mise à jour. + Wees geduldig en koppel niets los.<br /> voordat de update is voltooid. + + + Chargement des mises à jour effectué avec succès !<br /><br />L'activation des nouvelles version est en cours sur tous les modules concernés.<br /><br />Merci de patienter encore quelques secondes... + Updates zijn succesvol geladen!<br /><br /> De activering van nieuwe versies is bezig voor alle betrokken modules.<br /><br /> Wacht nog een paar seconden... + + + ShipHeart va redémarrer pour effectuer une mise à jour.<br /><br />Cette opération va prendre quelques minutes au maximum.<br />Merci de patienter et de ne rien débrancher jusqu'au redémarrage final... + ShipHeart zal opnieuw opstarten om een update uit te voeren.<br /><br /> Deze handeling duurt maximaal enkele minuten.<br /> Wacht alstublieft en koppel niets los tot de laatste keer opnieuw opstarten... + + + Votre système ShipHeart est dorénavant équipé de la version<br /><br /><b>%1</b><br /><br />(la version précédente était la %2) + Uw ShipHeart-systeem is nu uitgerust met de versie<br /><br /> <b>%1</b><br /><br /> (vorige versie was %2) + + + Le nombre de modules détectés sur le réseau ShipHeart est insuffisant par rapport à la configuration du bateau.<br /><br />Vérifiez les connexions entre le module <b>%1</b> à la <b>position @%2</b> %3 et le module <b>%4</b> suivant%5<br /><br />Vous pouvez visualiser l'état complet du réseau ShipHeart et les anomalies détectées dans le menu 'Réseau > ShipHeart' dans les Paramètres Avancés + Het aantal gedetecteerde modules op het ShipHeart-netwerk is onvoldoende vergeleken met de configuratie van de boot.<br /><br /> Controleer de verbindingen tussen module <b>%1</b> op <b>positie @%2</b> %3 en module <b>%4</b> naast %5<br /><br /> U kunt de volledige ShipHeart-netwerkstatus en gedetecteerde afwijkingen bekijken in het menu 'Netwerk > ShipHeart' in Geavanceerde instellingen + + + Le modules détecté en <b>position @%1</b> est un <b>%2</b>. Cela ne correspond pas à la configuration actuelle du bateau (<b>%3</b>).<br /><br />Cela peut provenir de l'ajout, de la suppression ou d'un déplacement de module.<br /><br />Vous pouvez visualiser toutes les anomalies détectées et les corriger dans le menu 'Réseau > ShipHeart' dans les Paramètres Avancés + De module die is gedetecteerd op <b>positie @%1</b> is een <b>%2</b> . Dit komt niet overeen met de huidige configuratie van de boot ( <b>%3</b> ).<br /><br /> Dit kan komen door het toevoegen, verwijderen of verplaatsen van een module.<br /><br /> U kunt alle gedetecteerde afwijkingen bekijken en corrigeren in het menu 'Netwerk > ShipHeart' in Geavanceerde instellingen + + + + home_accueil + + Bienvenue à bord de + Welkom aan boord + + + + home_suncy + + L'accès au bateau est protégé. +Merci d'entrer votre code de déverrouillage pour y accéder... + De toegang tot de boot is beveiligd. + Voer uw ontgrendelingscode in om toegang te krijgen... + + + + journal_de_bord + + Tous + Alle + + + Batteries + Batterijen + + + Capteurs + Sensoren + + + Circuits + Circuits + + + Réservoirs + Tanks + + + Système + Systeem + + + Ports USB + USB-poorten + + + Journal de bord + Logboek + + + Aucun type n'est configuré... + Er is geen type geconfigureerd... + + + %1<br /><br /><br />%2 + %1<br /><br /><br />%2 + + + Aucune entrée d'historique n'est disponible pour cette sélection... + Er zijn geen historie-items beschikbaar voor deze selectie... + + + Toutes + Alle + + + + main + + Type d'installation : +0 : ShipBase standard, +1 : écran déporté + Installatietype: + 0: Standaard scheepsbasis, + 1: extern scherm + + + valeur + waarde + + + Adresse IPv4 de ShipBase dans le cas d'une installation déportée + ShipBase IPv4-adres voor installatie op afstand + + + xxx:xxx:xxx:xxx + xxx:xxx:xxx:xxx + + + Taille de l'écran en pouces : +7, +10 (ShipBase standard), +22 + Schermgrootte in inches: + 7, + 10 (standaard ShipBase), + 22 + + + Original + Origineel + + + Sombre + Donker + + + Métallique + Metalen + + + Triangles + Driehoeken + + + Sable + Zand + + + Thème 5 + Thema 5 + + + Thème 6 + Thema 6 + + + Thème 7 + Thema 7 + + + Thème 8 + Thema 8 + + + + page_personnalisee + + <i>--- Circuit non affecté ---</i> + <i>--- Circuit niet beïnvloed ---</i> + + + [renfort] + [versterking] + + + <i>--- Aucune batterie affectée ---</i> + <i>--- Geen batterij aangetast ---</i> + + + + parametres + + Paramètres + Parameters + + + Langue + Taal + + + Températures + Temperaturen + + + Volumes + Volumes + + + Affichage + Weergave + + + Date et heure + Datum en tijd + + + Protection + Bescherming + + + Son + Geluid + + + Luminosité + Helderheid + + + Economiseur d'écran : désactivé + Schermbeveiliging: uitgeschakeld + + + Economiseur d'écran : normal + Schermbeveiliging: normaal + + + Flash LEDs : désactivé + Flash-LED's: uitgeschakeld + + + Flash LEDs : normal + Flash-LED's: normaal + + + Nettoyage de l'écran + Het scherm schoonmaken + + + Heure d'été + Zomertijd + + + Heure d'hiver + Wintertijd + + + Verrouiller le bateau + De boot vergrendelen + + + + parametres_avances + + Paramètres avancés + Geavanceerde instellingen + + + Circuits + Circuits + + + Réservoirs + Tanks + + + Batteries + Batterijen + + + Capteurs + Sensoren + + + Vos paramètres + Uw instellingen + + + Votre installation + Uw installatie + + + Système + Systeem + + + Affichage + Weergave + + + Audio + Audio + + + Ship2net + Ship2net + + + Accès au paramètres + Toegang tot parameters + + + Configuration ShipRS + ShipRS configuratie + + + Version + Versie + + + Accès réservé Koriolan + Gereserveerde toegang Koriolan + + + Spécifique Suncy + Specifiek Suncy + + + Réseaux + Netwerken + + + Cette page est actuellement en travaux. <br />Elle sera rendue disponible très rapidement à travers une mise à jour.<br /><br />Merci de votre patience...<br /><br />L'équipe ShipHeart + Deze pagina is momenteel in aanbouw. <br />Het zal zeer snel beschikbaar worden gemaakt via een update.<br /><br /> Bedankt voor uw geduld...<br /><br /> Het ShipHeart-team + + + Evènements + Evenementen + + + ShipHeart + Schiphart + + + Ethernet & Wifi + Ethernet en wifi + + + One Wire + Eén draad + + + NMEA 2000 + NMEA 2000 + + + J1939 + J1939 + + + DMX + DMX + + + Journal de bord + Logboek + + + Installation + Faciliteit + + + Menu accueil + Startmenu + + + + protection + + Accès protégé + Beveiligde toegang + + + L'accès aux paramètres avancés est protégé. +Merci d'entrer le code de déverrouillage pour y accéder... + De toegang tot geavanceerde instellingen is beveiligd. + Voer de ontgrendelingscode in om toegang te krijgen... + + + Mode administrateur validé<br />Entrer votre code dédié + Beheerdersmodus ingeschakeld<br />Voer uw specifieke code in + + + + reservoir + + [ %1 % ] + [ %1 % ] + + + Aucune donnée n'est disponible pour cette période + Geen gegevens beschikbaar voor deze periode + + + Le module assurant la supervision de ce réservoir n'est pas accessible !<br /><br />Si des ajouts/suppression/déplacements de modules ont eu lieu récemment, mettez à jour la configuration correspondant dans le menu MODULES de PARAMETRES AVANCES.<br /><br />Dans le cas où aucune modification n'a été effectuée récemment, vérifier les connexions de tous les modules. + De module die het toezicht op deze tank verzekert, is niet toegankelijk!<br /><br /> Als er onlangs modules zijn toegevoegd/verwijderd/verplaatst, update dan de overeenkomstige configuratie in het menu MODULES van GEAVANCEERDE INSTELLINGEN.<br /><br /> Indien er recentelijk geen wijzigingen zijn aangebracht, controleer dan de aansluitingen van alle modules. + + + Niveau + Niveau + + + La valeur lue sur les electrodes plongées de ce réservoir est incohérente.<br />Vérifier l'ordre de cablage des électrodes sur les entrées auxiliaires à l'arrière de ShipBase. + De waarde die wordt afgelezen op de elektroden die in deze tank zijn ondergedompeld, is inconsistent.<br /> Controleer de bedradingsvolgorde van de elektroden op de hulpingangen aan de achterkant van ShipBase. + + + + shipheart_test_config + + Vitesse de test de l'écran + Schermtestsnelheid + + + Nombre de colonnes de test du touchpad + Aantal touchpad-testkolommen + + + Nombre de lignes de test du touchpad + Aantal touchpad-testlijnen + + + + shipheart_test_home + + Tests matériel + Hardwaretests + + + Configuration des tests + Test opstelling + + + Test du backlight + Testen van tegenlicht + + + Test de l'écran + Scherm test + + + Test du touchpad + Touchpad-test + + + Liste des fonts disponibles + Lijst met beschikbare lettertypen + + + + shipheart_test_liste_fonts + + Liste des fonts disponibles + Lijst met beschikbare lettertypen + + + + test_batterie + + Batteries de servitude + Service batterijen + + + Autonomie optimale + Optimale autonomie + + + Autonomie actuelle + Huidige autonomie + + + Autonomie<br />maximale + Maximaal bereik<br /> + + + dans + in + + + environ + over + + + + test_tri_liste + + TEST DE TRI DE LISTE + TEST DE TRI DE LISTE + + + diff --git a/shipheart_pt_PT.qm b/shipheart_pt_PT.qm new file mode 100755 index 0000000..536ee65 Binary files /dev/null and b/shipheart_pt_PT.qm differ diff --git a/shipheart_pt_PT.ts b/shipheart_pt_PT.ts new file mode 100755 index 0000000..0c56ad0 --- /dev/null +++ b/shipheart_pt_PT.ts @@ -0,0 +1,5528 @@ + + + + + Shipheart_boite_dialogue + + + OK + OK + + + + Annuler + Cancelar + + + + Plus tard + Posterior + + + + Shipheart_boite_dialogue_action_circuit + + + Action à appliquer au circuit lorsque l'évènement se déclenche : + Ação a ser aplicada ao circuito quando o evento é acionado: + + + + Aucune + Não + + + + Le circuit <b>bascule</b> + O circuito <b>balança</b> + + + + [passe à <b>ON</b> s'il est <b>OFF</b><br /> ou à <b>OFF</b> s'il est <b>ON</b>] + [mudar para <b>LIGADO</b> se estiver <b>DESLIGADO</b><br />ou <b>DESLIGADO</b> se <b>LIGADO]</b> + + + + OFF + OFF + + + + ON + ON + + + + Annuler + Cancelar + + + + Shipheart_boite_dialogue_affichage_duree + + + Ok + OK + + + + Shipheart_boite_dialogue_condition_horaire + + + OK + OK + + + + Annuler + Cancelar + + + + Supprimer + Excluir + + + + Aube nautique + Alvorada Náutica + + + + Lever du soleil + Nascer do sol + + + + Zénith + Zênite + + + + Coucher du soleil + Ocaso + + + + Crépuscule nautique + Crepúsculo Náutico + + + + Shipheart_boite_dialogue_entrees_aux + + + Entrées Auxiliaires + Insumos Auxiliares + + + + Affectation de l'entrée n° %1 du %2 + Atribuição do número de entrada %1 de %2 + + + + Annuler + Cancelar + + + + Shipheart_boite_dialogue_entrees_level_sensor + + + Entrées Level Sensor + Entradas do sensor de nível + + + + Affectation de l'entrée du réservoir + Atribuição de entrada de tanque + + + + Annuler + Cancelar + + + + Shipheart_boite_dialogue_liste_alarmes + + + Ok + OK + + + + Shipheart_boite_dialogue_minuteur + + + Heures + Horas + + + + Minutes + Ata + + + + Secondes + Segundos + + + + Annuler + Cancelar + + + + Démarrer + Começar + + + + Shipheart_boite_dialogue_nettoyage_ecran + + + Nettoyage de l'écran + Limpeza de tela + + + + 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. + A tela está atualmente congelada para que você possa limpá-la sem o risco de desencadear ações indesejadas.<br /><br />Mantenha pressionado o botão abaixo por mais de %1 segundos para sair desse modo. + + + + Sortie + Sair + + + + Shipheart_boite_dialogue_reveils + + + Annuler + Cancelar + + + + Enregistrer + Registro + + + + Shipheart_boite_dialogue_validation_securisee + + + OK + OK + + + + Annuler + Cancelar + + + + --- + --- + + + + Shipheart_bouton_circuit + + + + + Off + OFF + + + + + On + ON + + + + batterie + + + + Aucune consommation d'énergie sur cette période... + Nenhum consumo de energia neste período... + + + + Aucune donnée n'est disponible pour cette période + Não há dados disponíveis para este período + + + + Le module assurant la supervision de cette batterie n'est pas accessible !<br /><br />Si des ajouts/suppression/déplacements de modules ont eu lieu récemment, mettez à jour la configuration correspondant dans le menu MODULES de PARAMETRES AVANCES.<br /><br />Dans le cas où aucune modification n'a été effectuée récemment, vérifier les connexions de tous les modules. + O módulo que supervisiona esta bateria não está acessível!<br /><br />Se houve adições/releções/movimentações recentes de módulos, atualize a configuração correspondente no menu MÓDULOS de CONFIGURAÇÕES AVANÇADAS.<br /><br />Caso nenhuma alteração tenha sido feita recentemente, verifique as conexões de todos os módulos. + + + + capteur + + + Max + Max + + + + Moyen + Média + + + + Min + Min + + + + Delta (Max - Min) + Delta (1h) + Delta (Máx. - Mín) + + + + Aucune donnée n'est disponible pour cette période + Não há dados disponíveis para este período + + + + La sonde One Wire correspondant à ce capteur n'est pas accessible.<br />Vérifier son câblage entre le port One Wire à l'arrière de ShipBase et la sonde. + A sonda One Wire correspondente a este sensor não está acessível.<br />Verifique sua fiação entre a porta One Wire na parte traseira do ShipBase e a sonda. + + + + Le module assurant la supervision de ce capteur n'est pas accessible !<br /><br />Si des ajouts/suppression/déplacements de modules ont eu lieu récemment, mettez à jour la configuration correspondant dans le menu MODULES de PARAMETRES AVANCES.<br /><br />Dans le cas où aucune modification n'a été effectuée récemment, vérifier les connexions de tous les modules. + O módulo que supervisiona este sensor não está acessível!<br /><br />Se houve adições/releções/movimentações recentes de módulos, atualize a configuração correspondente no menu MÓDULOS de CONFIGURAÇÕES AVANÇADAS.<br /><br />Caso nenhuma alteração tenha sido feita recentemente, verifique as conexões de todos os módulos. + + + + La sonde One Wire du capteur est détectée en défaut.<br />Vérifier son câblage depuis l'arrière de ShipBase. + A sonda One Wire do sensor é detectada como uma falha.<br />Verifique sua fiação na parte traseira do ShipBase. + + + + Le capteur n'a pas reçu de mise à jour sur le réseau NMEA depuis<br />%1<br />Les données affichées sont donc probablement obsolètes. + O sensor não recebeu uma atualização na rede NMEA desde<br />%1<br />Portanto, os dados apresentados estão provavelmente desatualizados. + + + + circuit + + + + + + Off + OFF + + + + + On + ON + + + + On +%1% + Um +%1% + + + + Aucune donnée n'est disponible pour cette période + Não há dados disponíveis para este período + + + + Aucune consommation d'énergie sur cette période... + Nenhum consumo de energia neste período... + + + + Le module assurant le pilotage de ce circuit n'est pas accessible !<br /><br />Si des ajouts/suppression/déplacements de modules ont eu lieu récemment, mettez à jour la configuration correspondant dans le menu [Réseau ShipHeart] de [Paramètres Avancés].<br /><br />Dans le cas où aucune modification n'a été effectuée récemment, vérifier les connexions de tous les modules. + O módulo que controla este circuito não está acessível!<br /><br />Se houver adições/remoções/movimentações recentes de módulos, atualize a configuração correspondente no menu [ShipHeart Network] de [Configurações avançadas].<br /><br />Caso nenhuma alteração tenha sido feita recentemente, verifique as conexões de todos os módulos. + + + + Ce circuit est configuré comme <i>Non Affecté</i> et n'est donc pas accessible !<br /><br />Pour accéder à nouveau à ce circuit, merci de l'affecter à un circuit disponible dans le menu [Circuits] de [Paramètres Avancés]. + Este circuito está definido como <i>Não afetado</i> e, portanto, não pode ser acessado!<br /><br />Para recuperar o acesso a esta faixa, atribua-a a uma faixa disponível no menu [Faixas] em [Configurações avançadas]. + + + + Non défini + Indefinido + + + + Le module pilotant ce circuit n'est pas alimentée correctement. + Vérifier l'alimentation correspondante. + O módulo que conduz este circuito não está sendo alimentado corretamente. + Verifique a fonte de alimentação correspondente. + + + + Le module pilotant ce circuit est en mode MANUEL. + Repositionnez le module en mode AUTO pour commander à nouveau ce circuit normalement. + O módulo que conduz este circuito está no modo MANUAL. + Reposicione o módulo no modo AUTO para recontrolar este circuito normalmente. + + + + Le port USB du bas est en défaut. + A porta USB inferior está com defeito. + + + + Le port USB du milieu est en défaut. + A porta USB do meio está em falta. + + + + Les 2 ports USB du milieu et du bas sont en défaut. + As 2 portas USB no meio e na parte inferior estão em falta. + + + + Le port USB du haut est en défaut. + A porta USB na parte superior está em falta. + + + + Les 2 ports USB du haut et du bas sont en défaut. + As 2 portas USB na parte superior e inferior estão em falta. + + + + Les 2 ports USB du haut et du milieu sont en défaut. + As 2 portas USB na parte superior e média estão em falta. + + + + Les 3 ports USB du haut, du milieu et du bas sont en défaut. + As 3 portas USB na parte superior, central e inferior estão em falta. + + + + Le port USB est en défaut. + A porta USB está com defeito. + + + + L'alimentation du circuit a été coupée + car sa limite de courant (%1 A) + a été dépassée. + A fonte de alimentação do circuito foi cortada + porque seu limite atual (%1 A) + foi ultrapassado. + + + + L'alimentation du circuit a été coupée + car les circuits de protection interne ont détecté une anomalie. + A fonte de alimentação do circuito foi cortada + porque os circuitos internos de proteção detectaram uma anomalia. + + + + L'alimentation du circuit a été coupée + car le seuil de disjonction du circuit a été dépassé. + A fonte de alimentação do circuito foi cortada + porque o limite de disjunção do circuito foi excedido. + + + + Le circuit est en court-circuit avec le + batterie. + O circuito é encurtado com a bateria +. + + + + L'alimentation du circuit a été coupée<br />car la consommation totale du module a dépassé %1 A pendant plus de %2 secondes (limite du module) + A fonte de alimentação do circuito foi cortada<br />porque o consumo total de energia do módulo excedeu %1 A por mais de %2 segundos (limite do módulo) + + + + La tension du circuit est anormalement basse. + A tensão do circuito é anormalmente baixa. + + + + La phase et le neutre sont inversés sur ce circuit. + Fase e neutro são invertidos neste circuito. + + + + DANGER : Le neutre n'est pas référencé à la terre sur ce circuit ("absence de terre"). + DANGER : la terre est absente de ce circuit. + PERIGO: O neutro não está referenciado ao aterramento neste circuito ("sem aterramento"). + + + + La masse est absente du connecteur d'alimentation du module + Falta terra no conector de alimentação do módulo + + + + Evènements actuellement actifs qui sont susceptibles de commander ce circuit : + Eventos atualmente ativos que provavelmente comandarão este circuito: + + + + + + Etat inconnu... + Estado desconhecido... + + + + config_acces_parametres + + + Configuration de l'accès aux paramètres avancés + Definindo o acesso a configurações avançadas + + + + Durée de maintien de l'accès + Duração do acesso + + + + Nouveau code + Novo Código + + + + Code d'accès + Código de acesso + + + + Répéter le code d'accès + Repita o código de acesso + + + + Enregistrer + Registro + + + + Aucune (saisie du code à chaque accès) + Nenhum (digite o código cada vez que você acessar) + + + + 1 minute + 1 minuto + + + + 5 minutes + 5 minutos + + + + 15 minutes + 15 minutos + + + + 1 heure + 1 hora + + + + Infinie (aucune protection des paramètres avancés) + Infinito (sem proteção de configurações avançadas) + + + + Les deux valeurs saisies doivent être identiques ! + +De plus, le code doit contenir : +- %1 chiffres au minimum +- %2 chiffres au maximum. + Os dois valores inseridos devem ser idênticos! + +Além disso, o código deve conter: +- Mínimo de %1 dígitos +- %2 dígitos máximos. + + + + Le nouveau code doit contenir : +- %1 chiffres au minimum +- %2 chiffres au maximum. + +Le code saisi ne répond pas à ces critères et sa mise à jour n'est donc pas effectuée. + +Merci de saisir un code au format valide si vous souhaitez le modifier. + O novo código deve conter: +- Mínimo de %1 dígitos +- %2 dígitos máximos. + +O código inserido não atende a esses critérios e, portanto, não é atualizado. + +Por favor, insira um código em um formato válido se você deseja alterá-lo. + + + + config_affichage + + + Configuration de l'affichage + Configurando a exibição + + + + Nom du bateau + Nome do barco + + + + Fuseau horaire + Fuso horário + + + + Temporisaton économiseur d'écran + Temporizador do protetor de tela + + + + Thème d'affichage + Tema de exibição + + + + Enregistrer + Registro + + + + UTC-12 (Yankee) + UTC-12 (Yankee) + + + + UTC-11 (X-Ray) + UTC-11 (Raio-X) + + + + UTC-10 (Whisky) + UTC-10 (Whisky) + + + + UTC-9 (Victor) + UTC-9 (Victor) + + + + UTC-8 (Uniform) + UTC-8 (Uniforme) + + + + UTC-7 (Tango) + UTC-7 (Tango) + + + + UTC-6 (Sierra) + UTC-6 (Serra) + + + + UTC-5 (Romeo) + UTC-5 (Romeu) + + + + UTC-4 (Quebec) + UTC-4 (Quebec) + + + + UTC-3 (Papa) + UTC-3 (Pai) + + + + UTC-2 (Oscar) + UTC-2 (Oscar) + + + + UTC-1 (November) + UTC-1 (novembro) + + + + UTC (Zoulou) + UTC (Zulu) + + + + UTC+1 (Alpha) + UTC+1 (Alfa) + + + + UTC+2 (Bravo) + UTC+2 (Bravo) + + + + UTC+3 (Charlie) + UTC+3 (Charlie) + + + + UTC+4 (Delta) + UTC+4 (Delta) + + + + UTC+5 (Echo) + UTC+5 (Eco) + + + + UTC+6 (Foxtrot) + UTC+6 (Foxtrot) + + + + UTC+7 (Golf) + UTC+7 (Golfe) + + + + UTC+8 (Hotel) + UTC+8 (Hotel) + + + + UTC+9 (India) + UTC+9 (Índia) + + + + UTC+10 (Kilo) + UTC+10 (Quilo) + + + + UTC+11 (Lima) + UTC+11 (Lima) + + + + UTC+12 (Mike) + UTC+12 (Mike) + + + + 15 secondes + 15 segundos + + + + 30 secondes + Trinta segundos + + + + 1 minute + 1 minuto + + + + 3 minutes + 3 minutos + + + + 10 minutes + 10 minutos + + + + Aucune limite + Sem limites + + + + config_audio + + + Configuration audio + Configuração de áudio + + + + Bips de clic + Clique em bipes + + + + Fonctionnement de la sortie Audio + Operação de saída de áudio + + + + Enregistrer + Registro + + + + Aucun bip + Sem bipes + + + + Bip par défaut + Bipe padrão + + + + Bip 2 + Bipe 2 + + + + Bip 3 + Bipe 3 + + + + Bip 4 + Bipe 4 + + + + Bip 5 + Bipe 5 + + + + Bip 6 + Bipe 6 + + + + Bip 7 + Sinal sonoro 7 + + + + Bip 8 + Bipe 8 + + + + Bip 9 + Bipe 9 + + + + Bip 10 + Bipe 10 + + + + Bip 11 + Sinal sonoro 11 + + + + Bip 12 + Bipe 12 + + + + Bip 13 + Bipe 13 + + + + Bip 14 + Bipe 14 + + + + Le son de ShipBase est coupé. Le son est uniquement diffusé sur la sortie AUDIO + O ShipBase está mudo. O som só é reproduzido na saída AUDIO + + + + Le son est diffusé sur ShipBase et sur la sortie AUDIO + O som é transmitido para o ShipBase e a saída AUDIO + + + + config_batterie + + + Nom de la batterie + Nome da bateria + + + + Tension nominale + Tensão nominal + + + + Créer la batterie + Criar a bateria + + + + Enregistrer + Registro + + + + Supprimer + Excluir + + + + + Confirmer + Confirmar + + + + Etalonner + Etalonnage + Calibrar + + + + + Non défini + Indefinido + + + + Création d'un parc de batteries + Criação de um banco de baterias + + + + Configuration du parc de batteries + Configuração do banco de baterias + + + + Groupe de batteries + Banco de baterias + + + + Point de mesure + Ponto de medição + + + + Type de batterie(s) + Tipo(s) de Bateria + + + + La modification du <b>type</b> de batterie(s) va nécessiter la remise en <i>configuration usine</i> de certains paramètres.<br /><br />Si vous ne souhaitez pas que cette reconfiguration soit effectuée, notamment si vous avez effectué des réglages spécifiques, cliquez sur ANNULER. <br /><br />Sinon, cliquez sur CONFIRMER pour valider le changement. + Alterar o(s) <b>tipo</b> (s) de bateria(s) exigirá a <i>redefinição de fábrica</i> de certos parâmetros.<br /><br />Se você não quiser que essa reconfiguração seja executada, especialmente se tiver feito configurações específicas, clique em CANCELAR. <br /><br />Caso contrário, clique em CONFIRMAR para confirmar a alteração. + + + + La modification de la <b>tension nominale</b> du parc de batteries va nécessiter la remise en <i>configuration usine</i> de certains paramètres.<br /><br />Si vous ne souhaitez pas que cette reconfiguration soit effectuée, notamment si vous avez effectué des réglages spécifiques, cliquez sur ANNULER. <br /><br />Sinon, cliquez sur CONFIRMER pour valider le changement. + Alterar a <b>tensão nominal</b> do banco de baterias exigirá a <i>redefinição de fábrica</i> de certos parâmetros.<br /><br />Se você não quiser que essa reconfiguração seja executada, especialmente se tiver feito configurações específicas, clique em CANCELAR. <br /><br />Caso contrário, clique em CONFIRMAR para confirmar a alteração. + + + + Capacité + Capacidade + + + + + Ah + Ah + + + + Masquer les paramètres avancés + Ocultar configurações avançadas + + + + Afficher les paramètres avancés + Mostrar configurações avançadas + + + + Coefficient correcteur d'entrée de tension + Coeficiente de correção de entrada de tensão + + + + + + + + + Caractéristiques du parc de batteries + Características do Banco de Baterias + + + + Durée correspondant à la capacité + Duração correspondente à capacidade + + + + + h + h + + + + Capacité 2 + Capacidade 2 + + + + Durée de capacité 2 + Duração da habilidade 2 + + + + Coefficient de Peukert + Coefficient de Peukert + + + + Résistance interne + Resistência interna + + + + mΩ + + + + + Soh actuel + Soh Atual + + + + % + % + + + + Paramètres de pleine charge + Configurações de carga completa + + + + Tension mini pleine charge + Mini tensão de carga total + + + + + V + V + + + + Courant maxi pleine charge + Corrente máxima de carga total + + + + A + Tem + + + + Temporisation pleine charge + Atraso de carga total + + + + + s + s + + + + Efficacité de charge + Eficiência de carregamento + + + + Caractéristiques de charge nulle + Características de carga zero + + + + Tension de détection charge nulle + Tensão de detecção de carga zero + + + + Temporisation charge nulle + Atraso de carga zero + + + + Alimentation %1 + Potência %1 + + + + 48V + 48V + + + + Cette batterie est utilisée par l'évènement ci-dessous.<br />Vous devez modifier ou supprimer cet évènement pour qu'il ne dépende plus de cette batterie avant de pouvoir la supprimer. + Esta bateria é usada pelo evento abaixo.<br />Você deve editar ou excluir esse evento para que ele não dependa mais desse farm antes de excluí-lo. + + + + Cette batterie est utilisée par les %1 évènements ci-dessous.<br />Vous devez modifier ou supprimer ces évènements pour qu'ils ne dépendent plus de cette batterie avant de pouvoir la supprimer. + Essa bateria é usada pelos eventos %1 abaixo.<br />Você deve editar ou excluir esses eventos para que eles não dependam mais desse farm antes de excluí-lo. + + + + Cette batterie est utilisée par le capteur calculé ci-dessous.<br />Vous devez modifier ou supprimer ce capteur calculé pour qu'il ne dépende plus de cette id_batterie avant de pouvoir la supprimer. + Esta bateria é usada pelo sensor calculado abaixo.<br />Você deve editar ou excluir esse sensor calculado para que ele não dependa mais desse id_batterie antes de excluí-lo. + + + + Cette id_batterie est utilisée par les %1 capteurs calculés ci-dessous.<br />Vous devez modifier ou supprimer ces capteurs calculés pour qu'ils ne dépendent plus de cette id_batterie avant de pouvoir la supprimer. + Esse id_batterie é usado pelos sensores %1 calculados abaixo.<br />Você deve modificar ou excluir esses sensores calculados para que eles não dependam mais desse id_batterie antes de excluí-lo. + + + + Ok + OK + + + + Historique + Histórico + + + + Nombre de cycles de charge + Número de ciclos de carregamento + + + + Nombre de décharges complètes + Número de descargas completas + + + + Forcer Pleine Charge + Força Carga Completa + + + + Réinitialiser SOH + Redefinir SOH + + + + Réinitialiser Compteurs + Redefinir contadores + + + + ShipBS [@ %1] + ShipBS [@%1] + + + + Entrée VOLT n° %1 + Entrada VOLT %1 + + + + Plomb - Acide liquide + Chumbo - Ácido líquido + + + + Plomb - AGM / VRLA + Líder - AGM / VRLA + + + + Plomb - Gel + Chumbo - Gel + + + + Plomb - Carbone + Chumbo - Carbono + + + + Lithium + Lítio + + + + Non définie + Indefinido + + + + 12V + 12V + + + + 24V + 24V + + + + config_batteries + + + Configuration des batteries + Configuração da bateria + + + + Aucune batterie n'est encore configurée... + Nenhuma bateria está configurada ainda... + + + + + + + + + + + config_capteur + + + Création d'un capteur + Criando um sensor + + + + Configuration du capteur + Configuração do sensor + + + + Nom du capteur + Nome do sensor + + + + Type de capteur + Tipo de sensor + + + + Module + Módulo + + + + Affectation + Afetação + + + + %1 : Non définie + %1: Não definido + + + + %1 : %2 + %1 : %2 + + + + Mode du capteur + Modo do sensor + + + + Groupe de capteurs + Grupo de sensores + + + + Libellé du capteur pour la valeur %1 + Etiqueta do sensor para o valor %1 + + + + + + + Non défini + Indefinido + + + + Entrées Auxiliaires (AUX INPUTS) + Entradas Auxiliares (AUX INPUTS) + + + + Entrées Niveau (LEVEL SENSORS) + Entradas de Nível (SENSORES DE NÍVEL) + + + + Entrées Tension (VOLTAGE INPUTS) + ENTRADAS DE TENSÃO + + + + Capteurs de température (ONE WIRE) + Sensores de temperatura (UM FIO) + + + + Entrées NMEA2000 + Entradas NMEA2000 + + + + Capteurs sur modules + Sensores nos módulos + + + + Calculé (conditions logiques) + Calculado (condições lógicas) + + + + + <i>Entrée non utilisée</i> + <i>Entrada não utilizada</i> + + + + Pression Atmosphérique + Pressão atmosférica + + + + + + Température module + Módulo de temperatura + + + + + Tension d'entrée module + Módulo de tensão de entrada + + + + Consommation module + Consumo do módulo + + + + Consommation ports USB + Consumo de porta USB + + + + Chocs + Choque + + + + Accélération X + Aceleração X + + + + Accélération Y + Aceleração em Y + + + + Accélération Z + Aceleração Z + + + + GNSS - SOG<br />Speed Over Ground + GNSS - SOG<br />Velocidade sobre o solo + + + + GNSS - COG<br />Course Over Ground + GNSS - COG<br />Curso sobre o solo + + + + GNSS - SIV<br />Satellites In View + GNSS - SIV<br />Satélites à vista + + + + GNSS - HPA<br />Horizontal Precision Accuracy + GNSS - HPA<br />Precisão Horizontal + + + + GNSS - VPA<br />Vertical Precision Accuracy + GNSS - VPA<br />Precisão Vertical + + + + Modem 4G/LTE - RSSI<br />Received Signal Strength Indicator + MODEM 4G/LTE - CISO<br />Indicador de Intensidade do Sinal Recebido + + + + Modem 4G/LTE - SINR<br />Signal to Interference & Noise Ratio + Modem 4G/LTE - SINR<br />Relação Sinal/Interferência e Ruído + + + + Normal + Normal + + + + Inversé + Invertido + + + + Tension 0 - 10 V + Voltagem 0 - 10 V + + + + Résistance 0 - 500 Ohms + Resistência 0 - 500 Ohms + + + + Courant 4 - 20 mA + Corrente 4 - 20 mA + + + + Défaut d'isolement + Falta de isolamento + + + + Ce capteur est utilisé par l'évènement ci-dessous.<br />Vous devez modifier ou supprimer cet évènement pour qu'il ne dépende plus de ce capteur avant de pouvoir le supprimer. + Este sensor é usado pelo evento abaixo.<br />Você deve editar ou excluir esse evento para que ele não dependa mais desse sensor antes de excluí-lo. + + + + Ce capteur est utilisé par les %1 évènements ci-dessous.<br />Vous devez modifier ou supprimer ces évènements pour qu'ils ne dépendent plus de ce capteur avant de pouvoir le supprimer. + Esse sensor é usado pelos eventos %1 abaixo.<br />Você deve editar ou excluir esses eventos para que eles não dependam mais desse sensor antes de excluí-lo. + + + + Ce capteur est utilisé par le capteur calculé ci-dessous.<br />Vous devez modifier ou supprimer ce capteur calculé pour qu'il ne dépende plus de ce capteur avant de pouvoir le supprimer. + Este sensor é usado pelo sensor calculado abaixo.<br />Você deve editar ou excluir esse sensor calculado para que ele não dependa mais desse sensor antes de excluí-lo. + + + + Ce capteur est utilisé par les %1 capteurs calculés ci-dessous.<br />Vous devez modifier ou supprimer ces capteurs calculés pour qu'ils ne dépendent plus de ce capteur avant de pouvoir le supprimer. + Este sensor é usado pelos sensores %1 calculados abaixo.<br />Você deve modificar ou excluir esses sensores calculados para que eles não sejam mais dependentes desse sensor antes de excluí-lo. + + + + Masquer sur la page Capteurs + Ocultar na página Sensores + + + + Créer le capteur + Criar o sensor + + + + Enregistrer + Registro + + + + Equation + Equação + + + + Supprimer + Excluir + + + + Etalonner + Calibrar + + + + Humidité + Humidade + + + + GNSS - Latitude + GNSS - Latitude + + + + GNSS - Longitude + GNSS - Longitude + + + + GNSS - Altitude + GNSS - Altitude + + + + config_capteur_calcule_booleen + + + Equation du capteur calculé [%1] + Equação calculada do sensor [%1] + + + + Enregistrer + Registro + + + + Supprimer + Excluir + + + + Le nombre de conditions par capteur est limité à %1.<br /><br />Vous ne pouvez pas ajouter de groupe ou de nouvelle condition avant d'en avoir supprimé préalablement. + O número de condições por sensor é limitado a %1.<br /><br />Não é possível adicionar um grupo ou uma nova condição até remover um. + + + + Des modifications ont été apportées au capteur<br />mais n'ont pas été enregistrées.<br /><br />Cliquer sur ANNULER pour revenir au menu en cours.<br /><br />Cliquer sur Ok pour sortir sans enregistrer. + Foram feitas alterações no sensor<br />mas não foram gravados.<br /><br />Clique em CANCELAR para retornar ao menu atual.<br /><br />Clique em Ok para sair sem salvar. + + + + est actif + está ativo + + + + est inactif + está inativo + + + + Ou + Ou + + + + Et + E + + + + X-Ou + X-OU + + + + config_capteur_calcule_booleen_condition + + + Création d'une condition du capteur [%1] + Criando uma condição de sensor [%1] + + + + Type + Tipo + + + + Source + Primavera + + + + Variable + Variável + + + + Test + Teste + + + + Seuil + Limiar + + + + Créer la condition + Criar a condição + + + + Enregistrer + Registro + + + + + + + Non défini + Indefinido + + + + Circuit + Circuito + + + + Capteur + Sensor + + + + Réservoir + Reservatório + + + + Batterie + Bateria + + + + Actif + Ativo + + + + Inactif + Inativo + + + + &lt; au seuil + < no limiar + + + + &le; au seuil + ≤ no limiar + + + + = au seuil + = no limiar + + + + &ge; au seuil + ≥ no limiar + + + + &gt; au seuil + > no limiar + + + + config_capteurs + + + Configuration des capteurs + Configuração do sensor + + + + Aucun capteur n'est encore configuré... + Nenhum sensor está configurado ainda... + + + + + + + + + + + config_circuit + + + Configuration du circuit + Configuração do circuito + + + + Nom du circuit + Nome do Tour + + + + Affectation + Afetação + + + + Circuit renfort + Circuito de reforço + + + + Mode de commande + Modo de encomenda + + + + Vitesse de démarrage/arrêt + Velocidade de Início/Parada + + + + Seuil de disjonction + Limiar de disjunção + + + + Vitesse de disjonction + Velocidade de disjunção + + + + Filtrage du courant consommé + Filtragem da corrente consumida + + + + Masquer sur la page d'accueil + Ocultar na página inicial + + + + Créer le circuit + Criar o circuito + + + + Enregistrer + Registro + + + + L'affectation du circuit vient d'être modifiée alors que le circuit était actif. +Avant d'effectuer ce changement, le circuit a été passé sur OFF. + +Pensez à le réactiver si besoin... + A atribuição do circuito acaba de ser alterada enquanto o circuito estava ativo. +Antes de fazer essa alteração, o circuito foi desligado. + +Lembre-se de reativá-lo se necessário... + + + + Supprimer + Excluir + + + + Aucun + Nenhum + + + + ShipPower812 [@ %1] + ShipPower812 [@%1] + + + + ShipPower4AC [@ %1] + ShipPower4AC [@%1] + + + + ShipPower8DC [@ %1] + ShipPower8DC [@%1] + + + + + Circuit %1 + Circuito %1 + + + + Groupe de circuits + Groupe de circuit + Grupo Circuito + + + + Commande impulsionnelle + Controle de impulsos + + + + + %1 - %2 + %1 - %2 + + + + Non affecté + Afetado + + + + On-Off + Liga-desliga + + + + On-Off progressif + Liga-desliga progressiva + + + + Variateur + Variador + + + + Aucun filtrage + Sem filtragem + + + + Très faible + Muito baixo + + + + Faible + Fraco + + + + Moyen + Média + + + + Elevé + Alto + + + + Très élevé + Muito alto + + + + + Très rapide + Rápido + + + + + Rapide + Rápido + + + + + Moyenne + Média + + + + + Lente + Lêndea + + + + + Très lente + Muito lento + + + + Non + Não + + + + 1 seconde + 1 segundo + + + + 2 secondes + 2 segundos + + + + 5 secondes + 5 segundos + + + + Ce circuit est utilisé pour la commande du moteur.<br />Vous devez d'abord affecter la commande moteur à un autre circuit avant de pouvoir supprimer celui-ci. + Este circuito é usado para controle do motor.<br />Você deve primeiro atribuir o controle do motor a outro circuito antes de removê-lo. + + + + Ce circuit est utilisé par l'évènement ci-dessous.<br />Vous devez modifier ou supprimer cet évènement pour qu'il ne dépende plus de ce circuit avant de pouvoir le supprimer. + Este circuito é utilizado pelo evento abaixo.<br />Você deve editar ou excluir esse evento para que ele não dependa mais desse circuito antes de excluí-lo. + + + + Ce circuit est utilisé par les %1 évènements ci-dessous.<br />Vous devez modifier ou supprimer ces évènements pour qu'ils ne dépendent plus de ce circuit avant de pouvoir le supprimer. + Esse circuito é usado pelos eventos %1 abaixo.<br />Você deve editar ou excluir esses eventos para que eles não sejam mais dependentes desse circuito antes de excluí-lo. + + + + Ce circuit est utilisé par le capteur calculé ci-dessous.<br />Vous devez modifier ou supprimer ce capteur calculé pour qu'il ne dépende plus de ce circuit avant de pouvoir le supprimer. + Este circuito é utilizado pelo sensor calculado abaixo.<br />Você deve modificar ou excluir este sensor calculado para que ele não seja mais dependente deste circuito antes de poder removê-lo. + + + + Ce circuit est utilisé par les %1 capteurs calculés ci-dessous.<br />Vous devez modifier ou supprimer ces capteurs calculés pour qu'ils ne dépendent plus de ce circuit avant de pouvoir le supprimer. + Este circuito é usado pelos sensores %1 calculados abaixo.<br />Você deve modificar ou excluir esses sensores calculados para que eles não sejam mais dependentes deste circuito antes de poder removê-lo. + + + + 15 secondes + 15 segundos + + + + 30 secondes + Trinta segundos + + + + 45 secondes + 45 segundos + + + + 1 minute + 1 minuto + + + + 5 minutes + 5 minutos + + + + 15 minutes + 15 minutos + + + + 1 heure + 1 hora + + + + 4 heures + 4 horas + + + + L'utilisation d'un circuit de renfort rend l'utilisation du mode de commande [Variateur] impossible.<br /><br />Le mode de commande vient donc d'être ramené à [On-Off Progressif]. + O uso de um circuito de reforço impossibilita o uso do modo de controle [Drive].<br /><br />O modo de controle, portanto, acaba de ser reduzido para [Progressive On-Off]. + + + + config_circuits + + + Configuration des circuits + Configuração do Circuito + + + + Pack de batteries : + Bateria: + + + + Aucun capteur n'est encore configuré... + Nenhum sensor está configurado ainda... + + + + Oui + Sim + + + + Non + Não + + + + Le module n'est affecté à aucune batterie... + O módulo não é atribuído a nenhuma bateria... + + + + Circuit non utilisé + Circuito não utilizado + + + + Circuits Non Affectés + Circuitos não afetados + + + + Ce circuit est configuré comme renfort du circuit <b>%1</b> et ne peut donc pas être configuré individuellement.<br /><br />Merci de cliquer sur le circuit <b>%1</b> de ce même module pour accéder à leurs paramètres communs<br />(y compris pour supprimer le circuit de renfort actuel). + Este circuito é configurado como um reforço do circuito <b>%1</b> e, portanto, não pode ser configurado individualmente.<br /><br />Por favor, clique no circuito <b>%1</b> deste mesmo módulo para acessar seus parâmetros comuns<br />(inclusive para remover o circuito de reforço de corrente). + + + + Type de carte inconnu... + Tipo de cartão desconhecido... + + + + Le module <br /><b>%1</b><br /> n'est affecté à aucun pack de batteries. <br /><br />Souhaitez-vous laisser la configuration en l'état ? + O módulo <br /><b>%1</b><br /> não está atribuído a nenhuma bateria. <br /><br />Deseja deixar a configuração como está? + + + + Les modules suivants ne sont affectés à aucun pack de batteries :<br /><b>%1</b><br /><br /><br />Souhaitez-vous laisser la configuration en l'état ? + Os seguintes módulos não são atribuídos a nenhuma bateria:<br /><b>%1</b><br /><br /><br />Deseja deixar a configuração como está? + + + + config_event + + + Création d'un évènement + Criando um evento + + + + Configuration de l'évènement + Configuração do evento + + + + Nom de l'évènement + Nome do Evento + + + + Type de la source + Tipo de origem + + + + Source + Primavera + + + + Variable de la source + Variável de origem + + + + Déclenchement si + Acionamento se + + + + Seuil de déclenchement + Limite de gatilho + + + + Temporisation de déclenchement + Temporizador de gatilho + + + + s + s + + + + Masquer sur la page d'accueil + Ocultar na página inicial + + + + Conditions horaire + Condições de tempo + + + + Le nombre maximal de conditions horaires [%1] est atteint : ajout impossible... + O número máximo de condições horárias [%1] foi atingido: não é possível adicionar... + + + + Aucune condition horaire n'est configurée pour cet évènement... + Não há condições de tempo definidas para este evento... + + + + Signalisation + Sinalização + + + + Alarme sonore + Alarme sonoro + + + + La validation des alarmes sonores a nécessité de valider également l'affichage des messages liés à cet évènement.<br /><br />Cet affichage est en effet nécessaire au fonctionnement des alarmes sonores, afin de pouvoir les acquitter. + A validação dos alarmes sonoros também exigiu a validação da exibição das mensagens relacionadas a esse evento.<br /><br />Este display é necessário para o funcionamento de alarmes sonoros, a fim de ser capaz de reconhecê-los. + + + + Alarme sur LED + Alarme LED + + + + La validation des alarmes sur LED a nécessité de valider également l'affichage des messages liés à cet évènement.<br /><br />Cet affichage est en effet nécessaire au fonctionnement des alarmes sur LED, afin de pouvoir les acquitter. + A validação dos alarmes LED também exigiu a validação da exibição de mensagens relacionadas a este evento.<br /><br />Este display é necessário para o funcionamento dos alarmes LED, a fim de ser capaz de reconhecê-los. + + + + Alarme sur sortie(s) de soutien + Alarme na(s) saída(s) de suporte + + + + La validation des alarmes sur sortie(s) de soutien a nécessité de valider également l'affichage des messages liés à cet évènement.<br /><br />Cet affichage est en effet nécessaire au fonctionnement des alarmes sur sortie(s) de soutien, afin de pouvoir les acquitter. + A validação dos alarmes na(s) saída(s) de suporte também exigiu a validação da exibição de mensagens relacionadas a este evento.<br /><br />Este display é necessário para o funcionamento dos alarmes na(s) saída(s) de suporte, a fim de poder reconhecê-los. + + + + Alarme sur la source + Alarme na fonte + + + + Affichage message sur ShipBase + Exibindo uma mensagem no ShipBase + + + + La dévalidation de l'affichage des messages a nécessité de dévalider également :<ul><li>les alarmes sonores,</li><li>les alarmes sur led</li><li>et les alarmes sur sortie(s) de soutien</li></ul><br />L'affichage de message est en effet nécessaire à leur fonctionnement, afin de pouvoir les acquitter. + A desvalidação da exibição de mensagens também exigiu a desvalidação:<ul><li>alarmes sonoros,</li><li>Alarmes LED</li><li>e alarmes na(s) saída(s) de suporte</li></ul><br />A exibição de mensagens é de fato necessária para o seu funcionamento, a fim de poder absolvê-las. + + + + Texte du message à afficher + Texto da mensagem a ser exibido + + + + Emission SMS + Transmissão de SMS + + + + Texte du SMS à envoyer + Texto SMS para enviar + + + + Emission Email + Transmissão de e-mail + + + + Texte de l'email à envoyer + Texto do e-mail a ser enviado + + + + Action sur circuits + Acompanhe a ação + + + + Aucune + Não + + + + Le circuit "bascule" + O circuito "rocking" + + + + Le circuit passe à OFF + O circuito OFF + + + + Le circuit passe à ON + O circuito passa para ON + + + + Le nombre de circuits commandés par un évènement est limité à %1.<br /><br />Vous ne pouvez pas ajouter d'action sur un nouveau circuit avant d'en avoir supprimé préalablement. + O número de faixas ordenadas por um evento é limitado a %1.<br /><br />Você não pode adicionar uma ação em uma nova faixa até que tenha removido uma ação primeiro. + + + + Créer l'évènement + Criar o evento + + + + Enregistrer + Registro + + + + Supprimer + Excluir + + + + + + + Non défini + Indefinido + + + + Condition horaire seule + Apenas requisito de tempo + + + + Circuit + Circuito + + + + Capteur + Sensor + + + + Réservoir + Reservatório + + + + Batterie + Bateria + + + + Passage à <b>actif</b> + Atualizar para <b>Ativo</b> + + + + Passage à <b>inactif</b> + Mudar para <b>inativo</b> + + + + &lt; au seuil + &lt; no limiar + + + + &le; au seuil + &le; no limiar + + + + = au seuil + = no limiar + + + + &ge; au seuil + &ge; no limiar + + + + &gt; au seuil + &gt; no limiar + + + + config_events + + + Configuration des évènements + Configuração do evento + + + + Aucun évènement n'est encore configuré... + Nenhum evento está definido ainda... + + + + 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. + O número total de eventos é limitado a %1.<br /><br />Não é possível adicionar um novo evento até que você tenha removido um novo evento. + + + + Sur circuits + Na pista + + + + Sur capteurs + Nos sensores + + + + Sur réservoirs + Em tanques + + + + Sur batteries + Em baterias + + + + Horaire seulement + Apenas agendamento + + + + config_groupe_elements + + + Création d'un groupe + Criando um grupo + + + + Modification d'un groupe + Editando um grupo + + + + Nom du groupe + Nome do Grupo + + + + Créer le groupe + Criar o grupo + + + + Enregistrer + Registro + + + + Supprimer + Excluir + + + + batteries + Baterias + + + + capteurs + Sensores + + + + circuits + Circuitos + + + + réservoirs + Tanques + + + + 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). + Este grupo é o último ainda válido.<br /><br />Você só poderá excluí-lo depois de ter criado pelo menos um outro grupo (não é possível trabalhar sem nenhum grupo de %1). + + + + Ce groupe comprend encore %1 %2.<br /><br />Il est nécessaire d'affecter ces %2 à un autre groupe avant de pouvoir le supprimer. + Esse grupo ainda inclui %1 %2.<br /><br />É necessário atribuir esses %2 a outro grupo antes que ele possa ser excluído. + + + + 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. + Esse grupo ainda inclui %1 %2,<br />dos quais %3 estão configurados como "ocultos".<br /><br />É necessário atribuir esses %2 a outro grupo antes que ele possa ser excluído. + + + + config_image_accueil + + + Image d'accueil + Imagem inicial + + + + Aucune image n'a encore été chargée... + Nenhuma imagem foi carregada ainda... + + + + Sélectionner l'image par défaut + Selecione a imagem padrão + + + + Sélectionner cette image + Selecione esta imagem + + + + Copier + Copiar + + + + Supprimer + Excluir + + + + Ejection + Ejetar + + + + Insérer une clé USB dans le port <u>du bas</u>, à droite + Insira uma unidade flash USB na porta <u>inferior</u> direita + + + + Vous pouvez retirer la clé en toute sécurité... + Você pode remover a chave com segurança... + + + + Seuls les fichiers de type '.jpg' ou '.png' de taille inférieure à %1 sont autorisés. + Somente arquivos do tipo '.jpg' ou '.png' menores que %1 são permitidos. + + + + La clé USB a été <i>éjectée</i> automatiquement.<br />Vous pouvez la retirer dès maintenant en toute sécurité... + A unidade USB foi <i>ejetada</i> automaticamente.<br />Você pode removê-lo com segurança agora... + + + + USB Arrière + USB Traseira + + + + Spare + Poupar + + + + USB Avant + Frente USB + + + + Touch pad + Teclado tátil + + + + La clé USB a été retirée sans avoir préalablement été <i>éjectée</i> !<br />Cela peut conduire à des pertes de données sur la clé, voire sur ShipHeart.<br /><br />Lors de vos prochaines utilisations, pensez à <i>éjecter</i> la clé avec le bouton en haut de page avant de la retirer... Merci ! + A chave USB foi removida sem ter sido <i>ejetada</i> antes!<br />Isso pode levar à perda de dados na chave, ou até mesmo no ShipHeart.<br /><br />Na próxima vez que você usá-lo, lembre-se de <i>ejetar</i> a tecla com o botão na parte superior da página antes de removê-lo... Obrigado! + + + + config_installation + + + Configuration de l'installation + Configurando o sistema + + + + Raison sociale + Nome da empresa + + + + N° & Rue + N° & Rua + + + + Complément d'adresse + Endereço adicional + + + + Code postal + Código Postal + + + + Ville + Cidade + + + + Nom du contact + Nome do Contato + + + + Téléphone + Telefone + + + + Email + Email + + + + Site web + Sítio Web + + + + Enregistrer + Registro + + + + Rapports + Comércio + + + + config_koriolan + + + Accès réservé Koriolan + Acesso reservado Koriolan + + + + Client spécifique + Específico do Cliente + + + + Mode de mise à jour des firmwares + Modo de atualização de firmware + + + + Enregistrer + Registro + + + + Tests matériel + Teste de hardware + + + + Nombre jours avant suppression historique + Número de dias para exclusão do histórico + + + + Nombre jours avant suppression mesures + Número de dias antes das medidas de eliminação + + + + Période de sauvegarde BDD + Período de backup do BDD + + + + Période de vérification download + Download do período de verificação + + + + Date de dernier archivage mesures + Medidas da data do último arquivamento + + + + Aucune spécificité + Sem especificidade + + + + Client Suncy Concept + Conceito Suncy do Cliente + + + + Normal (si version installée est antérieure à la version en cours) + Normal (se a versão instalada for mais antiga que a versão atual) + + + + Différente (si version installée est différente de version en cours) + Diferente (se a versão instalada for diferente da versão atual) + + + + Toujours (à utiliser avec modération...) + Sempre (use com moderação...) + + + + config_module + + + Modifier + Modificar + + + + Localiser le module + Localize o módulo + + + + Paramètres du module [%1] + Parâmetros do módulo [%1] + + + + Paramètres du module [%1] à l'adresse [%2] + Parâmetros do módulo [%1] em [%2] + + + + N° de série + Número de série + + + + Nom du firmware + Nome do firmware + + + + Version du firmware + Versão do firmware + + + + Version matérielle + Versão do hardware + + + + Résistance de terminaison + Resistor de Terminação + + + + Oui + Sim + + + + Non + Não + + + + CRC du firmware + Firmware CRC + + + + Courant de masses sur réseau + Corrente de massa na rede + + + + <i>--- Circuit non affecté ---</i> + <i>--- Circuito não afetado---</i> + + + + [renfort] + [reforço] + + + + Affectations + Atribuições + + + + <i>--- Aucune batterie affectée ---</i> + <i>--- Nenhuma bateria afetada---</i> + + + + Affectation + Afetação + + + + Version processeur + Versão do processador + + + + Emplacement du module à bord + Localização do módulo integrado + + + + Commentaires + Realimentação + + + + config_module_modification + + + Configuration du module [%1] à l'adresse [%2] + Configurando o módulo [%1] em [%2] + + + + Emplacement du module à bord + Localização do módulo integrado + + + + Commentaires + Realimentação + + + + Courant de masses max. sur réseau + Corrente máxima de massa na rede + + + + A + A + + + + Enregistrer + Registro + + + + config_ordre_elements + + + 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... + Para mover um grupo, mantenha-o pressionado e arraste-o.<br />Para editar ou excluir um grupo, clique duas vezes no grupo.<br />Para adicionar um grupo, clique em '+'.<br /><br />Nota: se apenas um grupo, nenhuma guia é exibida na página em questão... + + + + Aucun groupe n'est actuellement configuré... + Nenhum grupo está configurado no momento... + + + + Aucun élément n'est actuellement configuré... + Não há itens configurados no momento... + + + + Aucun groupe de batteries n'est actuellement configuré... + No momento, não há bancos de baterias configurados... + + + + Aucune batterie n'est actuellement affectée à ce groupe... + No momento, nenhuma bateria está atribuída a este grupo... + + + + Affichage des batteries sur la page d'accueil + Exibição de baterias na página inicial + + + + Aucun capteur n'est actuellement affecté ce groupe... + Nenhum sensor é afetado atualmente neste grupo... + + + + Affichage des capteurs sur la page d'accueil + Exibição de sensores na página inicial + + + + Aucun circuit n'est actuellement affecté à ce groupe... + Atualmente não há circuitos atribuídos a este grupo... + + + + Affichage des circuits sur la page d'accueil + Visualizando passeios na página inicial + + + + Aucun groupe de réservoirs n'est actuellement configuré... + No momento, não há grupos de tanques configurados... + + + + Aucun réservoir n'est actuellement affecté à ce groupe... + Atualmente, nenhum reservatório está alocado nesse grupo... + + + + Affichage des réservoirs sur la page d'accueil + Exibindo tanques na página inicial + + + + Aucun groupe de capteurs n'est actuellement configuré... + No momento, não há nenhum grupo de sensores configurado... + + + + Aucun groupe de circuits n'est actuellement configuré... + No momento, não há grupos de circuitos configurados... + + + + config_page + + + Création d'une page + Criação de uma página + + + + Configuration de la page + Configuração da página + + + + Nom de la page + Nome da página + + + + Opacité de la silhouette + Opacidade da silhueta + + + + Fichier de silhouette + Arquivo de silhueta + + + + Créer la page + Crie a página + + + + Enregistrer + Registro + + + + Silhouette + Silhueta + + + + Supprimer + Excluir + + + + + Aucun + Nenhum + + + + config_page_edition + + + Edition de la page [%1] + Editar a página [%1] + + + + Aucun équipement n'est configuré sur cette page pour le moment... + Nenhum equipamento está configurado nesta página de momento... + + + + Page + Página + + + + Enregistrer + Registro + + + + 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. + Você fez alterações que não foram salvas<br />Clique em Cancelar para voltar e salvá-los.<br />Clique em OK para sair sem salvar. + + + + config_page_point + + + Création d'un point + Criando um ponto + + + + Configuration du point + Configuração de ponto + + + + Type de la source + Tipo de origem + + + + Source + Primavera + + + + Type de point + Tipo de ponto + + + + Taille du point + Tamanho do ponto + + + + Enregistrer + Registro + + + + Créer le point + Crie o ponto + + + + Supprimer + Excluir + + + + + Non défini + Indefinido + + + + Capteur + Sensor + + + + Circuit + Circuito + + + + Réservoir + Reservatório + + + + Batterie + Bateria + + + + Modules + Módulos + + + + config_page_silhouette + + + Silhouette de la page + Silhueta da página + + + + Aucune image n'a encore été chargée... + Nenhuma imagem foi carregada ainda... + + + + Aucune image + Sem fotos + + + + Sélectionner cette image + Selecione esta imagem + + + + Copier + Copiar + + + + Supprimer + Excluir + + + + Ejection + Ejetar + + + + Insérer une clé USB dans le port <u>du bas</u>, à droite + Insira uma unidade flash USB na porta <u>inferior</u> direita + + + + Vous pouvez retirer la clé en toute sécurité... + Você pode remover a chave com segurança... + + + + Seuls les fichiers de type '.jpg' ou '.png' de taille inférieure à %1 sont autorisés. + Somente arquivos do tipo '.jpg' ou '.png' menores que %1 são permitidos. + + + + La clé USB a été <i>éjectée</i> automatiquement.<br />Vous pouvez la retirer dès maintenant en toute sécurité... + A unidade USB foi <i>ejetada</i> automaticamente.<br />Você pode removê-lo com segurança agora... + + + + USB Arrière + USB Traseira + + + + Spare + Poupar + + + + USB Avant + Frente USB + + + + Touch pad + Teclado tátil + + + + La clé USB a été retirée sans avoir préalablement été <i>éjectée</i> !<br />Cela peut conduire à des pertes de données sur la clé, voire sur ShipHeart.<br /><br />Lors de vos prochaines utilisations, pensez à <i>éjecter</i> la clé avec le bouton en haut de page avant de la retirer... Merci ! + A chave USB foi removida sem ter sido <i>ejetada</i> antes!<br />Isso pode levar à perda de dados na chave, ou até mesmo no ShipHeart.<br /><br />Na próxima vez que você usá-lo, lembre-se de <i>ejetar</i> a tecla com o botão na parte superior da página antes de removê-lo... Obrigado! + + + + config_pages + + + Configuration des pages + Configuração da página + + + + Aucune page n'est encore configurée... + Ainda não há página configurada... + + + + Image accueil + Imagem Inicial + + + + + + + + + + + config_pdf + + + Ship2net + Ship2net + + + + Enregistrer + Registro + + + + config_rapports + + + Rapports d'installation + Relatórios de Instalação + + + + Aucun rapport d'installation n'est encore disponible... + Nenhum relatório de instalação está disponível ainda... + + + + Nouveau rapport d'installation + Novo Relatório de Instalação + + + + Copier + Copiar + + + + Déplacer + Mover + + + + Supprimer + Excluir + + + + Ejection + Ejetar + + + + Insérer une clé USB dans le port <u>du bas</u>, à droite + Insira uma unidade flash USB na porta <u>inferior</u> direita + + + + Vous pouvez retirer la clé en toute sécurité... + Você pode remover a chave com segurança... + + + + La clé USB a été <i>éjectée</i> automatiquement.<br />Vous pouvez la retirer dès maintenant en toute sécurité... + A unidade USB foi <i>ejetada</i> automaticamente.<br />Você pode removê-lo com segurança agora... + + + + USB Arrière + USB Traseira + + + + Spare + Poupar + + + + USB Avant + Frente USB + + + + Touch pad + Teclado tátil + + + + La clé USB a été retirée sans avoir préalablement été <i>éjectée</i> !<br />Cela peut conduire à des pertes de données sur la clé, voire sur ShipHeart.<br /><br />Lors de vos prochaines utilisations, pensez à <i>éjecter</i> la clé avec le bouton en haut de page avant de la retirer... Merci ! + A chave USB foi removida sem ter sido <i>ejetada</i> antes!<br />Isso pode levar à perda de dados na chave, ou até mesmo no ShipHeart.<br /><br />Na próxima vez que você usá-lo, lembre-se de <i>ejetar</i> a tecla com o botão na parte superior da página antes de removê-lo... Obrigado! + + + + Le rapport d'installation<br /><br /><b>%1</b><br /><br />a été généré. + O relatório de instalação<br /><br /><b>%1</b><br /><br />foi gerado. + + + + config_reseau_ethernet_wifi + + + Réseau Ethernet & Wifi + Ethernet & Rede Wi-Fi + + + + + Modifier + Modificar + + + + Ethernet + Ethernet + + + + + + Adresse IP + Endereço IP + + + + + + Non connecté + Não conectado + + + + Connexion à un réseau existant + Conectando-se a uma rede existente + + + + + Etat + Estado + + + + + On + ON + + + + + Off + OFF + + + + + Nom du réseau [SSID] + Nome da rede [SSID] + + + + Génération d'un réseau spécifique + Geração de uma rede específica + + + + Canal + Canal + + + + config_reseau_k_bus + + + Réseau ShipHeart + Rede ShipHeart + + + + Modules physiquement présents + Módulos fisicamente presentes + + + + %1 - %2 + %1 - %2 + + + + Modules utilisés par la configuration actuelle + Módulos usados pela configuração atual + + + + [@ %1] : %2 + [@ %1] : %2 + + + + La configuration actuelle ne fait appel à aucun autre module que ShipBase... + A configuração atual não usa nenhum outro módulo além do ShipBase... + + + + Module non utilisé en configuration + Módulo não utilizado na configuração + + + + [renfort] + [reforço] + + + + Enregistrer + Registro + + + + Retour + Retornar + + + + Quitter + Sair + + + + Aucune modification n'a été apportée à la configuration actuelle.<br />Celle-ci contient toujours des anomalies !<br /><br /><br />Souhaitez-vous :<br />Poursuivre les modifications [%1]<br />Quitter ce menu sans enregistrer les modifications [%2] + Nenhuma alteração foi feita na configuração atual.<br />Este sempre contém anomalias!<br /><br /><br />Seria:<br />Continuar editando [%1]<br />Saia deste menu sem guardar as alterações [%2] + + + + La configuration actuelle contient toujours des anomalies !<br /><br /><br />Souhaitez-vous :<br />Enregistrer cette nouvelle configuration et quitter ce menu [%1]<br />Poursuivre les modifications [%2]<br />Quitter ce menu sans enregistrer les modifications [%3] + A configuração atual ainda contém anomalias!<br /><br /><br />Seria:<br />Salve esta nova configuração e saia deste menu [%1]<br />Continuar editando [%2]<br />Saia deste menu sem guardar as alterações [%3] + + + + La configuration actuelle est correcte <br />mais n'a pas encore été enregistrée.<br /><br /><br />Souhaitez-vous :<br />Enregistrer cette nouvelle configuration et quitter ce menu [%1]<br />Poursuivre les modifications [%2]<br />Quitter ce menu sans enregistrer les modifications [%3] + A configuração atual está correta <br />mas ainda não foi registrado.<br /><br /><br />Seria:<br />Salve esta nova configuração e saia deste menu [%1]<br />Continuar editando [%2]<br />Saia deste menu sem guardar as alterações [%3] + + + + config_reseau_nmea + + + Réseau NMEA2000 + Rede NMEA2000 + + + + Aucun PGN n'a encore été détecté sur le réseau NMEA2000... + Não foi detectado qualquer PGN na rede NMEA2000 até à data... + + + + PGN non affecté + PGN não atribuído + + + + config_reseau_one_wire + + + Réseau One Wire + Rede de um fio + + + + Aucune sonde n'est encore installée... + Nenhuma sonda ainda foi instalada... + + + + 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. + O barramento One Wire está atualmente sendo curto-circuitado. <br />Este estado não apresenta nenhum perigo, mas impede que ele funcione. <br /><br />Verifique a fiação correspondente até que essa mensagem desapareça. + + + + Type inconnu + Tipo desconhecido + + + + Sonde non affectée + Sonda não afetada + + + + config_reseau_one_wire_modification + + + Configuration de la sonde [%1] + Configuração da sonda [%1] + + + + Emplacement de la sonde + Localização da sonda + + + + Enregistrer + Registro + + + + config_reseau_wifi_ap + + + Configuration Wifi en mode AP + Configuração Wi-Fi no modo AP + + + + Etat + Estado + + + + Nom du réseau (SSID) + Nome da rede (SSID) + + + + Mot de passe d'accès au réseau + Senha de acesso à rede + + + + Canal + Canal + + + + Adresse IP + Endereço IP + + + + Non connecté + Não conectado + + + + Enregistrer + Registro + + + + Off + OFF + + + + On + ON + + + + Canal %1 - [%2GHz] + Canal %1 - [%2GHz] + + + + Le nom du réseau (SSID) doit comprendre entre 1 et 32 caractères. <br />Merci d'entrer un nom valide. + O nome da rede (SSID) deve ter entre 1 e 32 caracteres. <br />Introduza um nome válido. + + + + 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. + A senha de acesso à rede deve ter entre 8 e 63 caracteres. <br />Introduza uma palavra-passe válida. + + + + 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. + O nome da rede (SSID) deve incluir apenas:<br />- letras maiúsculas [A - Z],<br />- letras minúsculas [a - z],<br />- Números [0 - 9]<br />- Caracteres especiais [%1]<br /><br />Introduza um nome válido. + + + + 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. + A senha de acesso à rede deve incluir apenas:<br />- letras maiúsculas [A - Z],<br />- letras minúsculas [a - z],<br />- Números [0 - 9]<br />- Caracteres especiais [%1]<br /><br />Introduza um nome válido. + + + + config_reseau_wifi_sta + + + Configuration Wifi en mode STA + Configuração Wi-Fi no modo STA + + + + Etat + Estado + + + + Réseau + Rede + + + + Mot de passe d'accès au réseau + Senha de acesso à rede + + + + Enregistrer + Registro + + + + Réseaux connus + Redes conhecidas + + + + Off + OFF + + + + On + ON + + + + Aucun réseau... + Sem rede... + + + + config_reseau_wifi_sta_liste + + + Liste des réseaux Wifi connus + Lista de redes Wi-Fi conhecidas + + + + Aucun réseau n'a été détecté... + Nenhuma rede foi detectada... + + + + Oublier tous les réseaux + Esqueça todas as redes + + + + Oublier ce réseau + Esquecendo esta rede + + + + config_reservoir + + + Création d'un réservoir + Criando um reservatório + + + + Configuration du réservoir + Configuração do Tanque + + + + Nom du réservoir + Nome do tanque + + + + Famille de réservoirs + Família de tanques + + + + Type de capteur de niveau + Tipo de sensor de nível + + + + %1 : Non définie + %1: Não definido + + + + %1 : %2 + %1 : %2 + + + + Sonde la plus basse dans le réservoir + Sonda mais baixa no tanque + + + + Non définie + Indefinido + + + + Logique d'alarme + Lógica de alarme + + + + Filtrage des mesures + Métricas de filtragem + + + + Créer le réservoir + Crie o Tanque + + + + Enregistrer + Registro + + + + Supprimer + Excluir + + + + Etalonnage + Calibração + + + + + AUX INPUT %1 + ENTRADA AUX %1 + + + + + LEVEL SENSOR %1 + SENSOR DE NÍVEL %1 + + + + Confirmer + Confirmar + + + + Capacité du réservoir + Capacidade do Tanque + + + + litres + Litros + + + + Logique des entrées inversée + Lógica de entrada reversa + + + + La modification du <b>type de capteur</b> va nécessiter la remise en <i>configuration usine</i> de tous les paramètres du réservoir.<br /><br />Si vous ne souhaitez pas que cette reconfiguration soit effectuée, cliquez sur ANNULER. <br /><br />Sinon, cliquez sur CONFIRMER pour valider le changement. + A alteração do <b>tipo de sensor</b> exigirá que todos os parâmetros do tanque sejam redefinidos para a <i>configuração de fábrica</i> .<br /><br />Se você não quiser que essa reconfiguração seja executada, clique em CANCELAR. <br /><br />Caso contrário, clique em CONFIRMAR para confirmar a alteração. + + + + Non défini + Indefinido + + + + Electrodes plongées ou contacts secs + Eletrodos mergulhados ou contatos secos + + + + Résistif 0 - 190Ω + Resistiva 0 - 190Ω + + + + Résistif 240 - 30Ω + Resistiva 240 - 30Ω + + + + Résistif 0 - 700Ω + Resistiva 0 - 700Ω + + + + Boucle de courant 4 - 20mA + Laço de Corrente 4 - 20mA + + + + Tension 0 - 10V + Voltagem 0 - 10V + + + + Aucun filtrage + Sem filtragem + + + + Très faible + Muito baixo + + + + Faible + Fraco + + + + Moyen + Média + + + + Elevé + Alto + + + + Très élevé + Muito alto + + + + Ce réservoir est utilisé par l'évènement ci-dessous.<br />Vous devez modifier ou supprimer cet évènement pour qu'il ne dépende plus de ce réservoir avant de pouvoir le supprimer. + Este tanque é usado pelo evento abaixo.<br />Você deve editar ou excluir esse evento para que ele não dependa mais desse pool antes de excluí-lo. + + + + Ce réservoir est utilisé par les %1 évènements ci-dessous.<br />Vous devez modifier ou supprimer ces évènements pour qu'ils ne dépendent plus de ce réservoir avant de pouvoir le supprimer. + Esse reservatório é usado pelos eventos %1 abaixo.<br />Você deve editar ou excluir esses eventos para que eles não dependam mais desse pool antes de excluí-lo. + + + + Ce réservoir est utilisé par le capteur calculé ci-dessous.<br />Vous devez modifier ou supprimer ce capteur calculé pour qu'il ne dépende plus de ce réservoir avant de pouvoir le supprimer. + Este tanque é usado pelo sensor calculado abaixo.<br />Você deve modificar ou excluir esse sensor calculado para que ele não dependa mais desse reservatório antes de excluí-lo. + + + + Ce réservoir est utilisé par les %1 capteurs calculés ci-dessous.<br />Vous devez modifier ou supprimer ces capteurs calculés pour qu'ils ne dépendent plus de ce réservoir avant de pouvoir le supprimer. + Este tanque é usado pelos sensores %1 calculados abaixo.<br />Você deve modificar ou excluir esses sensores calculados para que eles não sejam mais dependentes desse reservatório antes de excluí-lo. + + + + Alerte sur niveau faible + Alerta de baixo nível + + + + Alerte sur niveau élevé + Alerta de alto nível + + + + config_reservoirs + + + Configuration des réservoirs + Configuração do Tanque + + + + Aucun réservoir n'est encore configuré... + Nenhum tanque está configurado ainda... + + + + + + + + + + + config_ship2net + + + Ship2net + Ship2net + + + + Période des sauvegardes + Período de salvaguardas + + + + Période de connexion à Ship2net + Período de login do Ship2net + + + + Mode de validation des mises à jour + Como as atualizações são validadas + + + + Accès distant WebGL #1 + Acesso remoto WebGL nº 1 + + + + Accès distant WebGL #2 + Acesso remoto WebGL nº 2 + + + + Accès distant WebGL #3 + Acesso remoto WebGL nº 3 + + + + Enregistrer + Registro + + + + + Jamais + Nunca + + + + + 2 minutes + 2 minutos + + + + + 30 minutes + 30 minutos + + + + + 1 heure + 1 hora + + + + 2 heures + 2 horas + + + + + 4 heures + 4 horas + + + + + 12 heures + 12 horas + + + + + 24 heures + 24 horas + + + + + + Dévalidé + Desvalidado + + + + + + Valide [port %1] + Válido [porta %1] + + + + + 10 minutes + 10 minutos + + + + Aucune mise à jour + Sem atualizações + + + + Validation manuelle des mises à jour reçues + Validação manual das atualizações recebidas + + + + Validation automatique des mises à jour reçues + Validação automática das atualizações recebidas + + + + config_specifique_client_suncy + + + Configuration spécifique à Suncy Concept + Configuração específica do Suncy Concept + + + + Circuit d'activation moteur + Circuito de acionamento do motor + + + + Nouveau code + Novo Código + + + + Code d'accès au bateau + Código de acesso ao barco + + + + Répéter le code d'accès + Repita o código de acesso + + + + Enregistrer + Registro + + + + Aucune + Não + + + + [module %1 - circuit %2] %3 + [Módulo %1 - Circuito %2] %3 + + + + Les deux valeurs saisies doivent être identiques ! + +De plus, le code doit contenir : +- %1 chiffres au minimum +- %2 chiffres au maximum. + Os dois valores inseridos devem ser idênticos! + +Além disso, o código deve conter: +- Mínimo de %1 dígitos +- %2 dígitos máximos. + + + + Le nouveau code doit contenir : +- %1 chiffres au minimum +- %2 chiffres au maximum. + +Le code saisi ne répond pas à ces critères et sa mise à jour n'est donc pas effectuée. + +Merci de saisir un code au format valide si vous souhaitez le modifier. + O novo código deve conter: +- Mínimo de %1 dígitos +- %2 dígitos máximos. + +O código inserido não atende a esses critérios e, portanto, não é atualizado. + +Por favor, insira um código em um formato válido se você deseja alterá-lo. + + + + config_valeurs_niveaux + + + Aucun point de conversion n'est configuré pour le moment... + Nenhum ponto de conversão está configurado no momento... + + + + Le nombre maximal de points d'étalonnage a été atteint (%1 points)<br />Vous ne pouvez pas en ajouter sans en avoir prélablement supprimé. + O número máximo de pontos de calibração foi atingido (%1 pontos)<br />Não pode adicionar nenhum sem primeiro eliminar alguns. + + + + Courbe usine + Curva de fábrica + + + + Enregistrer + Registro + + + + La valeur lue sur les electrodes plongées de ce réservoir est incohérente.<br />Vérifier l'ordre de cablage des électrodes sur les entrées auxiliaires à l'arrière de ShipBase. + O valor lido nos elétrodos imersos deste reservatório é inconsistente.<br />Verifique a ordem da cablagem dos elétrodos nas entradas auxiliares na parte traseira do ShipBase. + + + + Aucune donnée n'est disponible... + Não há dados disponíveis... + + + + 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. + Você fez alterações que não foram salvas<br />Clique em Cancelar para voltar e salvá-los.<br />Clique em OK para sair sem salvar. + + + + Aucun point n'est actuellement configuré pour cette batterie... + No momento, não há pontos configurados para este farm... + + + + + Courbe de conversion de [%1] + Curva de conversão de [%1] + + + + Aucun réservoir n'est actuellement configuré... + Nenhum tanque está configurado no momento... + + + + Aucun point n'est actuellement configuré pour cet élément... + No momento, não há pontos configurados para este item... + + + + Courbe de conversion de type INCONNU + Curva de conversão do tipo UNKNOWN + + + + config_version + + + Version + Versão + + + + %1 : %2 + %1 : %2 + + + + 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 : + A versão <b>%1</b> está disponível.<br /><br />Ele será instalado automaticamente na próxima vez que você iniciar o ShipHeart.<br />A menos que você escolha uma das opções abaixo: + + + + La version <b>%1</b> est disponible.<br /><br />Souhaitez-vous : + A versão <b>%1</b> está disponível.<br /><br />Seria: + + + + + L'installer +maintenant + Instale-o +Agora + + + + L'installer au prochain démarrage de ShipHeart + Instale-o na próxima vez que iniciar o ShipHeart + + + + + Ne jamais l'installer + Nunca o instale + + + + Supprimer + Excluir + + + + Si vous confirmez, cette mise à jour sera définitivement supprimée.<br />Cliquez sur Annuler pour revenir en arrière et la conserver. + Se você confirmar, esta atualização será excluída permanentemente.<br />Clique em Cancelar para voltar e mantê-la. + + + + Installer + Instalar + + + + 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 la conserver pour une installation ultérieure. + Se você confirmar, esta atualização poderá levar <u>alguns minutos</u> durante os quais <b>seu sistema ShipHeart não estará acessível</b>.<br /><br />Você não precisa confirmar o instalação somente se você estiver em uma situação segura (no porto, fundeado, etc.) e a perda de controle de seus sistemas de bordo durante este período de tempo não apresentar nenhum perigo!<br /><br />Clique em Cancele para voltar e salvá-lo para instalação posterior. + + + + 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 'shipheart.tech' ou de nous contacter à l'adresse 'contact@shipheart.tech'. + 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 'shipheart.tech' ou de nous contacter à l'adresser 'contact@shipheart.tech'. + Este produto é projetado e fabricado pela empresa Koriolan, que detém todas as licenças e direitos de exploração sobre as imagens, software e patentes utilizadas tanto para o seu design como para o seu funcionamento. ShipHeart™, Ship2net™ e Koriolan são marcas registradas da empresa Koriolan™. Se você tiver alguma dúvida sobre este produto, visite o site 'shipheart.tech' ou entre em contato conosco em 'contact@shipheart.tech'. + + + + Version du package logiciel + Versão do pacote de software + + + + Version de l'application + Versão do aplicativo + + + + Version de l'interface graphique + Versão da GUI + + + + Version du firmware du modem + Versão do firmware do modem + + + + Numéro d'IMEI + Número IMEI + + + + Numéro d'ICCID + Número ICCID + + + + Numéro d'IMSI + Número IMSI + + + + ephemeride + + + Ephéméride + Efeméride + + + + Heure d'hiver + Horário de inverno + + + + Heure d'été + Horário de verão + + + + Aube nautique + Alvorada Náutica + + + + Lever du soleil + Nascer do sol + + + + Zénith + Zênite + + + + Coucher du soleil + Ocaso + + + + Crépuscule nautique + Crepúsculo Náutico + + + + Lune + Lua + + + + Latitude + Latitude + + + + Longitude + Longitude + + + + etalonnage_capteur + + + Etalonnage du capteur [%1] + Calibração do sensor [%1] + + + + Valeur brute actuelle + Valor Bruto Presente + + + + Valeur corrigée actuelle (%1) + Valor corrigido atual (%1) + + + + Correction + Correção + + + + Enregistrer + Registro + + + + etalonnage_carte + + + Etalonnage du module [%1 - #%2] + Calibração do módulo [%1 - #%2] + + + + Point 1 + Item 1 + + + + Point 2 + Item 2 + + + + Courant de décharge + Corrente de descarga + + + + Courant différentiel + Corrente diferencial + + + + + Recalculer ce point + Recalcular este ponto + + + + + Mémoriser ce point + Memorizando este ponto + + + + Off + OFF + + + + On + ON + + + + On (%1 %%) + Em (%1%%) + + + + Enregistrer + Registro + + + + Aide + Ajuda + + + + 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 /> + A calibração não pode ser feita com dois pontos idênticos.<br /><br /> + Tente modificar pelo menos um dos dois pontos de referência jogando com o controle de circuito abaixo.<br /> + + + + 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. + O princípio da calibração é comparar em 2 pontos diferentes o valor diferencial de corrente medido pelo ShipBS, por um lado, e + a corrente de descarga medida pelo sistema ShipHeart, por outro lado. + Por exemplo, submetendo o ShipBS que está sendo calibrado a baixa ou nenhuma potência (primeiro ponto) + em seguida, ligando um ou mais dispositivos para obter um consumo de vários amperes, se possível (segundo ponto). + Muito importante : durante toda a fase de calibração, nenhuma corrente de carregamento deve ser aplicada no ShipBS! + Portanto, é essencial desconectar todos os carregadores, controladores solares, etc. durante a calibração. + Caso contrário, os valores de calibração estarão incorretos... + Observações: + - todo o consumo deve passar pelo sistema ShipHeart! Portanto, é necessário garantir que nenhuma carga esteja conectada diretamente + para o banco de baterias. + - Os valores atuais não importam. + - a corrente do ponto 2 pode ser inferior ou superior à do ponto 1 (mas o mais "longe" possível uma da outra). + - É aconselhável escolher cargas cujo consumo seja relativamente estável ou, no mínimo, mude pouco ao longo de um período de poucos segundos. + + + + fonctions + + + Modèle inconnu + Modelo desconhecido + + + + Circuit + Circuito + + + + Capteur + Sensor + + + + Réservoir + Reservatório + + + + Batterie + Bateria + + + + Type inconnu + Tipo desconhecido + + + + Consigne + Vestiário + + + + + + Tension + Tensão + + + + Courant + Atual + + + + Fréquence + Frequência + + + + + Puissance + Poder + + + + + Energie + Energia + + + + Température + Temperatura + + + + Courant différentiel + Corrente diferencial + + + + Courant de charge + Corrente de carregamento + + + + Courant de décharge + Corrente de descarga + + + + SOH (state Of Health) + SOH (estado de saúde) + + + + SOC (State Of Charge) + SOC (Estado de Carga) + + + + Autonomie + Autonomia + + + + fonctions_date_heure + + + 1 heure + 1 hora + + + + 24 heures + 24 horas + + + + 7 jours + 7 dias + + + + 30 jours + 30 dias + + + + Fin de nuit + Tarde da noite + + + + Aube nautique + Alvorada Náutica + + + + Aube + Amanhecer + + + + Lever du soleil + Nascer do sol + + + + Zénith + Zênite + + + + Coucher du soleil + Ocaso + + + + Crépuscule + Crepúsculo + + + + Crépuscule nautique + Crepúsculo Náutico + + + + Début de nuit + Noite cedo + + + + %1h + %1h + + + + Dimanche + Domingo + + + + Lundi + Segunda-feira + + + + Mardi + Terça-feira + + + + Mercredi + Quarta-feira + + + + Jeudi + Quinta-feira + + + + Vendredi + Sexta-feira + + + + Samedi + Sábado + + + + Tous les jours + Todos os dias + + + + janvier + Janeiro + + + + février + Fevereiro + + + + mars + Março + + + + avril + Abril + + + + mai + Maio + + + + juin + Junho + + + + juillet + Julho + + + + août + Agosto + + + + septembre + Setembro + + + + octobre + Outubro + + + + novembre + Novembro + + + + décembre + Dezembro + + + + fonctions_historique + + + Commande 'OFF' du circuit %1 + Comando 'OFF' do circuito %1 + + + + Commande 'ON' du circuit %1 + Comando do circuito 'ON' %1 + + + + Commande à %1 % du circuit %2 + Ordem em %1% do circuito %2 + + + + Le circuit %1 est revenu à son état de fonctionnement normal + O circuito %1 voltou ao status normal de operação + + + + L'alimentation du circuit %1 a été coupée car sa limite de courant (%2 A) a été dépassée + A fonte de alimentação do circuito %1 foi cortada porque seu limite de corrente (%2 A) foi excedido + + + + L'alimentation du circuit %1 a été coupée car les circuits de protection interne ont détecté une anomalie + A alimentação do circuito %1 foi cortada porque os circuitos internos de proteção detectaram uma anomalia + + + + L'alimentation du circuit %1 a été coupée car le seuil de disjonction a été dépassé + A alimentação do circuito %1 foi cortada porque o limite de disjunção foi excedido + + + + Le circuit %1 est en court-circuit avec le + batterie + O circuito %1 é curto com a bateria + + + + + L'alimentation du circuit %1 a été coupée car la consommation totale du module a été dépassé + A fonte de alimentação do circuito %1 foi cortada porque o consumo total do módulo foi excedido + + + + Le circuit %1 a été créé + O circuito %1 foi criado + + + + La configuration du circuit %1 a été modifiée + A configuração do circuito %1 foi alterada + + + + Le circuit %1 a été supprimé + O circuito %1 foi removido + + + + La configuration du circuit %1 est invalide car le module sur lequel le circuit est configuré n'est pas présent + A configuração do circuito %1 é inválida porque o módulo no qual o circuito está configurado não está presente + + + + Le circuit %1 a fonctionné trop longtemps (> %2 secondes). Il a donc été désactivé automatiquement. + O circuito %1 está funcionando há muito tempo (>%2 segundos). Por isso, foi desativado automaticamente. + + + + Evénement de type CIRCUITS avec code de sous-type inconnu [%1] + Evento do tipo CIRCUITS com código de subtipo desconhecido [%1] + + + + Le capteur %1 est repassé à l'état normal + O sensor %1 voltou ao normal + + + + Le capteur %1 est passé à l'état ALERTE + O sensor %1 foi movido para o estado ALERT + + + + Le capteur %1 est passé à l'état ALARME + O sensor %1 foi movido para o estado ALARM + + + + Evénement de type CAPTEURS avec code de sous-type inconnu [%1] + Evento SENSORS com código de subtipo desconhecido [%1] + + + + Le niveau de charge de la batterie %1 est repassé au niveau normal + O nível de carga da bateria %1 voltou ao normal + + + + Le niveau de charge de la batterie %1 est passé en dessous du niveau d'alerte + O nível de carga da bateria %1 caiu abaixo do nível de alerta + + + + Le niveau de charge de la batterie %1 est passé au-dessus du niveau d'alarme (il est maintenant au niveau d'alerte uniquement) + O nível de carga da bateria %1 foi movido acima do nível de alarme (agora está apenas no nível de alerta) + + + + Le niveau de charge de la batterie %1 est passé en-dessous du niveau d'alarme + O nível de carga da bateria %1 caiu abaixo do nível de alarme + + + + Evénement de type BATTERIES avec code de sous-type inconnu [%1] + Evento BATTERIES com código de subtipo desconhecido [%1] + + + + Le niveau du réservoir %1 est repassé au niveau normal + O nível do tanque %1 voltou ao nível normal + + + + Le niveau du réservoir %1 est passé en dessous du niveau d'alerte + O nível do tanque %1 se moveu abaixo do nível de alerta + + + + Le niveau du réservoir %1 est passé au-dessus du niveau d'alarme (il est maintenant au niveau d'alerte uniquement) + O nível do tanque %1 se moveu acima do nível de alarme (agora está apenas no nível de alerta) + + + + Le niveau du réservoir %1 est passé en-dessous du niveau d'alarme + O nível do tanque %1 caiu abaixo do nível de alarme + + + + Evénement de type RESERVOIRS avec code de sous-type inconnu [%1] + Evento do tipo RESERVOIRS com código de subtipo desconhecido [%1] + + + + La consigne des ports USB est passée à %1 + Conjunto de portas USB alterado para %1 + + + + L'état des ports USB est redevenu normal + O estado das portas USB voltou ao normal + + + + Défaut détecté sur les ports USB + Falha detectada nas portas USB + + + + Evénement de type USB avec code de sous-type inconnu [%1] + Evento de tipo USB com código de subtipo desconhecido [%1] + + + + Evénement de type INCONNU (avec code de sous-type [%1] + Evento do tipo UNKNOWN (com código de subtipo [%1] + + + + home + + + Aucun circuit n'est configuré pour ce groupe...<br /><br />Si ce groupe n'a pas d'utilité, vous pouvez le supprimer dans le menu [Circuits] des Paramètres Avancés. + Nenhum circuito está configurado para este grupo...<br /><br />Se esse grupo não for necessário, você poderá excluí-lo no menu [Faixas] em Configurações avançadas. + + + + Aucun capteur n'est configuré pour ce groupe...<br /><br />Si ce groupe n'a pas d'utilité, vous pouvez le supprimer dans le menu [Capteurs] des Paramètres Avancés. + Nenhum sensor está configurado para este grupo...<br /><br />Se esse grupo não for necessário, você poderá excluí-lo no menu [Sensores] em Configurações avançadas. + + + + Aucun réservoir n'est configuré pour ce groupe...<br /><br />Si ce groupe n'a pas d'utilité, vous pouvez le supprimer dans le menu [Réservoirs] des Paramètres Avancés. + Nenhum tanque está configurado para este grupo...<br /><br />Se esse grupo não for necessário, você poderá excluí-lo no menu [Tanques] em Configurações avançadas. + + + + Aucun parc de batterie n'est configuré pour ce groupe...<br /><br />Si ce groupe n'a pas d'utilité, vous pouvez le supprimer dans le menu [Batteries] des Paramètres Avancés. + Nenhum banco de baterias está configurado para este grupo...<br /><br />Se esse grupo não for necessário, você poderá excluí-lo no menu [Baterias] em Configurações avançadas. + + + + Cette page est actuellement en travaux. <br />Elle sera rendue disponible très rapidement à travers une mise à jour.<br /><br />Merci de votre patience...<br /><br />L'équipe ShipHeart + Esta página está atualmente em construção. <br />Ele será disponibilizado muito rapidamente através de uma atualização.<br /><br />Obrigado por sua paciência...<br /><br />A Equipe ShipHeart + + + + + + Déconnecté + Desconectado + + + + Nombre de satellites visibles + Número de satélites visíveis + + + + + Connecté + Conectado + + + + + OFF + OFF + + + + + ON + ON + + + + Niveau + Nível + + + + Actif + Ativo + + + + Inactif + Inativo + + + + + + <b>%1</b> + <b>%1</b> + + + + Démarrage + Inicialização + + + + Firmware de <b>ShipBase</b> + <b>Firmware do ShipBase</b> + + + + Firmware du <b>ShipPower812</b> à l'adresse <b>%1</b> + <b>Firmware ShipPower812</b> em <b>%1</b> + + + + Firmware du <b>ShipBS</b> à l'adresse <b>%1</b> + <b>Firmware do ShipBS</b> em <b>%1</b> + + + + Firmware du <b>ShipPower4AC</b> à l'adresse <b>%1</b> + <b>Firmware ShipPower4AC</b> em <b>%1</b> + + + + Firmware du <b>ShipPower8DC</b> à l'adresse <b>%1</b> + <b>Firmware ShipPower8DC</b> em <b>%1</b> + + + + Firmware du module à l'adresse <b>%1</b> + Firmware do módulo em <b>%1</b> + + + + Merci de patienter et de ne rien débrancher<br />avant la fin de la mise à jour. + Por favor, seja paciente e não desligue nada<br />antes que a atualização seja concluída. + + + + Chargement des mises à jour effectué avec succès !<br /><br />L'activation des nouvelles version est en cours sur tous les modules concernés.<br /><br />Merci de patienter encore quelques secondes... + Carregamento de atualizações com sucesso!<br /><br />A ativação das novas versões está em andamento em todos os módulos envolvidos.<br /><br />Aguarde mais alguns segundos... + + + + ShipHeart va redémarrer pour effectuer une mise à jour.<br /><br />Cette opération va prendre quelques minutes au maximum.<br />Merci de patienter et de ne rien débrancher jusqu'au redémarrage final... + O ShipHeart será reiniciado para executar uma atualização.<br /><br />Esta operação levará alguns minutos no máximo.<br />Por favor, seja paciente e não desconecte nada até a reinicialização final... + + + + Votre système ShipHeart est dorénavant équipé de la version<br /><br /><b>%1</b><br /><br />(la version précédente était la %2) + O seu sistema ShipHeart está agora equipado com o<br /><br /><b>%1</b><br /><br />(a versão anterior era %2) + + + + Le nombre de modules détectés sur le réseau ShipHeart est insuffisant par rapport à la configuration du bateau.<br /><br />Vérifiez les connexions entre le module <b>%1</b> à la <b>position @%2</b> %3 et le module <b>%4</b> suivant%5<br /><br />Vous pouvez visualiser l'état complet du réseau ShipHeart et les anomalies détectées dans le menu 'Réseau > ShipHeart' dans les Paramètres Avancés + O número de módulos detectados na rede ShipHeart é insuficiente em comparação com a configuração do barco.<br /><br />Verifique as conexões entre o módulo <b>%1</b> na <b>posição @%2</b> %3 e o módulo <b>%4</b> próximo %5<br /><br />Você pode ver o status completo da rede ShipHeart e anomalias detectadas no menu 'ShipHeart > Network' nas Configurações avançadas + + + + Le modules détecté en <b>position @%1</b> est un <b>%2</b>. Cela ne correspond pas à la configuration actuelle du bateau (<b>%3</b>).<br /><br />Cela peut provenir de l'ajout, de la suppression ou d'un déplacement de module.<br /><br />Vous pouvez visualiser toutes les anomalies détectées et les corriger dans le menu 'Réseau > ShipHeart' dans les Paramètres Avancés + Os módulos detectados na <b>posição @%1</b> é um <b>%2</b>. Isso não corresponde à configuração atual do barco (<b>%3</b>).<br /><br />Isso pode vir da adição, remoção ou movimentação de um módulo.<br /><br />Você pode visualizar todas as anomalias detectadas e corrigi-las no menu 'ShipHeart > Network' em Configurações avançadas + + + + Code inconnu + Código desconhecido + + + + home_accueil + + + Bienvenue à bord de + Bem-vindo a bordo + + + + home_suncy + + + L'accès au bateau est protégé. +Merci d'entrer votre code de déverrouillage pour y accéder... + O acesso ao barco é protegido. +Por favor, insira seu código de desbloqueio para acessá-lo... + + + + journal_de_bord + + + + + + Tous + Todo + + + + Batteries + Baterias + + + + Capteurs + Sensores + + + + Circuits + Circuitos + + + + Réservoirs + Tanques + + + + Système + Sistema + + + + Ports USB + Portas USB + + + + Journal de bord + Diário + + + + Aucun type n'est configuré... + Nenhum tipo está configurado... + + + + %1<br /><br /><br />%2 + %1<br /><br /><br />%2 + + + + Aucune entrée d'historique n'est disponible pour cette sélection... + Não há entradas de histórico disponíveis para esta seleção... + + + + Toutes + Todo + + + + main + + + Type d'installation : +0 : ShipBase standard, +1 : écran déporté + Tipo de instalação: +0: ShipBase padrão, +1: tela remota + + + + + valeur + valor + + + + Adresse IPv4 de ShipBase dans le cas d'une installation déportée + Endereço IPv4 do ShipBase no caso de uma instalação remota + + + + xxx:xxx:xxx:xxx + xxx:xxx:xxx:xxx + + + + Taille de l'écran en pouces : +7, +10 (ShipBase standard), +22 + Tamanho da tela em polegadas: +7, +10 (padrão ShipBase), +22 + + + + Original + Original + + + + Sombre + Escuro + + + + Métallique + Metálico + + + + Triangles + Triângulos + + + + Sable + Areia + + + + Thème 5 + Tema 5 + + + + Thème 6 + Tema 6 + + + + Thème 7 + Tema 7 + + + + Thème 8 + Tema 8 + + + + page_personnalisee + + + <i>--- Circuit non affecté ---</i> + <i>--- Circuito não afetado---</i> + + + + [renfort] + [reforço] + + + + <i>--- Aucune batterie affectée ---</i> + <i>--- Nenhuma bateria afetada---</i> + + + + parametres + + + Paramètres + Parâmetros + + + + Langue + Língua + + + + Températures + Temperaturas + + + + Volumes + Volumes + + + + Affichage + Exposição + + + + Date et heure + Data e hora + + + + Protection + Proteção + + + + Son + Som + + + + Luminosité + Luminosidade + + + + Economiseur d'écran : désactivé + Proteção de tela: Desativado + + + + Economiseur d'écran : normal + Protetor de tela: Normal + + + + Flash LEDs : désactivé + Flash LED: Desligado + + + + Flash LEDs : normal + Flash LED: normal + + + + Nettoyage de l'écran + Limpeza de tela + + + + Heure d'été + Horário de verão + + + + Heure d'hiver + Horário de inverno + + + + Verrouiller le bateau + Bloqueie o barco + + + + parametres_avances + + + Paramètres avancés + Configurações avançadas + + + + Réseaux + Redes + + + + Cette page est actuellement en travaux. <br />Elle sera rendue disponible très rapidement à travers une mise à jour.<br /><br />Merci de votre patience...<br /><br />L'équipe ShipHeart + Esta página está atualmente em construção. <br />Ele será disponibilizado muito rapidamente através de uma atualização.<br /><br />Obrigado por sua paciência...<br /><br />A Equipe ShipHeart + + + + Circuits + Circuitos + + + + Réservoirs + Tanques + + + + Batteries + Baterias + + + + Capteurs + Sensores + + + + Menu accueil + Menu inicial + + + + Evènements + Eventos + + + + ShipHeart + Coração de navio + + + + Ethernet & Wifi + Ethernet & Wifi + + + + One Wire + Um fio + + + + NMEA 2000 + NMEA 2000 + + + + J1939 + J1939 + + + + DMX + DMX + + + + Journal de bord + Diário + + + + Vos paramètres + Suas configurações + + + + Votre installation + Sua instalação + + + + Système + Sistema + + + + Affichage + Exposição + + + + Audio + Áudio + + + + Ship2net + Ship2net + + + + Accès au paramètres + Acesso às configurações + + + + Configuration ShipRS + Configuração ShipRS + + + + Installation + Instalação + + + + Version + Versão + + + + Accès réservé Koriolan + Acesso reservado Koriolan + + + + Spécifique Suncy + Suncy Específico + + + + protection + + + Accès protégé + Acesso protegido + + + + L'accès aux paramètres avancés est protégé. +Merci d'entrer le code de déverrouillage pour y accéder... + O acesso às configurações avançadas é protegido. +Por favor, insira o código de desbloqueio para acessá-lo... + + + + Mode administrateur validé<br />Entrer votre code dédié + Modo de administração validado<br />Digite seu código dedicado + + + + reservoir + + + [ %1 % ] + [ %1 % ] + + + + Le module assurant la supervision de ce réservoir n'est pas accessible !<br /><br />Si des ajouts/suppression/déplacements de modules ont eu lieu récemment, mettez à jour la configuration correspondant dans le menu MODULES de PARAMETRES AVANCES.<br /><br />Dans le cas où aucune modification n'a été effectuée récemment, vérifier les connexions de tous les modules. + O módulo que supervisiona este tanque não é acessível!<br /><br />Se houve adições/releções/movimentações recentes de módulos, atualize a configuração correspondente no menu MÓDULOS de CONFIGURAÇÕES AVANÇADAS.<br /><br />Caso nenhuma alteração tenha sido feita recentemente, verifique as conexões de todos os módulos. + + + + Niveau + Nível + + + + La valeur lue sur les electrodes plongées de ce réservoir est incohérente.<br />Vérifier l'ordre de cablage des électrodes sur les entrées auxiliaires à l'arrière de ShipBase. + O valor lido nos eletrodos mergulhados deste tanque é inconsistente.<br />Verifique a ordem de fiação dos eletrodos nas entradas auxiliares na parte traseira do ShipBase. + + + + Aucune donnée n'est disponible pour cette période + Não há dados disponíveis para este período + + + + shipheart_test_config + + + Vitesse de test de l'écran + Velocidade de teste de tela + + + + Nombre de colonnes de test du touchpad + Número de colunas de teste do touchpad + + + + Nombre de lignes de test du touchpad + Número de linhas de teste do touchpad + + + + shipheart_test_home + + + Tests matériel + Teste de hardware + + + + Configuration des tests + Configuração de teste + + + + Test du backlight + Teste de luz de fundo + + + + Test de l'écran + Teste de tela + + + + Test du touchpad + Teste do touchpad + + + + Liste des fonts disponibles + Lista de fontes disponíveis + + + + shipheart_test_liste_fonts + + + Liste des fonts disponibles + Lista de fontes disponíveis + + + + test_batterie + + + Batteries de servitude + Baterias de Serviço + + + + Autonomie optimale + Autonomia ideal + + + + Autonomie actuelle + Duração atual da bateria + + + + Autonomie<br />maximale + Autonomia<br />Máximo + + + + dans + em + + + + environ + aproximadamente + + + + test_tri_liste + + + TEST DE TRI DE LISTE + TESTE DE CLASSIFICAÇÃO DE LISTA + + + diff --git a/shipheart_test_backlight.qml b/shipheart_test_backlight.qml new file mode 100644 index 0000000..7afb5e5 --- /dev/null +++ b/shipheart_test_backlight.qml @@ -0,0 +1,257 @@ +import QtQuick 2.12 +import QtQuick.Controls 2.12 + +import qt.koriolan.shipheart 1.0 + + +Shipheart_page { + id: page_parametres + + + readonly property int periode_init_raffraichissement_parametres: 1 // En ms + readonly property int periode_raffraichissement_parametres: 1000 // En ms + + property var table_backlight: [0, 13.75, 26.30, 37.85, 48.54, 58.50, 67.81, 76.55, 84.80, 92.60, 100.00] // Les valeurs correspondent à 0, 10%, 20%,... 90%, 100% + + // Modèles : + property Bdd bdd : Bdd{} + + + + //=========================================================== + // 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(); + } + + } + } + + // Titre de la page : + Shipheart_titre_1 {titre:"Paramètres"; hauteur: shipheart_hauteur_bandeau_haut} + + + + + + //------------------------------------------------------- + // Ecran bas - Droite : + //------------------------------------------------------- + Rectangle { + id: zone_affichage_slider_backlight + anchors.fill: parent + color: "white" + + Slider { + id: slider_backlight + + y: shipheart_hauteur_titre_2 + width: parent.width * 0.7 + height: 100 + padding: 0 + anchors { + horizontalCenter: parent.horizontalCenter + } + from: 20 + value: 25 + to: 100 + stepSize:1 // Permet de n'avoir que des valeurs en %, sans décimales (il est probable que cela accélère le traitement mais pas vérifié...) + + background: Rectangle { + x: parent.leftPadding + y: 0 + width: parent.width + height: parent.height + radius: shipheart_rayon_bouton + color: shipheart_couleur_fond_bouton + + Rectangle { + width: slider_backlight.visualPosition * parent.width + height: parent.height + color: shipheart_couleur_texte_slider + radius: shipheart_rayon_bouton + Behavior on width { + NumberAnimation { + properties:"width" + duration: 350 + easing.type: Easing.OutQuad + } + } + Text { // Affichage de la valeur dans la barre + text: slider_backlight.value.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: 18 + font.weight: Font.Bold + color: couleur_blanc_casse + } + } + } + handle: Rectangle { + x: parent.leftPadding + (parent.visualPosition * (parent.availableWidth - width)) + y: (parent.availableHeight / 2) - (height / 2) + implicitWidth: 80 // Le bouton n'étant pas visible + implicitHeight: parent.height + color: "transparent" + visible: false + } + + onMoved: { + shipheart_clic(); + if (!timer_time_out_backlight.running) + { + timer_time_out_backlight.running = true + + var req + req = 'UPDATE TB_Configuration SET Valeur="' + consigne_backlight(slider_backlight.value).toFixed(2) + '" WHERE Nom="Consigne_backlight" ' + bdd.requete_unique(req); + synchro_bdd(shipheart_type_synchro_data); +//console.log("ON MOVED : Nouvelle valeur de backlight = " + value + " et la requête est : " + req) + } + } + Timer { // Timer qui permet de brider les envoi de mise à jour dans la BDD + id: timer_time_out_backlight + interval: 200 + triggeredOnStart: false + running: false + repeat: false + onTriggered: { // Permet d'être sûr que la dernière position est bien enregistrée dans la BDD, même si l'arrêt s'est produit pendant que le timer tournait + var req + req = 'UPDATE TB_Configuration SET Valeur="' + consigne_backlight(slider_backlight.value).toFixed(2) + '" WHERE Nom="Consigne_backlight" ' + bdd.requete_unique(req); + req = 'UPDATE TB_Configuration SET Valeur="' + consigne_backlight(slider_backlight.value).toFixed(2) + '" WHERE Nom="Consigne_leds" ' + bdd.requete_unique(req); + synchro_bdd(shipheart_type_synchro_data); +//console.log("TIMER : Nouvelle valeur de backlight = " + slider_backlight.value + " et la requête est : " + req) + } + } + } + } + + + //------------------------------------------------------- + // 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: shipheart_largeur_page / nombre_colonnes_matrice_test + height: shipheart_hauteur_bandeau_bas - parent.topPadding - parent.bottomPadding; + radius: shipheart_rayon_bouton + color: "transparent" + + 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 + pressAndHoldInterval: shipheart_mouse_press_and_hold_interval_court + onClicked: { + stackView.pop() + } + } + } + + + } + + + //============================================================================================================= + // Init de la page + //============================================================================================================= + function init_page() + { + mise_a_jour_table_backlight(); + } + + + + + + + //============================================================================================================= + // Mise à jour de la table de correspondace du backlight + //============================================================================================================= + function mise_a_jour_table_backlight() + { + var req, res; + var i; + var nb; + var val; + + + // Récupération de la valeur actuelle du backlight : + var consigne; + var rang; + res = bdd.requete_unique('SELECT Valeur FROM TB_Configuration WHERE Nom="Consigne_backlight" '); + consigne = Number(res[0]); + + if (consigne < 0) rang = -1; + else if (consigne < table_backlight[1]) rang = 0; + else if (consigne < table_backlight[2]) rang = 1; + else if (consigne < table_backlight[3]) rang = 2; + else if (consigne < table_backlight[4]) rang = 3; + else if (consigne < table_backlight[5]) rang = 4; + else if (consigne < table_backlight[6]) rang = 5; + else if (consigne < table_backlight[7]) rang = 6; + else if (consigne < table_backlight[8]) rang = 7; + else if (consigne < table_backlight[9]) rang = 8; + else if (consigne < table_backlight[10]) rang = 9; + else if (consigne < table_backlight[11]) rang = 10; + else rang = 11; + + if (rang < 0) slider_backlight.value = 0; + else if (rang > 10) slider_backlight.value = 100; + else slider_backlight.value = (10 * (rang + 1)) - (10 * (table_backlight[rang + 1] - consigne) / (table_backlight[rang + 1] - table_backlight[rang])); + } + + //============================================================================================================= + // Calcul de la consigne du backlight en fonction de la position du slider + //============================================================================================================= + function consigne_backlight(pc) + { + var i; + var a, b; + var val; + + if (pc <= 0) return (0); + if (pc >= 100) return (100); + + i = Math.trunc(pc / 10); + +//console.log("Conversion Backlight : PC=" + Number(pc) + " i=" + Number(i) + " et valeur de retour =" + (((table_backlight[i+1] - table_backlight[i]) * (pc % 10) / 10) + table_backlight[i])); + return ((table_backlight[i+1] - table_backlight[i]) * (pc % 10) / 10) + table_backlight[i]; + } + + + +} + diff --git a/shipheart_test_config.qml b/shipheart_test_config.qml new file mode 100644 index 0000000..871ab43 --- /dev/null +++ b/shipheart_test_config.qml @@ -0,0 +1,366 @@ +import QtQuick 2.12 +import QtQml.Models + +import qt.koriolan.shipheart 1.0 + + +Shipheart_page { + id: page_config_circuit + + + // 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.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 int protection_mode: 0 + + + // Données : + + + + // Modèles : + property Bdd bdd : Bdd{} + + + + + + + + + //=========================================================== + // 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:"Configuration des tests"; 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 : Vitesse de test écran + Rectangle { + width: parent.width + height: visible ? hauteur_ligne_formulaire : 0 + color: "transparent" + + Shipheart_formulaire_label { + text: qsTr("Vitesse de test de l'écran") + width: parent.width * pourcentage_largeur_labels_formulaire + } + + Shipheart_formulaire_combobox { + id: champ_formulaire_Vitesse_test_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 + } + } + + //------------------------------------------------------------------------------- + // Ligne de formulaire : Nombre colonnes de la matrice de test + Rectangle { + width: parent.width + height: visible ? hauteur_ligne_formulaire : 0 + color: "transparent" + + Shipheart_formulaire_label { + text: qsTr("Nombre de colonnes de test du touchpad") + width: parent.width * pourcentage_largeur_labels_formulaire + } + + Shipheart_formulaire_combobox { + id: champ_formulaire_Nombre_colonnes_matrice_test + 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 : Nombre lignes de la matrice de test + Rectangle { + width: parent.width + height: visible ? hauteur_ligne_formulaire : 0 + color: "transparent" + + Shipheart_formulaire_label { + text: qsTr("Nombre de lignes de test du touchpad") + width: parent.width * pourcentage_largeur_labels_formulaire + } + + Shipheart_formulaire_combobox { + id: champ_formulaire_Nombre_lignes_matrice_test + 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 + Text { + anchors { + verticalCenter: parent.verticalCenter + horizontalCenter: parent.horizontalCenter + } + font.pixelSize: 20 + text: "Enregistrer" + color: couleur_blanc_casse + } + MouseArea { + anchors.fill: parent + pressAndHoldInterval: shipheart_mouse_press_and_hold_interval_tres_court + onPressAndHold: { + shipheart_test_vitesse_test_ecran = champ_formulaire_Vitesse_test_ecran.model.get(champ_formulaire_Vitesse_test_ecran.currentIndex).valeur + nombre_colonnes_matrice_test = champ_formulaire_Nombre_colonnes_matrice_test.model.get(champ_formulaire_Nombre_colonnes_matrice_test.currentIndex).valeur + nombre_lignes_matrice_test = champ_formulaire_Nombre_lignes_matrice_test.model.get(champ_formulaire_Nombre_lignes_matrice_test.currentIndex).valeur + 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: { // Si la pression n'a pas duré assez longtemps, on ne fait rien + stackView.pop() + } + } + } + } + + + + + + + //============================================================================================================= + // Init de la page + //============================================================================================================= + function init_page() + { + var i, j; + + //--------------------------------------------------------------------------------------- + // Vitesse de test d'écran : + champ_formulaire_Vitesse_test_ecran.model.clear(); + champ_formulaire_Vitesse_test_ecran.model.append({"valeur": 500, "texte": "Très rapide (500ms par page)" }); + champ_formulaire_Vitesse_test_ecran.model.append({"valeur": 1000, "texte": "Rapide (1s par page)" }); + champ_formulaire_Vitesse_test_ecran.model.append({"valeur": shipheart_test_vitesse_test_ecran, "texte": "Moyenne (1.5s par page)" }); + champ_formulaire_Vitesse_test_ecran.model.append({"valeur": 2000, "texte": "Lente (2s par page)" }); + champ_formulaire_Vitesse_test_ecran.model.append({"valeur": 3000, "texte": "Très lente (3s par page)" }); + + // Positionnement de l'index sur la valeur en cours : + i = recherche_index_valeur_modele(shipheart_test_vitesse_test_ecran, champ_formulaire_Vitesse_test_ecran.model, "Vitesse_test_ecran"); + if (i === -1) champ_formulaire_Vitesse_test_ecran.currentIndex = 2; + else champ_formulaire_Vitesse_test_ecran.currentIndex = i; + + + //--------------------------------------------------------------------------------------- + // Nombre de colonnes de la matrice de test : + champ_formulaire_Nombre_colonnes_matrice_test.model.clear(); + champ_formulaire_Nombre_colonnes_matrice_test.model.append({"valeur": 4, "texte": "4" }); + champ_formulaire_Nombre_colonnes_matrice_test.model.append({"valeur": 5, "texte": "5" }); + champ_formulaire_Nombre_colonnes_matrice_test.model.append({"valeur": 6, "texte": "6" }); + champ_formulaire_Nombre_colonnes_matrice_test.model.append({"valeur": 7, "texte": "7" }); + champ_formulaire_Nombre_colonnes_matrice_test.model.append({"valeur": 8, "texte": "8" }); + champ_formulaire_Nombre_colonnes_matrice_test.model.append({"valeur": 9, "texte": "9" }); + champ_formulaire_Nombre_colonnes_matrice_test.model.append({"valeur": 10, "texte": "10" }); + champ_formulaire_Nombre_colonnes_matrice_test.model.append({"valeur": 11, "texte": "11" }); + champ_formulaire_Nombre_colonnes_matrice_test.model.append({"valeur": 12, "texte": "12" }); + + // Positionnement de l'index sur la valeur en cours : + i = recherche_index_valeur_modele(nombre_colonnes_matrice_test, champ_formulaire_Nombre_colonnes_matrice_test.model, "Nombre_colonnes_matrice_test"); + if (i === -1) champ_formulaire_Nombre_colonnes_matrice_test.currentIndex = 2; + else champ_formulaire_Nombre_colonnes_matrice_test.currentIndex = i; + + //--------------------------------------------------------------------------------------- + // Nombre de lignes de la matrice de test : + champ_formulaire_Nombre_lignes_matrice_test.model.clear(); + champ_formulaire_Nombre_lignes_matrice_test.model.append({"valeur": 2, "texte": "2" }); + champ_formulaire_Nombre_lignes_matrice_test.model.append({"valeur": 3, "texte": "3" }); + champ_formulaire_Nombre_lignes_matrice_test.model.append({"valeur": 4, "texte": "4" }); + champ_formulaire_Nombre_lignes_matrice_test.model.append({"valeur": 5, "texte": "5" }); + champ_formulaire_Nombre_lignes_matrice_test.model.append({"valeur": 6, "texte": "6" }); + champ_formulaire_Nombre_lignes_matrice_test.model.append({"valeur": 7, "texte": "7" }); + champ_formulaire_Nombre_lignes_matrice_test.model.append({"valeur": 8, "texte": "8" }); + champ_formulaire_Nombre_lignes_matrice_test.model.append({"valeur": 9, "texte": "9" }); + champ_formulaire_Nombre_lignes_matrice_test.model.append({"valeur": 10, "texte": "10" }); + champ_formulaire_Nombre_lignes_matrice_test.model.append({"valeur": 11, "texte": "11" }); + champ_formulaire_Nombre_lignes_matrice_test.model.append({"valeur": 12, "texte": "12" }); + + // Positionnement de l'index sur la valeur en cours : + i = recherche_index_valeur_modele(nombre_lignes_matrice_test, champ_formulaire_Nombre_lignes_matrice_test.model, "Nombre_lignes_matrice_test"); + if (i === -1) champ_formulaire_Nombre_lignes_matrice_test.currentIndex = 2; + else champ_formulaire_Nombre_lignes_matrice_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 converted to rad: + return 0.0002967 / Math.tan(h + 0.00312536 / (h + 0.08901179)); +} + +// general sun calculations + +function solarMeanAnomaly(d) { return rad * (357.5291 + 0.98560028 * d); } + +function eclipticLongitude(M) { + + var C = rad * (1.9148 * sin(M) + 0.02 * sin(2 * M) + 0.0003 * sin(3 * M)), // equation of center + P = rad * 102.9372; // perihelion of the Earth + + return M + C + P + PI; +} + +function sunCoords(d) { + + var M = solarMeanAnomaly(d), + L = eclipticLongitude(M); + + return { + dec: declination(L, 0), + ra: rightAscension(L, 0) + }; +} + + +var SunCalc = {}; + + +// calculates sun position for a given date and latitude/longitude + +SunCalc.getPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = sunCoords(d), + H = siderealTime(d, lw) - c.ra; + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: altitude(H, phi, c.dec) + }; +}; + + +// sun times configuration (angle, morning name, evening name) + +var times = SunCalc.times = [ + [-0.833, 'sunrise', 'sunset' ], + [ -0.3, 'sunriseEnd', 'sunsetStart' ], + [ -6, 'dawn', 'dusk' ], + [ -12, 'nauticalDawn', 'nauticalDusk'], + [ -18, 'nightEnd', 'night' ], + [ 6, 'goldenHourEnd', 'goldenHour' ] +]; + +// adds a custom time to the times config + +SunCalc.addTime = function (angle, riseName, setName) { + times.push([angle, riseName, setName]); +}; + + +// calculations for sun times + +var J0 = 0.0009; + +function julianCycle(d, lw) { return Math.round(d - J0 - lw / (2 * PI)); } + +function approxTransit(Ht, lw, n) { return J0 + (Ht + lw) / (2 * PI) + n; } +function solarTransitJ(ds, M, L) { return J2000 + ds + 0.0053 * sin(M) - 0.0069 * sin(2 * L); } + +function hourAngle(h, phi, d) { return acos((sin(h) - sin(phi) * sin(d)) / (cos(phi) * cos(d))); } +function observerAngle(height) { return -2.076 * Math.sqrt(height) / 60; } + +// returns set time for the given sun altitude +function getSetJ(h, lw, phi, dec, n, M, L) { + + var w = hourAngle(h, phi, dec), + a = approxTransit(w, lw, n); + return solarTransitJ(a, M, L); +} + + + + + +// calculates sun times for a given date, latitude/longitude, and, optionally, +// the observer height (in meters) relative to the horizon + +SunCalc.getTimes = function (date, lat, lng, height) { + + height = height || 0; + + var lw = rad * -lng, + phi = rad * lat, + + dh = observerAngle(height), + + d = toDays(date), + n = julianCycle(d, lw), + ds = approxTransit(0, lw, n), + + M = solarMeanAnomaly(ds), + L = eclipticLongitude(M), + dec = declination(L, 0), + + Jnoon = solarTransitJ(ds, M, L), + + i, len, time, h0, Jset, Jrise; + + + var result = { + solarNoon: fromJulian(Jnoon), + nadir: fromJulian(Jnoon - 0.5) + }; + + for (i = 0, len = times.length; i < len; i += 1) { + time = times[i]; + h0 = (time[0] + dh) * rad; + + Jset = getSetJ(h0, lw, phi, dec, n, M, L); + Jrise = Jnoon - (Jset - Jnoon); + + result[time[1]] = fromJulian(Jrise); + result[time[2]] = fromJulian(Jset); + } + + return result; +}; + + + + + +// moon calculations, based on http://aa.quae.nl/en/reken/hemelpositie.html formulas + +function moonCoords(d) { // geocentric ecliptic coordinates of the moon + + var L = rad * (218.316 + 13.176396 * d), // ecliptic longitude + M = rad * (134.963 + 13.064993 * d), // mean anomaly + F = rad * (93.272 + 13.229350 * d), // mean distance + + l = L + rad * 6.289 * sin(M), // longitude + b = rad * 5.128 * sin(F), // latitude + dt = 385001 - 20905 * cos(M); // distance to the moon in km + + return { + ra: rightAscension(l, b), + dec: declination(l, b), + dist: dt + }; +} + +SunCalc.getMoonPosition = function (date, lat, lng) { + + var lw = rad * -lng, + phi = rad * lat, + d = toDays(date), + + c = moonCoords(d), + H = siderealTime(d, lw) - c.ra, + h = altitude(H, phi, c.dec), + // formula 14.1 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + pa = atan(sin(H), tan(phi) * cos(c.dec) - sin(c.dec) * cos(H)); + + h = h + astroRefraction(h); // altitude correction for refraction + + return { + azimuth: azimuth(H, phi, c.dec), + altitude: h, + distance: c.dist, + parallacticAngle: pa + }; +} + + + + +// calculations for illumination parameters of the moon, +// based on http://idlastro.gsfc.nasa.gov/ftp/pro/astro/mphase.pro formulas and +// Chapter 48 of "Astronomical Algorithms" 2nd edition by Jean Meeus (Willmann-Bell, Richmond) 1998. + +SunCalc.getMoonIllumination = function (date) { + + var d = toDays(date || new Date()), + s = sunCoords(d), + m = moonCoords(d), + + sdist = 149598000, // distance from Earth to Sun in km + + phi = acos(sin(s.dec) * sin(m.dec) + cos(s.dec) * cos(m.dec) * cos(s.ra - m.ra)), + inc = atan(sdist * sin(phi), m.dist - sdist * cos(phi)), + angle = atan(cos(s.dec) * sin(s.ra - m.ra), sin(s.dec) * cos(m.dec) - + cos(s.dec) * sin(m.dec) * cos(s.ra - m.ra)); + + return { + fraction: (1 + cos(inc)) / 2, + phase: 0.5 + 0.5 * inc * (angle < 0 ? -1 : 1) / Math.PI, + angle: angle + }; +} + + +function hoursLater(date, h) { + return new Date(date.valueOf() + h * dayMs / 24); +} + + + +// calculations for moon rise/set times are based on http://www.stargazing.net/kepler/moonrise.html article + +SunCalc.getMoonTimes = function (date, lat, lng, inUTC) { + var t = new Date(date); + if (inUTC) t.setUTCHours(0, 0, 0, 0); + else t.setHours(0, 0, 0, 0); + + var hc = 0.133 * rad, + h0 = SunCalc.getMoonPosition(t, lat, lng).altitude - hc, + h1, h2, rise, set, a, b, xe, ye, d, roots, x1, x2, dx; + + // go in 2-hour chunks, each time seeing if a 3-point quadratic curve crosses zero (which means rise or set) + for (var i = 1; i <= 24; i += 2) { + h1 = SunCalc.getMoonPosition(hoursLater(t, i), lat, lng).altitude - hc; + h2 = SunCalc.getMoonPosition(hoursLater(t, i + 1), lat, lng).altitude - hc; + + a = (h0 + h2) / 2 - h1; + b = (h2 - h0) / 2; + xe = -b / (2 * a); + ye = (a * xe + b) * xe + h1; + d = b * b - 4 * a * h1; + roots = 0; + + if (d >= 0) { + dx = Math.sqrt(d) / (Math.abs(a) * 2); + x1 = xe - dx; + x2 = xe + dx; + if (Math.abs(x1) <= 1) roots++; + if (Math.abs(x2) <= 1) roots++; + if (x1 < -1) x1 = x2; + } + + if (roots === 1) { + if (h0 < 0) rise = i + x1; + else set = i + x1; + + } else if (roots === 2) { + rise = i + (ye < 0 ? x2 : x1); + set = i + (ye < 0 ? x1 : x2); + } + + if (rise && set) break; + + h0 = h2; + } + + var result = {}; + + if (rise) result.rise = hoursLater(t, rise); + if (set) result.set = hoursLater(t, set); + + if (!rise && !set) result[ye > 0 ? 'alwaysUp' : 'alwaysDown'] = true; + + return result; +} + diff --git a/systeme.cpp b/systeme.cpp new file mode 100644 index 0000000..2c53abb --- /dev/null +++ b/systeme.cpp @@ -0,0 +1,143 @@ +#include "systeme.h" + +#include + + +Systeme::Systeme() : QObject() +{ +} + + + +//================================================================================================================================ +// Fonction : Lit le contenu d'un fichier texte et le retourne +// Reçoit : Le nom du fichier +// Retour : Une ligne "Ok" ou "Nok" représentant le résultat de la lecture puis la liste des lignes lues dans le fichier. +//================================================================================================================================ +QStringList Systeme::lecture_fichier(QString fichier) +{ +QStringList retour; + + QFile file(fichier); // Appel du constructeur de la classe QFile + + if (file.open(QIODevice::ReadOnly | QIODevice::Text)) // Si l'ouverture du fichier en lecture à réussie + { +//qDebug() << "Ouverture du fichier [" << fichier << "] en lecture effectué avec succès !"; + retour << "Ok"; + + QTextStream entree(&file); + + while(!entree.atEnd()) // Boucle sur toutes les lignes du fichier (attention, il y en a toujours une de plus à la fin...) + { + QString ligne = entree.readLine(); // Lecture de la ligne + retour << ligne; // Ajout à la structure de retour +//qDebug() << "Ligne lue dans le fichier : " << ligne; + } + + file.close(); // Fermeture du fichier + } + else + { + qDebug() << "Erreur d'ouverture du fichier [" << fichier << "]. La lecture est abandonnée..."; + retour << "Nok"; + } + + return(retour); +} + + + +//================================================================================================================================ +// Fonction : Lit le contenu d'un fichier texte et le retourne +// Reçoit : Le nom du fichier +// Retour : 0 si Ok, -1 si Nok +//================================================================================================================================ +qint8 Systeme::ecriture_fichier(QString fichier, QStringList lignes) +{ + QFile file(fichier); // Appel du constructeur de la classe QFile + + if (file.open(QIODevice::WriteOnly | QIODevice::Text)) // Si l'ouverture du fichier en écriture à réussie + { +//qDebug() << "Ouverture du fichier [" << fichier << "] en écriture effectué avec succès !"; + + QTextStream sortie(&file); + + for ( const auto& ligne : lignes ) + { + sortie << ligne << "\n"; +//qDebug() << "Ligne écrite dans le fichier : " << ligne; + } + + file.close(); // Fermeture du fichier + return(0); + } + else + { + qDebug() << "Erreur d'ouverture du fichier [" << fichier << "]. L'écriture est abandonnée..."; + return(-1); + } +} + + + + +//=================================================================================================== +// Fonction : Exécute la commande shelle reçue, attend la fin d'exécution et renvoi la réponse de +// la commande. +// Reçoit : la chaine de la commande +// Renvoit : La chaine de retour de la commande +//=================================================================================================== +QString Systeme::commande_shell(QString commande, QString fichier_sortie) +{ + +//qDebug() << "Commande shell à lancer = [" << commande << "]"; + + QProcess process; + + // Mise en place du fichier de sortie : + // ATTENTION : l'utilisation d'une redirection du type ' > fichier_sortie' ne fonctionne PAS avec QProcess... + if (fichier_sortie != "") process.setStandardOutputFile(fichier_sortie); + + // Lancement de la commande : +// process.start(commande); +// Modif de 08/2026 lors du passage à Qt6 sur CM5 : l'appel direct ne fonctionnait pas avec certaines commandes précédée de sudo. +// Le version ci-dessous fait le découpage ... avant d'appeler la fonction de start avec le découpage déjà fait. +// Résoud le problème mais sans savoir exactement ce qui bloquait dans la commande précédente... + QStringList args = QProcess::splitCommand(commande); + QString programme = args.takeFirst(); + process.start(programme, args); + + // Attente de la fin d'exécution : + // ATTENTION : on bloque l'éxécution jusqu'à la fin de la commande...! + process.waitForFinished(); + +//qDebug() << "QProcess error() =" << process.error(); +//qDebug() << "QProcess exitCode() =" << process.exitCode(); +//qDebug() << "QProcess exitStatus() =" << process.exitStatus(); + +// QThread::msleep(5); + QString out(process.readAllStandardOutput()); +// qDebug()<<"Sortie standard = "< +#include +#include +#include + +class Systeme : public QObject +{ + Q_OBJECT + + +public: + Systeme(); + + Q_INVOKABLE QStringList lecture_fichier(QString fichier); + Q_INVOKABLE qint8 ecriture_fichier(QString fichier, QStringList lignes); + Q_INVOKABLE QString commande_shell(QString commande, QString fichier_sortie); + Q_INVOKABLE void commande_shell_non_bloquante(QString commande); +}; + + +#endif // SYSTEME_H + + + + diff --git a/tb_mesures.cpp b/tb_mesures.cpp new file mode 100644 index 0000000..3ed843a --- /dev/null +++ b/tb_mesures.cpp @@ -0,0 +1,312 @@ +#include "tb_mesures.h" +#include "shipheart.h" + +//#include +#include +#include +#include +#include +#include + + +//============================================================================ +// Prototypes : +//============================================================================ +qreal conversion_unite(qreal val, quint8 type_unite, quint32 unite); + + +//============================================================================ +// Création du modèle +//============================================================================ +TbMesuresModel::TbMesuresModel() : + QObject() { + +} + + + +//================================================================================================================================ +// Fonction : Fonction principale de mise à jour des data à partir des données de la BDD. Les données proprement dites sont +// stockées dans le vecteur 'points'. Et les valeurs de min et max en x et y sont également calculées. +// Reçoit : Le pointeur sur la série (donc la courbe), +// le début de la requête à exécuter, en UTC (jusqu'aux filtre sur les Dates), +// la fin de la requete à exécuter, en UTC (après le filtre sur les Dates). En général, comprend les GROUP BY et les SORT, +// la date de début de la courbe, +// la date de fin de la courbe, +// le coefficient valeur/unité du capteur en cours (pour pouvoir calculer les valeurs réelles de Y auxquelles on ne touchera ensuite plus jusqu'à l'affichage de la courbe), +// le fuseau horaire afin de retourner les points avec des DateTime dans le bon fuseau (NB : l'heure d'été peut être ajoutée dedans lors de l'appel). +// Retour : Une liste de chaine contenant le nombre de lignes retournées, les points m_xMin(x, y), m_xMax(x, y), m_yMin(x, y), +// m_yMax(x, y) et la valeur m_yAvg. +//================================================================================================================================ +QStringList TbMesuresModel::maj_data(QAbstractSeries *serie, QString table, quint32 id, quint32 id_variable, QDateTime date_debut, QDateTime date_fin, quint32 regroupement_donnees, qreal coeff_valeur_unite, qreal fuseau, quint8 type_unite, quint32 unite) +{ +QStringList retour; +QVector temp_points; // Vecteur temporaire +QPointF m_xMin; +QPointF m_xMax; +QPointF m_yMin; +QPointF m_yMax; +qreal xVal, yVal; +qreal xVal_prec, yVal_prec; +qreal xCumul, yCumul; +qreal moyenne; +quint32 diviseur; +QString requete; +QSqlQuery query; +QSqlRecord resultat; +qint32 nb_lignes; +quint32 i; +bool flag_premier_point_ok; + +QElapsedTimer myTimer; +myTimer.start(); + + + //----------------------------------------------- + // Init des valeurs par défaut : + nb_lignes = 0; + temp_points.reserve(1500); // A priori, on réserve la mémoire pour 1500 lignes (soit un peu plus que 24h x 60 min.). Mais la taille sera agrandie en dynamique si besoin... + m_xMin.ry() = std::numeric_limits::max(); + m_xMax.ry() = std::numeric_limits::min(); + m_yMin.ry() = std::numeric_limits::max(); + m_yMax.ry() = std::numeric_limits::min(); + if (coeff_valeur_unite == 0) diviseur = 1; + else diviseur = coeff_valeur_unite; + xCumul = 0; + yCumul = 0; + + query.setForwardOnly(true); + + //----------------------------------------------- + // Recherche du point de départ : + requete = " SELECT Date, Valeur FROM " + table + " WHERE ID='" + QString::number(id) + "' AND ID_Variable='" + QString::number(id_variable) + "' "; + requete += " AND Date<'" + date_debut.toString(FORMAT_DATE_HEURE_BDD) + "' "; +// requete += " AND Valeur IS NOT NULL "; + requete += " ORDER BY Date DESC LIMIT 1 "; +//qDebug() << "Requête de recherche du premier point : " << requete; + + yVal = 0; + flag_premier_point_ok = false; + if (query.exec(requete) == true) // Exécution sans erreur de la requête : + { + if (query.next()) // Cas normal où on a trouvé un point précédent l'intervalle : + { + yVal = conversion_unite(query.record().value(1).toReal() / diviseur, type_unite, unite); + flag_premier_point_ok = true; + + } + else qDebug() << "La requête de recherche du premier point n'a trouvé aucune valeur précédent le début de la courbe. La valeur Y initiale est fixée à " + QString::number(yVal); + } + else qDebug() << "/!\\ Erreur d'exécution de la requête de recherche du premier point. La valeur Y initiale est fixée à " + QString::number(yVal); + + xVal = date_debut.toMSecsSinceEpoch() + (fuseau * 60 * 60 * 1000); // On ajuste immédiatement les valeurs de date au fuseau en cours + m_xMin = QPointF(xVal, yVal); // Mémorisation du point de début de l'axe X + + if (flag_premier_point_ok) + { + temp_points << QPointF(xVal, yVal); // Ajout à la courbe, comme premier point... + + if (yVal < m_yMin.ry()) m_yMin = QPointF(xVal, yVal); // Mise à jour du mini + if (yVal > m_yMax.ry()) m_yMax = QPointF(xVal, yVal); // Mise à jour du maxi + + nb_lignes ++; + } + + //------------------------------------------------------------------- + // Génération de la requête principale de récupération des data de la courbe : + if (regroupement_donnees <= 1) + { + requete = " SELECT Date, Valeur FROM " + table + " WHERE ID='" + QString::number(id) + "' AND ID_Variable='" + QString::number(id_variable) + "' "; + requete += " AND Date>'" + date_debut.toString(FORMAT_DATE_HEURE_BDD) + "' AND Date<='" + date_fin.toString(FORMAT_DATE_HEURE_BDD) + "' "; + requete += " AND Valeur IS NOT NULL "; + requete += " ORDER BY Date "; + } + else + { + requete = " SELECT Date, AVG(Valeur) FROM " + table + " WHERE ID='" + QString::number(id) + "' AND ID_Variable='" + QString::number(id_variable) + "' "; + requete += " AND Date>'" + date_debut.toString(FORMAT_DATE_HEURE_BDD) + "' AND Date<='" + date_fin.toString(FORMAT_DATE_HEURE_BDD) + "' "; + requete += " AND Valeur IS NOT NULL "; + requete += " GROUP BY (UNIX_TIMESTAMP(Date) DIV " + QString::number(regroupement_donnees) + ") ORDER BY Date "; + } +//qDebug() << "Requête générée : " << requete; + + + //----------------------------------------------- + // Récupération des données dans la BDD : + if (query.exec(requete) == true) // TRUE = pas d'erreur + { + nb_lignes += query.size(); + +//qDebug() << "Nombre d'enregistrements récupérés par la requête : " << nb_lignes << " et temps écoulé : " << myTimer.elapsed() << "ms"; + + //----------------------------------------------- + // Traitement des tous les enregistrements récupérés : + for (i = 0; i < (quint32)nb_lignes; i ++) + { + if (!query.next()) break; // Ce break ne devrait pas arriver puisqu'on a compté la taille du query avant de lancer la boucle... + + resultat = query.record(); + + // Mise à jour des valeurs précédentes avant de calculer les nouvelles : + xVal_prec = xVal; + yVal_prec = yVal; + + // Mise à jour des nouvelles valeurs : + xVal = resultat.value(0).toDateTime().toMSecsSinceEpoch() + (fuseau * 60 * 60 * 1000); // On ajuste immédiatement les valeurs de date au fuseau en cours + yVal = resultat.value(1).toReal() / diviseur; + + // Ajustement des valeurs en fonction de la conversion d'unité concernée : + yVal = conversion_unite(yVal, type_unite, unite); + +//qDebug() << "Nouveau point " << i << " : Date = " << resultat.value(0).toDateTime() << " / " << xVal << " et y = " << yVal; + + // Calcul des cumuls : + if ((flag_premier_point_ok) || (i > 0)) // Si le premier point n'a pas été trouvé, on ne prends pas en compte l'intervalle entre le départ et le premier point dans la fenêtre + { + yCumul += (xVal - xVal_prec) * (yVal_prec); + xCumul += (xVal - xVal_prec); + } + + // Calcul des points yMin et yMax : + if (yVal < m_yMin.ry()) m_yMin = QPointF(xVal, yVal); + if (yVal > m_yMax.ry()) m_yMax = QPointF(xVal, yVal); + + // Ajout des points dans la série temporaire : + temp_points << QPointF(xVal, yVal_prec); // Ajout d'un point avec la valeur courante de X mais avec le Y du point précédent (permet de "maintenir" la valeur précédente jusqu'au point en cours). + temp_points << QPointF(xVal, yVal); // Point en cours + } + +//qDebug() << "Fin de boucle et temps écoulé : " << myTimer.elapsed() << "ms"; + + //----------------------------------------------- + // Calcul du point de fin : + if (nb_lignes > 0) // Si aucun point n'a été trouvé, il ne faut pas ajouter le dernier point (qui n'aura aucune signification) + { + xVal_prec = xVal; + yVal_prec = yVal; + xVal = date_fin.toMSecsSinceEpoch() + (fuseau * 60 * 60 * 1000); // On ajuste immédiatement les valeurs de date au fuseau en cours + yCumul += (xVal - xVal_prec) * (yVal_prec); // Dernier calcul de cumul + xCumul += (xVal - xVal_prec); // Dernier calcul de cumul + m_xMax = QPointF(xVal, yVal); // Mémorisation du point de fin de l'axe X. NB : la valeur de yVal est volontairement laissée inchangée (valeur Y du dernier point). Au passage, on évite les ajustements d'unités... + temp_points << QPointF(xVal, yVal); // Ajout à la courbe, comme dernier point... + nb_lignes ++; + } + + //----------------------------------------------- + // Mise à jour des valeurs de la courbe : + if (serie) + { + QXYSeries *xySeries = static_cast(serie); + xySeries->replace(temp_points); // Mise à jour des valeurs de la courbe avec le vecteur temporaire (Use replace instead of clear + append, it's optimized for performance) + } + else qDebug() << "Valeur de 'series' non valide !"; + +//qDebug() << "yMin : " << m_yMin.ry() << " et yMax : " << m_yMax.ry(); + + //----------------------------------------------- + // Préparation des valeurs de retour : + // NB : le 'f' est nécessaire pour les dates ('-----rx()') au moins ; sinon la précision n'est pas suffisante !! + if (xCumul != 0) moyenne = yCumul / xCumul; + else moyenne = 0; + + retour << QString::number(nb_lignes); + retour = retour << QString::number(m_xMin.rx(), 'f') << QString::number(m_xMin.ry(), 'f') << QString::number(m_xMax.rx(), 'f') << QString::number(m_xMax.ry(), 'f'); + retour = retour << QString::number(m_yMin.rx(), 'f') << QString::number(m_yMin.ry(), 'f') << QString::number(m_yMax.rx(), 'f') << QString::number(m_yMax.ry(), 'f'); + retour = retour << QString::number(moyenne, 'f'); + +//qDebug() << "FIN de maj_data : " << nb_lignes << " enregistrements en " << myTimer.elapsed() << "ms\n"; + + } + else // Si une erreur lors de la requête a été détectée : + { + qDebug() << "/!\\ Erreur à l'exécution de la requête principale de 'maj_data()' "; + retour << QString::number(0); + } + +//qDebug() << "FIN de maj_data"; + return(retour); +} + + +//================================================================================================================================ +// Fonction : Calcule une valeur dans l'unité demandée. +// Reçoit : La valeur à convertir (dans l'une des unités de base : °C ou litres. Les autres sont laissées inchangées +// Retour : la valeur converte +//================================================================================================================================ +qreal conversion_unite(qreal val, quint8 type_unite, quint32 unite) +{ +qreal retour = val; + + switch(type_unite) + { + //----------------------- + case UNITE_VOLUME : + { + switch(unite) + { + case UNITE_VOLUME_LITRES: { break; } // Aucune conversion, on reste en litres + case UNITE_VOLUME_US_GALLONS: { retour = val / 3.785411784; break; } // Conversion litres => US Ga + case UNITE_VOLUME_IMP_GALLONS: { retour = val / 4.54609; break; } // Conversion litres => Imp. Ga + default : { break; } // Aucune conversion, on reste en ... ce qu'on est. + } + break; + } + + //----------------------- + case UNITE_TEMPERATURE : + { + switch(unite) + { + case UNITE_TEMPERATURE_CELSIUS: { break; } // Aucune conversion, on reste en °C + case UNITE_TEMPERATURE_FAHRENHEIT: { retour = (1.8 * val) + 32; break; } // Conversion °C => °F + default : { break; } // Aucune conversion, on reste en ... ce qu'on est. + } + break; + } + + //----------------------- + default: break; + } + + return (retour); +} + + +//================================================================================================================================ +// Fonction : Fonction de copie des points d'une série (par exemple, une LineSerie d'un graphique) dans ceux d'une autre série. +// Reçoit : Le pointeur sur la série source et un sur la série destinataire. +// Retour : Rien +//================================================================================================================================ +void TbMesuresModel::copie_series(QAbstractSeries *serie_source, QAbstractSeries *serie_destination) +{ +QVector tempo; +qint64 i; +qint64 nb; +qint64 taille_destination; + +//QElapsedTimer myTimer; +//myTimer.start(); + + if ((serie_source) && (serie_destination)) + { + QXYSeries *xySerie_source = static_cast(serie_source); + QXYSeries *xySerie_destination = static_cast(serie_destination); + + // Copie des points de la source vers destination : + nb = xySerie_source->count(); // Nombre de points à transférer + for (i = 0; i < nb; i ++) // Boucle sur tous les points de la source + { + tempo << xySerie_source->at(i); // Copie de chaque point dans une structure temporaire + } + + xySerie_destination->replace(tempo); // Copie de la structure temporaire dans la série destination + + // Suppression des éventuels points de la destination si la source est plus petite : + taille_destination = xySerie_destination->count(); + if (taille_destination > nb) xySerie_destination->removePoints(nb, (taille_destination - nb)); + +//qDebug() << "Copie Série faite. Nb d'enregistrements copiés = " << nb << "Temps d'exécution = " << myTimer.elapsed() << "ms\n"; + } + else qDebug() << "Copie série impossible car au moins un pointeur (source et/ou destination) est NULL\n"; +} + diff --git a/tb_mesures.h b/tb_mesures.h new file mode 100644 index 0000000..bfa78e0 --- /dev/null +++ b/tb_mesures.h @@ -0,0 +1,31 @@ +#ifndef TB_MESURES_H +#define TB_MESURES_H + +#include +#include +#include +#include +#include +#include +#include + + +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + QT_CHARTS_USE_NAMESPACE +#endif + +//============================================================== +class TbMesuresModel : public QObject +{ + Q_OBJECT + +public: + TbMesuresModel(); + + Q_INVOKABLE QStringList maj_data(QAbstractSeries *serie, QString table, quint32 id, quint32 id_variable, QDateTime date_debut, QDateTime date_fin, quint32 regroupement_donnees, qreal coeff_valeur_unite, qreal fuseau, quint8 type_unite, quint32 unite); + Q_INVOKABLE void copie_series(QAbstractSeries *serie_source, QAbstractSeries *serie_destination); + +}; + +#endif + diff --git a/test_batterie.qml b/test_batterie.qml new file mode 100644 index 0000000..1e67545 --- /dev/null +++ b/test_batterie.qml @@ -0,0 +1,488 @@ +//======================================================================================================================================================================== +// TEST !!!!! +//======================================================================================================================================================================== +import QtQuick 2.12 + +import qt.koriolan.shipheart 1.0 + + +Shipheart_page { + id: page_test_batterie + + + // Mis en forme : + readonly property double pourcentage_largeur_colonne_gauche: 0.75 + readonly property double espace_colonnes_principales: 60 + 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 marge_haute_zone_barres: 50 + readonly property int espace_barre_autonomie_barres_circuits: 40 + readonly property int largeur_barre_autonomie: 80 + readonly property int espace_barres_circuits: 10 + readonly property int hauteur_nom_barres_circuits: 80 + readonly property int rayon_barres: 3 + + readonly property int hauteur_barre_optimale: zone_affichage_haut_gauche.height - marge_haute_zone_barres - hauteur_nom_barres_circuits + + + 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 autonomie_optimale: 0 + property int autonomie_actuelle: 0 + property int position_autonomie_actuelle: 0 + property int nb_barres_circuits: 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(); + } + } + } + + + + // Titre de la page : + Shipheart_titre_1 {titre:qsTr("Batteries de servitude"); 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" + + // Barre d'autonomie optimale : + Rectangle { + id: barre_autonomie_optimale + x: espace_colonnes_principales + y: marge_haute_zone_barres + width: largeur_barre_autonomie + height: hauteur_barre_optimale + color: couleur_gris_tres_pale_transparent + radius: rayon_barres + Text { + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + text: qsTr("Autonomie optimale") + font.pixelSize: 16 + color: couleur_blanc_casse + rotation: 270 + } + Text { + anchors.bottom: parent.top + anchors.horizontalCenter: parent.horizontalCenter + text: Math.trunc(autonomie_optimale / 60) + ":" + String(Math.trunc(autonomie_optimale % 60)).padStart(2, '0') + font.pixelSize: 18 + font.bold: true + color: couleur_gris_tres_tres_pale + } + } + + + Rectangle { // Zone des barres de circuits : + id: barres_circuits + + x: barre_autonomie_optimale.x + barre_autonomie_optimale.width + espace_barre_autonomie_barres_circuits + y: marge_haute_zone_barres + width: parent.width - x - espace_barre_autonomie_barres_circuits - largeur_barre_autonomie + height: hauteur_barre_optimale + color: "transparent" + + Repeater { + model: modele_barres_circuits + delegate: Rectangle { + + x: ((width + espace_barres_circuits) * index) + (espace_barres_circuits / 2) + y: position + width: (barres_circuits.width / nb_barres_circuits) - espace_barres_circuits + height: barres_circuits.height - position + color: "transparent" + border { + color: couleur_gris_tres_pale_transparent + width: 1 + } + Text { // Nombre d'heures d'autonomie (au-dessus de la barre) + anchors.bottom: barre_active_travaux.top + anchors.horizontalCenter: parent.horizontalCenter + text: String(Math.trunc((valeur + valeur_travaux) / 60)).padStart(2, '0') + ":" + String(Math.trunc((valeur + valeur_travaux) % 60)).padStart(2, '0') + font.pixelSize: 16 + color: couleur_gris_tres_tres_pale + } + Rectangle { // Barre de consommation "anormale" du circuit : + id: barre_active_travaux + width: parent.width + height: valeur_travaux * hauteur_barre_optimale / autonomie_optimale; + visible: (valeur_travaux > 0) + color: couleur_rouge_transparent + border.width: 0 + radius: rayon_barres + + Image { // Pictogramme au sein de la barre "anormale" + source: "/images/ak14.png" + sourceSize.height: ((parent.width * 0.4) > (parent.height * 0.9)) ? (parent.height * 0.9) : (parent.width * 0.4); + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + } + } + Rectangle { // Barre de consommation normale du circuit : + id: barre_active + y: barre_active_travaux.height + width: parent.width + height: valeur * hauteur_barre_optimale / autonomie_optimale; + color: couleur_orange_transparent + border.width: 0 + radius: rayon_barres + } + Rectangle { // Libellé de la barre : + x: (parent.width / 2) * (-1) + y: barres_circuits.height - position + ((index % 2 === 0) ? 0 : (hauteur_nom_barres_circuits / 2)) + width: parent.width * 2 + height: hauteur_nom_barres_circuits / 2 + color: "transparent" + Rectangle { // Trait vertical de liaison entre la barre et libellé + x: parent.width / 2 + y: (index % 2 === 0) ? 5 : ((-1) * hauteur_nom_barres_circuits / 2) + 5 + width: 2 + height: (index % 2 === 0) ? 5 : (hauteur_nom_barres_circuits / 2) + 5 + color: couleur_gris_fonce + } + Text { + anchors.fill: parent + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + wrapMode: Text.Wrap + maximumLineCount: 2 + elide: Text.ElideRight + text: libelle + font.pixelSize: 12 + color: couleur_blanc_casse + } + } + } + } + + ListModel { + id: modele_barres_circuits + } + } + + // Barre d'autonomie actuelle : + Rectangle { + id: barre_autonomie_actuelle + x: barres_circuits.x + barres_circuits.width + espace_barre_autonomie_barres_circuits + y: marge_haute_zone_barres + position_autonomie_actuelle + width: largeur_barre_autonomie + height: hauteur_barre_optimale - position_autonomie_actuelle + color: couleur_blanc_casse_transparent + radius: rayon_barres + Rectangle { // Trait vertical de liaison entre la barre et la valeur de l'autonomie actuelle + x: parent.width / 2 + y: ((-1) * position_autonomie_actuelle / 2) - 5 + width: 2 + height: (position_autonomie_actuelle / 2) - 5 + color: couleur_gris_fonce + } + Text { // Valeur de l'autonomie actuelle + id: libelle_autonomie_actuelle + anchors.bottom: barre_autonomie_actuelle.top + anchors.bottomMargin: position_autonomie_actuelle / 2 + anchors.horizontalCenter: parent.horizontalCenter + text: String(Math.trunc(autonomie_actuelle / 60)).padStart(2, '0') + ":" + String(Math.trunc(autonomie_actuelle % 60)).padStart(2, '0') + font.pixelSize: 64 + font.bold: true + color: couleur_gris_tres_tres_pale + } + Text { // Titre de l'autonomie actuelle + anchors.bottom: libelle_autonomie_actuelle.top + anchors.bottomMargin: 10 + anchors.horizontalCenter: parent.horizontalCenter + text: qsTr("Autonomie actuelle") + font.pixelSize: 24 + font.bold: true + color: couleur_gris_fonce + } + } + + + } + + + + //------------------------------------------------------- + // 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" + + Rectangle { + x: 0 + y: 0//marge_haute_zone_barres + width: parent.width + height: position_autonomie_actuelle + color: "transparent" + Text { // Titre de l'autonomie maxi + anchors.bottom: valeur_autonomie_maxi.top + anchors.bottomMargin: 10 + anchors.horizontalCenter: parent.horizontalCenter + text: qsTr("Autonomie
maximale") + horizontalAlignment: Text.AlignHCenter + font.pixelSize: 24 + font.bold: true + color: couleur_gris_fonce + } + Text { // Valeur de l'autonomie maxi + id: valeur_autonomie_maxi + + anchors.bottom: image_tendance.top + anchors.bottomMargin: 30 + anchors.horizontalCenter: parent.horizontalCenter + text: "18:30" + font.pixelSize: 24 + font.bold: true + color: couleur_gris_tres_tres_pale + } + Image { + id: image_tendance + + source: "/images/fleche_tendance_haut_verte.png" + sourceSize.height: 100 + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + } + Text { // Titre de la durée d'atteinte de l'autonomie maxi + id: libelle_duree_autonomie_maxi + + anchors.top: image_tendance.bottom + anchors.topMargin: 30 + anchors.horizontalCenter: parent.horizontalCenter + text: qsTr("dans") + font.pixelSize: 24 + font.bold: true + color: couleur_gris_fonce + } + Text { // Valeur de la durée d'atteinte de l'autonomie maxi + id: valeur_duree_autonomie_maxi + anchors.top: libelle_duree_autonomie_maxi.bottom + anchors.topMargin: 10 + anchors.horizontalCenter: parent.horizontalCenter + text: "06:30" + font.pixelSize: 24 + font.bold: true + color: couleur_gris_tres_tres_pale + } + Text { // Titre de la durée d'atteinte de l'autonomie maxi + anchors.top: valeur_duree_autonomie_maxi.bottom + anchors.topMargin: 10 + anchors.horizontalCenter: parent.horizontalCenter + text: qsTr("environ") + font.pixelSize: 24 + font.bold: true + color: couleur_gris_fonce + } + } + + + + } + + + //------------------------------------------------------- + // 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); + } + } + + //============================================================================================================= + // Init de la page + //============================================================================================================= + function init_page() + { + var libelle, valeur, valeur_travaux; + var position; + + autonomie_optimale = (14 * 60) + 20 // En minutes + autonomie_actuelle = autonomie_optimale; + position = 0; + valeur = 0; + valeur_travaux = 0; + modele_barres_circuits.clear(); + + + //--------------------------------------- + position += (valeur + valeur_travaux) * hauteur_barre_optimale / autonomie_optimale; + autonomie_actuelle -= (valeur + valeur_travaux); + libelle = "Vieillissement batterie"; + valeur = 0; + valeur_travaux = 165; + modele_barres_circuits.append({"libelle": libelle, "valeur": valeur, "valeur_travaux": valeur_travaux, "position": position }); + + //--------------------------------------- + position += (valeur + valeur_travaux) * hauteur_barre_optimale / autonomie_optimale; + autonomie_actuelle -= (valeur + valeur_travaux); + libelle = "Pilote automatique"; + valeur = 130; + valeur_travaux = 0; + modele_barres_circuits.append({"libelle": libelle, "valeur": valeur, "valeur_travaux": valeur_travaux, "position": position }); + + //--------------------------------------- + position += (valeur + valeur_travaux) * hauteur_barre_optimale / autonomie_optimale; + autonomie_actuelle -= (valeur + valeur_travaux); + libelle = "Réfrigérateur"; + valeur = 40; + valeur_travaux = 65; + modele_barres_circuits.append({"libelle": libelle, "valeur": valeur, "valeur_travaux": valeur_travaux, "position": position }); + + //--------------------------------------- + position += (valeur + valeur_travaux) * hauteur_barre_optimale / autonomie_optimale; + autonomie_actuelle -= (valeur + valeur_travaux); + libelle = "Prises USB"; + valeur = 50; + valeur_travaux = 0; + modele_barres_circuits.append({"libelle": libelle, "valeur": valeur, "valeur_travaux": valeur_travaux, "position": position }); + + //--------------------------------------- + position += (valeur + valeur_travaux) * hauteur_barre_optimale / autonomie_optimale; + autonomie_actuelle -= (valeur + valeur_travaux); + libelle = "Centrale de navigation"; + valeur = 30; + valeur_travaux = 0; + modele_barres_circuits.append({"libelle": libelle, "valeur": valeur, "valeur_travaux": valeur_travaux, "position": position }); + + //--------------------------------------- + position += (valeur + valeur_travaux) * hauteur_barre_optimale / autonomie_optimale; + autonomie_actuelle -= (valeur + valeur_travaux); + libelle = "Eclairage carré"; + valeur = 15; + valeur_travaux = 0; + modele_barres_circuits.append({"libelle": libelle, "valeur": valeur, "valeur_travaux": valeur_travaux, "position": position }); + + //--------------------------------------- + position += (valeur + valeur_travaux) * hauteur_barre_optimale / autonomie_optimale; + autonomie_actuelle -= (valeur + valeur_travaux); + libelle = "VHF"; + valeur = 10; + valeur_travaux = 0; + modele_barres_circuits.append({"libelle": libelle, "valeur": valeur, "valeur_travaux": valeur_travaux, "position": position }); + + //--------------------------------------- + position += (valeur + valeur_travaux) * hauteur_barre_optimale / autonomie_optimale; + autonomie_actuelle -= (valeur + valeur_travaux); + libelle = "Autres"; + valeur = 25; + valeur_travaux = 0; + modele_barres_circuits.append({"libelle": libelle, "valeur": valeur, "valeur_travaux": valeur_travaux, "position": position }); + + + position_autonomie_actuelle = position + ((valeur + valeur_travaux) * hauteur_barre_optimale / autonomie_optimale); + autonomie_actuelle -= (valeur + valeur_travaux); + if (autonomie_actuelle <= 0) console.log("!!! ERREUR : L'autonomie actuelle calculée est inférieures à 0 (la somme des consommations des circuits est supérieure à l'autonomie optimale)") + + nb_barres_circuits = modele_barres_circuits.count; + } + + + //============================================================================================================= + // Mise à jour des valeurs saisies + //============================================================================================================= + function mise_a_jour() + { + + + } + + + + +} diff --git a/test_tri_liste.qml b/test_tri_liste.qml new file mode 100644 index 0000000..11eca51 --- /dev/null +++ b/test_tri_liste.qml @@ -0,0 +1,339 @@ +//======================================================================================================================================================================== +// TEST !!!!! +//======================================================================================================================================================================== +import QtQuick 2.12 +import QtQml.Models 2.1 + +import qt.koriolan.shipheart 1.0 + + + +Shipheart_page { + id: page_test_tri_liste + + + // Mis en forme : + readonly property double pourcentage_largeur_colonne_gauche: 0.75 + readonly property double espace_colonnes_principales: 60 + 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 nombre_modules_affiches_sur_une_colonne: 5 + + + 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(); + } + } + } + + + + // Titre de la page : + Shipheart_titre_1 {titre:qsTr("TEST DE TRI DE LISTE"); 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_modules_configures + anchors.fill: parent + + clip: true + + model: modele_modules_configures + delegate: bouton_module + + displaced: Transition { + NumberAnimation{ + properties: "x,y" + duration: 500 // Vitesse à laquelle se déplacent les boutons lorsqu'on les déplace + } + } + + Component { + id: bouton_module + + + MouseArea { + id: dragArea + + width: grille_modules_configures.width + height: grille_modules_configures.height / nombre_modules_affiches_sur_une_colonne + + property bool appui_en_cours: false + property int derniere_position_y: 0 + property bool vers_le_bas: false + + + pressAndHoldInterval: 500; // Temporise avant de passer en moide "déplacement" + + drag.target: appui_en_cours ? contenu_bouton_module : undefined + drag.axis: Drag.YAxis // On ne se déplace que sur l'axe Y + + onPressAndHold: appui_en_cours = true + onReleased: appui_en_cours = false + onYChanged: { + vers_le_bas = derniere_position_y < y; // Détection du sens de déplacement. Utilisé pour toujours afficher un élément de plus en bas (si descente) ou en haut (si montée) + derniere_position_y = y; + } + + Rectangle { + id: contenu_bouton_module + + anchors { + horizontalCenter: parent.horizontalCenter + verticalCenter: parent.verticalCenter + } + width: dragArea.width - 5 + height: dragArea.height - 5 + color: shipheart_couleur_fond_bouton + opacity: dragArea.appui_en_cours ? 0.6 : 1.0 + + Text { + anchors.fill: parent + horizontalAlignment: Qt.AlignCenter + verticalAlignment: Qt.AlignVCenter +text: index +color: couleur_green_yellow + font.pixelSize: 18 + } + + Drag.active: dragArea.appui_en_cours + Drag.source: dragArea + Drag.hotSpot.x: width / 2 + Drag.hotSpot.y: height / 2 + + states: State{ + when: dragArea.appui_en_cours + ParentChange { + target: contenu_bouton_module + parent: grille_modules_configures + } + AnchorChanges { + target: contenu_bouton_module + anchors { + horizontalCenter: undefined + verticalCenter: undefined + } + } + } + } + + DropArea { + anchors.fill: parent + onEntered: { + modele_modules_configures.move( drag.source.DelegateModel.itemsIndex, dragArea.DelegateModel.itemsIndex, 1) + + // Ajout d'un élément en partie basse/haute pour avoir toujours une vision sur le prochain élément à "sauter" : + if (dragArea.vers_le_bas) + grille_modules_configures.currentIndex = dragArea.DelegateModel.itemsIndex + 1 + else + grille_modules_configures.currentIndex = dragArea.DelegateModel.itemsIndex - 1 + } + } + } + } + } + + + + + ListModel { + id: modele_modules_configures + + ListElement { colore: "blue" } + ListElement { colore: "orange" } + ListElement { colore: "red" } + ListElement { colore: "green" } + ListElement { colore: "blue" } + ListElement { colore: "green" } + ListElement { colore: "red" } + ListElement { colore: "blue" } + ListElement { colore: "blue" } + ListElement { colore: "orange" } + ListElement { colore: "red" } + ListElement { colore: "green" } + ListElement { colore: "blue" } + ListElement { colore: "green" } + ListElement { colore: "red" } + ListElement { colore: "blue" } + ListElement { colore: "orange" } + ListElement { colore: "red" } + ListElement { colore: "green" } + ListElement { colore: "blue" } + ListElement { colore: "green" } + ListElement { colore: "red" } + + } + + + + + + + + + + + + + + + + + + + + + + + + } + + + + //------------------------------------------------------- + // 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" + + + + + + } + + + //------------------------------------------------------- + // 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); + } + } + + //============================================================================================================= + // Init de la page + //============================================================================================================= + function init_page() + { + + } + + + //============================================================================================================= + // Mise à jour des valeurs saisies + //============================================================================================================= + function mise_a_jour() + { + + + } + + + + +} diff --git a/traductions.qrc b/traductions.qrc new file mode 100755 index 0000000..f7f6dbc --- /dev/null +++ b/traductions.qrc @@ -0,0 +1,13 @@ + + + shipheart_en_EN.qm + shipheart_fr_FR.qm + shipheart_de_DE.qm + shipheart_es_ES.qm + shipheart_it_IT.qm + shipheart_pt_PT.qm + shipheart_nl_NL.qm + shipheart_ca_ES.qm + shipheart_lv_LV.qm + + diff --git a/versions/shipheart_qt_260804_114616 b/versions/shipheart_qt_260804_114616 new file mode 100755 index 0000000..a274a96 Binary files /dev/null and b/versions/shipheart_qt_260804_114616 differ diff --git a/virtualkeyboard_layouts_koriolan/layouts/ar_AR/dialpad.fallback b/virtualkeyboard_layouts_koriolan/layouts/ar_AR/dialpad.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/ar_AR/digits.qml b/virtualkeyboard_layouts_koriolan/layouts/ar_AR/digits.qml new file mode 100755 index 0000000..6d7047f --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/ar_AR/digits.qml @@ -0,0 +1,121 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Layouts 1.0 +import QtQuick.VirtualKeyboard 2.1 +import QtQuick.VirtualKeyboard.Plugins 2.3 + +KeyboardLayout { + inputMethod: PlainInputMethod {} + inputMode: InputEngine.InputMode.Numeric + + KeyboardColumn { + Layout.fillWidth: false + Layout.fillHeight: true + Layout.alignment: Qt.AlignHCenter + Layout.preferredWidth: height + KeyboardRow { + Key { + key: 0x0667 + text: "\u0667" + alternativeKeys: "\u06677" + } + Key { + key: 0x0668 + text: "\u0668" + alternativeKeys: "\u06688" + } + Key { + key: 0x0669 + text: "\u0669" + alternativeKeys: "\u06699" + } + BackspaceKey {} + } + KeyboardRow { + Key { + key: 0x0664 + text: "\u0664" + alternativeKeys: "\u06644" + } + Key { + key: 0x0665 + text: "\u0665" + alternativeKeys: "\u06655" + } + Key { + key: 0x0666 + text: "\u0666" + alternativeKeys: "\u06666" + } + Key { + text: " " + displayText: "\u2423" + repeat: true + showPreview: false + key: Qt.Key_Space + } + } + KeyboardRow { + Key { + key: 0x0661 + text: "\u0661" + alternativeKeys: "\u06611" + } + Key { + key: 0x0662 + text: "\u0662" + alternativeKeys: "\u06622" + } + Key { + key: 0x0663 + text: "\u0663" + alternativeKeys: "\u06633" + } + HideKeyboardKey {} + } + KeyboardRow { + ChangeLanguageKey { + customLayoutsOnly: true + } + Key { + key: 0x0660 + text: "\u0660" + alternativeKeys: "\u06600" + } + Key { + key: Qt.Key_Comma + text: "\u066B" + alternativeKeys: "\u066B,." + } + EnterKey {} + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/ar_AR/handwriting.qml b/virtualkeyboard_layouts_koriolan/layouts/ar_AR/handwriting.qml new file mode 100755 index 0000000..f82e4b6 --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/ar_AR/handwriting.qml @@ -0,0 +1,116 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Layouts 1.0 +import QtQuick.VirtualKeyboard 2.3 + +KeyboardLayout { + function createInputMethod() { + return Qt.createQmlObject('import QtQuick 2.0; import QtQuick.VirtualKeyboard.Plugins 2.3; HandwritingInputMethod {}', parent) + } + sharedLayouts: ['symbols'] + inputMode: InputEngine.InputMode.Arabic + readonly property bool alphabeticInputMode: [InputEngine.InputMode.Latin, InputEngine.InputMode.Dialable].indexOf(InputContext.inputEngine.inputMode) !== -1 + + KeyboardRow { + Layout.preferredHeight: 3 + KeyboardColumn { + Layout.preferredWidth: bottomRow.width - hideKeyboardKey.width + KeyboardRow { + TraceInputKey { + objectName: "hwrInputArea" + patternRecognitionMode: InputEngine.PatternRecognitionMode.Handwriting + horizontalRulers: + alphabeticInputMode ? [] : + [Math.round(boundingBox.height / 4), Math.round(boundingBox.height / 4) * 2, Math.round(boundingBox.height / 4) * 3] + } + } + } + KeyboardColumn { + Layout.preferredWidth: hideKeyboardKey.width + KeyboardRow { + BackspaceKey {} + } + KeyboardRow { + EnterKey {} + } + KeyboardRow { + ShiftKey { } + } + } + } + KeyboardRow { + id: bottomRow + Layout.preferredHeight: 1 + keyWeight: 154 + InputModeKey { + weight: 217 + inputModeNameList: [ + "ABC", // InputEngine.InputMode.Latin + "\u0660\u0661\u0662", // InputEngine.InputMode.Numeric + "123", // InputEngine.InputMode.Dialable + "", // InputEngine.InputMode.Pinyin + "", // InputEngine.InputMode.Cangjie + "", // InputEngine.InputMode.Zhuyin + "", // InputEngine.InputMode.Hangul + "", // InputEngine.InputMode.Hiragana + "", // InputEngine.InputMode.Katakana + "", // InputEngine.InputMode.FullwidthLatin + "", // InputEngine.InputMode.Greek + "", // InputEngine.InputMode.Cyrillic + "\u0623\u200C\u0628\u200C\u062C", // InputEngine.InputMode.Arabic + ] + } + ChangeLanguageKey { + weight: 154 + customLayoutsOnly: true + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: alphabeticInputMode ? Qt.Key_Apostrophe : 0x060C + text: alphabeticInputMode ? "'" : "\u060C" + alternativeKeys: alphabeticInputMode ? "<>()#%&*/\\\"'=+-_" : "\"\u060C\u066B\u066C\u066D" + } + Key { + key: Qt.Key_Period + text: "." + alternativeKeys: alphabeticInputMode ? ":;,.?!" : ":\u061B.\u061F!" + } + HideKeyboardKey { + id: hideKeyboardKey + weight: 204 + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/ar_AR/main.qml b/virtualkeyboard_layouts_koriolan/layouts/ar_AR/main.qml new file mode 100755 index 0000000..a7f0e5b --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/ar_AR/main.qml @@ -0,0 +1,340 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.VirtualKeyboard 2.3 + +KeyboardLayoutLoader { + inputMode: InputEngine.InputMode.Arabic + sourceComponent: InputContext.shiftActive ? page2 : page1 + Component { + id: page1 + KeyboardLayout { + keyWeight: 160 + KeyboardRow { + Key { + text: "\u0636" + } + Key { + text: "\u0635" + } + Key { + text: "\u062B" + } + Key { + text: "\u0642" + } + Key { + text: "\u0641" + } + Key { + text: "\u063A" + } + Key { + text: "\u0639" + } + Key { + text: "\u0647" + } + Key { + text: "\u062E" + } + Key { + text: "\u062D" + } + Key { + text: "\u062C" + } + Key { + text: "\u062F" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Key { + text: "\u0634" + } + Key { + text: "\u0633" + } + Key { + text: "\u064A" + } + Key { + text: "\u0628" + } + Key { + text: "\u0644" + } + Key { + text: "\u0627" + } + Key { + text: "\u062A" + } + Key { + text: "\u0646" + } + Key { + text: "\u0645" + } + Key { + text: "\u0643" + } + Key { + text: "\u0637" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + ShiftKey {} + Key { + text: "\u0626" + } + Key { + text: "\u0621" + } + Key { + text: "\u0624" + } + Key { + text: "\u0631" + } + Key { + text: "\u0644\u0627" + } + Key { + text: "\u0649" + } + Key { + text: "\u0629" + } + Key { + text: "\u0648" + } + Key { + text: "\u0632" + } + Key { + text: "\u0638" + } + ShiftKey { + weight: 264 + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + displayText: "\u0661\u0662\u0663\u061F" + } + ChangeLanguageKey { + weight: 154 + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: 0x060C + text: "\u060C" + alternativeKeys: "\"\u061F\u060C.!:\u061B\u066B\u066C\u066D" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } + } + } + Component { + id: page2 + KeyboardLayout { + keyWeight: 160 + KeyboardRow { + Key { + text: "\u064E" + } + Key { + text: "\u064B" + } + Key { + text: "\u064F" + } + Key { + text: "\u064C" + } + Key { + text: "\uFEF9" + } + Key { + text: "\u0625" + } + Key { + enabled: false + } + Key { + enabled: false + } + Key { + enabled: false + } + Key { + enabled: false + } + Key { + enabled: false + } + Key { + text: "\u0630" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Key { + text: "\u0650" + } + Key { + text: "\u064D" + } + Key { + enabled: false + } + Key { + enabled: false + } + Key { + text: "\u0644\u0623" + } + Key { + text: "\u0623" + } + Key { + enabled: false + } + Key { + enabled: false + } + Key { + enabled: false + } + Key { + enabled: false + } + Key { + enabled: false + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + ShiftKey {} + Key { + enabled: false + } + Key { + text: "\u0652" + } + Key { + enabled: false + } + Key { + enabled: false + } + Key { + text: "\u0644\u0622" + } + Key { + text: "\u0622" + } + Key { + enabled: false + } + Key { + enabled: false + } + Key { + enabled: false + } + Key { + enabled: false + } + ShiftKey { + weight: 264 + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + displayText: "\u0661\u0662\u0663\u061F" + } + ChangeLanguageKey { + weight: 154 + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: 0x061F + text: "\u061F" + alternativeKeys: ".,\u060C\u061F" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/ar_AR/numbers.qml b/virtualkeyboard_layouts_koriolan/layouts/ar_AR/numbers.qml new file mode 100755 index 0000000..fe70948 --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/ar_AR/numbers.qml @@ -0,0 +1,194 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Layouts 1.0 +import QtQuick.VirtualKeyboard 2.1 +import QtQuick.VirtualKeyboard.Plugins 2.3 + +KeyboardLayout { + inputMethod: PlainInputMethod {} + inputMode: InputEngine.InputMode.Numeric + + KeyboardRow { + Layout.fillWidth: false + Layout.fillHeight: true + Layout.alignment: Qt.AlignHCenter + KeyboardColumn { + Layout.fillWidth: false + Layout.fillHeight: true + Layout.preferredWidth: parent.height / 4 * 3 + KeyboardRow { + Key { + key: Qt.Key_ParenLeft + text: "(" + } + Key { + key: Qt.Key_ParenRight + text: ")" + } + Key { + key: Qt.Key_Period + text: "." + } + } + KeyboardRow { + Key { + key: Qt.Key_division + text: "\u00F7" + } + Key { + key: Qt.Key_multiply + text: "\u00D7" + } + Key { + key: Qt.Key_Plus + text: "+" + } + } + KeyboardRow { + Key { + key: Qt.Key_AsciiCircum + text: "^" + } + Key { + key: Qt.Key_Slash + text: "/" + } + Key { + key: Qt.Key_Minus + text: "-" + } + } + KeyboardRow { + Key { + key: 0x221A + text: "√" + } + Key { + key: Qt.Key_Percent + text: "%" + } + Key { + key: Qt.Key_Asterisk + text: "*" + } + } + } + KeyboardColumn { + Layout.fillWidth: false + Layout.fillHeight: true + Layout.preferredWidth: parent.height / 8 + KeyboardRow { + FillerKey {} + } + } + KeyboardColumn { + Layout.fillWidth: false + Layout.fillHeight: true + Layout.preferredWidth: parent.height + KeyboardRow { + Key { + key: 0x0667 + text: "\u0667" + alternativeKeys: "\u06677" + } + Key { + key: 0x0668 + text: "\u0668" + alternativeKeys: "\u06688" + } + Key { + key: 0x0669 + text: "\u0669" + alternativeKeys: "\u06699" + } + BackspaceKey {} + } + KeyboardRow { + Key { + key: 0x0664 + text: "\u0664" + alternativeKeys: "\u06644" + } + Key { + key: 0x0665 + text: "\u0665" + alternativeKeys: "\u06655" + } + Key { + key: 0x0666 + text: "\u0666" + alternativeKeys: "\u06666" + } + Key { + text: " " + displayText: "\u2423" + repeat: true + showPreview: false + key: Qt.Key_Space + } + } + KeyboardRow { + Key { + key: 0x0661 + text: "\u0661" + alternativeKeys: "\u06611" + } + Key { + key: 0x0662 + text: "\u0662" + alternativeKeys: "\u06622" + } + Key { + key: 0x0663 + text: "\u0663" + alternativeKeys: "\u06633" + } + HideKeyboardKey {} + } + KeyboardRow { + ChangeLanguageKey { + customLayoutsOnly: true + } + Key { + key: 0x0660 + text: "\u0660" + alternativeKeys: "\u06600" + } + Key { + key: Qt.Key_Comma + text: "\u066B" + alternativeKeys: "\u066B,." + } + EnterKey {} + } + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/ar_AR/symbols.qml b/virtualkeyboard_layouts_koriolan/layouts/ar_AR/symbols.qml new file mode 100755 index 0000000..2da5292 --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/ar_AR/symbols.qml @@ -0,0 +1,388 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Layouts 1.0 +import QtQuick.VirtualKeyboard 2.1 + +KeyboardLayoutLoader { + property bool secondPage + onVisibleChanged: if (!visible) secondPage = false + sourceComponent: secondPage ? page2 : page1 + Component { + id: page1 + KeyboardLayout { + keyWeight: 160 + KeyboardRow { + Key { + key: 0x0661 + text: "\u0661" + alternativeKeys: "\u06611" + } + Key { + key: 0x0662 + text: "\u0662" + alternativeKeys: "\u06622" + } + Key { + key: 0x0663 + text: "\u0663" + alternativeKeys: "\u06633" + } + Key { + key: 0x0664 + text: "\u0664" + alternativeKeys: "\u06644" + } + Key { + key: 0x0665 + text: "\u0665" + alternativeKeys: "\u06655" + } + Key { + key: 0x0666 + text: "\u0666" + alternativeKeys: "\u06666" + } + Key { + key: 0x0667 + text: "\u0667" + alternativeKeys: "\u06677" + } + Key { + key: 0x0668 + text: "\u0668" + alternativeKeys: "\u06688" + } + Key { + key: 0x0669 + text: "\u0669" + alternativeKeys: "\u06699" + } + Key { + key: 0x0660 + text: "\u0660" + alternativeKeys: "\u06600" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Key { + key: Qt.Key_At + text: "@" + } + Key { + key: Qt.Key_NumberSign + text: "#" + } + Key { + key: Qt.Key_Percent + text: "%" + } + Key { + key: Qt.Key_Ampersand + text: "&" + } + Key { + key: Qt.Key_Asterisk + text: "*" + } + Key { + key: Qt.Key_Minus + text: "-" + } + Key { + key: Qt.Key_Plus + text: "+" + } + Key { + key: Qt.Key_ParenLeft + text: "(" + } + Key { + key: Qt.Key_ParenRight + text: ")" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + Key { + displayText: "1/2" + functionKey: true + onClicked: secondPage = !secondPage + } + Key { + key: Qt.Key_Exclam + text: "!" + } + Key { + key: Qt.Key_QuoteDbl + text: '"' + } + Key { + key: Qt.Key_Less + text: "<" + } + Key { + key: Qt.Key_Greater + text: ">" + } + Key { + key: Qt.Key_Apostrophe + text: "'" + } + Key { + key: Qt.Key_Colon + text: ":" + } + Key { + key: 0x061B + text: "\u061B" + alternativeKeys: "\u061B;" + } + Key { + key: Qt.Key_Slash + text: "/" + } + Key { + key: 0x061F + text: "\u061F" + alternativeKeys: "\u061F?" + } + Key { + weight: 204 + displayText: "1/2" + functionKey: true + onClicked: secondPage = !secondPage + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + displayText: "\u0623\u200C\u0628\u200C\u062C" + } + ChangeLanguageKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Period + text: "." + alternativeKeys: ".\u060C," + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } + } + } + Component { + id: page2 + KeyboardLayout { + keyWeight: 160 + KeyboardRow { + Key { + key: Qt.Key_AsciiTilde + text: "~" + } + Key { + key: Qt.Key_Agrave + text: "`" + } + Key { + key: Qt.Key_Bar + text: "|" + } + Key { + key: 0x7B + text: "·" + } + Key { + key: 0x221A + text: "√" + } + Key { + key: Qt.Key_division + text: "÷" + } + Key { + key: Qt.Key_multiply + text: "×" + } + Key { + key: Qt.Key_onehalf + text: "½" + alternativeKeys: "¼⅓½¾⅞" + } + Key { + key: Qt.Key_BraceLeft + text: "{" + } + Key { + key: Qt.Key_BraceRight + text: "}" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Key { + key: Qt.Key_Dollar + text: "$" + } + Key { + key: 0x20AC + text: "€" + } + Key { + key: 0xC2 + text: "£" + } + Key { + key: 0xA2 + text: "¢" + } + Key { + key: 0xA5 + text: "¥" + } + Key { + key: Qt.Key_Equal + text: "=" + } + Key { + key: Qt.Key_section + text: "§" + } + Key { + key: Qt.Key_BracketLeft + text: "[" + } + Key { + key: Qt.Key_BracketRight + text: "]" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + Key { + displayText: "2/2" + functionKey: true + onClicked: secondPage = !secondPage + } + Key { + key: Qt.Key_Underscore + text: "_" + } + Key { + key: 0x2122 + text: '™' + } + Key { + key: 0x00AE + text: '®' + } + Key { + key: Qt.Key_guillemotleft + text: '«' + } + Key { + key: Qt.Key_guillemotright + text: '»' + } + Key { + key: 0x201C + text: '“' + } + Key { + key: 0x201D + text: '”' + } + Key { + key: Qt.Key_Backslash + text: "\\" + } + Key { + key: Qt.Key_AsciiCircum + text: "^" + } + Key { + weight: 204 + displayText: "2/2" + functionKey: true + onClicked: secondPage = !secondPage + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + displayText: "\u0623\u200C\u0628\u200C\u062C" + } + ChangeLanguageKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: 0x2026 + text: "\u2026" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/bg_BG/dialpad.fallback b/virtualkeyboard_layouts_koriolan/layouts/bg_BG/dialpad.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/bg_BG/digits.fallback b/virtualkeyboard_layouts_koriolan/layouts/bg_BG/digits.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/bg_BG/handwriting.qml b/virtualkeyboard_layouts_koriolan/layouts/bg_BG/handwriting.qml new file mode 100755 index 0000000..16f078c --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/bg_BG/handwriting.qml @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Layouts 1.0 +import QtQuick.VirtualKeyboard 2.3 + +KeyboardLayout { + function createInputMethod() { + return Qt.createQmlObject('import QtQuick 2.0; import QtQuick.VirtualKeyboard.Plugins 2.3; HandwritingInputMethod {}', parent) + } + sharedLayouts: ['symbols'] + + KeyboardRow { + Layout.preferredHeight: 3 + KeyboardColumn { + Layout.preferredWidth: bottomRow.width - hideKeyboardKey.width + KeyboardRow { + TraceInputKey { + objectName: "hwrInputArea" + patternRecognitionMode: InputEngine.PatternRecognitionMode.Handwriting + horizontalRulers: + InputContext.inputEngine.inputMode !== InputEngine.InputMode.Cyrillic ? [] : + [Math.round(boundingBox.height / 4), Math.round(boundingBox.height / 4) * 2, Math.round(boundingBox.height / 4) * 3] + } + } + } + KeyboardColumn { + Layout.preferredWidth: hideKeyboardKey.width + KeyboardRow { + BackspaceKey {} + } + KeyboardRow { + EnterKey {} + } + KeyboardRow { + ShiftKey { } + } + } + } + KeyboardRow { + id: bottomRow + Layout.preferredHeight: 1 + keyWeight: 154 + InputModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + customLayoutsOnly: true + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Apostrophe + text: "'" + alternativeKeys: "<>()#%&*/\\\"'=+-_" + } + Key { + key: Qt.Key_Period + text: "." + alternativeKeys: "!,.;:?" + } + HideKeyboardKey { + id: hideKeyboardKey + weight: 204 + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/bg_BG/main.qml b/virtualkeyboard_layouts_koriolan/layouts/bg_BG/main.qml new file mode 100755 index 0000000..2e958aa --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/bg_BG/main.qml @@ -0,0 +1,370 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.VirtualKeyboard 2.3 + +KeyboardLayoutLoader { + sharedLayouts: ['symbols'] + sourceComponent: InputContext.inputEngine.inputMode === InputEngine.InputMode.Cyrillic ? cyrillicLayout : latinLayout + Component { + id: cyrillicLayout + KeyboardLayout { + keyWeight: 160 + KeyboardRow { + Key { + text: "я" + } + Key { + text: "в" + } + Key { + text: "е" + } + Key { + text: "р" + } + Key { + text: "т" + } + Key { + text: "ъ" + } + Key { + text: "у" + } + Key { + text: "и" + } + Key { + text: "о" + } + Key { + text: "п" + } + Key { + text: "ч" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Key { + text: "а" + } + Key { + text: "с" + } + Key { + text: "д" + } + Key { + text: "ф" + } + Key { + text: "г" + } + Key { + text: "х" + } + Key { + text: "й" + } + Key { + text: "к" + } + Key { + text: "л" + } + Key { + text: "ш" + } + Key { + text: "щ" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + InputModeKey { + inputModes: [InputEngine.InputMode.Cyrillic, InputEngine.InputMode.Latin] + } + Key { + text: "з" + } + Key { + text: "ь" + } + Key { + text: "ц" + } + Key { + text: "ж" + } + Key { + text: "б" + } + Key { + text: "н" + } + Key { + text: "м" + } + Key { + text: "ю" + } + Key { + key: Qt.Key_Comma + text: "," + } + Key { + key: Qt.Key_Period + text: "." + alternativeKeys: "!.;?" + } + ShiftKey { + weight: 204 + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Apostrophe + text: "'" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } + } + } + Component { + id: latinLayout + KeyboardLayout { + keyWeight: 160 + KeyboardRow { + Key { + key: Qt.Key_Q + text: "q" + } + Key { + key: Qt.Key_W + text: "w" + } + Key { + key: Qt.Key_E + text: "e" + alternativeKeys: "êeëèé" + } + Key { + key: Qt.Key_R + text: "r" + alternativeKeys: "ŕrř" + } + Key { + key: Qt.Key_T + text: "t" + alternativeKeys: "ţtŧť" + } + Key { + key: Qt.Key_Y + text: "y" + alternativeKeys: "ÿyýŷ" + } + Key { + key: Qt.Key_U + text: "u" + alternativeKeys: "űūũûüuùú" + } + Key { + key: Qt.Key_I + text: "i" + alternativeKeys: "îïīĩiìí" + } + Key { + key: Qt.Key_O + text: "o" + alternativeKeys: "œøõôöòóo" + } + Key { + key: Qt.Key_P + text: "p" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Key { + key: Qt.Key_A + text: "a" + alternativeKeys: (InputContext.inputMethodHints & (Qt.ImhEmailCharactersOnly | Qt.ImhUrlCharactersOnly)) ? "a@äåãâàá" : "aäåãâàá" + smallTextVisible: (InputContext.inputMethodHints & (Qt.ImhEmailCharactersOnly | Qt.ImhUrlCharactersOnly)) + } + Key { + key: Qt.Key_S + text: "s" + alternativeKeys: "šsşś" + } + Key { + key: Qt.Key_D + text: "d" + alternativeKeys: "dđď" + } + Key { + key: Qt.Key_F + text: "f" + } + Key { + key: Qt.Key_G + text: "g" + alternativeKeys: "ġgģĝğ" + } + Key { + key: Qt.Key_H + text: "h" + } + Key { + key: Qt.Key_J + text: "j" + } + Key { + key: Qt.Key_K + text: "k" + } + Key { + key: Qt.Key_L + text: "l" + alternativeKeys: "ĺŀłļľl" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + InputModeKey { + enabled: !(InputContext.inputMethodHints & Qt.ImhLatinOnly) && inputModeCount > 1 + inputModes: [InputEngine.InputMode.Cyrillic, InputEngine.InputMode.Latin] + } + Key { + key: Qt.Key_Z + text: "z" + alternativeKeys: "zžż" + } + Key { + key: Qt.Key_X + text: "x" + } + Key { + key: Qt.Key_C + text: "c" + alternativeKeys: "çcċčć" + } + Key { + key: Qt.Key_V + text: "v" + } + Key { + key: Qt.Key_B + text: "b" + } + Key { + key: Qt.Key_N + text: "n" + alternativeKeys: "ņńnň" + } + Key { + key: Qt.Key_M + text: "m" + } + Key { + key: Qt.Key_Comma + text: "," + } + Key { + key: Qt.Key_Period + text: "." + } + ShiftKey { + weight: 204 + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Apostrophe + text: "'" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/bg_BG/numbers.fallback b/virtualkeyboard_layouts_koriolan/layouts/bg_BG/numbers.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/bg_BG/symbols.fallback b/virtualkeyboard_layouts_koriolan/layouts/bg_BG/symbols.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/cs_CZ/dialpad.fallback b/virtualkeyboard_layouts_koriolan/layouts/cs_CZ/dialpad.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/cs_CZ/digits.fallback b/virtualkeyboard_layouts_koriolan/layouts/cs_CZ/digits.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/cs_CZ/handwriting.qml b/virtualkeyboard_layouts_koriolan/layouts/cs_CZ/handwriting.qml new file mode 100755 index 0000000..caf820a --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/cs_CZ/handwriting.qml @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Layouts 1.0 +import QtQuick.VirtualKeyboard 2.3 + +KeyboardLayout { + function createInputMethod() { + return Qt.createQmlObject('import QtQuick 2.0; import QtQuick.VirtualKeyboard.Plugins 2.3; HandwritingInputMethod {}', parent) + } + sharedLayouts: ['symbols'] + inputMode: InputEngine.InputMode.Latin + + KeyboardRow { + Layout.preferredHeight: 3 + KeyboardColumn { + Layout.preferredWidth: bottomRow.width - hideKeyboardKey.width + KeyboardRow { + TraceInputKey { + objectName: "hwrInputArea" + patternRecognitionMode: InputEngine.PatternRecognitionMode.Handwriting + } + } + } + KeyboardColumn { + Layout.preferredWidth: hideKeyboardKey.width + KeyboardRow { + BackspaceKey {} + } + KeyboardRow { + EnterKey {} + } + KeyboardRow { + ShiftKey { } + } + } + } + KeyboardRow { + id: bottomRow + Layout.preferredHeight: 1 + keyWeight: 154 + InputModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + customLayoutsOnly: true + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Minus + text: "-" + alternativeKeys: "<>()#%&*/\\\"'=+-_" + } + Key { + key: Qt.Key_Period + text: "." + alternativeKeys: ":;,.?!" + } + HideKeyboardKey { + id: hideKeyboardKey + weight: 204 + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/cs_CZ/main.qml b/virtualkeyboard_layouts_koriolan/layouts/cs_CZ/main.qml new file mode 100755 index 0000000..4d328bf --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/cs_CZ/main.qml @@ -0,0 +1,207 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.VirtualKeyboard 2.3 + +KeyboardLayout { + inputMode: InputEngine.InputMode.Latin + keyWeight: 160 + KeyboardRow { + Key { + key: Qt.Key_Q + text: "q" + } + Key { + key: Qt.Key_W + text: "w" + } + Key { + key: Qt.Key_E + text: "e" + alternativeKeys: "eéě" + } + Key { + key: Qt.Key_R + text: "r" + alternativeKeys: "rř" + } + Key { + key: Qt.Key_T + text: "t" + alternativeKeys: "tť" + } + Key { + key: Qt.Key_Z + text: "z" + alternativeKeys: "zž" + } + Key { + key: Qt.Key_U + text: "u" + alternativeKeys: "uúů" + } + Key { + key: Qt.Key_I + text: "i" + alternativeKeys: "ií" + } + Key { + key: Qt.Key_O + text: "o" + alternativeKeys: "oóö" + } + Key { + key: Qt.Key_P + text: "p" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Key { + key: Qt.Key_A + text: "a" + alternativeKeys: "aåäá" + } + Key { + key: Qt.Key_S + text: "s" + alternativeKeys: "sš" + } + Key { + key: Qt.Key_D + text: "d" + alternativeKeys: "dď" + } + Key { + key: Qt.Key_F + text: "f" + } + Key { + key: Qt.Key_G + text: "g" + } + Key { + key: Qt.Key_H + text: "h" + } + Key { + key: Qt.Key_J + text: "j" + } + Key { + key: Qt.Key_K + text: "k" + } + Key { + key: Qt.Key_L + text: "l" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + ShiftKey {} + Key { + key: Qt.Key_Y + text: "y" + alternativeKeys: "yý" + } + Key { + key: Qt.Key_X + text: "x" + } + Key { + key: Qt.Key_C + text: "c" + alternativeKeys: "cćč" + } + Key { + key: Qt.Key_V + text: "v" + } + Key { + key: Qt.Key_B + text: "b" + } + Key { + key: Qt.Key_N + text: "n" + alternativeKeys: "nń" + } + Key { + key: Qt.Key_M + text: "m" + } + Key { + key: Qt.Key_Comma + text: "," + } + Key { + key: Qt.Key_Period + text: "." + } + ShiftKey { + weight: 204 + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Minus + text: "-" + alternativeKeys: "-\"'" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/cs_CZ/numbers.fallback b/virtualkeyboard_layouts_koriolan/layouts/cs_CZ/numbers.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/cs_CZ/symbols.fallback b/virtualkeyboard_layouts_koriolan/layouts/cs_CZ/symbols.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/da_DK/dialpad.fallback b/virtualkeyboard_layouts_koriolan/layouts/da_DK/dialpad.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/da_DK/digits.fallback b/virtualkeyboard_layouts_koriolan/layouts/da_DK/digits.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/da_DK/handwriting.fallback b/virtualkeyboard_layouts_koriolan/layouts/da_DK/handwriting.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/da_DK/main.qml b/virtualkeyboard_layouts_koriolan/layouts/da_DK/main.qml new file mode 100755 index 0000000..b03860e --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/da_DK/main.qml @@ -0,0 +1,215 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.VirtualKeyboard 2.1 + +KeyboardLayout { + inputMode: InputEngine.InputMode.Latin + keyWeight: 160 + KeyboardRow { + Key { + key: Qt.Key_Q + text: "q" + } + Key { + key: Qt.Key_W + text: "w" + } + Key { + key: Qt.Key_E + text: "e" + alternativeKeys: "eé" + } + Key { + key: Qt.Key_R + text: "r" + } + Key { + key: Qt.Key_T + text: "t" + } + Key { + key: Qt.Key_Y + text: "y" + } + Key { + key: Qt.Key_U + text: "u" + } + Key { + key: Qt.Key_I + text: "i" + alternativeKeys: "ií" + } + Key { + key: Qt.Key_O + text: "o" + alternativeKeys: "oó" + } + Key { + key: Qt.Key_P + text: "p" + } + Key { + key: Qt.Key_Aring + text: "å" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 66 + } + Key { + key: Qt.Key_A + text: "a" + alternativeKeys: "aá" + } + Key { + key: Qt.Key_S + text: "s" + } + Key { + key: Qt.Key_D + text: "d" + } + Key { + key: Qt.Key_F + text: "f" + } + Key { + key: Qt.Key_G + text: "g" + } + Key { + key: Qt.Key_H + text: "h" + } + Key { + key: Qt.Key_J + text: "j" + } + Key { + key: Qt.Key_K + text: "k" + } + Key { + key: Qt.Key_L + text: "l" + } + Key { + key: Qt.Key_AE + text: "æ" + alternativeKeys: "æǽ" + } + Key { + key: Qt.Key_Ooblique + text: "ø" + alternativeKeys: "øǿ" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + ShiftKey { } + Key { + key: Qt.Key_Z + text: "z" + } + Key { + key: Qt.Key_X + text: "x" + } + Key { + key: Qt.Key_C + text: "c" + } + Key { + key: Qt.Key_V + text: "v" + } + Key { + key: Qt.Key_B + text: "b" + } + Key { + key: Qt.Key_N + text: "n" + } + Key { + key: Qt.Key_M + text: "m" + } + Key { + key: Qt.Key_Comma + text: "," + } + Key { + key: Qt.Key_Period + text: "." + } + Key { + key: Qt.Key_Minus + text: "-" + } + ShiftKey { + weight: 264 + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Apostrophe + text: "'" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/da_DK/numbers.fallback b/virtualkeyboard_layouts_koriolan/layouts/da_DK/numbers.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/da_DK/symbols.fallback b/virtualkeyboard_layouts_koriolan/layouts/da_DK/symbols.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/de_DE/dialpad.fallback b/virtualkeyboard_layouts_koriolan/layouts/de_DE/dialpad.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/de_DE/digits.fallback b/virtualkeyboard_layouts_koriolan/layouts/de_DE/digits.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/de_DE/handwriting.fallback b/virtualkeyboard_layouts_koriolan/layouts/de_DE/handwriting.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/de_DE/main.qml b/virtualkeyboard_layouts_koriolan/layouts/de_DE/main.qml new file mode 100755 index 0000000..bd91ec5 --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/de_DE/main.qml @@ -0,0 +1,210 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.VirtualKeyboard 2.1 + +KeyboardLayout { + inputMode: InputEngine.InputMode.Latin + keyWeight: 160 + KeyboardRow { + Key { + key: Qt.Key_Q + text: "q" + } + Key { + key: Qt.Key_W + text: "w" + } + Key { + key: Qt.Key_E + text: "e" + } + Key { + key: Qt.Key_R + text: "r" + } + Key { + key: Qt.Key_T + text: "t" + } + Key { + key: Qt.Key_Z + text: "z" + } + Key { + key: Qt.Key_U + text: "u" + } + Key { + key: Qt.Key_I + text: "i" + } + Key { + key: Qt.Key_O + text: "o" + } + Key { + key: Qt.Key_P + text: "p" + } + Key { + key: Qt.Key_Udiaeresis + text: "ü" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 66 + } + Key { + key: Qt.Key_A + text: "a" + } + Key { + key: Qt.Key_S + text: "s" + alternativeKeys: "sß" + } + Key { + key: Qt.Key_D + text: "d" + } + Key { + key: Qt.Key_F + text: "f" + } + Key { + key: Qt.Key_G + text: "g" + } + Key { + key: Qt.Key_H + text: "h" + } + Key { + key: Qt.Key_J + text: "j" + } + Key { + key: Qt.Key_K + text: "k" + } + Key { + key: Qt.Key_L + text: "l" + } + Key { + key: Qt.Key_Odiaeresis + text: "ö" + } + Key { + key: Qt.Key_Adiaeresis + text: "ä" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + ShiftKey { } + Key { + key: Qt.Key_Y + text: "y" + } + Key { + key: Qt.Key_X + text: "x" + } + Key { + key: Qt.Key_C + text: "c" + } + Key { + key: Qt.Key_V + text: "v" + } + Key { + key: Qt.Key_B + text: "b" + } + Key { + key: Qt.Key_N + text: "n" + } + Key { + key: Qt.Key_M + text: "m" + } + Key { + key: Qt.Key_Comma + text: "," + } + Key { + key: Qt.Key_Period + text: "." + } + Key { + key: Qt.Key_Minus + text: "-" + } + ShiftKey { + weight: 264 + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Apostrophe + text: "'" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/de_DE/numbers.fallback b/virtualkeyboard_layouts_koriolan/layouts/de_DE/numbers.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/de_DE/symbols.fallback b/virtualkeyboard_layouts_koriolan/layouts/de_DE/symbols.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/el_GR/dialpad.fallback b/virtualkeyboard_layouts_koriolan/layouts/el_GR/dialpad.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/el_GR/digits.fallback b/virtualkeyboard_layouts_koriolan/layouts/el_GR/digits.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/el_GR/handwriting.qml b/virtualkeyboard_layouts_koriolan/layouts/el_GR/handwriting.qml new file mode 100755 index 0000000..b010ecf --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/el_GR/handwriting.qml @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Layouts 1.0 +import QtQuick.VirtualKeyboard 2.3 + +KeyboardLayout { + function createInputMethod() { + return Qt.createQmlObject('import QtQuick 2.0; import QtQuick.VirtualKeyboard.Plugins 2.3; HandwritingInputMethod {}', parent) + } + sharedLayouts: ['symbols'] + + KeyboardRow { + Layout.preferredHeight: 3 + KeyboardColumn { + Layout.preferredWidth: bottomRow.width - hideKeyboardKey.width + KeyboardRow { + TraceInputKey { + objectName: "hwrInputArea" + patternRecognitionMode: InputEngine.PatternRecognitionMode.Handwriting + horizontalRulers: + InputContext.inputEngine.inputMode !== InputEngine.InputMode.Greek ? [] : + [Math.round(boundingBox.height / 4), Math.round(boundingBox.height / 4) * 2, Math.round(boundingBox.height / 4) * 3] + } + } + } + KeyboardColumn { + Layout.preferredWidth: hideKeyboardKey.width + KeyboardRow { + BackspaceKey {} + } + KeyboardRow { + EnterKey {} + } + KeyboardRow { + ShiftKey { } + } + } + } + KeyboardRow { + id: bottomRow + Layout.preferredHeight: 1 + keyWeight: 154 + InputModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + customLayoutsOnly: true + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Apostrophe + text: "'" + alternativeKeys: "<>()#%&*/\\\"'=+-_" + } + Key { + key: Qt.Key_Period + text: "." + alternativeKeys: "!,.;:?" + } + HideKeyboardKey { + id: hideKeyboardKey + weight: 204 + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/el_GR/main.qml b/virtualkeyboard_layouts_koriolan/layouts/el_GR/main.qml new file mode 100755 index 0000000..d9fbaf9 --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/el_GR/main.qml @@ -0,0 +1,364 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.VirtualKeyboard 2.3 + +KeyboardLayoutLoader { + sharedLayouts: ['symbols'] + sourceComponent: InputContext.inputEngine.inputMode === InputEngine.InputMode.Greek ? greekLayout : latinLayout + Component { + id: greekLayout + KeyboardLayout { + keyWeight: 160 + KeyboardRow { + Key { + text: "ς" + } + Key { + text: "ε" + alternativeKeys: "εέ" + } + Key { + text: "ρ" + } + Key { + text: "τ" + } + Key { + text: "ψ" + } + Key { + text: "υ" + alternativeKeys: "υύϋΰ" + } + Key { + text: "θ" + } + Key { + text: "ι" + alternativeKeys: "ιίϊΐ" + } + Key { + text: "ο" + alternativeKeys: "οό" + } + Key { + text: "π" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Key { + text: "α" + alternativeKeys: "αά" + } + Key { + text: "σ" + } + Key { + text: "δ" + } + Key { + text: "φ" + } + Key { + text: "γ" + } + Key { + text: "η" + alternativeKeys: "ηή" + } + Key { + text: "ξ" + } + Key { + text: "κ" + } + Key { + text: "λ" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + InputModeKey { + inputModes: [InputEngine.InputMode.Greek, InputEngine.InputMode.Latin] + } + Key { + text: "ζ" + } + Key { + text: "χ" + } + Key { + text: "ψ" + } + Key { + text: "ω" + alternativeKeys: "ωώ" + } + Key { + text: "β" + } + Key { + text: "ν" + } + Key { + text: "μ" + } + Key { + key: Qt.Key_Comma + text: "," + } + Key { + key: Qt.Key_Period + text: "." + alternativeKeys: "!.;?" + } + ShiftKey { + weight: 204 + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Apostrophe + text: "'" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } + } + } + Component { + id: latinLayout + KeyboardLayout { + keyWeight: 160 + KeyboardRow { + Key { + key: Qt.Key_Q + text: "q" + } + Key { + key: Qt.Key_W + text: "w" + } + Key { + key: Qt.Key_E + text: "e" + alternativeKeys: "êeëèé" + } + Key { + key: Qt.Key_R + text: "r" + alternativeKeys: "ŕrř" + } + Key { + key: Qt.Key_T + text: "t" + alternativeKeys: "ţtŧť" + } + Key { + key: Qt.Key_Y + text: "y" + alternativeKeys: "ÿyýŷ" + } + Key { + key: Qt.Key_U + text: "u" + alternativeKeys: "űūũûüuùú" + } + Key { + key: Qt.Key_I + text: "i" + alternativeKeys: "îïīĩiìí" + } + Key { + key: Qt.Key_O + text: "o" + alternativeKeys: "œøõôöòóo" + } + Key { + key: Qt.Key_P + text: "p" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Key { + key: Qt.Key_A + text: "a" + alternativeKeys: (InputContext.inputMethodHints & (Qt.ImhEmailCharactersOnly | Qt.ImhUrlCharactersOnly)) ? "a@äåãâàá" : "aäåãâàá" + smallTextVisible: (InputContext.inputMethodHints & (Qt.ImhEmailCharactersOnly | Qt.ImhUrlCharactersOnly)) + } + Key { + key: Qt.Key_S + text: "s" + alternativeKeys: "šsşś" + } + Key { + key: Qt.Key_D + text: "d" + alternativeKeys: "dđď" + } + Key { + key: Qt.Key_F + text: "f" + } + Key { + key: Qt.Key_G + text: "g" + alternativeKeys: "ġgģĝğ" + } + Key { + key: Qt.Key_H + text: "h" + } + Key { + key: Qt.Key_J + text: "j" + } + Key { + key: Qt.Key_K + text: "k" + } + Key { + key: Qt.Key_L + text: "l" + alternativeKeys: "ĺŀłļľl" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + InputModeKey { + inputModes: [InputEngine.InputMode.Greek, InputEngine.InputMode.Latin] + } + Key { + key: Qt.Key_Z + text: "z" + alternativeKeys: "zžż" + } + Key { + key: Qt.Key_X + text: "x" + } + Key { + key: Qt.Key_C + text: "c" + alternativeKeys: "çcċčć" + } + Key { + key: Qt.Key_V + text: "v" + } + Key { + key: Qt.Key_B + text: "b" + } + Key { + key: Qt.Key_N + text: "n" + alternativeKeys: "ņńnň" + } + Key { + key: Qt.Key_M + text: "m" + } + Key { + key: Qt.Key_Comma + text: "," + } + Key { + key: Qt.Key_Period + text: "." + } + ShiftKey { + weight: 204 + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Apostrophe + text: "'" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/el_GR/numbers.fallback b/virtualkeyboard_layouts_koriolan/layouts/el_GR/numbers.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/el_GR/symbols.fallback b/virtualkeyboard_layouts_koriolan/layouts/el_GR/symbols.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/en_GB/dialpad.fallback b/virtualkeyboard_layouts_koriolan/layouts/en_GB/dialpad.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/en_GB/digits.fallback b/virtualkeyboard_layouts_koriolan/layouts/en_GB/digits.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/en_GB/handwriting.fallback b/virtualkeyboard_layouts_koriolan/layouts/en_GB/handwriting.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/en_GB/main.fallback b/virtualkeyboard_layouts_koriolan/layouts/en_GB/main.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/en_GB/numbers.fallback b/virtualkeyboard_layouts_koriolan/layouts/en_GB/numbers.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/en_GB/symbols.fallback b/virtualkeyboard_layouts_koriolan/layouts/en_GB/symbols.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/en_US/dialpad.fallback b/virtualkeyboard_layouts_koriolan/layouts/en_US/dialpad.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/en_US/digits.fallback b/virtualkeyboard_layouts_koriolan/layouts/en_US/digits.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/en_US/handwriting.fallback b/virtualkeyboard_layouts_koriolan/layouts/en_US/handwriting.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/en_US/main.fallback b/virtualkeyboard_layouts_koriolan/layouts/en_US/main.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/en_US/numbers.fallback b/virtualkeyboard_layouts_koriolan/layouts/en_US/numbers.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/en_US/symbols.fallback b/virtualkeyboard_layouts_koriolan/layouts/en_US/symbols.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/es_ES/dialpad.fallback b/virtualkeyboard_layouts_koriolan/layouts/es_ES/dialpad.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/es_ES/digits.fallback b/virtualkeyboard_layouts_koriolan/layouts/es_ES/digits.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/es_ES/handwriting.qml b/virtualkeyboard_layouts_koriolan/layouts/es_ES/handwriting.qml new file mode 100755 index 0000000..d489640 --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/es_ES/handwriting.qml @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Layouts 1.0 +import QtQuick.VirtualKeyboard 2.3 + +KeyboardLayout { + function createInputMethod() { + return Qt.createQmlObject('import QtQuick 2.0; import QtQuick.VirtualKeyboard.Plugins 2.3; HandwritingInputMethod {}', parent) + } + sharedLayouts: ['symbols'] + inputMode: InputEngine.InputMode.Latin + + KeyboardRow { + Layout.preferredHeight: 3 + KeyboardColumn { + Layout.preferredWidth: bottomRow.width - hideKeyboardKey.width + KeyboardRow { + TraceInputKey { + objectName: "hwrInputArea" + patternRecognitionMode: InputEngine.PatternRecognitionMode.Handwriting + } + } + } + KeyboardColumn { + Layout.preferredWidth: hideKeyboardKey.width + KeyboardRow { + BackspaceKey {} + } + KeyboardRow { + EnterKey {} + } + KeyboardRow { + ShiftKey { } + } + } + } + KeyboardRow { + id: bottomRow + Layout.preferredHeight: 1 + keyWeight: 154 + InputModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + customLayoutsOnly: true + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Apostrophe + text: "'" + alternativeKeys: "<>()#%&*/\\\"'=+-_" + } + Key { + key: Qt.Key_Period + text: "." + alternativeKeys: ":;,.¿?¡!" + } + HideKeyboardKey { + id: hideKeyboardKey + weight: 204 + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/es_ES/main.qml b/virtualkeyboard_layouts_koriolan/layouts/es_ES/main.qml new file mode 100755 index 0000000..b98980b --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/es_ES/main.qml @@ -0,0 +1,211 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.VirtualKeyboard 2.1 + +KeyboardLayout { + inputMode: InputEngine.InputMode.Latin + keyWeight: 160 + KeyboardRow { + Key { + key: Qt.Key_Q + text: "q" + } + Key { + key: Qt.Key_W + text: "w" + } + Key { + key: Qt.Key_E + text: "e" + alternativeKeys: "ēęėëeêèé" + } + Key { + key: Qt.Key_R + text: "r" + } + Key { + key: Qt.Key_T + text: "t" + } + Key { + key: Qt.Key_Y + text: "y" + } + Key { + key: Qt.Key_U + text: "u" + alternativeKeys: "üûuùú" + } + Key { + key: Qt.Key_I + text: "i" + alternativeKeys: "ïįîiìí" + } + Key { + key: Qt.Key_O + text: "o" + alternativeKeys: "öõôoòóº" + } + Key { + key: Qt.Key_P + text: "p" + } + BackspaceKey { + weight: 180 + } + } + KeyboardRow { + keyWeight: 156 + FillerKey { + weight: 56 + } + Key { + key: Qt.Key_A + text: "a" + alternativeKeys: "äãaâàáª" + } + Key { + key: Qt.Key_S + text: "s" + } + Key { + key: Qt.Key_D + text: "d" + } + Key { + key: Qt.Key_F + text: "f" + } + Key { + key: Qt.Key_G + text: "g" + } + Key { + key: Qt.Key_H + text: "h" + } + Key { + key: Qt.Key_J + text: "j" + } + Key { + key: Qt.Key_K + text: "k" + } + Key { + key: Qt.Key_L + text: "l" + } + Key { + key: Qt.Key_Ntilde + text: "ñ" + } + EnterKey { + weight: 246 + } + } + KeyboardRow { + keyWeight: 156 + ShiftKey {} + Key { + key: Qt.Key_Z + text: "z" + } + Key { + key: Qt.Key_X + text: "x" + } + Key { + key: Qt.Key_C + text: "c" + alternativeKeys: "čcçć" + } + Key { + key: Qt.Key_V + text: "v" + } + Key { + key: Qt.Key_B + text: "b" + } + Key { + key: Qt.Key_N + text: "n" + } + Key { + key: Qt.Key_M + text: "m" + } + Key { + key: Qt.Key_Comma + text: "," + } + Key { + key: Qt.Key_Period + text: "." + } + Key { + key: Qt.Key_Minus + text: "-" + } + ShiftKey { + weight: 264 + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Question + text: "?" + alternativeKeys: "¿?¡!" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/es_ES/numbers.fallback b/virtualkeyboard_layouts_koriolan/layouts/es_ES/numbers.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/es_ES/symbols.qml b/virtualkeyboard_layouts_koriolan/layouts/es_ES/symbols.qml new file mode 100755 index 0000000..17bd3c3 --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/es_ES/symbols.qml @@ -0,0 +1,378 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Layouts 1.0 +import QtQuick.VirtualKeyboard 2.1 + +KeyboardLayoutLoader { + property bool secondPage + onVisibleChanged: if (!visible) secondPage = false + sourceComponent: secondPage ? page2 : page1 + Component { + id: page1 + KeyboardLayout { + keyWeight: 160 + KeyboardRow { + Key { + key: Qt.Key_1 + text: "1" + } + Key { + key: Qt.Key_2 + text: "2" + } + Key { + key: Qt.Key_3 + text: "3" + } + Key { + key: Qt.Key_4 + text: "4" + } + Key { + key: Qt.Key_5 + text: "5" + } + Key { + key: Qt.Key_6 + text: "6" + } + Key { + key: Qt.Key_7 + text: "7" + } + Key { + key: Qt.Key_8 + text: "8" + } + Key { + key: Qt.Key_9 + text: "9" + } + Key { + key: Qt.Key_0 + text: "0" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Key { + key: Qt.Key_At + text: "@" + } + Key { + key: Qt.Key_NumberSign + text: "#" + } + Key { + key: Qt.Key_Percent + text: "%" + } + Key { + key: Qt.Key_Ampersand + text: "&" + } + Key { + key: Qt.Key_Asterisk + text: "*" + } + Key { + key: Qt.Key_Minus + text: "-" + } + Key { + key: Qt.Key_Plus + text: "+" + } + Key { + key: Qt.Key_ParenLeft + text: "(" + } + Key { + key: Qt.Key_ParenRight + text: ")" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + Key { + displayText: "1/2" + functionKey: true + onClicked: secondPage = !secondPage + } + Key { + key: Qt.Key_exclamdown + text: "¡" + alternativeKeys: "¡!" + } + Key { + key: Qt.Key_QuoteDbl + text: '"' + } + Key { + key: Qt.Key_Less + text: "<" + } + Key { + key: Qt.Key_Greater + text: ">" + } + Key { + key: Qt.Key_Apostrophe + text: "'" + } + Key { + key: Qt.Key_Colon + text: ":" + } + Key { + key: Qt.Key_Semicolon + text: ";" + } + Key { + key: Qt.Key_Slash + text: "/" + } + Key { + key: Qt.Key_questiondown + text: "¿" + alternativeKeys: "¿?" + } + Key { + weight: 204 + displayText: "1/2" + functionKey: true + onClicked: secondPage = !secondPage + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + displayText: "ABC" + } + ChangeLanguageKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Period + text: "." + alternativeKeys: ".," + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } + } + } + Component { + id: page2 + KeyboardLayout { + keyWeight: 160 + KeyboardRow { + Key { + key: Qt.Key_AsciiTilde + text: "~" + } + Key { + key: Qt.Key_Agrave + text: "`" + } + Key { + key: Qt.Key_Bar + text: "|" + } + Key { + key: 0x7B + text: "·" + } + Key { + key: 0x221A + text: "√" + } + Key { + key: Qt.Key_division + text: "÷" + } + Key { + key: Qt.Key_multiply + text: "×" + } + Key { + key: Qt.Key_onehalf + text: "½" + alternativeKeys: "¼⅓½¾⅞" + } + Key { + key: Qt.Key_BraceLeft + text: "{" + } + Key { + key: Qt.Key_BraceRight + text: "}" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Key { + key: Qt.Key_Dollar + text: "$" + } + Key { + key: 0x20AC + text: "€" + } + Key { + key: 0xC2 + text: "£" + } + Key { + key: 0xA2 + text: "¢" + } + Key { + key: 0xA5 + text: "¥" + } + Key { + key: Qt.Key_Equal + text: "=" + } + Key { + key: Qt.Key_section + text: "§" + } + Key { + key: Qt.Key_BracketLeft + text: "[" + } + Key { + key: Qt.Key_BracketRight + text: "]" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + Key { + displayText: "2/2" + functionKey: true + onClicked: secondPage = !secondPage + } + Key { + key: Qt.Key_Underscore + text: "_" + } + Key { + key: 0x2122 + text: '™' + } + Key { + key: 0x00AE + text: '®' + } + Key { + key: Qt.Key_guillemotleft + text: '«' + } + Key { + key: Qt.Key_guillemotright + text: '»' + } + Key { + key: 0x201C + text: '“' + } + Key { + key: 0x201D + text: '”' + } + Key { + key: Qt.Key_Backslash + text: "\\" + } + Key { + key: Qt.Key_AsciiCircum + text: "^" + } + Key { + weight: 204 + displayText: "2/2" + functionKey: true + onClicked: secondPage = !secondPage + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + displayText: "ABC" + } + ChangeLanguageKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: 0x2026 + text: "\u2026" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/es_MX/dialpad.fallback b/virtualkeyboard_layouts_koriolan/layouts/es_MX/dialpad.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/es_MX/digits.fallback b/virtualkeyboard_layouts_koriolan/layouts/es_MX/digits.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/es_MX/handwriting.qml b/virtualkeyboard_layouts_koriolan/layouts/es_MX/handwriting.qml new file mode 100755 index 0000000..d489640 --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/es_MX/handwriting.qml @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Layouts 1.0 +import QtQuick.VirtualKeyboard 2.3 + +KeyboardLayout { + function createInputMethod() { + return Qt.createQmlObject('import QtQuick 2.0; import QtQuick.VirtualKeyboard.Plugins 2.3; HandwritingInputMethod {}', parent) + } + sharedLayouts: ['symbols'] + inputMode: InputEngine.InputMode.Latin + + KeyboardRow { + Layout.preferredHeight: 3 + KeyboardColumn { + Layout.preferredWidth: bottomRow.width - hideKeyboardKey.width + KeyboardRow { + TraceInputKey { + objectName: "hwrInputArea" + patternRecognitionMode: InputEngine.PatternRecognitionMode.Handwriting + } + } + } + KeyboardColumn { + Layout.preferredWidth: hideKeyboardKey.width + KeyboardRow { + BackspaceKey {} + } + KeyboardRow { + EnterKey {} + } + KeyboardRow { + ShiftKey { } + } + } + } + KeyboardRow { + id: bottomRow + Layout.preferredHeight: 1 + keyWeight: 154 + InputModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + customLayoutsOnly: true + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Apostrophe + text: "'" + alternativeKeys: "<>()#%&*/\\\"'=+-_" + } + Key { + key: Qt.Key_Period + text: "." + alternativeKeys: ":;,.¿?¡!" + } + HideKeyboardKey { + id: hideKeyboardKey + weight: 204 + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/es_MX/main.qml b/virtualkeyboard_layouts_koriolan/layouts/es_MX/main.qml new file mode 100755 index 0000000..b98980b --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/es_MX/main.qml @@ -0,0 +1,211 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.VirtualKeyboard 2.1 + +KeyboardLayout { + inputMode: InputEngine.InputMode.Latin + keyWeight: 160 + KeyboardRow { + Key { + key: Qt.Key_Q + text: "q" + } + Key { + key: Qt.Key_W + text: "w" + } + Key { + key: Qt.Key_E + text: "e" + alternativeKeys: "ēęėëeêèé" + } + Key { + key: Qt.Key_R + text: "r" + } + Key { + key: Qt.Key_T + text: "t" + } + Key { + key: Qt.Key_Y + text: "y" + } + Key { + key: Qt.Key_U + text: "u" + alternativeKeys: "üûuùú" + } + Key { + key: Qt.Key_I + text: "i" + alternativeKeys: "ïįîiìí" + } + Key { + key: Qt.Key_O + text: "o" + alternativeKeys: "öõôoòóº" + } + Key { + key: Qt.Key_P + text: "p" + } + BackspaceKey { + weight: 180 + } + } + KeyboardRow { + keyWeight: 156 + FillerKey { + weight: 56 + } + Key { + key: Qt.Key_A + text: "a" + alternativeKeys: "äãaâàáª" + } + Key { + key: Qt.Key_S + text: "s" + } + Key { + key: Qt.Key_D + text: "d" + } + Key { + key: Qt.Key_F + text: "f" + } + Key { + key: Qt.Key_G + text: "g" + } + Key { + key: Qt.Key_H + text: "h" + } + Key { + key: Qt.Key_J + text: "j" + } + Key { + key: Qt.Key_K + text: "k" + } + Key { + key: Qt.Key_L + text: "l" + } + Key { + key: Qt.Key_Ntilde + text: "ñ" + } + EnterKey { + weight: 246 + } + } + KeyboardRow { + keyWeight: 156 + ShiftKey {} + Key { + key: Qt.Key_Z + text: "z" + } + Key { + key: Qt.Key_X + text: "x" + } + Key { + key: Qt.Key_C + text: "c" + alternativeKeys: "čcçć" + } + Key { + key: Qt.Key_V + text: "v" + } + Key { + key: Qt.Key_B + text: "b" + } + Key { + key: Qt.Key_N + text: "n" + } + Key { + key: Qt.Key_M + text: "m" + } + Key { + key: Qt.Key_Comma + text: "," + } + Key { + key: Qt.Key_Period + text: "." + } + Key { + key: Qt.Key_Minus + text: "-" + } + ShiftKey { + weight: 264 + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Question + text: "?" + alternativeKeys: "¿?¡!" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/es_MX/numbers.fallback b/virtualkeyboard_layouts_koriolan/layouts/es_MX/numbers.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/es_MX/symbols.qml b/virtualkeyboard_layouts_koriolan/layouts/es_MX/symbols.qml new file mode 100755 index 0000000..17bd3c3 --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/es_MX/symbols.qml @@ -0,0 +1,378 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Layouts 1.0 +import QtQuick.VirtualKeyboard 2.1 + +KeyboardLayoutLoader { + property bool secondPage + onVisibleChanged: if (!visible) secondPage = false + sourceComponent: secondPage ? page2 : page1 + Component { + id: page1 + KeyboardLayout { + keyWeight: 160 + KeyboardRow { + Key { + key: Qt.Key_1 + text: "1" + } + Key { + key: Qt.Key_2 + text: "2" + } + Key { + key: Qt.Key_3 + text: "3" + } + Key { + key: Qt.Key_4 + text: "4" + } + Key { + key: Qt.Key_5 + text: "5" + } + Key { + key: Qt.Key_6 + text: "6" + } + Key { + key: Qt.Key_7 + text: "7" + } + Key { + key: Qt.Key_8 + text: "8" + } + Key { + key: Qt.Key_9 + text: "9" + } + Key { + key: Qt.Key_0 + text: "0" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Key { + key: Qt.Key_At + text: "@" + } + Key { + key: Qt.Key_NumberSign + text: "#" + } + Key { + key: Qt.Key_Percent + text: "%" + } + Key { + key: Qt.Key_Ampersand + text: "&" + } + Key { + key: Qt.Key_Asterisk + text: "*" + } + Key { + key: Qt.Key_Minus + text: "-" + } + Key { + key: Qt.Key_Plus + text: "+" + } + Key { + key: Qt.Key_ParenLeft + text: "(" + } + Key { + key: Qt.Key_ParenRight + text: ")" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + Key { + displayText: "1/2" + functionKey: true + onClicked: secondPage = !secondPage + } + Key { + key: Qt.Key_exclamdown + text: "¡" + alternativeKeys: "¡!" + } + Key { + key: Qt.Key_QuoteDbl + text: '"' + } + Key { + key: Qt.Key_Less + text: "<" + } + Key { + key: Qt.Key_Greater + text: ">" + } + Key { + key: Qt.Key_Apostrophe + text: "'" + } + Key { + key: Qt.Key_Colon + text: ":" + } + Key { + key: Qt.Key_Semicolon + text: ";" + } + Key { + key: Qt.Key_Slash + text: "/" + } + Key { + key: Qt.Key_questiondown + text: "¿" + alternativeKeys: "¿?" + } + Key { + weight: 204 + displayText: "1/2" + functionKey: true + onClicked: secondPage = !secondPage + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + displayText: "ABC" + } + ChangeLanguageKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Period + text: "." + alternativeKeys: ".," + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } + } + } + Component { + id: page2 + KeyboardLayout { + keyWeight: 160 + KeyboardRow { + Key { + key: Qt.Key_AsciiTilde + text: "~" + } + Key { + key: Qt.Key_Agrave + text: "`" + } + Key { + key: Qt.Key_Bar + text: "|" + } + Key { + key: 0x7B + text: "·" + } + Key { + key: 0x221A + text: "√" + } + Key { + key: Qt.Key_division + text: "÷" + } + Key { + key: Qt.Key_multiply + text: "×" + } + Key { + key: Qt.Key_onehalf + text: "½" + alternativeKeys: "¼⅓½¾⅞" + } + Key { + key: Qt.Key_BraceLeft + text: "{" + } + Key { + key: Qt.Key_BraceRight + text: "}" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Key { + key: Qt.Key_Dollar + text: "$" + } + Key { + key: 0x20AC + text: "€" + } + Key { + key: 0xC2 + text: "£" + } + Key { + key: 0xA2 + text: "¢" + } + Key { + key: 0xA5 + text: "¥" + } + Key { + key: Qt.Key_Equal + text: "=" + } + Key { + key: Qt.Key_section + text: "§" + } + Key { + key: Qt.Key_BracketLeft + text: "[" + } + Key { + key: Qt.Key_BracketRight + text: "]" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + Key { + displayText: "2/2" + functionKey: true + onClicked: secondPage = !secondPage + } + Key { + key: Qt.Key_Underscore + text: "_" + } + Key { + key: 0x2122 + text: '™' + } + Key { + key: 0x00AE + text: '®' + } + Key { + key: Qt.Key_guillemotleft + text: '«' + } + Key { + key: Qt.Key_guillemotright + text: '»' + } + Key { + key: 0x201C + text: '“' + } + Key { + key: 0x201D + text: '”' + } + Key { + key: Qt.Key_Backslash + text: "\\" + } + Key { + key: Qt.Key_AsciiCircum + text: "^" + } + Key { + weight: 204 + displayText: "2/2" + functionKey: true + onClicked: secondPage = !secondPage + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + displayText: "ABC" + } + ChangeLanguageKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: 0x2026 + text: "\u2026" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/et_EE/dialpad.fallback b/virtualkeyboard_layouts_koriolan/layouts/et_EE/dialpad.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/et_EE/digits.fallback b/virtualkeyboard_layouts_koriolan/layouts/et_EE/digits.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/et_EE/handwriting.fallback b/virtualkeyboard_layouts_koriolan/layouts/et_EE/handwriting.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/et_EE/main.qml b/virtualkeyboard_layouts_koriolan/layouts/et_EE/main.qml new file mode 100755 index 0000000..4d62e93 --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/et_EE/main.qml @@ -0,0 +1,215 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.VirtualKeyboard 2.1 + +KeyboardLayout { + inputMode: InputEngine.InputMode.Latin + keyWeight: 160 + KeyboardRow { + Key { + key: Qt.Key_Q + text: "q" + } + Key { + key: Qt.Key_W + text: "w" + } + Key { + key: Qt.Key_E + text: "e" + } + Key { + key: Qt.Key_R + text: "r" + } + Key { + key: Qt.Key_T + text: "t" + } + Key { + key: Qt.Key_Y + text: "y" + } + Key { + key: Qt.Key_U + text: "u" + } + Key { + key: Qt.Key_I + text: "i" + } + Key { + key: Qt.Key_O + text: "o" + } + Key { + key: Qt.Key_P + text: "p" + } + Key { + key: Qt.Key_Udiaeresis + text: "ü" + } + Key { + key: Qt.Key_Otilde + text: "õ" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 66 + } + Key { + key: Qt.Key_A + text: "a" + } + Key { + key: Qt.Key_S + text: "s" + alternativeKeys: "sš" + } + Key { + key: Qt.Key_D + text: "d" + } + Key { + key: Qt.Key_F + text: "f" + } + Key { + key: Qt.Key_G + text: "g" + } + Key { + key: Qt.Key_H + text: "h" + } + Key { + key: Qt.Key_J + text: "j" + } + Key { + key: Qt.Key_K + text: "k" + } + Key { + key: Qt.Key_L + text: "l" + } + Key { + key: Qt.Key_Odiaeresis + text: "ö" + } + Key { + key: Qt.Key_Adiaeresis + text: "ä" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + ShiftKey { } + Key { + key: Qt.Key_Z + text: "z" + alternativeKeys: "zž" + } + Key { + key: Qt.Key_X + text: "x" + } + Key { + key: Qt.Key_C + text: "c" + } + Key { + key: Qt.Key_V + text: "v" + } + Key { + key: Qt.Key_B + text: "b" + } + Key { + key: Qt.Key_N + text: "n" + } + Key { + key: Qt.Key_M + text: "m" + } + Key { + key: Qt.Key_Comma + text: "," + } + Key { + key: Qt.Key_Period + text: "." + } + Key { + key: Qt.Key_Minus + text: "-" + } + ShiftKey { + weight: 264 + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Apostrophe + text: "'" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/et_EE/numbers.fallback b/virtualkeyboard_layouts_koriolan/layouts/et_EE/numbers.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/et_EE/symbols.fallback b/virtualkeyboard_layouts_koriolan/layouts/et_EE/symbols.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/fa_FA/dialpad.fallback b/virtualkeyboard_layouts_koriolan/layouts/fa_FA/dialpad.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/fa_FA/digits.qml b/virtualkeyboard_layouts_koriolan/layouts/fa_FA/digits.qml new file mode 100755 index 0000000..ed92201 --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/fa_FA/digits.qml @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Layouts 1.0 +import QtQuick.VirtualKeyboard 2.1 +import QtQuick.VirtualKeyboard.Plugins 2.3 + +KeyboardLayout { + inputMethod: PlainInputMethod {} + inputMode: InputEngine.InputMode.Numeric + + KeyboardColumn { + Layout.fillWidth: false + Layout.fillHeight: true + Layout.alignment: Qt.AlignHCenter + Layout.preferredWidth: height + KeyboardRow { + Key { + text: "\u06F7" + alternativeKeys: "\u06F77" + } + Key { + text: "\u06F8" + alternativeKeys: "\u06F88" + } + Key { + text: "\u06F9" + alternativeKeys: "\u06F99" + } + BackspaceKey {} + } + KeyboardRow { + Key { + text: "\u06F4" + alternativeKeys: "\u06F44" + } + Key { + text: "\u06F5" + alternativeKeys: "\u06F55" + } + Key { + text: "\u06F6" + alternativeKeys: "\u06F66" + } + Key { + text: " " + displayText: "\u2423" + repeat: true + showPreview: false + key: Qt.Key_Space + } + } + KeyboardRow { + Key { + text: "\u06F1" + alternativeKeys: "\u06F11" + } + Key { + text: "\u06F2" + alternativeKeys: "\u06F22" + } + Key { + text: "\u06F3" + alternativeKeys: "\u06F33" + } + HideKeyboardKey {} + } + KeyboardRow { + ChangeLanguageKey { + customLayoutsOnly: true + } + Key { + text: "\u06F0" + alternativeKeys: "\u06F00" + } + Key { + key: Qt.Key_Comma + text: "\u066B" + alternativeKeys: "\u066B,." + } + EnterKey {} + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/fa_FA/handwriting.qml b/virtualkeyboard_layouts_koriolan/layouts/fa_FA/handwriting.qml new file mode 100755 index 0000000..1a43b05 --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/fa_FA/handwriting.qml @@ -0,0 +1,116 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Layouts 1.0 +import QtQuick.VirtualKeyboard 2.3 + +KeyboardLayout { + function createInputMethod() { + return Qt.createQmlObject('import QtQuick 2.0; import QtQuick.VirtualKeyboard.Plugins 2.3; HandwritingInputMethod {}', parent) + } + sharedLayouts: ['symbols'] + inputMode: InputEngine.InputMode.Arabic + readonly property bool alphabeticInputMode: [InputEngine.InputMode.Latin, InputEngine.InputMode.Dialable].indexOf(InputContext.inputEngine.inputMode) !== -1 + + KeyboardRow { + Layout.preferredHeight: 3 + KeyboardColumn { + Layout.preferredWidth: bottomRow.width - hideKeyboardKey.width + KeyboardRow { + TraceInputKey { + objectName: "hwrInputArea" + patternRecognitionMode: InputEngine.PatternRecognitionMode.Handwriting + horizontalRulers: + alphabeticInputMode ? [] : + [Math.round(boundingBox.height / 4), Math.round(boundingBox.height / 4) * 2, Math.round(boundingBox.height / 4) * 3] + } + } + } + KeyboardColumn { + Layout.preferredWidth: hideKeyboardKey.width + KeyboardRow { + BackspaceKey {} + } + KeyboardRow { + EnterKey {} + } + KeyboardRow { + ShiftKey { } + } + } + } + KeyboardRow { + id: bottomRow + Layout.preferredHeight: 1 + keyWeight: 154 + InputModeKey { + weight: 217 + inputModeNameList: [ + "ABC", // InputEngine.InputMode.Latin + "\u0660\u0661\u0662", // InputEngine.InputMode.Numeric + "123", // InputEngine.InputMode.Dialable + "", // InputEngine.InputMode.Pinyin + "", // InputEngine.InputMode.Cangjie + "", // InputEngine.InputMode.Zhuyin + "", // InputEngine.InputMode.Hangul + "", // InputEngine.InputMode.Hiragana + "", // InputEngine.InputMode.Katakana + "", // InputEngine.InputMode.FullwidthLatin + "", // InputEngine.InputMode.Greek + "", // InputEngine.InputMode.Cyrillic + "\u0627\u200C\u0628\u200C\u067E", // InputEngine.InputMode.Arabic + ] + } + ChangeLanguageKey { + weight: 154 + customLayoutsOnly: true + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: alphabeticInputMode ? Qt.Key_Apostrophe : 0x060C + text: alphabeticInputMode ? "'" : "\u060C" + alternativeKeys: alphabeticInputMode ? "<>()#%&*/\\\"'=+-_" : "\"\u060C\u066B\u066C\u066D" + } + Key { + key: Qt.Key_Period + text: "." + alternativeKeys: alphabeticInputMode ? ":;,.?!" : ":\u061B.\u061F!" + } + HideKeyboardKey { + id: hideKeyboardKey + weight: 204 + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/fa_FA/main.qml b/virtualkeyboard_layouts_koriolan/layouts/fa_FA/main.qml new file mode 100755 index 0000000..0450c77 --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/fa_FA/main.qml @@ -0,0 +1,344 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.VirtualKeyboard 2.3 + +KeyboardLayoutLoader { + inputMode: InputEngine.InputMode.Arabic + sourceComponent: InputContext.shiftActive ? page2 : page1 + Component { + id: page1 + KeyboardLayout { + keyWeight: 160 + KeyboardRow { + Key { + text: "\u0636" + } + Key { + text: "\u0635" + } + Key { + text: "\u062B" + } + Key { + text: "\u0642" + } + Key { + text: "\u0641" + } + Key { + text: "\u063A" + } + Key { + text: "\u0639" + } + Key { + text: "\u0647" + } + Key { + text: "\u062E" + } + Key { + text: "\u062D" + } + Key { + text: "\u062C" + } + Key { + text: "\u0686" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Key { + text: "\u0634" + } + Key { + text: "\u0633" + } + Key { + text: "\u06CC" + } + Key { + text: "\u0628" + } + Key { + text: "\u0644" + } + Key { + text: "\u0627" + } + Key { + text: "\u062A" + } + Key { + text: "\u0646" + } + Key { + text: "\u0645" + } + Key { + text: "\u06A9" + } + Key { + text: "\u06AF" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + ShiftKey {} + Key { + text: "\u0638" + } + Key { + text: "\u0637" + } + Key { + text: "\u0632" + } + Key { + text: "\u0631" + } + Key { + text: "\u0630" + } + Key { + text: "\u062F" + } + Key { + text: "\u067E" + } + Key { + text: "\u0648" + } + Key { + key: 0x060C + text: "\u060C" + alternativeKeys: "\u060C," + } + Key { + key: Qt.Key_Period + text: "." + } + ShiftKey { + weight: 204 + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + displayText: "\u06F1\u06F2\u06F3\u061F" + } + ChangeLanguageKey { + weight: 154 + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + text: "\u200D" + displayText: "ZWJ" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } + } + } + Component { + id: page2 + KeyboardLayout { + keyWeight: 160 + KeyboardRow { + Key { + text: "\u0652" + } + Key { + text: "\u064C" + } + Key { + text: "\u064D" + } + Key { + text: "\u064B" + } + Key { + text: "\u064F" + } + Key { + text: "\u0650" + } + Key { + text: "\u064E" + } + Key { + text: "\u0651" + } + Key { + enabled: false + } + Key { + enabled: false + } + Key { + enabled: false + } + Key { + enabled: false + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Key { + enabled: false + } + Key { + text: "\u064F" + } + Key { + text: "\u064A" + } + Key { + text: "\u0625" + } + Key { + text: "\u0623" + } + Key { + text: "\u0622" + } + Key { + text: "\u0629" + } + Key { + enabled: false + } + Key { + enabled: false + } + Key { + enabled: false + } + Key { + enabled: false + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + ShiftKey {} + Key { + text: "\u0643" + } + Key { + text: "\u0653" + } + Key { + text: "\u0698" + } + Key { + text: "\u0670" + } + Key { + text: "\u0621" + } + Key { + enabled: false + } + Key { + enabled: false + } + Key { + text: "\u0624" + } + Key { + key: 0x060C + text: "\u060C" + alternativeKeys: "\u060C," + } + Key { + key: Qt.Key_Period + text: "." + } + ShiftKey { + weight: 204 + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + displayText: "\u06F1\u06F2\u06F3\u061F" + } + ChangeLanguageKey { + weight: 154 + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + text: "\u200C" + displayText: "ZWNJ" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/fa_FA/numbers.qml b/virtualkeyboard_layouts_koriolan/layouts/fa_FA/numbers.qml new file mode 100755 index 0000000..e32a1e7 --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/fa_FA/numbers.qml @@ -0,0 +1,184 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Layouts 1.0 +import QtQuick.VirtualKeyboard 2.1 +import QtQuick.VirtualKeyboard.Plugins 2.3 + +KeyboardLayout { + inputMethod: PlainInputMethod {} + inputMode: InputEngine.InputMode.Numeric + + KeyboardRow { + Layout.fillWidth: false + Layout.fillHeight: true + Layout.alignment: Qt.AlignHCenter + KeyboardColumn { + Layout.fillWidth: false + Layout.fillHeight: true + Layout.preferredWidth: parent.height / 4 * 3 + KeyboardRow { + Key { + key: Qt.Key_ParenLeft + text: "(" + } + Key { + key: Qt.Key_ParenRight + text: ")" + } + Key { + key: Qt.Key_Period + text: "." + } + } + KeyboardRow { + Key { + key: Qt.Key_division + text: "\u00F7" + } + Key { + key: Qt.Key_multiply + text: "\u00D7" + } + Key { + key: Qt.Key_Plus + text: "+" + } + } + KeyboardRow { + Key { + key: Qt.Key_AsciiCircum + text: "^" + } + Key { + key: Qt.Key_Slash + text: "/" + } + Key { + key: Qt.Key_Minus + text: "-" + } + } + KeyboardRow { + Key { + key: 0x221A + text: "√" + } + Key { + key: Qt.Key_Percent + text: "%" + } + Key { + key: Qt.Key_Asterisk + text: "*" + } + } + } + KeyboardColumn { + Layout.fillWidth: false + Layout.fillHeight: true + Layout.preferredWidth: parent.height / 8 + KeyboardRow { + FillerKey {} + } + } + KeyboardColumn { + Layout.fillWidth: false + Layout.fillHeight: true + Layout.preferredWidth: parent.height + KeyboardRow { + Key { + text: "\u06F7" + alternativeKeys: "\u06F77" + } + Key { + text: "\u06F8" + alternativeKeys: "\u06F88" + } + Key { + text: "\u06F9" + alternativeKeys: "\u06F99" + } + BackspaceKey {} + } + KeyboardRow { + Key { + text: "\u06F4" + alternativeKeys: "\u06F44" + } + Key { + text: "\u06F5" + alternativeKeys: "\u06F55" + } + Key { + text: "\u06F6" + alternativeKeys: "\u06F66" + } + Key { + text: " " + displayText: "\u2423" + repeat: true + showPreview: false + key: Qt.Key_Space + } + } + KeyboardRow { + Key { + text: "\u06F1" + alternativeKeys: "\u06F11" + } + Key { + text: "\u06F2" + alternativeKeys: "\u06F22" + } + Key { + text: "\u06F3" + alternativeKeys: "\u06F33" + } + HideKeyboardKey {} + } + KeyboardRow { + ChangeLanguageKey { + customLayoutsOnly: true + } + Key { + text: "\u06F0" + alternativeKeys: "\u06F00" + } + Key { + key: Qt.Key_Comma + text: "\u066B" + alternativeKeys: "\u066B,." + } + EnterKey {} + } + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/fa_FA/symbols.qml b/virtualkeyboard_layouts_koriolan/layouts/fa_FA/symbols.qml new file mode 100755 index 0000000..8641fdb --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/fa_FA/symbols.qml @@ -0,0 +1,378 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Layouts 1.0 +import QtQuick.VirtualKeyboard 2.1 + +KeyboardLayoutLoader { + property bool secondPage + onVisibleChanged: if (!visible) secondPage = false + sourceComponent: secondPage ? page2 : page1 + Component { + id: page1 + KeyboardLayout { + keyWeight: 160 + KeyboardRow { + Key { + text: "\u06F1" + alternativeKeys: "\u06F11" + } + Key { + text: "\u06F2" + alternativeKeys: "\u06F22" + } + Key { + text: "\u06F3" + alternativeKeys: "\u06F33" + } + Key { + text: "\u06F4" + alternativeKeys: "\u06F44" + } + Key { + text: "\u06F5" + alternativeKeys: "\u06F55" + } + Key { + text: "\u06F6" + alternativeKeys: "\u06F66" + } + Key { + text: "\u06F7" + alternativeKeys: "\u06F77" + } + Key { + text: "\u06F8" + alternativeKeys: "\u06F88" + } + Key { + text: "\u06F9" + alternativeKeys: "\u06F99" + } + Key { + text: "\u06F0" + alternativeKeys: "\u06F00" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Key { + key: Qt.Key_At + text: "@" + } + Key { + key: Qt.Key_NumberSign + text: "#" + } + Key { + key: Qt.Key_Percent + text: "%" + } + Key { + key: Qt.Key_Ampersand + text: "&" + } + Key { + key: Qt.Key_Asterisk + text: "*" + } + Key { + key: Qt.Key_Minus + text: "-" + } + Key { + key: Qt.Key_Plus + text: "+" + } + Key { + key: Qt.Key_ParenLeft + text: "(" + } + Key { + key: Qt.Key_ParenRight + text: ")" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + Key { + displayText: "1/2" + functionKey: true + onClicked: secondPage = !secondPage + } + Key { + key: Qt.Key_Exclam + text: "!" + } + Key { + key: Qt.Key_QuoteDbl + text: '"' + } + Key { + key: Qt.Key_Less + text: "<" + } + Key { + key: Qt.Key_Greater + text: ">" + } + Key { + key: Qt.Key_Apostrophe + text: "'" + } + Key { + key: Qt.Key_Colon + text: ":" + } + Key { + key: 0x061B + text: "\u061B" + alternativeKeys: "\u061B;" + } + Key { + key: Qt.Key_Slash + text: "/" + } + Key { + key: 0x061F + text: "\u061F" + alternativeKeys: "\u061F?" + } + Key { + weight: 204 + displayText: "1/2" + functionKey: true + onClicked: secondPage = !secondPage + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + displayText: "\u0627\u200C\u0628\u200C\u067E" + } + ChangeLanguageKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Period + text: "." + alternativeKeys: ".\u060C," + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } + } + } + Component { + id: page2 + KeyboardLayout { + keyWeight: 160 + KeyboardRow { + Key { + key: Qt.Key_AsciiTilde + text: "~" + } + Key { + key: Qt.Key_Agrave + text: "`" + } + Key { + key: Qt.Key_Bar + text: "|" + } + Key { + key: 0x7B + text: "·" + } + Key { + key: 0x221A + text: "√" + } + Key { + key: Qt.Key_division + text: "÷" + } + Key { + key: Qt.Key_multiply + text: "×" + } + Key { + key: Qt.Key_onehalf + text: "½" + alternativeKeys: "¼⅓½¾⅞" + } + Key { + key: Qt.Key_BraceLeft + text: "{" + } + Key { + key: Qt.Key_BraceRight + text: "}" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Key { + key: 0xFDFC + text: "\uFDFC" + } + Key { + key: Qt.Key_Dollar + text: "$" + } + Key { + key: 0x20AC + text: "€" + } + Key { + key: 0xC2 + text: "£" + } + Key { + key: 0xA2 + text: "¢" + } + Key { + key: Qt.Key_Equal + text: "=" + } + Key { + key: Qt.Key_section + text: "§" + } + Key { + key: Qt.Key_BracketLeft + text: "[" + } + Key { + key: Qt.Key_BracketRight + text: "]" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + Key { + displayText: "2/2" + functionKey: true + onClicked: secondPage = !secondPage + } + Key { + key: Qt.Key_Underscore + text: "_" + } + Key { + key: 0x2122 + text: '™' + } + Key { + key: 0x00AE + text: '®' + } + Key { + key: Qt.Key_guillemotleft + text: '«' + } + Key { + key: Qt.Key_guillemotright + text: '»' + } + Key { + key: 0x201C + text: '“' + } + Key { + key: 0x201D + text: '”' + } + Key { + key: Qt.Key_Backslash + text: "\\" + } + Key { + key: Qt.Key_AsciiCircum + text: "^" + } + Key { + weight: 204 + displayText: "2/2" + functionKey: true + onClicked: secondPage = !secondPage + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + displayText: "\u0627\u200C\u0628\u200C\u067E" + } + ChangeLanguageKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: 0x2026 + text: "\u2026" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/fallback/dialpad.qml b/virtualkeyboard_layouts_koriolan/layouts/fallback/dialpad.qml new file mode 100755 index 0000000..89f6873 --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/fallback/dialpad.qml @@ -0,0 +1,113 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Layouts 1.0 +import QtQuick.VirtualKeyboard 2.1 +import QtQuick.VirtualKeyboard.Plugins 2.3 + +KeyboardLayout { + inputMethod: PlainInputMethod {} + inputMode: InputEngine.InputMode.Numeric + + KeyboardColumn { + Layout.fillWidth: false + Layout.fillHeight: true + Layout.alignment: Qt.AlignHCenter + Layout.preferredWidth: height + KeyboardRow { + Key { + key: Qt.Key_1 + text: "1" + } + Key { + key: Qt.Key_2 + text: "2" + } + Key { + key: Qt.Key_3 + text: "3" + } + BackspaceKey {} + } + KeyboardRow { + Key { + key: Qt.Key_4 + text: "4" + } + Key { + key: Qt.Key_5 + text: "5" + } + Key { + key: Qt.Key_6 + text: "6" + } + Key { + text: " " + displayText: "\u2423" + repeat: true + showPreview: false + key: Qt.Key_Space + } + } + KeyboardRow { + Key { + key: Qt.Key_7 + text: "7" + } + Key { + key: Qt.Key_8 + text: "8" + } + Key { + key: Qt.Key_9 + text: "9" + } + HideKeyboardKey {} + } + KeyboardRow { + Key { + key: Qt.Key_Asterisk + displayText: "*+" + text: "*" + alternativeKeys: "*+" + } + Key { + key: Qt.Key_0 + text: "0" + } + Key { + text: "#" + key: Qt.Key_NumberSign + } + EnterKey {} + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/fallback/digits.qml b/virtualkeyboard_layouts_koriolan/layouts/fallback/digits.qml new file mode 100755 index 0000000..481a1d8 --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/fallback/digits.qml @@ -0,0 +1,116 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Layouts 1.0 +import QtQuick.VirtualKeyboard 2.1 +import QtQuick.VirtualKeyboard.Plugins 2.3 + +KeyboardLayout { + inputMethod: PlainInputMethod {} + inputMode: InputEngine.InputMode.Numeric + + KeyboardColumn { + Layout.fillWidth: false + Layout.fillHeight: true + Layout.alignment: Qt.AlignHCenter + Layout.preferredWidth: height + KeyboardRow { + Key { + key: Qt.Key_7 + text: "7" + } + Key { + key: Qt.Key_8 + text: "8" + } + Key { + key: Qt.Key_9 + text: "9" + } + BackspaceKey {} + } + KeyboardRow { + Key { + key: Qt.Key_4 + text: "4" + } + Key { + key: Qt.Key_5 + text: "5" + } + Key { + key: Qt.Key_6 + text: "6" + } + Key { + key: Qt.Key_Minus + text: "-" + } +/* Key { + text: " " + displayText: "\u2423" + repeat: true + showPreview: false + key: Qt.Key_Space + }*/ + } + KeyboardRow { + Key { + key: Qt.Key_1 + text: "1" + } + Key { + key: Qt.Key_2 + text: "2" + } + Key { + key: Qt.Key_3 + text: "3" + } + HideKeyboardKey {} + } + KeyboardRow { + ChangeLanguageKey { + customLayoutsOnly: true + } + Key { + key: Qt.Key_0 + text: "0" + } + Key { + // The decimal key, if it is not "," then we fallback to + // "." in case it is an unhandled different result + key: Qt.locale().decimalPoint === "," ? Qt.Key_Comma : Qt.Key_Period + text: Qt.locale().decimalPoint === "," ? "," : "." + } + EnterKey {} + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/fallback/handwriting.qml b/virtualkeyboard_layouts_koriolan/layouts/fallback/handwriting.qml new file mode 100755 index 0000000..1da3fc8 --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/fallback/handwriting.qml @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Layouts 1.0 +import QtQuick.VirtualKeyboard 2.3 + +KeyboardLayout { + function createInputMethod() { + return Qt.createQmlObject('import QtQuick 2.0; import QtQuick.VirtualKeyboard.Plugins 2.3; HandwritingInputMethod {}', parent) + } + sharedLayouts: ['symbols'] + + KeyboardRow { + Layout.preferredHeight: 3 + KeyboardColumn { + Layout.preferredWidth: bottomRow.width - hideKeyboardKey.width + KeyboardRow { + TraceInputKey { + objectName: "hwrInputArea" + patternRecognitionMode: InputEngine.PatternRecognitionMode.Handwriting + } + } + } + KeyboardColumn { + Layout.preferredWidth: hideKeyboardKey.width + KeyboardRow { + BackspaceKey {} + } + KeyboardRow { + EnterKey {} + } + KeyboardRow { + ShiftKey { } + } + } + } + KeyboardRow { + id: bottomRow + Layout.preferredHeight: 1 + keyWeight: 154 + InputModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + customLayoutsOnly: true + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Apostrophe + text: "'" + alternativeKeys: "<>()#%&*/\\\"'=+-_" + } + Key { + key: Qt.Key_Period + text: "." + alternativeKeys: ":;,.?!" + } + HideKeyboardKey { + id: hideKeyboardKey + weight: 204 + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/fallback/main.qml b/virtualkeyboard_layouts_koriolan/layouts/fallback/main.qml new file mode 100755 index 0000000..c9a736f --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/fallback/main.qml @@ -0,0 +1,208 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.VirtualKeyboard 2.1 + +KeyboardLayout { + inputMode: InputEngine.InputMode.Latin + keyWeight: 160 + KeyboardRow { + Key { + key: Qt.Key_Q + text: "q" + } + Key { + key: Qt.Key_W + text: "w" + } + Key { + key: Qt.Key_E + text: "e" + alternativeKeys: "êeëèé" + } + Key { + key: Qt.Key_R + text: "r" + alternativeKeys: "ŕrř" + } + Key { + key: Qt.Key_T + text: "t" + alternativeKeys: "ţtŧť" + } + Key { + key: Qt.Key_Y + text: "y" + alternativeKeys: "ÿyýŷ" + } + Key { + key: Qt.Key_U + text: "u" + alternativeKeys: "űūũûüuùú" + } + Key { + key: Qt.Key_I + text: "i" + alternativeKeys: "îïīĩiìí" + } + Key { + key: Qt.Key_O + text: "o" + alternativeKeys: "œøõôöòóo" + } + Key { + key: Qt.Key_P + text: "p" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Key { + key: Qt.Key_A + text: "a" + alternativeKeys: "aäåãâàá" + } + Key { + key: Qt.Key_S + text: "s" + alternativeKeys: "šsşś" + } + Key { + key: Qt.Key_D + text: "d" + alternativeKeys: "dđď" + } + Key { + key: Qt.Key_F + text: "f" + } + Key { + key: Qt.Key_G + text: "g" + alternativeKeys: "ġgģĝğ" + } + Key { + key: Qt.Key_H + text: "h" + } + Key { + key: Qt.Key_J + text: "j" + } + Key { + key: Qt.Key_K + text: "k" + } + Key { + key: Qt.Key_L + text: "l" + alternativeKeys: "ĺŀłļľl" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + ShiftKey {} + Key { + key: Qt.Key_Z + text: "z" + alternativeKeys: "zžż" + } + Key { + key: Qt.Key_X + text: "x" + } + Key { + key: Qt.Key_C + text: "c" + alternativeKeys: "çcċčć" + } + Key { + key: Qt.Key_V + text: "v" + } + Key { + key: Qt.Key_B + text: "b" + } + Key { + key: Qt.Key_N + text: "n" + alternativeKeys: "ņńnň" + } + Key { + key: Qt.Key_M + text: "m" + } + Key { + key: Qt.Key_Comma + text: "," + } + Key { + key: Qt.Key_Period + text: "." + } + ShiftKey { + weight: 204 + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Apostrophe + text: "'" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/fallback/numbers.qml b/virtualkeyboard_layouts_koriolan/layouts/fallback/numbers.qml new file mode 100755 index 0000000..7fd0a2a --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/fallback/numbers.qml @@ -0,0 +1,184 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Layouts 1.0 +import QtQuick.VirtualKeyboard 2.1 +import QtQuick.VirtualKeyboard.Plugins 2.3 + +KeyboardLayout { + inputMethod: PlainInputMethod {} + inputMode: InputEngine.InputMode.Numeric + + KeyboardRow { + Layout.fillWidth: false + Layout.fillHeight: true + Layout.alignment: Qt.AlignHCenter + KeyboardColumn { + Layout.fillWidth: false + Layout.fillHeight: true + Layout.preferredWidth: parent.height / 4 * 3 + KeyboardRow { + Key { + key: Qt.Key_ParenLeft + text: "(" + } + Key { + key: Qt.Key_ParenRight + text: ")" + } + Key { + key: Qt.Key_Comma + text: "," + } + } + KeyboardRow { + Key { + key: Qt.Key_division + text: "\u00F7" + } + Key { + key: Qt.Key_multiply + text: "\u00D7" + } + Key { + key: Qt.Key_Plus + text: "+" + } + } + KeyboardRow { + Key { + key: Qt.Key_AsciiCircum + text: "^" + } + Key { + key: Qt.Key_Slash + text: "/" + } + Key { + key: Qt.Key_Minus + text: "-" + } + } + KeyboardRow { + Key { + key: 0x221A + text: "√" + } + Key { + key: Qt.Key_Percent + text: "%" + } + Key { + key: Qt.Key_Asterisk + text: "*" + } + } + } + KeyboardColumn { + Layout.fillWidth: false + Layout.fillHeight: true + Layout.preferredWidth: parent.height / 8 + KeyboardRow { + FillerKey {} + } + } + KeyboardColumn { + Layout.fillWidth: false + Layout.fillHeight: true + Layout.preferredWidth: parent.height + KeyboardRow { + Key { + key: Qt.Key_7 + text: "7" + } + Key { + key: Qt.Key_8 + text: "8" + } + Key { + key: Qt.Key_9 + text: "9" + } + BackspaceKey {} + } + KeyboardRow { + Key { + key: Qt.Key_4 + text: "4" + } + Key { + key: Qt.Key_5 + text: "5" + } + Key { + key: Qt.Key_6 + text: "6" + } + Key { + text: " " + displayText: "\u2423" + repeat: true + showPreview: false + key: Qt.Key_Space + } + } + KeyboardRow { + Key { + key: Qt.Key_1 + text: "1" + } + Key { + key: Qt.Key_2 + text: "2" + } + Key { + key: Qt.Key_3 + text: "3" + } + HideKeyboardKey {} + } + KeyboardRow { + ChangeLanguageKey { + customLayoutsOnly: true + } + Key { + key: Qt.Key_0 + text: "0" + } + Key { + key: Qt.Key_Period + text: "." + alternativeKeys: ".," + } + EnterKey {} + } + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/fallback/symbols.qml b/virtualkeyboard_layouts_koriolan/layouts/fallback/symbols.qml new file mode 100755 index 0000000..26d6295 --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/fallback/symbols.qml @@ -0,0 +1,376 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Layouts 1.0 +import QtQuick.VirtualKeyboard 2.1 + +KeyboardLayoutLoader { + property bool secondPage + onVisibleChanged: if (!visible) secondPage = false + sourceComponent: secondPage ? page2 : page1 + Component { + id: page1 + KeyboardLayout { + keyWeight: 160 + KeyboardRow { + Key { + key: Qt.Key_1 + text: "1" + } + Key { + key: Qt.Key_2 + text: "2" + } + Key { + key: Qt.Key_3 + text: "3" + } + Key { + key: Qt.Key_4 + text: "4" + } + Key { + key: Qt.Key_5 + text: "5" + } + Key { + key: Qt.Key_6 + text: "6" + } + Key { + key: Qt.Key_7 + text: "7" + } + Key { + key: Qt.Key_8 + text: "8" + } + Key { + key: Qt.Key_9 + text: "9" + } + Key { + key: Qt.Key_0 + text: "0" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Key { + key: Qt.Key_At + text: "@" + } + Key { + key: Qt.Key_NumberSign + text: "#" + } + Key { + key: Qt.Key_Percent + text: "%" + } + Key { + key: Qt.Key_Ampersand + text: "&" + } + Key { + key: Qt.Key_Asterisk + text: "*" + } + Key { + key: Qt.Key_Minus + text: "-" + } + Key { + key: Qt.Key_Plus + text: "+" + } + Key { + key: Qt.Key_ParenLeft + text: "(" + } + Key { + key: Qt.Key_ParenRight + text: ")" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + Key { + displayText: "1/2" + functionKey: true + onClicked: secondPage = !secondPage + } + Key { + key: Qt.Key_Exclam + text: "!" + } + Key { + key: Qt.Key_QuoteDbl + text: '"' + } + Key { + key: Qt.Key_Less + text: "<" + } + Key { + key: Qt.Key_Greater + text: ">" + } + Key { + key: Qt.Key_Apostrophe + text: "'" + } + Key { + key: Qt.Key_Colon + text: ":" + } + Key { + key: Qt.Key_Semicolon + text: ";" + } + Key { + key: Qt.Key_Slash + text: "/" + } + Key { + key: Qt.Key_Question + text: "?" + } + Key { + weight: 204 + displayText: "1/2" + functionKey: true + onClicked: secondPage = !secondPage + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + displayText: InputContext.inputEngine.inputMode === InputEngine.InputMode.Cyrillic ? "АБВ" : "ABC" + } + ChangeLanguageKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Period + text: "." + alternativeKeys: ".," + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } + } + } + Component { + id: page2 + KeyboardLayout { + keyWeight: 160 + KeyboardRow { + Key { + key: Qt.Key_AsciiTilde + text: "~" + } + Key { + key: Qt.Key_Agrave + text: "`" + } + Key { + key: Qt.Key_Bar + text: "|" + } + Key { + key: 0x7B + text: "·" + } + Key { + key: 0x221A + text: "√" + } + Key { + key: Qt.Key_division + text: "÷" + } + Key { + key: Qt.Key_multiply + text: "×" + } + Key { + key: Qt.Key_onehalf + text: "½" + alternativeKeys: "¼⅓½¾⅞" + } + Key { + key: Qt.Key_BraceLeft + text: "{" + } + Key { + key: Qt.Key_BraceRight + text: "}" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Key { + key: Qt.Key_Dollar + text: "$" + } + Key { + key: 0x20AC + text: "€" + } + Key { + key: 0xC2 + text: "£" + } + Key { + key: 0xA2 + text: "¢" + } + Key { + key: 0xA5 + text: "¥" + } + Key { + key: Qt.Key_Equal + text: "=" + } + Key { + key: Qt.Key_section + text: "§" + } + Key { + key: Qt.Key_BracketLeft + text: "[" + } + Key { + key: Qt.Key_BracketRight + text: "]" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + Key { + displayText: "2/2" + functionKey: true + onClicked: secondPage = !secondPage + } + Key { + key: Qt.Key_Underscore + text: "_" + } + Key { + key: 0x2122 + text: '™' + } + Key { + key: 0x00AE + text: '®' + } + Key { + key: Qt.Key_guillemotleft + text: '«' + } + Key { + key: Qt.Key_guillemotright + text: '»' + } + Key { + key: 0x201C + text: '“' + } + Key { + key: 0x201D + text: '”' + } + Key { + key: Qt.Key_Backslash + text: "\\" + } + Key { + key: Qt.Key_AsciiCircum + text: "^" + } + Key { + weight: 204 + displayText: "2/2" + functionKey: true + onClicked: secondPage = !secondPage + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + displayText: InputContext.inputEngine.inputMode === InputEngine.InputMode.Cyrillic ? "АБВ" : "ABC" + } + ChangeLanguageKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: 0x2026 + text: "\u2026" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/fi_FI/dialpad.fallback b/virtualkeyboard_layouts_koriolan/layouts/fi_FI/dialpad.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/fi_FI/digits.fallback b/virtualkeyboard_layouts_koriolan/layouts/fi_FI/digits.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/fi_FI/handwriting.fallback b/virtualkeyboard_layouts_koriolan/layouts/fi_FI/handwriting.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/fi_FI/main.qml b/virtualkeyboard_layouts_koriolan/layouts/fi_FI/main.qml new file mode 100755 index 0000000..a3a8a86 --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/fi_FI/main.qml @@ -0,0 +1,209 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.VirtualKeyboard 2.1 + +KeyboardLayout { + inputMode: InputEngine.InputMode.Latin + keyWeight: 160 + KeyboardRow { + Key { + key: Qt.Key_Q + text: "q" + } + Key { + key: Qt.Key_W + text: "w" + } + Key { + key: Qt.Key_E + text: "e" + } + Key { + key: Qt.Key_R + text: "r" + } + Key { + key: Qt.Key_T + text: "t" + } + Key { + key: Qt.Key_Y + text: "y" + } + Key { + key: Qt.Key_U + text: "u" + } + Key { + key: Qt.Key_I + text: "i" + } + Key { + key: Qt.Key_O + text: "o" + } + Key { + key: Qt.Key_P + text: "p" + } + Key { + key: Qt.Key_Aring + text: "å" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 66 + } + Key { + key: Qt.Key_A + text: "a" + } + Key { + key: Qt.Key_S + text: "s" + } + Key { + key: Qt.Key_D + text: "d" + } + Key { + key: Qt.Key_F + text: "f" + } + Key { + key: Qt.Key_G + text: "g" + } + Key { + key: Qt.Key_H + text: "h" + } + Key { + key: Qt.Key_J + text: "j" + } + Key { + key: Qt.Key_K + text: "k" + } + Key { + key: Qt.Key_L + text: "l" + } + Key { + key: Qt.Key_Odiaeresis + text: "ö" + } + Key { + key: Qt.Key_Adiaeresis + text: "ä" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + ShiftKey { } + Key { + key: Qt.Key_Z + text: "z" + } + Key { + key: Qt.Key_X + text: "x" + } + Key { + key: Qt.Key_C + text: "c" + } + Key { + key: Qt.Key_V + text: "v" + } + Key { + key: Qt.Key_B + text: "b" + } + Key { + key: Qt.Key_N + text: "n" + } + Key { + key: Qt.Key_M + text: "m" + } + Key { + key: Qt.Key_Comma + text: "," + } + Key { + key: Qt.Key_Period + text: "." + } + Key { + key: Qt.Key_Minus + text: "-" + } + ShiftKey { + weight: 264 + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Apostrophe + text: "'" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/fi_FI/numbers.fallback b/virtualkeyboard_layouts_koriolan/layouts/fi_FI/numbers.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/fi_FI/symbols.fallback b/virtualkeyboard_layouts_koriolan/layouts/fi_FI/symbols.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/fr_CA/dialpad.fallback b/virtualkeyboard_layouts_koriolan/layouts/fr_CA/dialpad.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/fr_CA/digits.fallback b/virtualkeyboard_layouts_koriolan/layouts/fr_CA/digits.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/fr_CA/handwriting.fallback b/virtualkeyboard_layouts_koriolan/layouts/fr_CA/handwriting.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/fr_CA/main.qml b/virtualkeyboard_layouts_koriolan/layouts/fr_CA/main.qml new file mode 100755 index 0000000..8866dfd --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/fr_CA/main.qml @@ -0,0 +1,200 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.VirtualKeyboard 2.1 + +KeyboardLayout { + inputMode: InputEngine.InputMode.Latin + keyWeight: 160 + KeyboardRow { + Key { + key: Qt.Key_Q + text: "q" + } + Key { + key: Qt.Key_W + text: "w" + } + Key { + key: Qt.Key_E + text: "e" + alternativeKeys: "éèeêë" + } + Key { + key: Qt.Key_R + text: "r" + } + Key { + key: Qt.Key_T + text: "t" + } + Key { + key: Qt.Key_Y + text: "y" + alternativeKeys: "yÿ" + } + Key { + key: Qt.Key_U + text: "u" + alternativeKeys: "ùuûü" + } + Key { + key: Qt.Key_I + text: "i" + alternativeKeys: "îiï" + } + Key { + key: Qt.Key_O + text: "o" + alternativeKeys: "ôoœ" + } + Key { + key: Qt.Key_P + text: "p" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Key { + key: Qt.Key_A + text: "a" + alternativeKeys: "aàâæ" + } + Key { + key: Qt.Key_S + text: "s" + } + Key { + key: Qt.Key_D + text: "d" + } + Key { + key: Qt.Key_F + text: "f" + } + Key { + key: Qt.Key_G + text: "g" + } + Key { + key: Qt.Key_H + text: "h" + } + Key { + key: Qt.Key_J + text: "j" + } + Key { + key: Qt.Key_K + text: "k" + } + Key { + key: Qt.Key_L + text: "l" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + ShiftKey {} + Key { + key: Qt.Key_Z + text: "z" + } + Key { + key: Qt.Key_X + text: "x" + } + Key { + key: Qt.Key_C + text: "c" + alternativeKeys: "cç" + } + Key { + key: Qt.Key_V + text: "v" + } + Key { + key: Qt.Key_B + text: "b" + } + Key { + key: Qt.Key_N + text: "n" + } + Key { + key: Qt.Key_M + text: "m" + } + Key { + key: Qt.Key_Comma + text: "," + } + Key { + key: Qt.Key_Period + text: "." + } + ShiftKey { + weight: 204 + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Apostrophe + text: "'" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/fr_CA/numbers.fallback b/virtualkeyboard_layouts_koriolan/layouts/fr_CA/numbers.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/fr_CA/symbols.fallback b/virtualkeyboard_layouts_koriolan/layouts/fr_CA/symbols.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/fr_FR/dialpad.fallback b/virtualkeyboard_layouts_koriolan/layouts/fr_FR/dialpad.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/fr_FR/digits.fallback b/virtualkeyboard_layouts_koriolan/layouts/fr_FR/digits.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/fr_FR/handwriting.fallback b/virtualkeyboard_layouts_koriolan/layouts/fr_FR/handwriting.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/fr_FR/main.qml b/virtualkeyboard_layouts_koriolan/layouts/fr_FR/main.qml new file mode 100755 index 0000000..753d8e6 --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/fr_FR/main.qml @@ -0,0 +1,204 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.VirtualKeyboard 2.1 + +KeyboardLayout { + inputMode: InputEngine.InputMode.Latin + keyWeight: 160 + KeyboardRow { + Key { + key: Qt.Key_A + text: "a" + alternativeKeys: "aàâæ" + } + Key { + key: Qt.Key_Z + text: "z" + } + Key { + key: Qt.Key_E + text: "e" + alternativeKeys: "éèeêë" + } + Key { + key: Qt.Key_R + text: "r" + } + Key { + key: Qt.Key_T + text: "t" + } + Key { + key: Qt.Key_Y + text: "y" + alternativeKeys: "yÿ" + } + Key { + key: Qt.Key_U + text: "u" + alternativeKeys: "ùuûü" + } + Key { + key: Qt.Key_I + text: "i" + alternativeKeys: "îiï" + } + Key { + key: Qt.Key_O + text: "o" + alternativeKeys: "ôoœ" + } + Key { + key: Qt.Key_P + text: "p" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Key { + key: Qt.Key_Q + text: "q" + } + Key { + key: Qt.Key_S + text: "s" + } + Key { + key: Qt.Key_D + text: "d" + } + Key { + key: Qt.Key_F + text: "f" + } + Key { + key: Qt.Key_G + text: "g" + } + Key { + key: Qt.Key_H + text: "h" + } + Key { + key: Qt.Key_J + text: "j" + } + Key { + key: Qt.Key_K + text: "k" + } + Key { + key: Qt.Key_L + text: "l" + } + Key { + key: Qt.Key_M + text: "m" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + ShiftKey {} + Key { + key: Qt.Key_W + text: "w" + } + Key { + key: Qt.Key_X + text: "x" + } + Key { + key: Qt.Key_C + text: "c" + alternativeKeys: "cç" + } + Key { + key: Qt.Key_V + text: "v" + } + Key { + key: Qt.Key_B + text: "b" + } + Key { + key: Qt.Key_N + text: "n" + } + Key { + key: Qt.Key_Comma + text: "," + } + Key { + key: Qt.Key_Period + text: "." + } + Key { + key: Qt.Key_Minus + text: "-" + } + ShiftKey { + weight: 264 + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Apostrophe + text: "'" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/fr_FR/numbers.fallback b/virtualkeyboard_layouts_koriolan/layouts/fr_FR/numbers.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/fr_FR/symbols.fallback b/virtualkeyboard_layouts_koriolan/layouts/fr_FR/symbols.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/he_IL/dialpad.fallback b/virtualkeyboard_layouts_koriolan/layouts/he_IL/dialpad.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/he_IL/digits.fallback b/virtualkeyboard_layouts_koriolan/layouts/he_IL/digits.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/he_IL/handwriting.qml b/virtualkeyboard_layouts_koriolan/layouts/he_IL/handwriting.qml new file mode 100755 index 0000000..66914c7 --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/he_IL/handwriting.qml @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Layouts 1.0 +import QtQuick.VirtualKeyboard 2.3 + +KeyboardLayout { + function createInputMethod() { + return Qt.createQmlObject('import QtQuick 2.0; import QtQuick.VirtualKeyboard.Plugins 2.3; HandwritingInputMethod {}', parent) + } + sharedLayouts: ['symbols'] + + KeyboardRow { + Layout.preferredHeight: 3 + KeyboardColumn { + Layout.preferredWidth: bottomRow.width - hideKeyboardKey.width + KeyboardRow { + TraceInputKey { + objectName: "hwrInputArea" + patternRecognitionMode: InputEngine.PatternRecognitionMode.Handwriting + horizontalRulers: + InputContext.inputEngine.inputMode !== InputEngine.InputMode.Hebrew ? [] : + [Math.round(boundingBox.height / 4), Math.round(boundingBox.height / 4) * 2, Math.round(boundingBox.height / 4) * 3] + } + } + } + KeyboardColumn { + Layout.preferredWidth: hideKeyboardKey.width + KeyboardRow { + BackspaceKey {} + } + KeyboardRow { + EnterKey {} + } + KeyboardRow { + ShiftKey { } + } + } + } + KeyboardRow { + id: bottomRow + Layout.preferredHeight: 1 + keyWeight: 154 + InputModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + customLayoutsOnly: true + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Apostrophe + text: "'" + alternativeKeys: "<>()#%&*/\\'\"=+-_" + } + Key { + key: Qt.Key_Period + text: "." + alternativeKeys: ":;,.?!" + } + HideKeyboardKey { + id: hideKeyboardKey + weight: 204 + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/he_IL/main.qml b/virtualkeyboard_layouts_koriolan/layouts/he_IL/main.qml new file mode 100755 index 0000000..4c47fc5 --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/he_IL/main.qml @@ -0,0 +1,381 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.VirtualKeyboard 2.3 + +KeyboardLayoutLoader { + sharedLayouts: ['symbols'] + sourceComponent: InputContext.inputEngine.inputMode === InputEngine.InputMode.Hebrew ? hebrewLayout : latinLayout + Component { + id: hebrewLayout + KeyboardLayout { + keyWeight: 160 + KeyboardRow { + Key { + key: Qt.Key_Apostrophe + text: "'" + alternativeKeys: "'\"" + } + Key { + key: Qt.Key_Minus + text: "-" + } + Key { + text: "\u05E7" + alternativeKeys: "\u05B3\u05E7\u05B8\u05BB" + } + Key { + text: "\u05E8" + } + Key { + text: "\u05D0" + } + Key { + text: "\u05D8" + } + Key { + text: "\u05D5" + alternativeKeys: [ "\u05D5", "\u05D5\u05B9", "\u05D5\u05BC" ] + } + Key { + text: "\u05DF" + } + Key { + text: "\u05DD" + } + Key { + text: "\u05E4" + alternativeKeys: "\u05B2\u05B7\u05E4" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Key { + text: "\u05E9" + alternativeKeys: [ "\u05E9", "\u05B0", "\u05E9\u05C2", "\u05E9\u05C1" ] + } + Key { + text: "\u05D3" + alternativeKeys: "\u05D3\u05BC" + } + Key { + text: "\u05D2" + alternativeKeys: [ "\u05D2", "\u05D2\u05F3" ] + } + Key { + text: "\u05DB" + } + Key { + text: "\u05E2" + } + Key { + text: "\u05D9" + alternativeKeys: [ "\u05D9", "\u05F2\u05B7" ] + } + Key { + text: "\u05D7" + alternativeKeys: [ "\u05B9", "\u05D7", "\u05D7\u05F3", "\u05B4" ] + } + Key { + text: "\u05DC" + } + Key { + text: "\u05DA" + } + Key { + text: "\u05E3" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + InputModeKey { + inputModes: [InputEngine.InputMode.Hebrew, InputEngine.InputMode.Latin] + } + Key { + text: "\u05D6" + alternativeKeys: [ "\u05D6", "\u05D6\u05F3" ] + } + Key { + text: "\u05E1" + alternativeKeys: "\u05E1\u05B6\u05B1" + } + Key { + text: "\u05D1" + } + Key { + text: "\u05D4" + } + Key { + text: "\u05E0" + } + Key { + text: "\u05DE" + } + Key { + text: "\u05E6" + alternativeKeys: [ "\u05E6", "\u05E6\u05F3", "\u05B5" ] + } + Key { + text: "\u05EA" + alternativeKeys: [ "\u05EA", "\u05EA\u05F3" ] + } + Key { + text: "\u05E5" + alternativeKeys: [ "\u05E5", "\u05E5\u05F3" ] + } + Key { + key: Qt.Key_Comma + text: "," + alternativeKeys: ":,;" + } + ShiftKey { + weight: 204 + enabled: false + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Period + text: "." + alternativeKeys: "!.?" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } + } + } + Component { + id: latinLayout + KeyboardLayout { + keyWeight: 160 + KeyboardRow { + Key { + key: Qt.Key_Q + text: "q" + } + Key { + key: Qt.Key_W + text: "w" + } + Key { + key: Qt.Key_E + text: "e" + alternativeKeys: "êeëèé" + } + Key { + key: Qt.Key_R + text: "r" + alternativeKeys: "ŕrř" + } + Key { + key: Qt.Key_T + text: "t" + alternativeKeys: "ţtŧť" + } + Key { + key: Qt.Key_Y + text: "y" + alternativeKeys: "ÿyýŷ" + } + Key { + key: Qt.Key_U + text: "u" + alternativeKeys: "űūũûüuùú" + } + Key { + key: Qt.Key_I + text: "i" + alternativeKeys: "îïīĩiìí" + } + Key { + key: Qt.Key_O + text: "o" + alternativeKeys: "œøõôöòóo" + } + Key { + key: Qt.Key_P + text: "p" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Key { + key: Qt.Key_A + text: "a" + alternativeKeys: "aäåãâàá" + } + Key { + key: Qt.Key_S + text: "s" + alternativeKeys: "šsşś" + } + Key { + key: Qt.Key_D + text: "d" + alternativeKeys: "dđď" + } + Key { + key: Qt.Key_F + text: "f" + } + Key { + key: Qt.Key_G + text: "g" + alternativeKeys: "ġgģĝğ" + } + Key { + key: Qt.Key_H + text: "h" + } + Key { + key: Qt.Key_J + text: "j" + } + Key { + key: Qt.Key_K + text: "k" + } + Key { + key: Qt.Key_L + text: "l" + alternativeKeys: "ĺŀłļľl" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + InputModeKey { + inputModes: [InputEngine.InputMode.Hebrew, InputEngine.InputMode.Latin] + } + Key { + key: Qt.Key_Z + text: "z" + alternativeKeys: "zžż" + } + Key { + key: Qt.Key_X + text: "x" + } + Key { + key: Qt.Key_C + text: "c" + alternativeKeys: "çcċčć" + } + Key { + key: Qt.Key_V + text: "v" + } + Key { + key: Qt.Key_B + text: "b" + } + Key { + key: Qt.Key_N + text: "n" + alternativeKeys: "ņńnň" + } + Key { + key: Qt.Key_M + text: "m" + } + Key { + key: Qt.Key_Comma + text: "," + alternativeKeys: ":,;" + } + Key { + key: Qt.Key_Period + text: "." + alternativeKeys: "!.?" + } + ShiftKey { + weight: 204 + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Apostrophe + text: "'" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/he_IL/numbers.fallback b/virtualkeyboard_layouts_koriolan/layouts/he_IL/numbers.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/he_IL/symbols.qml b/virtualkeyboard_layouts_koriolan/layouts/he_IL/symbols.qml new file mode 100755 index 0000000..f4e5865 --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/he_IL/symbols.qml @@ -0,0 +1,376 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Layouts 1.0 +import QtQuick.VirtualKeyboard 2.3 + +KeyboardLayoutLoader { + property bool secondPage + onVisibleChanged: if (!visible) secondPage = false + sourceComponent: secondPage ? page2 : page1 + Component { + id: page1 + KeyboardLayout { + keyWeight: 160 + KeyboardRow { + Key { + key: Qt.Key_1 + text: "1" + } + Key { + key: Qt.Key_2 + text: "2" + } + Key { + key: Qt.Key_3 + text: "3" + } + Key { + key: Qt.Key_4 + text: "4" + } + Key { + key: Qt.Key_5 + text: "5" + } + Key { + key: Qt.Key_6 + text: "6" + } + Key { + key: Qt.Key_7 + text: "7" + } + Key { + key: Qt.Key_8 + text: "8" + } + Key { + key: Qt.Key_9 + text: "9" + } + Key { + key: Qt.Key_0 + text: "0" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Key { + key: Qt.Key_At + text: "@" + } + Key { + key: Qt.Key_NumberSign + text: "#" + } + Key { + key: Qt.Key_Percent + text: "%" + } + Key { + key: Qt.Key_Ampersand + text: "&" + } + Key { + key: Qt.Key_Asterisk + text: "*" + } + Key { + key: Qt.Key_Minus + text: "-" + } + Key { + key: Qt.Key_Plus + text: "+" + } + Key { + key: Qt.Key_ParenLeft + text: "(" + } + Key { + key: Qt.Key_ParenRight + text: ")" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + Key { + displayText: "1/2" + functionKey: true + onClicked: secondPage = !secondPage + } + Key { + key: Qt.Key_Exclam + text: "!" + } + Key { + key: Qt.Key_QuoteDbl + text: '"' + } + Key { + key: Qt.Key_Less + text: "<" + } + Key { + key: Qt.Key_Greater + text: ">" + } + Key { + key: Qt.Key_Apostrophe + text: "'" + } + Key { + key: Qt.Key_Colon + text: ":" + } + Key { + key: Qt.Key_Semicolon + text: ";" + } + Key { + key: Qt.Key_Slash + text: "/" + } + Key { + key: Qt.Key_Question + text: "?" + } + Key { + weight: 204 + displayText: "1/2" + functionKey: true + onClicked: secondPage = !secondPage + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + displayText: InputContext.inputEngine.inputMode === InputEngine.InputMode.Hebrew ? "\u05D0\u05D1\u05D2" : "ABC" + } + ChangeLanguageKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Period + text: "." + alternativeKeys: ".," + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } + } + } + Component { + id: page2 + KeyboardLayout { + keyWeight: 160 + KeyboardRow { + Key { + key: Qt.Key_AsciiTilde + text: "~" + } + Key { + key: Qt.Key_Agrave + text: "`" + } + Key { + key: Qt.Key_Bar + text: "|" + } + Key { + key: 0x7B + text: "·" + } + Key { + key: 0x221A + text: "√" + } + Key { + key: Qt.Key_division + text: "÷" + } + Key { + key: Qt.Key_multiply + text: "×" + } + Key { + key: Qt.Key_onehalf + text: "½" + alternativeKeys: "¼⅓½¾⅞" + } + Key { + key: Qt.Key_BraceLeft + text: "{" + } + Key { + key: Qt.Key_BraceRight + text: "}" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Key { + key: Qt.Key_Dollar + text: "$" + alternativeKeys: "$¢" + } + Key { + key: 0x20AC + text: "€" + } + Key { + key: 0xC2 + text: "£" + } + Key { + text: "₪" + } + Key { + key: 0xA5 + text: "¥" + } + Key { + key: Qt.Key_Equal + text: "=" + } + Key { + key: Qt.Key_section + text: "§" + } + Key { + key: Qt.Key_BracketLeft + text: "[" + } + Key { + key: Qt.Key_BracketRight + text: "]" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + Key { + displayText: "2/2" + functionKey: true + onClicked: secondPage = !secondPage + } + Key { + key: Qt.Key_Underscore + text: "_" + } + Key { + key: 0x2122 + text: '™' + } + Key { + key: 0x00AE + text: '®' + } + Key { + key: Qt.Key_guillemotleft + text: '«' + } + Key { + key: Qt.Key_guillemotright + text: '»' + } + Key { + key: 0x201C + text: '“' + } + Key { + key: 0x201D + text: '”' + } + Key { + key: Qt.Key_Backslash + text: "\\" + } + Key { + key: Qt.Key_AsciiCircum + text: "^" + } + Key { + weight: 204 + displayText: "2/2" + functionKey: true + onClicked: secondPage = !secondPage + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + displayText: InputContext.inputEngine.inputMode === InputEngine.InputMode.Hebrew ? "\u05D0\u05D1\u05D2" : "ABC" + } + ChangeLanguageKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: 0x2026 + text: "\u2026" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/hi_IN/dialpad.fallback b/virtualkeyboard_layouts_koriolan/layouts/hi_IN/dialpad.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/hi_IN/digits.fallback b/virtualkeyboard_layouts_koriolan/layouts/hi_IN/digits.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/hi_IN/handwriting.qml b/virtualkeyboard_layouts_koriolan/layouts/hi_IN/handwriting.qml new file mode 100755 index 0000000..1ae1fa4 --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/hi_IN/handwriting.qml @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Layouts 1.0 +import QtQuick.VirtualKeyboard 2.1 + +KeyboardLayout { + function createInputMethod() { + return Qt.createQmlObject('import QtQuick 2.0; import QtQuick.VirtualKeyboard.Plugins 2.1; HandwritingInputMethod {}', parent) + } + sharedLayouts: ['symbols'] + + KeyboardRow { + Layout.preferredHeight: 3 + KeyboardColumn { + Layout.preferredWidth: bottomRow.width - hideKeyboardKey.width + KeyboardRow { + TraceInputKey { + objectName: "hwrInputArea" + patternRecognitionMode: InputEngine.PatternRecognitionMode.Handwriting + } + } + } + KeyboardColumn { + Layout.preferredWidth: hideKeyboardKey.width + KeyboardRow { + BackspaceKey {} + } + KeyboardRow { + EnterKey {} + } + KeyboardRow { + ShiftKey { } + } + } + } + KeyboardRow { + id: bottomRow + Layout.preferredHeight: 1 + keyWeight: 154 + Key { + weight: 217 + key: Qt.Key_Mode_switch + noKeyEvent: true + functionKey: true + text: InputContext.inputEngine.inputMode === InputEngine.InputMode.Latin ? "123" : "ABC" + onClicked: InputContext.inputEngine.inputMode = InputContext.inputEngine.inputMode === InputEngine.InputMode.Latin ? InputEngine.InputMode.Numeric : InputEngine.InputMode.Latin + enabled: !(InputContext.inputMethodHints & (Qt.ImhDialableCharactersOnly | Qt.ImhFormattedNumbersOnly | Qt.ImhDigitsOnly)) + keyPanelDelegate: keyboard.style ? keyboard.style.symbolKeyPanel : undefined + } + ChangeLanguageKey { + weight: 154 + customLayoutsOnly: true + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Apostrophe + text: "'" + alternativeKeys: "<>()#%&*/\\\"'=+-_" + } + Key { + key: Qt.Key_Period + text: "." + alternativeKeys: ":;,.?!" + } + HideKeyboardKey { + id: hideKeyboardKey + weight: 204 + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/hi_IN/main.qml b/virtualkeyboard_layouts_koriolan/layouts/hi_IN/main.qml new file mode 100755 index 0000000..aac186e --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/hi_IN/main.qml @@ -0,0 +1,340 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.VirtualKeyboard 2.1 + +KeyboardLayoutLoader { + inputMode: InputEngine.InputMode.Latin + sourceComponent: InputContext.shiftActive ? page2 : page1 + Component { + id: page1 + KeyboardLayout { + keyWeight: 160 + KeyboardRow { + Key { + text: "\u094C" + } + Key { + text: "\u0948" + } + Key { + text: "\u093E" + } + Key { + text: "\u0940" + } + Key { + text: "\u0942" + } + Key { + text: "\u092C" + } + Key { + text: "\u0939" + } + Key { + text: "\u0917" + } + Key { + text: "\u0926" + } + Key { + text: "\u091C" + } + Key { + text: "\u0921" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 66 + } + Key { + text: "\u094B" + alternativeKeys: ["\u094B", "\u094A"] + } + Key { + text: "\u0947" + } + Key { + text: "\u094D" + } + Key { + text: "\u093F" + } + Key { + text: "\u0941" + } + Key { + text: "\u092A" + } + Key { + text: "\u0930" + } + Key { + text: "\u0915" + } + Key { + text: "\u0924" + } + Key { + text: "\u091A" + } + Key { + text: "\u091F" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + ShiftKey { } + Key { + text: "\u0949" + } + Key { + text: "\u0902" + alternativeKeys: "\u0902\u0903" + } + Key { + text: "\u092E" + } + Key { + text: "\u0928" + } + Key { + text: "\u0935" + } + Key { + text: "\u0932" + } + Key { + text: "\u0938" + } + Key { + text: "\u092F" + } + Key { + text: "\u093C" + } + Key { + key: 0x2013 + text: "\u2013" + alternativeKeys: "\u2013-“”" + } + ShiftKey { + weight: 264 + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + displayText: "&\u0967\u0968\u0969" + } + ChangeLanguageKey { + weight: 154 + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Comma + text: "," + alternativeKeys: "!?:;.,|" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } + } + } + Component { + id: page2 + KeyboardLayout { + keyWeight: 160 + KeyboardRow { + Key { + text: "\u0914" + } + Key { + text: "\u0910" + } + Key { + text: "\u0906" + } + Key { + text: "\u0908" + } + Key { + text: "\u090A" + } + Key { + text: "\u092D" + } + Key { + text: "\u0919" + } + Key { + text: "\u0918" + } + Key { + text: "\u0927" + } + Key { + text: "\u091D" + } + Key { + text: "\u0922" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 66 + } + Key { + text: "\u0913" + } + Key { + text: "\u090F" + } + Key { + text: "\u0905" + } + Key { + text: "\u0907" + } + Key { + text: "\u0909" + } + Key { + text: "\u092B" + } + Key { + text: "\u0931" + } + Key { + text: "\u0916" + } + Key { + text: "\u0925" + } + Key { + text: "\u091B" + } + Key { + text: "\u0920" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + ShiftKey { } + Key { + text: "\u0911" + } + Key { + text: "\u0901" + } + Key { + text: "\u0923" + } + Key { + text: "\u0929" + } + Key { + text: "\u091E" + } + Key { + text: "\u0933" + } + Key { + text: "\u0936" + } + Key { + text: "\u0937" + } + Key { + text: "\u0943" + } + Key { + key: 0x2013 + text: "\u2013" + alternativeKeys: "\u2013-“”" + } + ShiftKey { + weight: 264 + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + displayText: "&\u0967\u0968\u0969" + } + ChangeLanguageKey { + weight: 154 + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Comma + text: "," + alternativeKeys: "!?:;.,|" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/hi_IN/numbers.fallback b/virtualkeyboard_layouts_koriolan/layouts/hi_IN/numbers.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/hi_IN/symbols.qml b/virtualkeyboard_layouts_koriolan/layouts/hi_IN/symbols.qml new file mode 100755 index 0000000..6ae785f --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/hi_IN/symbols.qml @@ -0,0 +1,386 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Layouts 1.0 +import QtQuick.VirtualKeyboard 2.1 + +KeyboardLayoutLoader { + property bool secondPage + onVisibleChanged: if (!visible) secondPage = false + sourceComponent: secondPage ? page2 : page1 + Component { + id: page1 + KeyboardLayout { + keyWeight: 160 + KeyboardRow { + Key { + key: Qt.Key_1 + text: "\u0967" + alternativeKeys: "\u09671" + } + Key { + key: Qt.Key_2 + text: "\u0968" + alternativeKeys: "\u09682" + } + Key { + key: Qt.Key_3 + text: "\u0969" + alternativeKeys: "\u09693" + } + Key { + key: Qt.Key_4 + text: "\u096A" + alternativeKeys: "\u096A4" + } + Key { + key: Qt.Key_5 + text: "\u096B" + alternativeKeys: "\u096B5" + } + Key { + key: Qt.Key_6 + text: "\u096C" + alternativeKeys: "\u096C6" + } + Key { + key: Qt.Key_7 + text: "\u096D" + alternativeKeys: "\u096D7" + } + Key { + key: Qt.Key_8 + text: "\u096E" + alternativeKeys: "\u096E8" + } + Key { + key: Qt.Key_9 + text: "\u096F" + alternativeKeys: "\u096F9" + } + Key { + key: Qt.Key_0 + text: "\u0966" + alternativeKeys: "\u09660" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Key { + key: Qt.Key_At + text: "@" + } + Key { + key: Qt.Key_NumberSign + text: "#" + } + Key { + key: Qt.Key_Percent + text: "%" + } + Key { + key: Qt.Key_Ampersand + text: "&" + } + Key { + key: Qt.Key_Asterisk + text: "*" + } + Key { + key: Qt.Key_Minus + text: "-" + } + Key { + key: Qt.Key_Plus + text: "+" + } + Key { + key: Qt.Key_ParenLeft + text: "(" + } + Key { + key: Qt.Key_ParenRight + text: ")" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + Key { + displayText: "1/2" + functionKey: true + onClicked: secondPage = !secondPage + } + Key { + key: Qt.Key_Exclam + text: "!" + } + Key { + key: Qt.Key_QuoteDbl + text: '"' + } + Key { + key: Qt.Key_Less + text: "<" + } + Key { + key: Qt.Key_Greater + text: ">" + } + Key { + key: Qt.Key_Apostrophe + text: "'" + } + Key { + key: Qt.Key_Colon + text: ":" + } + Key { + key: Qt.Key_Semicolon + text: ";" + } + Key { + key: Qt.Key_Slash + text: "/" + } + Key { + key: Qt.Key_Question + text: "?" + } + Key { + weight: 204 + displayText: "1/2" + functionKey: true + onClicked: secondPage = !secondPage + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + displayText: "\u0915\u0916\u0917" + } + ChangeLanguageKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Period + text: "." + alternativeKeys: ".," + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } + } + } + Component { + id: page2 + KeyboardLayout { + keyWeight: 160 + KeyboardRow { + Key { + key: Qt.Key_AsciiTilde + text: "~" + } + Key { + key: Qt.Key_Agrave + text: "`" + } + Key { + key: Qt.Key_Bar + text: "|" + } + Key { + key: 0x7B + text: "·" + } + Key { + key: 0x221A + text: "√" + } + Key { + key: Qt.Key_division + text: "÷" + } + Key { + key: Qt.Key_multiply + text: "×" + } + Key { + key: Qt.Key_onehalf + text: "½" + alternativeKeys: "¼⅓½¾⅞" + } + Key { + key: Qt.Key_BraceLeft + text: "{" + } + Key { + key: Qt.Key_BraceRight + text: "}" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Key { + key: 0x20B9 + text: "\u20B9" + } + Key { + key: Qt.Key_Dollar + text: "$" + } + Key { + key: 0x20AC + text: "€" + } + Key { + key: 0xC2 + text: "£" + } + Key { + key: 0xA2 + text: "¢" + } + Key { + key: Qt.Key_Equal + text: "=" + } + Key { + key: Qt.Key_section + text: "§" + } + Key { + key: Qt.Key_BracketLeft + text: "[" + } + Key { + key: Qt.Key_BracketRight + text: "]" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + Key { + displayText: "2/2" + functionKey: true + onClicked: secondPage = !secondPage + } + Key { + key: Qt.Key_Underscore + text: "_" + } + Key { + key: 0x2122 + text: '™' + } + Key { + key: 0x00AE + text: '®' + } + Key { + key: Qt.Key_guillemotleft + text: '«' + } + Key { + key: Qt.Key_guillemotright + text: '»' + } + Key { + key: 0x201C + text: '“' + } + Key { + key: 0x201D + text: '”' + } + Key { + key: Qt.Key_Backslash + text: "\\" + } + Key { + key: Qt.Key_AsciiCircum + text: "^" + } + Key { + weight: 204 + displayText: "2/2" + functionKey: true + onClicked: secondPage = !secondPage + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + displayText: "\u0915\u0916\u0917" + } + ChangeLanguageKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: 0x2026 + text: "\u2026" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/hr_HR/dialpad.fallback b/virtualkeyboard_layouts_koriolan/layouts/hr_HR/dialpad.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/hr_HR/digits.fallback b/virtualkeyboard_layouts_koriolan/layouts/hr_HR/digits.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/hr_HR/handwriting.qml b/virtualkeyboard_layouts_koriolan/layouts/hr_HR/handwriting.qml new file mode 100755 index 0000000..968bae8 --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/hr_HR/handwriting.qml @@ -0,0 +1,102 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Layouts 1.0 +import QtQuick.VirtualKeyboard 2.3 + +KeyboardLayout { + function createInputMethod() { + return Qt.createQmlObject('import QtQuick 2.0; import QtQuick.VirtualKeyboard.Plugins 2.3; HandwritingInputMethod {}', parent) + } + sharedLayouts: ['symbols'] + inputMode: InputEngine.InputMode.Latin + + KeyboardRow { + Layout.preferredHeight: 3 + KeyboardColumn { + Layout.preferredWidth: bottomRow.width - hideKeyboardKey.width + KeyboardRow { + TraceInputKey { + objectName: "hwrInputArea" + patternRecognitionMode: InputEngine.PatternRecognitionMode.Handwriting + } + } + } + KeyboardColumn { + Layout.preferredWidth: hideKeyboardKey.width + KeyboardRow { + BackspaceKey {} + } + KeyboardRow { + EnterKey {} + } + KeyboardRow { + ShiftKey { } + } + } + } + KeyboardRow { + id: bottomRow + Layout.preferredHeight: 1 + keyWeight: 154 + InputModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + customLayoutsOnly: true + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Minus + text: "-" + alternativeKeys: "<>()#%&*/\\\"'=+-_" + } + Key { + key: Qt.Key_Period + text: "." + alternativeKeys: ":;,.?!" + } + Key { + key: 0x102 + text: "ă" + alternativeKeys: "ăîâșț" + } + HideKeyboardKey { + id: hideKeyboardKey + weight: 204 + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/hr_HR/main.qml b/virtualkeyboard_layouts_koriolan/layouts/hr_HR/main.qml new file mode 100755 index 0000000..4b4c46d --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/hr_HR/main.qml @@ -0,0 +1,218 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.VirtualKeyboard 2.3 + +KeyboardLayout { + inputMode: InputEngine.InputMode.Latin + keyWeight: 160 + KeyboardRow { + Key { + key: Qt.Key_Q + text: "q" + } + Key { + key: Qt.Key_W + text: "w" + } + Key { + key: Qt.Key_E + text: "e" + } + Key { + key: Qt.Key_R + text: "r" + } + Key { + key: Qt.Key_T + text: "t" + } + Key { + key: Qt.Key_Z + text: "z" + } + Key { + key: Qt.Key_U + text: "u" + } + Key { + key: Qt.Key_I + text: "i" + } + Key { + key: Qt.Key_O + text: "o" + alternativeKeys: "oö" + } + Key { + key: Qt.Key_P + text: "p" + } + Key { + key: 0x160 + text: "š" + } + Key { + key: 0x110 + text: "đ" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Key { + key: Qt.Key_A + text: "a" + alternativeKeys: "aåä" + } + Key { + key: Qt.Key_S + text: "s" + } + Key { + key: Qt.Key_D + text: "d" + } + Key { + key: Qt.Key_F + text: "f" + } + Key { + key: Qt.Key_G + text: "g" + } + Key { + key: Qt.Key_H + text: "h" + } + Key { + key: Qt.Key_J + text: "j" + } + Key { + key: Qt.Key_K + text: "k" + } + Key { + key: Qt.Key_L + text: "l" + } + Key { + key: 0x10C + text: "č" + } + Key { + key: 0x106 + text: "ć" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + ShiftKey { + weight: 166 + } + Key { + key: Qt.Key_Y + text: "y" + } + Key { + key: Qt.Key_X + text: "x" + } + Key { + key: Qt.Key_C + text: "c" + } + Key { + key: Qt.Key_V + text: "v" + } + Key { + key: Qt.Key_B + text: "b" + } + Key { + key: Qt.Key_N + text: "n" + } + Key { + key: Qt.Key_M + text: "m" + } + Key { + key: 0x17D + text: "ž" + } + Key { + key: Qt.Key_Comma + text: "," + } + Key { + key: Qt.Key_Period + text: "." + } + ShiftKey { + weight: 234 + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Minus + text: "-" + alternativeKeys: [ "-", "\"", "'" ] + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/hr_HR/numbers.fallback b/virtualkeyboard_layouts_koriolan/layouts/hr_HR/numbers.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/hr_HR/symbols.fallback b/virtualkeyboard_layouts_koriolan/layouts/hr_HR/symbols.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/hu_HU/dialpad.fallback b/virtualkeyboard_layouts_koriolan/layouts/hu_HU/dialpad.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/hu_HU/digits.fallback b/virtualkeyboard_layouts_koriolan/layouts/hu_HU/digits.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/hu_HU/handwriting.qml b/virtualkeyboard_layouts_koriolan/layouts/hu_HU/handwriting.qml new file mode 100755 index 0000000..caf820a --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/hu_HU/handwriting.qml @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Layouts 1.0 +import QtQuick.VirtualKeyboard 2.3 + +KeyboardLayout { + function createInputMethod() { + return Qt.createQmlObject('import QtQuick 2.0; import QtQuick.VirtualKeyboard.Plugins 2.3; HandwritingInputMethod {}', parent) + } + sharedLayouts: ['symbols'] + inputMode: InputEngine.InputMode.Latin + + KeyboardRow { + Layout.preferredHeight: 3 + KeyboardColumn { + Layout.preferredWidth: bottomRow.width - hideKeyboardKey.width + KeyboardRow { + TraceInputKey { + objectName: "hwrInputArea" + patternRecognitionMode: InputEngine.PatternRecognitionMode.Handwriting + } + } + } + KeyboardColumn { + Layout.preferredWidth: hideKeyboardKey.width + KeyboardRow { + BackspaceKey {} + } + KeyboardRow { + EnterKey {} + } + KeyboardRow { + ShiftKey { } + } + } + } + KeyboardRow { + id: bottomRow + Layout.preferredHeight: 1 + keyWeight: 154 + InputModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + customLayoutsOnly: true + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Minus + text: "-" + alternativeKeys: "<>()#%&*/\\\"'=+-_" + } + Key { + key: Qt.Key_Period + text: "." + alternativeKeys: ":;,.?!" + } + HideKeyboardKey { + id: hideKeyboardKey + weight: 204 + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/hu_HU/main.qml b/virtualkeyboard_layouts_koriolan/layouts/hu_HU/main.qml new file mode 100755 index 0000000..0834dc0 --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/hu_HU/main.qml @@ -0,0 +1,201 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.VirtualKeyboard 2.3 + +KeyboardLayout { + inputMode: InputEngine.InputMode.Latin + keyWeight: 160 + KeyboardRow { + Key { + key: Qt.Key_Q + text: "q" + } + Key { + key: Qt.Key_W + text: "w" + } + Key { + key: Qt.Key_E + text: "e" + alternativeKeys: "eé" + } + Key { + key: Qt.Key_R + text: "r" + } + Key { + key: Qt.Key_T + text: "t" + } + Key { + key: Qt.Key_Z + text: "z" + alternativeKeys: "zž" + } + Key { + key: Qt.Key_U + text: "u" + alternativeKeys: "úűuü" + } + Key { + key: Qt.Key_I + text: "i" + alternativeKeys: "ií" + } + Key { + key: Qt.Key_O + text: "o" + alternativeKeys: "óőoö" + } + Key { + key: Qt.Key_P + text: "p" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Key { + key: Qt.Key_A + text: "a" + alternativeKeys: "aåäá" + } + Key { + key: Qt.Key_S + text: "s" + alternativeKeys: "sš" + } + Key { + key: Qt.Key_D + text: "d" + } + Key { + key: Qt.Key_F + text: "f" + } + Key { + key: Qt.Key_G + text: "g" + } + Key { + key: Qt.Key_H + text: "h" + } + Key { + key: Qt.Key_J + text: "j" + } + Key { + key: Qt.Key_K + text: "k" + } + Key { + key: Qt.Key_L + text: "l" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + ShiftKey {} + Key { + key: Qt.Key_Y + text: "y" + } + Key { + key: Qt.Key_X + text: "x" + } + Key { + key: Qt.Key_C + text: "c" + } + Key { + key: Qt.Key_V + text: "v" + } + Key { + key: Qt.Key_B + text: "b" + } + Key { + key: Qt.Key_N + text: "n" + } + Key { + key: Qt.Key_M + text: "m" + } + Key { + key: Qt.Key_Comma + text: "," + } + Key { + key: Qt.Key_Period + text: "." + } + ShiftKey { + weight: 204 + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Minus + text: "-" + alternativeKeys: "-\"'" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/hu_HU/numbers.fallback b/virtualkeyboard_layouts_koriolan/layouts/hu_HU/numbers.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/hu_HU/symbols.fallback b/virtualkeyboard_layouts_koriolan/layouts/hu_HU/symbols.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/id_ID/dialpad.fallback b/virtualkeyboard_layouts_koriolan/layouts/id_ID/dialpad.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/id_ID/digits.fallback b/virtualkeyboard_layouts_koriolan/layouts/id_ID/digits.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/id_ID/handwriting.fallback b/virtualkeyboard_layouts_koriolan/layouts/id_ID/handwriting.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/id_ID/main.fallback b/virtualkeyboard_layouts_koriolan/layouts/id_ID/main.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/id_ID/numbers.fallback b/virtualkeyboard_layouts_koriolan/layouts/id_ID/numbers.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/id_ID/symbols.fallback b/virtualkeyboard_layouts_koriolan/layouts/id_ID/symbols.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/it_IT/dialpad.fallback b/virtualkeyboard_layouts_koriolan/layouts/it_IT/dialpad.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/it_IT/digits.fallback b/virtualkeyboard_layouts_koriolan/layouts/it_IT/digits.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/it_IT/handwriting.fallback b/virtualkeyboard_layouts_koriolan/layouts/it_IT/handwriting.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/it_IT/main.qml b/virtualkeyboard_layouts_koriolan/layouts/it_IT/main.qml new file mode 100755 index 0000000..72d7c03 --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/it_IT/main.qml @@ -0,0 +1,198 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.VirtualKeyboard 2.1 + +KeyboardLayout { + inputMode: InputEngine.InputMode.Latin + keyWeight: 160 + KeyboardRow { + Key { + key: Qt.Key_Q + text: "q" + } + Key { + key: Qt.Key_W + text: "w" + } + Key { + key: Qt.Key_E + text: "e" + alternativeKeys: "eèé" + } + Key { + key: Qt.Key_R + text: "r" + } + Key { + key: Qt.Key_T + text: "t" + } + Key { + key: Qt.Key_Y + text: "y" + } + Key { + key: Qt.Key_U + text: "u" + alternativeKeys: "uùú" + } + Key { + key: Qt.Key_I + text: "i" + alternativeKeys: "iìí" + } + Key { + key: Qt.Key_O + text: "o" + alternativeKeys: "oòó" + } + Key { + key: Qt.Key_P + text: "p" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Key { + key: Qt.Key_A + text: "a" + alternativeKeys: "aàá" + } + Key { + key: Qt.Key_S + text: "s" + } + Key { + key: Qt.Key_D + text: "d" + } + Key { + key: Qt.Key_F + text: "f" + } + Key { + key: Qt.Key_G + text: "g" + } + Key { + key: Qt.Key_H + text: "h" + } + Key { + key: Qt.Key_J + text: "j" + } + Key { + key: Qt.Key_K + text: "k" + } + Key { + key: Qt.Key_L + text: "l" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + ShiftKey {} + Key { + key: Qt.Key_Z + text: "z" + } + Key { + key: Qt.Key_X + text: "x" + } + Key { + key: Qt.Key_C + text: "c" + } + Key { + key: Qt.Key_V + text: "v" + } + Key { + key: Qt.Key_B + text: "b" + } + Key { + key: Qt.Key_N + text: "n" + } + Key { + key: Qt.Key_M + text: "m" + } + Key { + key: Qt.Key_Comma + text: "," + } + Key { + key: Qt.Key_Period + text: "." + } + ShiftKey { + weight: 204 + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Apostrophe + text: "'" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/it_IT/numbers.fallback b/virtualkeyboard_layouts_koriolan/layouts/it_IT/numbers.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/it_IT/symbols.fallback b/virtualkeyboard_layouts_koriolan/layouts/it_IT/symbols.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/ja_JP/dialpad.fallback b/virtualkeyboard_layouts_koriolan/layouts/ja_JP/dialpad.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/ja_JP/digits.fallback b/virtualkeyboard_layouts_koriolan/layouts/ja_JP/digits.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/ja_JP/handwriting.qml b/virtualkeyboard_layouts_koriolan/layouts/ja_JP/handwriting.qml new file mode 100755 index 0000000..08a7438 --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/ja_JP/handwriting.qml @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Layouts 1.0 +import QtQuick.VirtualKeyboard 2.3 + +KeyboardLayout { + function createInputMethod() { + return Qt.createQmlObject('import QtQuick 2.0; import QtQuick.VirtualKeyboard.Plugins 2.3; HandwritingInputMethod {}', parent) + } + sharedLayouts: ['symbols'] + KeyboardRow { + Layout.preferredHeight: 3 + KeyboardColumn { + Layout.preferredWidth: bottomRow.width - hideKeyboardKey.width + KeyboardRow { + TraceInputKey { + objectName: "hwrInputArea" + patternRecognitionMode: InputEngine.PatternRecognitionMode.Handwriting + horizontalRulers: + InputContext.inputEngine.inputMode !== InputEngine.InputMode.JapaneseHandwriting ? [] : + [Math.round(boundingBox.height / 4), Math.round(boundingBox.height / 4) * 2, Math.round(boundingBox.height / 4) * 3] + + } + } + } + KeyboardColumn { + Layout.preferredWidth: hideKeyboardKey.width + KeyboardRow { + BackspaceKey {} + } + KeyboardRow { + EnterKey {} + } + KeyboardRow { + ShiftKey { } + } + } + } + KeyboardRow { + id: bottomRow + Layout.preferredHeight: 1 + keyWeight: 154 + InputModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + customLayoutsOnly: true + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Apostrophe + text: "‘" + alternativeKeys: "《》〈〉•…々〆‘’“”「」¥" + } + Key { + key: Qt.Key_Period + text: "." + alternativeKeys: ":;,.、。?!" + } + HideKeyboardKey { + id: hideKeyboardKey + weight: 204 + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/ja_JP/main.qml b/virtualkeyboard_layouts_koriolan/layouts/ja_JP/main.qml new file mode 100755 index 0000000..d3fb6ae --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/ja_JP/main.qml @@ -0,0 +1,432 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.VirtualKeyboard 2.3 + +KeyboardLayoutLoader { + function createInputMethod() { + return Qt.createQmlObject('import QtQuick 2.0; import QtQuick.VirtualKeyboard.Plugins 2.3; JapaneseInputMethod {}', parent, "japaneseInputMethod") + } + sharedLayouts: ['symbols'] + sourceComponent: InputContext.inputEngine.inputMode === InputEngine.InputMode.FullwidthLatin ? page2 : page1 + Component { + id: page1 + KeyboardLayout { + keyWeight: 160 + KeyboardRow { + Key { + key: Qt.Key_Q + text: "q" + } + Key { + key: Qt.Key_W + text: "w" + } + Key { + key: Qt.Key_E + text: "e" + } + Key { + key: Qt.Key_R + text: "r" + } + Key { + key: Qt.Key_T + text: "t" + } + Key { + key: Qt.Key_Y + text: "y" + } + Key { + key: Qt.Key_U + text: "u" + } + Key { + key: Qt.Key_I + text: "i" + } + Key { + key: Qt.Key_O + text: "o" + } + Key { + key: Qt.Key_P + text: "p" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Key { + key: Qt.Key_A + text: "a" + } + Key { + key: Qt.Key_S + text: "s" + } + Key { + key: Qt.Key_D + text: "d" + } + Key { + key: Qt.Key_F + text: "f" + } + Key { + key: Qt.Key_G + text: "g" + } + Key { + key: Qt.Key_H + text: "h" + } + Key { + key: Qt.Key_J + text: "j" + } + Key { + key: Qt.Key_K + text: "k" + } + Key { + key: Qt.Key_L + text: "l" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + InputModeKey { + enabled: !(InputContext.inputMethodHints & Qt.ImhLatinOnly) && inputModeCount > 1 + inputModeNameList: [ + "半角", // InputEngine.InputMode.Latin + "", // InputEngine.InputMode.Numeric + "", // InputEngine.InputMode.Dialable + "", // InputEngine.InputMode.Pinyin + "", // InputEngine.InputMode.Cangjie + "", // InputEngine.InputMode.Zhuyin + "", // InputEngine.InputMode.Hangul + "あ", // InputEngine.InputMode.Hiragana + "カ", // InputEngine.InputMode.Katakana + "全角", // InputEngine.InputMode.FullwidthLatin + ] + } + Key { + key: Qt.Key_Z + text: "z" + } + Key { + key: Qt.Key_X + text: "x" + } + Key { + key: Qt.Key_C + text: "c" + } + Key { + key: Qt.Key_V + text: "v" + } + Key { + key: Qt.Key_B + text: "b" + } + Key { + key: Qt.Key_N + text: "n" + } + Key { + key: Qt.Key_M + text: "m" + } + Key { + key: Qt.Key_Comma + text: "\u3001" + alternativeKeys: "\u3001\uFF01,!" + } + Key { + key: Qt.Key_Period + text: "\u3002" + alternativeKeys: "\u3002\uFF1F.?" + } + ShiftKey { + weight: 204 + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 194 + } + ChangeLanguageKey { + } + HandwritingModeKey { + } + Key { + key: Qt.Key_Left + displayText: "\u2190" + repeat: true + noModifier: true + functionKey: true + } + Key { + key: Qt.Key_Right + displayText: "\u2192" + repeat: true + noModifier: true + functionKey: true + } + SpaceKey { + weight: 556 + text: InputContext.inputEngine.inputMode != InputEngine.InputMode.Latin ? "\u3000" : " " + } + Key { + key: Qt.Key_Slash + text: "\u30FB" + alternativeKeys: "\u30FB/" + } + Key { + key: Qt.Key_Apostrophe + text: "\uFF07" + alternativeKeys: "\uFF07\uFF02'\"" + } + Key { + key: Qt.Key_Underscore + text: "\u30FC" + alternativeKeys: "\u30FC\uFF5E\uFF70\uFF3F_" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } + } + } + Component { + id: page2 + KeyboardLayout { + keyWeight: 160 + KeyboardRow { + Key { + key: Qt.Key_Q + text: "\uFF51" + } + Key { + key: Qt.Key_W + text: "\uFF57" + } + Key { + key: Qt.Key_E + text: "\uFF45" + } + Key { + key: Qt.Key_R + text: "\uFF52" + } + Key { + key: Qt.Key_T + text: "\uFF54" + } + Key { + key: Qt.Key_Y + text: "\uFF59" + } + Key { + key: Qt.Key_U + text: "\uFF55" + } + Key { + key: Qt.Key_I + text: "\uFF49" + } + Key { + key: Qt.Key_O + text: "\uFF4F" + } + Key { + key: Qt.Key_P + text: "\uFF50" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Key { + key: Qt.Key_A + text: "\uFF41" + } + Key { + key: Qt.Key_S + text: "\uFF53" + } + Key { + key: Qt.Key_D + text: "\uFF44" + } + Key { + key: Qt.Key_F + text: "\uFF46" + } + Key { + key: Qt.Key_G + text: "\uFF47" + } + Key { + key: Qt.Key_H + text: "\uFF48" + } + Key { + key: Qt.Key_J + text: "\uFF4A" + } + Key { + key: Qt.Key_K + text: "\uFF4B" + } + Key { + key: Qt.Key_L + text: "\uFF4C" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + InputModeKey { + } + Key { + key: Qt.Key_Z + text: "\uFF5A" + } + Key { + key: Qt.Key_X + text: "\uFF58" + } + Key { + key: Qt.Key_C + text: "\uFF43" + } + Key { + key: Qt.Key_V + text: "\uFF56" + } + Key { + key: Qt.Key_B + text: "\uFF42" + } + Key { + key: Qt.Key_N + text: "\uFF4E" + } + Key { + key: Qt.Key_M + text: "\uFF4D" + } + Key { + key: Qt.Key_Comma + text: "\u3001" + alternativeKeys: "\u3001\uFF01,!" + } + Key { + key: Qt.Key_Period + text: "\u3002" + alternativeKeys: "\u3002\uFF1F.?" + } + ShiftKey { + weight: 204 + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 194 + } + ChangeLanguageKey { + } + HandwritingModeKey { + } + Key { + key: Qt.Key_Left + displayText: "\u2190" + repeat: true + noModifier: true + functionKey: true + } + Key { + key: Qt.Key_Right + displayText: "\u2192" + repeat: true + noModifier: true + functionKey: true + } + SpaceKey { + weight: 556 + text: "\u3000" + } + Key { + key: Qt.Key_Slash + text: "\u30FB" + alternativeKeys: "\u30FB/" + } + Key { + key: Qt.Key_Apostrophe + text: "\uFF07" + alternativeKeys: "\uFF07\uFF02'\"" + } + Key { + key: Qt.Key_Underscore + text: "\u30FC" + alternativeKeys: "\u30FC\uFF5E\uFF70\uFF3F_" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/ja_JP/numbers.fallback b/virtualkeyboard_layouts_koriolan/layouts/ja_JP/numbers.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/ja_JP/symbols.qml b/virtualkeyboard_layouts_koriolan/layouts/ja_JP/symbols.qml new file mode 100755 index 0000000..66a4985 --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/ja_JP/symbols.qml @@ -0,0 +1,294 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Layouts 1.0 +import QtQuick.VirtualKeyboard 2.1 + +KeyboardLayoutLoader { + function createInputMethod() { + return Qt.createQmlObject('import QtQuick 2.0; import QtQuick.VirtualKeyboard.Plugins 2.1; JapaneseInputMethod {}', parent, "japaneseInputMethod") + } + sharedLayouts: ['main'] + property int page + readonly property int numPages: 3 + property var keysPage1: [ + "1234567890", + "@#$%^&*()", + "“”、=:;!?~" + ] + property var keysPage2: [ + "-+/\\|[]{}·", + "<>,.:;!?~", + "/\"'_§¥€£¢" + ] + property var keysPage3: [ + "()〔〕〈〉《》【】", + "→←↑↓↔■□●○", + "\『』「」★☆◆◇" + ] + sourceComponent: { + switch (page) { + case 2: return page3 + case 1: return page2 + default: return page1 + } + } + Component { + id: page1 + KeyboardLayout { + keyWeight: 160 + KeyboardRow { + Repeater { + model: keysPage1[0].length + Key { + key: keysPage1[0][index].charCodeAt(0) + text: keysPage1[0][index] + } + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Repeater { + model: keysPage1[1].length + Key { + key: keysPage1[1][index].charCodeAt(0) + text: keysPage1[1][index] + } + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + Key { + displayText: (page + 1) + "/" + numPages + functionKey: true + onClicked: page = (page + 1) % numPages + } + Repeater { + model: keysPage1[2].length + Key { + key: keysPage1[2][index].charCodeAt(0) + text: keysPage1[2][index] + } + } + Key { + weight: 204 + displayText: (page + 1) + "/" + numPages + functionKey: true + onClicked: page = (page + 1) % numPages + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + displayText: "ABC" + } + ChangeLanguageKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: 0x2014 + text: "—" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } + } + } + Component { + id: page2 + KeyboardLayout { + keyWeight: 160 + KeyboardRow { + Repeater { + model: keysPage2[0].length + Key { + key: keysPage2[0][index].charCodeAt(0) + text: keysPage2[0][index] + } + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Repeater { + model: keysPage2[1].length + Key { + key: keysPage2[1][index].charCodeAt(0) + text: keysPage2[1][index] + } + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + Key { + displayText: (page + 1) + "/" + numPages + functionKey: true + onClicked: page = (page + 1) % numPages + } + Repeater { + model: keysPage2[2].length + Key { + key: keysPage2[2][index].charCodeAt(0) + text: keysPage2[2][index] + } + } + Key { + weight: 204 + displayText: (page + 1) + "/" + numPages + functionKey: true + onClicked: page = (page + 1) % numPages + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + displayText: "ABC" + } + ChangeLanguageKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: 0x3002 + text: "。" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } + } + } + Component { + id: page3 + KeyboardLayout { + keyWeight: 160 + KeyboardRow { + Repeater { + model: keysPage3[0].length + Key { + key: keysPage3[0][index].charCodeAt(0) + text: keysPage3[0][index] + } + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Repeater { + model: keysPage3[1].length + Key { + key: keysPage3[1][index].charCodeAt(0) + text: keysPage3[1][index] + } + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + Key { + displayText: (page + 1) + "/" + numPages + functionKey: true + onClicked: page = (page + 1) % numPages + } + Repeater { + model: keysPage3[2].length + Key { + key: keysPage3[2][index].charCodeAt(0) + text: keysPage3[2][index] + } + } + Key { + weight: 204 + displayText: (page + 1) + "/" + numPages + functionKey: true + onClicked: page = (page + 1) % numPages + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + displayText: "ABC" + } + ChangeLanguageKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: 0x2026 + text: "…" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/ko_KR/dialpad.fallback b/virtualkeyboard_layouts_koriolan/layouts/ko_KR/dialpad.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/ko_KR/digits.fallback b/virtualkeyboard_layouts_koriolan/layouts/ko_KR/digits.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/ko_KR/handwriting.qml b/virtualkeyboard_layouts_koriolan/layouts/ko_KR/handwriting.qml new file mode 100755 index 0000000..563239a --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/ko_KR/handwriting.qml @@ -0,0 +1,118 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Layouts 1.0 +import QtQuick.VirtualKeyboard 2.3 + +KeyboardLayout { + function createInputMethod() { + return Qt.createQmlObject('import QtQuick 2.0; import QtQuick.VirtualKeyboard.Plugins 2.3; HandwritingInputMethod {}', parent) + } + sharedLayouts: ['symbols'] + inputMode: preferredInputMode() + + Connections { + target: InputContext + onInputMethodHintsChanged: { + var newInputMode = preferredInputMode() + if (InputContext.inputEngine.inputModes.indexOf(newInputMode) !== -1) + InputContext.inputEngine.inputMode = newInputMode + } + } + + function preferredInputMode() { + return InputContext.inputMethodHints & + (Qt.ImhPreferLatin | Qt.ImhEmailCharactersOnly | Qt.ImhUrlCharactersOnly | + Qt.ImhLatinOnly) ? InputEngine.InputMode.Latin : InputEngine.InputMode.KoreanHandwriting + } + + KeyboardRow { + Layout.preferredHeight: 3 + KeyboardColumn { + Layout.preferredWidth: bottomRow.width - hideKeyboardKey.width + KeyboardRow { + TraceInputKey { + objectName: "hwrInputArea" + patternRecognitionMode: InputEngine.PatternRecognitionMode.Handwriting + horizontalRulers: + InputContext.inputEngine.inputMode !== InputEngine.InputMode.KoreanHandwriting ? [] : + [Math.round(boundingBox.height / 4), Math.round(boundingBox.height / 4) * 2, Math.round(boundingBox.height / 4) * 3] + + } + } + } + KeyboardColumn { + Layout.preferredWidth: hideKeyboardKey.width + KeyboardRow { + BackspaceKey {} + } + KeyboardRow { + EnterKey {} + } + KeyboardRow { + ShiftKey { + enabled: InputContext.inputEngine.inputMode !== InputEngine.InputMode.KoreanHandwriting + } + } + } + } + KeyboardRow { + id: bottomRow + Layout.preferredHeight: 1 + keyWeight: 154 + InputModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + customLayoutsOnly: true + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Apostrophe + text: "'" + alternativeKeys: "<>()#%&*/\\\"'=+-_" + } + Key { + key: Qt.Key_Period + text: "." + alternativeKeys: ":;,.?!" + } + HideKeyboardKey { + id: hideKeyboardKey + weight: 204 + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/ko_KR/main.qml b/virtualkeyboard_layouts_koriolan/layouts/ko_KR/main.qml new file mode 100755 index 0000000..54e6ec5 --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/ko_KR/main.qml @@ -0,0 +1,313 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.VirtualKeyboard 2.1 + +KeyboardLayoutLoader { + function createInputMethod() { + return Qt.createQmlObject('import QtQuick 2.0; import QtQuick.VirtualKeyboard.Plugins 2.1; HangulInputMethod {}', parent, "hangulInputMethod") + } + sourceComponent: InputContext.shiftActive ? page2 : page1 + sharedLayouts: ['symbols'] + Component { + id: page1 + KeyboardLayout { + keyWeight: 160 + KeyboardRow { + Key { + text: "\u3142" + } + Key { + text: "\u3148" + } + Key { + text: "\u3137" + } + Key { + text: "\u3131" + } + Key { + text: "\u3145" + } + Key { + text: "\u315B" + } + Key { + text: "\u3155" + } + Key { + text: "\u3151" + } + Key { + text: "\u3150" + } + Key { + text: "\u3154" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Key { + text: "\u3141" + } + Key { + text: "\u3134" + } + Key { + text: "\u3147" + } + Key { + text: "\u3139" + } + Key { + text: "\u314E" + } + Key { + text: "\u3157" + } + Key { + text: "\u3153" + } + Key { + text: "\u314F" + } + Key { + text: "\u3163" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + ShiftKey {} + Key { + text: "\u314B" + } + Key { + text: "\u314C" + } + Key { + text: "\u314A" + } + Key { + text: "\u314D" + } + Key { + text: "\u3160" + } + Key { + text: "\u315C" + } + Key { + text: "\u3161" + } + Key { + key: Qt.Key_Comma + text: "," + } + Key { + key: Qt.Key_Period + text: "." + } + ShiftKey { + weight: 204 + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Apostrophe + text: "'" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } + } + } + Component { + id: page2 + KeyboardLayout { + keyWeight: 160 + KeyboardRow { + Key { + text: "\u3143" + } + Key { + text: "\u3149" + } + Key { + text: "\u3138" + } + Key { + text: "\u3132" + } + Key { + text: "\u3146" + } + Key { + text: "\u315B" + } + Key { + text: "\u3155" + } + Key { + text: "\u3151" + } + Key { + text: "\u3152" + } + Key { + text: "\u3156" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Key { + text: "\u3141" + } + Key { + text: "\u3134" + } + Key { + text: "\u3147" + } + Key { + text: "\u3139" + } + Key { + text: "\u314E" + } + Key { + text: "\u3157" + } + Key { + text: "\u3153" + } + Key { + text: "\u314F" + } + Key { + text: "\u3163" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + ShiftKey {} + Key { + text: "\u314B" + } + Key { + text: "\u314C" + } + Key { + text: "\u314A" + } + Key { + text: "\u314D" + } + Key { + text: "\u3160" + } + Key { + text: "\u315C" + } + Key { + text: "\u3161" + } + Key { + key: Qt.Key_Comma + text: "," + } + Key { + key: Qt.Key_Period + text: "." + } + ShiftKey { + weight: 204 + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Apostrophe + text: "'" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/ko_KR/numbers.fallback b/virtualkeyboard_layouts_koriolan/layouts/ko_KR/numbers.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/ko_KR/symbols.qml b/virtualkeyboard_layouts_koriolan/layouts/ko_KR/symbols.qml new file mode 100755 index 0000000..352a69e --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/ko_KR/symbols.qml @@ -0,0 +1,380 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Layouts 1.0 +import QtQuick.VirtualKeyboard 2.1 + +KeyboardLayoutLoader { + function createInputMethod() { + return Qt.createQmlObject('import QtQuick 2.0; import QtQuick.VirtualKeyboard.Plugins 2.1; HangulInputMethod {}', parent, "hangulInputMethod") + } + sharedLayouts: ['main'] + property bool secondPage + onVisibleChanged: if (!visible) secondPage = false + sourceComponent: secondPage ? page2 : page1 + Component { + id: page1 + KeyboardLayout { + keyWeight: 160 + KeyboardRow { + Key { + key: Qt.Key_1 + text: "1" + } + Key { + key: Qt.Key_2 + text: "2" + } + Key { + key: Qt.Key_3 + text: "3" + } + Key { + key: Qt.Key_4 + text: "4" + } + Key { + key: Qt.Key_5 + text: "5" + } + Key { + key: Qt.Key_6 + text: "6" + } + Key { + key: Qt.Key_7 + text: "7" + } + Key { + key: Qt.Key_8 + text: "8" + } + Key { + key: Qt.Key_9 + text: "9" + } + Key { + key: Qt.Key_0 + text: "0" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Key { + key: Qt.Key_At + text: "@" + } + Key { + key: Qt.Key_NumberSign + text: "#" + } + Key { + key: Qt.Key_Percent + text: "%" + } + Key { + key: Qt.Key_Ampersand + text: "&" + } + Key { + key: Qt.Key_Asterisk + text: "*" + } + Key { + key: Qt.Key_Minus + text: "-" + } + Key { + key: Qt.Key_Plus + text: "+" + } + Key { + key: Qt.Key_ParenLeft + text: "(" + } + Key { + key: Qt.Key_ParenRight + text: ")" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + Key { + displayText: "1/2" + functionKey: true + onClicked: secondPage = !secondPage + } + Key { + key: Qt.Key_Exclam + text: "!" + } + Key { + key: Qt.Key_QuoteDbl + text: '"' + } + Key { + key: Qt.Key_Less + text: "<" + } + Key { + key: Qt.Key_Greater + text: ">" + } + Key { + key: Qt.Key_Apostrophe + text: "'" + } + Key { + key: Qt.Key_Colon + text: ":" + } + Key { + key: Qt.Key_Semicolon + text: ";" + } + Key { + key: Qt.Key_Slash + text: "/" + } + Key { + key: Qt.Key_Question + text: "?" + } + Key { + weight: 204 + displayText: "1/2" + functionKey: true + onClicked: secondPage = !secondPage + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + displayText: "\uC54C\uD30C\uBCB3" + } + ChangeLanguageKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Period + text: "." + alternativeKeys: ".," + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } + } + } + Component { + id: page2 + KeyboardLayout { + keyWeight: 160 + KeyboardRow { + Key { + key: Qt.Key_AsciiTilde + text: "~" + } + Key { + key: Qt.Key_Agrave + text: "`" + } + Key { + key: Qt.Key_Bar + text: "|" + } + Key { + key: 0x7B + text: "·" + } + Key { + key: 0x221A + text: "√" + } + Key { + key: Qt.Key_division + text: "÷" + } + Key { + key: Qt.Key_multiply + text: "×" + } + Key { + key: Qt.Key_onehalf + text: "½" + alternativeKeys: "¼⅓½¾⅞" + } + Key { + key: Qt.Key_BraceLeft + text: "{" + } + Key { + key: Qt.Key_BraceRight + text: "}" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Key { + key: Qt.Key_Dollar + text: "$" + } + Key { + key: 0x20AC + text: "€" + } + Key { + key: 0xC2 + text: "£" + } + Key { + key: 0x20A9 + text: "\u20A9" + } + Key { + key: 0xA5 + text: "¥" + } + Key { + key: Qt.Key_Equal + text: "=" + } + Key { + key: Qt.Key_section + text: "§" + } + Key { + key: Qt.Key_BracketLeft + text: "[" + } + Key { + key: Qt.Key_BracketRight + text: "]" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + Key { + displayText: "2/2" + functionKey: true + onClicked: secondPage = !secondPage + } + Key { + key: Qt.Key_Underscore + text: "_" + } + Key { + key: 0x2122 + text: '™' + } + Key { + key: 0x00AE + text: '®' + } + Key { + key: Qt.Key_guillemotleft + text: '«' + } + Key { + key: Qt.Key_guillemotright + text: '»' + } + Key { + key: 0x201C + text: '“' + } + Key { + key: 0x201D + text: '”' + } + Key { + key: Qt.Key_Backslash + text: "\\" + } + Key { + key: Qt.Key_AsciiCircum + text: "^" + } + Key { + weight: 204 + displayText: "2/2" + functionKey: true + onClicked: secondPage = !secondPage + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + displayText: "\uC54C\uD30C\uBCB3" + } + ChangeLanguageKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: 0x2026 + text: "\u2026" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/ms_MY/dialpad.fallback b/virtualkeyboard_layouts_koriolan/layouts/ms_MY/dialpad.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/ms_MY/digits.fallback b/virtualkeyboard_layouts_koriolan/layouts/ms_MY/digits.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/ms_MY/handwriting.fallback b/virtualkeyboard_layouts_koriolan/layouts/ms_MY/handwriting.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/ms_MY/main.fallback b/virtualkeyboard_layouts_koriolan/layouts/ms_MY/main.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/ms_MY/numbers.fallback b/virtualkeyboard_layouts_koriolan/layouts/ms_MY/numbers.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/ms_MY/symbols.fallback b/virtualkeyboard_layouts_koriolan/layouts/ms_MY/symbols.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/nb_NO/dialpad.fallback b/virtualkeyboard_layouts_koriolan/layouts/nb_NO/dialpad.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/nb_NO/digits.fallback b/virtualkeyboard_layouts_koriolan/layouts/nb_NO/digits.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/nb_NO/handwriting.fallback b/virtualkeyboard_layouts_koriolan/layouts/nb_NO/handwriting.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/nb_NO/main.qml b/virtualkeyboard_layouts_koriolan/layouts/nb_NO/main.qml new file mode 100755 index 0000000..8580045 --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/nb_NO/main.qml @@ -0,0 +1,215 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.VirtualKeyboard 2.1 + +KeyboardLayout { + inputMode: InputEngine.InputMode.Latin + keyWeight: 160 + KeyboardRow { + Key { + key: Qt.Key_Q + text: "q" + } + Key { + key: Qt.Key_W + text: "w" + } + Key { + key: Qt.Key_E + text: "e" + alternativeKeys: "eéèê" + } + Key { + key: Qt.Key_R + text: "r" + } + Key { + key: Qt.Key_T + text: "t" + } + Key { + key: Qt.Key_Y + text: "y" + } + Key { + key: Qt.Key_U + text: "u" + alternativeKeys: "uü" + } + Key { + key: Qt.Key_I + text: "i" + } + Key { + key: Qt.Key_O + text: "o" + alternativeKeys: "oöóòô" + } + Key { + key: Qt.Key_P + text: "p" + } + Key { + key: Qt.Key_Aring + text: "å" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 66 + } + Key { + key: Qt.Key_A + text: "a" + alternativeKeys: "aäâá" + } + Key { + key: Qt.Key_S + text: "s" + } + Key { + key: Qt.Key_D + text: "d" + } + Key { + key: Qt.Key_F + text: "f" + } + Key { + key: Qt.Key_G + text: "g" + } + Key { + key: Qt.Key_H + text: "h" + } + Key { + key: Qt.Key_J + text: "j" + } + Key { + key: Qt.Key_K + text: "k" + } + Key { + key: Qt.Key_L + text: "l" + } + Key { + key: Qt.Key_Ooblique + text: "ø" + alternativeKeys: "øö" + } + Key { + key: Qt.Key_AE + text: "æ" + alternativeKeys: "æä" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + ShiftKey { } + Key { + key: Qt.Key_Z + text: "z" + } + Key { + key: Qt.Key_X + text: "x" + } + Key { + key: Qt.Key_C + text: "c" + } + Key { + key: Qt.Key_V + text: "v" + } + Key { + key: Qt.Key_B + text: "b" + } + Key { + key: Qt.Key_N + text: "n" + } + Key { + key: Qt.Key_M + text: "m" + } + Key { + key: Qt.Key_Comma + text: "," + } + Key { + key: Qt.Key_Period + text: "." + } + Key { + key: Qt.Key_Minus + text: "-" + } + ShiftKey { + weight: 264 + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Apostrophe + text: "'" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/nb_NO/numbers.fallback b/virtualkeyboard_layouts_koriolan/layouts/nb_NO/numbers.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/nb_NO/symbols.fallback b/virtualkeyboard_layouts_koriolan/layouts/nb_NO/symbols.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/nl_NL/dialpad.fallback b/virtualkeyboard_layouts_koriolan/layouts/nl_NL/dialpad.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/nl_NL/digits.fallback b/virtualkeyboard_layouts_koriolan/layouts/nl_NL/digits.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/nl_NL/handwriting.fallback b/virtualkeyboard_layouts_koriolan/layouts/nl_NL/handwriting.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/nl_NL/main.fallback b/virtualkeyboard_layouts_koriolan/layouts/nl_NL/main.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/nl_NL/numbers.fallback b/virtualkeyboard_layouts_koriolan/layouts/nl_NL/numbers.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/nl_NL/symbols.fallback b/virtualkeyboard_layouts_koriolan/layouts/nl_NL/symbols.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/pl_PL/dialpad.fallback b/virtualkeyboard_layouts_koriolan/layouts/pl_PL/dialpad.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/pl_PL/digits.fallback b/virtualkeyboard_layouts_koriolan/layouts/pl_PL/digits.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/pl_PL/handwriting.fallback b/virtualkeyboard_layouts_koriolan/layouts/pl_PL/handwriting.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/pl_PL/main.qml b/virtualkeyboard_layouts_koriolan/layouts/pl_PL/main.qml new file mode 100755 index 0000000..2a7ebfd --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/pl_PL/main.qml @@ -0,0 +1,202 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.VirtualKeyboard 2.1 + +KeyboardLayout { + inputMode: InputEngine.InputMode.Latin + keyWeight: 160 + KeyboardRow { + Key { + key: Qt.Key_Q + text: "q" + } + Key { + key: Qt.Key_W + text: "w" + } + Key { + key: Qt.Key_E + text: "e" + alternativeKeys: "eę" + } + Key { + key: Qt.Key_R + text: "r" + } + Key { + key: Qt.Key_T + text: "t" + } + Key { + key: Qt.Key_Y + text: "y" + } + Key { + key: Qt.Key_U + text: "u" + } + Key { + key: Qt.Key_I + text: "i" + } + Key { + key: Qt.Key_O + text: "o" + alternativeKeys: "oó" + } + Key { + key: Qt.Key_P + text: "p" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Key { + key: Qt.Key_A + text: "a" + alternativeKeys: "aą" + } + Key { + key: Qt.Key_S + text: "s" + alternativeKeys: "sś" + } + Key { + key: Qt.Key_D + text: "d" + } + Key { + key: Qt.Key_F + text: "f" + } + Key { + key: Qt.Key_G + text: "g" + } + Key { + key: Qt.Key_H + text: "h" + } + Key { + key: Qt.Key_J + text: "j" + } + Key { + key: Qt.Key_K + text: "k" + } + Key { + key: Qt.Key_L + text: "l" + alternativeKeys: "lł" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + ShiftKey {} + Key { + key: Qt.Key_Z + text: "z" + alternativeKeys: "zźż" + } + Key { + key: Qt.Key_X + text: "x" + alternativeKeys: "xź" + } + Key { + key: Qt.Key_C + text: "c" + alternativeKeys: "cć" + } + Key { + key: Qt.Key_V + text: "v" + } + Key { + key: Qt.Key_B + text: "b" + } + Key { + key: Qt.Key_N + text: "n" + alternativeKeys: "nń" + } + Key { + key: Qt.Key_M + text: "m" + } + Key { + key: Qt.Key_Comma + text: "," + } + Key { + key: Qt.Key_Period + text: "." + } + ShiftKey { + weight: 204 + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Apostrophe + text: "'" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/pl_PL/numbers.fallback b/virtualkeyboard_layouts_koriolan/layouts/pl_PL/numbers.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/pl_PL/symbols.fallback b/virtualkeyboard_layouts_koriolan/layouts/pl_PL/symbols.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/pt_BR/dialpad.fallback b/virtualkeyboard_layouts_koriolan/layouts/pt_BR/dialpad.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/pt_BR/digits.fallback b/virtualkeyboard_layouts_koriolan/layouts/pt_BR/digits.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/pt_BR/handwriting.fallback b/virtualkeyboard_layouts_koriolan/layouts/pt_BR/handwriting.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/pt_BR/main.qml b/virtualkeyboard_layouts_koriolan/layouts/pt_BR/main.qml new file mode 100755 index 0000000..53ed462 --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/pt_BR/main.qml @@ -0,0 +1,207 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.VirtualKeyboard 2.1 + +KeyboardLayout { + inputMode: InputEngine.InputMode.Latin + keyWeight: 160 + KeyboardRow { + Key { + key: Qt.Key_Q + text: "q" + } + Key { + key: Qt.Key_W + text: "w" + } + Key { + key: Qt.Key_E + text: "e" + alternativeKeys: "ēęėëeêèé" + } + Key { + key: Qt.Key_R + text: "r" + } + Key { + key: Qt.Key_T + text: "t" + } + Key { + key: Qt.Key_Y + text: "y" + } + Key { + key: Qt.Key_U + text: "u" + alternativeKeys: "üûuùú" + } + Key { + key: Qt.Key_I + text: "i" + alternativeKeys: "ïįîiìí" + } + Key { + key: Qt.Key_O + text: "o" + alternativeKeys: "öõôoòó" + } + Key { + key: Qt.Key_P + text: "p" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Key { + key: Qt.Key_A + text: "a" + alternativeKeys: "äãaâàá" + } + Key { + key: Qt.Key_S + text: "s" + } + Key { + key: Qt.Key_D + text: "d" + } + Key { + key: Qt.Key_F + text: "f" + } + Key { + key: Qt.Key_G + text: "g" + } + Key { + key: Qt.Key_H + text: "h" + } + Key { + key: Qt.Key_J + text: "j" + } + Key { + key: Qt.Key_K + text: "k" + } + Key { + key: Qt.Key_L + text: "l" + } + Key { + key: Qt.Key_Ccedilla + text: "ç" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + ShiftKey {} + Key { + key: Qt.Key_Z + text: "z" + } + Key { + key: Qt.Key_X + text: "x" + } + Key { + key: Qt.Key_C + text: "c" + alternativeKeys: "čcć" + } + Key { + key: Qt.Key_V + text: "v" + } + Key { + key: Qt.Key_B + text: "b" + } + Key { + key: Qt.Key_N + text: "n" + } + Key { + key: Qt.Key_M + text: "m" + } + Key { + key: Qt.Key_Comma + text: "," + } + Key { + key: Qt.Key_Period + text: "." + } + Key { + key: Qt.Key_Minus + text: "-" + } + ShiftKey { + weight: 244 + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Apostrophe + text: "'" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/pt_BR/numbers.fallback b/virtualkeyboard_layouts_koriolan/layouts/pt_BR/numbers.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/pt_BR/symbols.fallback b/virtualkeyboard_layouts_koriolan/layouts/pt_BR/symbols.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/pt_PT/dialpad.fallback b/virtualkeyboard_layouts_koriolan/layouts/pt_PT/dialpad.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/pt_PT/digits.fallback b/virtualkeyboard_layouts_koriolan/layouts/pt_PT/digits.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/pt_PT/handwriting.fallback b/virtualkeyboard_layouts_koriolan/layouts/pt_PT/handwriting.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/pt_PT/main.qml b/virtualkeyboard_layouts_koriolan/layouts/pt_PT/main.qml new file mode 100755 index 0000000..53ed462 --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/pt_PT/main.qml @@ -0,0 +1,207 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.VirtualKeyboard 2.1 + +KeyboardLayout { + inputMode: InputEngine.InputMode.Latin + keyWeight: 160 + KeyboardRow { + Key { + key: Qt.Key_Q + text: "q" + } + Key { + key: Qt.Key_W + text: "w" + } + Key { + key: Qt.Key_E + text: "e" + alternativeKeys: "ēęėëeêèé" + } + Key { + key: Qt.Key_R + text: "r" + } + Key { + key: Qt.Key_T + text: "t" + } + Key { + key: Qt.Key_Y + text: "y" + } + Key { + key: Qt.Key_U + text: "u" + alternativeKeys: "üûuùú" + } + Key { + key: Qt.Key_I + text: "i" + alternativeKeys: "ïįîiìí" + } + Key { + key: Qt.Key_O + text: "o" + alternativeKeys: "öõôoòó" + } + Key { + key: Qt.Key_P + text: "p" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Key { + key: Qt.Key_A + text: "a" + alternativeKeys: "äãaâàá" + } + Key { + key: Qt.Key_S + text: "s" + } + Key { + key: Qt.Key_D + text: "d" + } + Key { + key: Qt.Key_F + text: "f" + } + Key { + key: Qt.Key_G + text: "g" + } + Key { + key: Qt.Key_H + text: "h" + } + Key { + key: Qt.Key_J + text: "j" + } + Key { + key: Qt.Key_K + text: "k" + } + Key { + key: Qt.Key_L + text: "l" + } + Key { + key: Qt.Key_Ccedilla + text: "ç" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + ShiftKey {} + Key { + key: Qt.Key_Z + text: "z" + } + Key { + key: Qt.Key_X + text: "x" + } + Key { + key: Qt.Key_C + text: "c" + alternativeKeys: "čcć" + } + Key { + key: Qt.Key_V + text: "v" + } + Key { + key: Qt.Key_B + text: "b" + } + Key { + key: Qt.Key_N + text: "n" + } + Key { + key: Qt.Key_M + text: "m" + } + Key { + key: Qt.Key_Comma + text: "," + } + Key { + key: Qt.Key_Period + text: "." + } + Key { + key: Qt.Key_Minus + text: "-" + } + ShiftKey { + weight: 244 + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Apostrophe + text: "'" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/pt_PT/numbers.fallback b/virtualkeyboard_layouts_koriolan/layouts/pt_PT/numbers.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/pt_PT/symbols.fallback b/virtualkeyboard_layouts_koriolan/layouts/pt_PT/symbols.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/ro_RO/dialpad.fallback b/virtualkeyboard_layouts_koriolan/layouts/ro_RO/dialpad.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/ro_RO/digits.fallback b/virtualkeyboard_layouts_koriolan/layouts/ro_RO/digits.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/ro_RO/handwriting.qml b/virtualkeyboard_layouts_koriolan/layouts/ro_RO/handwriting.qml new file mode 100755 index 0000000..1d5dedb --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/ro_RO/handwriting.qml @@ -0,0 +1,102 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Layouts 1.0 +import QtQuick.VirtualKeyboard 2.3 + +KeyboardLayout { + function createInputMethod() { + return Qt.createQmlObject('import QtQuick 2.0; import QtQuick.VirtualKeyboard.Plugins 2.3; HandwritingInputMethod {}', parent) + } + sharedLayouts: ['symbols'] + inputMode: InputEngine.InputMode.Latin + + KeyboardRow { + Layout.preferredHeight: 3 + KeyboardColumn { + Layout.preferredWidth: bottomRow.width - hideKeyboardKey.width + KeyboardRow { + TraceInputKey { + objectName: "hwrInputArea" + patternRecognitionMode: InputEngine.PatternRecognitionMode.Handwriting + } + } + } + KeyboardColumn { + Layout.preferredWidth: hideKeyboardKey.width + KeyboardRow { + BackspaceKey {} + } + KeyboardRow { + EnterKey {} + } + KeyboardRow { + ShiftKey { } + } + } + } + KeyboardRow { + id: bottomRow + Layout.preferredHeight: 1 + keyWeight: 154 + InputModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + customLayoutsOnly: true + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Minus + text: "-" + alternativeKeys: "<>()#%&*/\\\"'=+-_" + } + Key { + key: Qt.Key_Period + text: "." + alternativeKeys: ":;,.?!" + } + Key { + key: 0x102 + text: "ă" + alternativeKeys: "ăîâșț" + } + HideKeyboardKey { + id: hideKeyboardKey + weight: 204 + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/ro_RO/main.qml b/virtualkeyboard_layouts_koriolan/layouts/ro_RO/main.qml new file mode 100755 index 0000000..ea3865e --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/ro_RO/main.qml @@ -0,0 +1,229 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.VirtualKeyboard 2.1 + +KeyboardLayout { + inputMode: InputEngine.InputMode.Latin + keyWeight: 160 + KeyboardRow { + Key { + key: Qt.Key_Q + text: "q" + } + Key { + key: Qt.Key_W + text: "w" + } + Key { + key: Qt.Key_E + text: "e" + alternativeKeys: "êeëèé" + } + Key { + key: Qt.Key_R + text: "r" + alternativeKeys: "ŕrř" + } + Key { + key: Qt.Key_T + text: "t" + alternativeKeys: "țţtŧť" + } + Key { + key: Qt.Key_Y + text: "y" + alternativeKeys: "ÿyýŷ" + } + Key { + key: Qt.Key_U + text: "u" + alternativeKeys: "űūũûüuùú" + } + Key { + key: Qt.Key_I + text: "i" + alternativeKeys: "îïīĩiìí" + } + Key { + key: Qt.Key_O + text: "o" + alternativeKeys: "œøõôöòóo" + } + Key { + key: Qt.Key_P + text: "p" + } + Key { + key: 0x102 + text: "ă" + } + Key { + key: Qt.Key_Icircumflex + text: "î" + } + Key { + key: Qt.Key_Acircumflex + text: "â" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Key { + key: Qt.Key_A + text: "a" + alternativeKeys: "aäåãăâàá" + } + Key { + key: Qt.Key_S + text: "s" + alternativeKeys: "șšsşś" + } + Key { + key: Qt.Key_D + text: "d" + alternativeKeys: "dđď" + } + Key { + key: Qt.Key_F + text: "f" + } + Key { + key: Qt.Key_G + text: "g" + alternativeKeys: "ġgģĝğ" + } + Key { + key: Qt.Key_H + text: "h" + } + Key { + key: Qt.Key_J + text: "j" + } + Key { + key: Qt.Key_K + text: "k" + } + Key { + key: Qt.Key_L + text: "l" + alternativeKeys: "ĺŀłļľl" + } + Key { + key: 0x218 + text: "ș" + } + Key { + key: 0x21a + text: "ț" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + ShiftKey {} + Key { + key: Qt.Key_Z + text: "z" + alternativeKeys: "zžż" + } + Key { + key: Qt.Key_X + text: "x" + } + Key { + key: Qt.Key_C + text: "c" + alternativeKeys: "çcċčć" + } + Key { + key: Qt.Key_V + text: "v" + } + Key { + key: Qt.Key_B + text: "b" + } + Key { + key: Qt.Key_N + text: "n" + alternativeKeys: "ņńnň" + } + Key { + key: Qt.Key_M + text: "m" + } + Key { + key: Qt.Key_Comma + text: "," + } + Key { + key: Qt.Key_Period + text: "." + } + ShiftKey { + weight: 204 + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Minus + text: "-" + alternativeKeys: [ "\"", "'" ] + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/ro_RO/numbers.fallback b/virtualkeyboard_layouts_koriolan/layouts/ro_RO/numbers.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/ro_RO/symbols.fallback b/virtualkeyboard_layouts_koriolan/layouts/ro_RO/symbols.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/ru_RU/dialpad.fallback b/virtualkeyboard_layouts_koriolan/layouts/ru_RU/dialpad.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/ru_RU/digits.fallback b/virtualkeyboard_layouts_koriolan/layouts/ru_RU/digits.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/ru_RU/handwriting.fallback b/virtualkeyboard_layouts_koriolan/layouts/ru_RU/handwriting.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/ru_RU/main.qml b/virtualkeyboard_layouts_koriolan/layouts/ru_RU/main.qml new file mode 100755 index 0000000..87eb238 --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/ru_RU/main.qml @@ -0,0 +1,394 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.10 +import QtQuick.VirtualKeyboard 2.3 + +KeyboardLayoutLoader { + sharedLayouts: ['symbols'] + sourceComponent: InputContext.inputEngine.inputMode === InputEngine.InputMode.Cyrillic ? cyrillicLayout : latinLayout + Component { + id: cyrillicLayout + KeyboardLayout { + keyWeight: 160 + KeyboardRow { + Key { + key: 0x0419 + text: "й" + } + Key { + key: 0x0426 + text: "ц" + } + Key { + key: 0x0423 + text: "у" + } + Key { + key: 0x041A + text: "к" + } + Key { + key: 0x0415 + text: "е" + alternativeKeys: "её" + } + Key { + key: 0x041D + text: "н" + } + Key { + key: 0x0413 + text: "г" + } + Key { + key: 0x0428 + text: "ш" + } + Key { + key: 0x0429 + text: "щ" + } + Key { + key: 0x0417 + text: "з" + } + Key { + key: 0x0425 + text: "х" + } + BackspaceKey { + weight: 180 + } + } + KeyboardRow { + FillerKey { + weight: 40 + } + Key { + key: 0x0424 + text: "ф" + } + Key { + key: 0x042B + text: "ы" + } + Key { + key: 0x0412 + text: "в" + } + Key { + key: 0x0410 + text: "а" + } + Key { + key: 0x041F + text: "п" + } + Key { + key: 0x0420 + text: "р" + } + Key { + key: 0x041E + text: "о" + } + Key { + key: 0x041B + text: "л" + } + Key { + key: 0x0414 + text: "д" + } + Key { + key: 0x0416 + text: "ж" + } + Key { + key: 0x042D + text: "э" + } + EnterKey { + weight: 280 + } + } + KeyboardRow { + InputModeKey { + inputModes: [InputEngine.InputMode.Cyrillic, InputEngine.InputMode.Latin] + } + Key { + key: 0x042F + text: "я" + } + Key { + key: 0x0427 + text: "ч" + } + Key { + key: 0x0421 + text: "с" + } + Key { + key: 0x041C + text: "м" + } + Key { + key: 0x0418 + text: "и" + } + Key { + key: 0x0422 + text: "т" + } + Key { + key: 0x042C + text: "ь" + alternativeKeys: "ьъ" + } + Key { + key: 0x0411 + text: "б" + } + Key { + key: 0x042E + text: "ю" + } + Key { + key: Qt.Key_Minus + text: "-" + alternativeKeys: "—" + } + ShiftKey { + weight: 272 + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Period + text: "." + alternativeKeys: ";:!?,." + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } + } + } + Component { + id: latinLayout + KeyboardLayout { + keyWeight: 160 + KeyboardRow { + Key { + key: Qt.Key_Q + text: "q" + } + Key { + key: Qt.Key_W + text: "w" + } + Key { + key: Qt.Key_E + text: "e" + } + Key { + key: Qt.Key_R + text: "r" + } + Key { + key: Qt.Key_T + text: "t" + } + Key { + key: Qt.Key_Z + text: "z" + alternativeKeys: "zž" + } + Key { + key: Qt.Key_U + text: "u" + } + Key { + key: Qt.Key_I + text: "i" + } + Key { + key: Qt.Key_O + text: "o" + alternativeKeys: "oö" + } + Key { + key: Qt.Key_P + text: "p" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Key { + key: Qt.Key_A + text: "a" + alternativeKeys: "aåä" + } + Key { + key: Qt.Key_S + text: "s" + alternativeKeys: "sš" + } + Key { + key: Qt.Key_D + text: "d" + alternativeKeys: "dđ" + } + Key { + key: Qt.Key_F + text: "f" + } + Key { + key: Qt.Key_G + text: "g" + } + Key { + key: Qt.Key_H + text: "h" + } + Key { + key: Qt.Key_J + text: "j" + } + Key { + key: Qt.Key_K + text: "k" + } + Key { + key: Qt.Key_L + text: "l" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + InputModeKey { + inputModes: [InputEngine.InputMode.Cyrillic, InputEngine.InputMode.Latin] + } + Key { + key: Qt.Key_Y + text: "y" + } + Key { + key: Qt.Key_X + text: "x" + } + Key { + key: Qt.Key_C + text: "c" + alternativeKeys: "ćcč" + } + Key { + key: Qt.Key_V + text: "v" + } + Key { + key: Qt.Key_B + text: "b" + } + Key { + key: Qt.Key_N + text: "n" + } + Key { + key: Qt.Key_M + text: "m" + } + Key { + key: Qt.Key_Comma + text: "," + } + Key { + key: Qt.Key_Period + text: "." + } + ShiftKey { + weight: 204 + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Minus + text: "-" + alternativeKeys: "-\"'" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/ru_RU/numbers.fallback b/virtualkeyboard_layouts_koriolan/layouts/ru_RU/numbers.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/ru_RU/symbols.fallback b/virtualkeyboard_layouts_koriolan/layouts/ru_RU/symbols.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/sk_SK/dialpad.fallback b/virtualkeyboard_layouts_koriolan/layouts/sk_SK/dialpad.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/sk_SK/digits.fallback b/virtualkeyboard_layouts_koriolan/layouts/sk_SK/digits.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/sk_SK/handwriting.fallback b/virtualkeyboard_layouts_koriolan/layouts/sk_SK/handwriting.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/sk_SK/main.qml b/virtualkeyboard_layouts_koriolan/layouts/sk_SK/main.qml new file mode 100755 index 0000000..1f739d3 --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/sk_SK/main.qml @@ -0,0 +1,208 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.VirtualKeyboard 2.3 + +KeyboardLayout { + inputMode: InputEngine.InputMode.Latin + keyWeight: 160 + KeyboardRow { + Key { + key: Qt.Key_Q + text: "q" + } + Key { + key: Qt.Key_W + text: "w" + } + Key { + key: Qt.Key_E + text: "e" + alternativeKeys: "eé" + } + Key { + key: Qt.Key_R + text: "r" + alternativeKeys: "rŕ" + } + Key { + key: Qt.Key_T + text: "t" + alternativeKeys: "tť" + } + Key { + key: Qt.Key_Z + text: "z" + alternativeKeys: "zž" + } + Key { + key: Qt.Key_U + text: "u" + alternativeKeys: "uú" + } + Key { + key: Qt.Key_I + text: "i" + alternativeKeys: "ií" + } + Key { + key: Qt.Key_O + text: "o" + alternativeKeys: "oóöô" + } + Key { + key: Qt.Key_P + text: "p" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Key { + key: Qt.Key_A + text: "a" + alternativeKeys: "aåäá" + } + Key { + key: Qt.Key_S + text: "s" + alternativeKeys: "sš" + } + Key { + key: Qt.Key_D + text: "d" + alternativeKeys: "dď" + } + Key { + key: Qt.Key_F + text: "f" + } + Key { + key: Qt.Key_G + text: "g" + } + Key { + key: Qt.Key_H + text: "h" + } + Key { + key: Qt.Key_J + text: "j" + } + Key { + key: Qt.Key_K + text: "k" + } + Key { + key: Qt.Key_L + text: "l" + alternativeKeys: "lĺľ" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + ShiftKey {} + Key { + key: Qt.Key_Y + text: "y" + alternativeKeys: "yý" + } + Key { + key: Qt.Key_X + text: "x" + } + Key { + key: Qt.Key_C + text: "c" + alternativeKeys: "cč" + } + Key { + key: Qt.Key_V + text: "v" + } + Key { + key: Qt.Key_B + text: "b" + } + Key { + key: Qt.Key_N + text: "n" + alternativeKeys: "nň" + } + Key { + key: Qt.Key_M + text: "m" + } + Key { + key: Qt.Key_Comma + text: "," + } + Key { + key: Qt.Key_Period + text: "." + } + ShiftKey { + weight: 204 + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Minus + text: "-" + alternativeKeys: "-\"'" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/sk_SK/numbers.fallback b/virtualkeyboard_layouts_koriolan/layouts/sk_SK/numbers.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/sk_SK/symbols.fallback b/virtualkeyboard_layouts_koriolan/layouts/sk_SK/symbols.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/sl_SI/dialpad.fallback b/virtualkeyboard_layouts_koriolan/layouts/sl_SI/dialpad.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/sl_SI/digits.fallback b/virtualkeyboard_layouts_koriolan/layouts/sl_SI/digits.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/sl_SI/handwriting.fallback b/virtualkeyboard_layouts_koriolan/layouts/sl_SI/handwriting.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/sl_SI/main.qml b/virtualkeyboard_layouts_koriolan/layouts/sl_SI/main.qml new file mode 100755 index 0000000..7629362 --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/sl_SI/main.qml @@ -0,0 +1,203 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.VirtualKeyboard 2.3 + +KeyboardLayout { + inputMode: InputEngine.InputMode.Latin + keyWeight: 160 + KeyboardRow { + Key { + key: Qt.Key_Q + text: "q" + } + Key { + key: Qt.Key_W + text: "w" + } + Key { + key: Qt.Key_E + text: "e" + alternativeKeys: "eèêëé" + } + Key { + key: Qt.Key_R + text: "r" + } + Key { + key: Qt.Key_T + text: "t" + } + Key { + key: Qt.Key_Z + text: "z" + alternativeKeys: "zž" + } + Key { + key: Qt.Key_U + text: "u" + alternativeKeys: "uúü" + } + Key { + key: Qt.Key_I + text: "i" + alternativeKeys: "ií" + } + Key { + key: Qt.Key_O + text: "o" + alternativeKeys: "òôöoó" + } + Key { + key: Qt.Key_P + text: "p" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Key { + key: Qt.Key_A + text: "a" + alternativeKeys: "aåäáà" + } + Key { + key: Qt.Key_S + text: "s" + alternativeKeys: "sš" + } + Key { + key: Qt.Key_D + text: "d" + alternativeKeys: "dđ" + } + Key { + key: Qt.Key_F + text: "f" + } + Key { + key: Qt.Key_G + text: "g" + } + Key { + key: Qt.Key_H + text: "h" + } + Key { + key: Qt.Key_J + text: "j" + } + Key { + key: Qt.Key_K + text: "k" + } + Key { + key: Qt.Key_L + text: "l" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + ShiftKey {} + Key { + key: Qt.Key_Y + text: "y" + } + Key { + key: Qt.Key_X + text: "x" + } + Key { + key: Qt.Key_C + text: "c" + alternativeKeys: "cćč" + } + Key { + key: Qt.Key_V + text: "v" + } + Key { + key: Qt.Key_B + text: "b" + } + Key { + key: Qt.Key_N + text: "n" + } + Key { + key: Qt.Key_M + text: "m" + } + Key { + key: Qt.Key_Comma + text: "," + } + Key { + key: Qt.Key_Period + text: "." + } + ShiftKey { + weight: 204 + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Minus + text: "-" + alternativeKeys: "-\"'" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/sl_SI/numbers.fallback b/virtualkeyboard_layouts_koriolan/layouts/sl_SI/numbers.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/sl_SI/symbols.fallback b/virtualkeyboard_layouts_koriolan/layouts/sl_SI/symbols.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/sq_AL/dialpad.fallback b/virtualkeyboard_layouts_koriolan/layouts/sq_AL/dialpad.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/sq_AL/digits.fallback b/virtualkeyboard_layouts_koriolan/layouts/sq_AL/digits.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/sq_AL/handwriting.fallback b/virtualkeyboard_layouts_koriolan/layouts/sq_AL/handwriting.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/sq_AL/main.qml b/virtualkeyboard_layouts_koriolan/layouts/sq_AL/main.qml new file mode 100755 index 0000000..4b50e88 --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/sq_AL/main.qml @@ -0,0 +1,205 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.VirtualKeyboard 2.3 + +KeyboardLayout { + inputMode: InputEngine.InputMode.Latin + keyWeight: 160 + KeyboardRow { + Key { + key: Qt.Key_Q + text: "q" + } + Key { + key: Qt.Key_W + text: "w" + } + Key { + key: Qt.Key_E + text: "e" + } + Key { + key: Qt.Key_R + text: "r" + } + Key { + key: Qt.Key_T + text: "t" + } + Key { + key: Qt.Key_Z + text: "z" + } + Key { + key: Qt.Key_U + text: "u" + } + Key { + key: Qt.Key_I + text: "i" + } + Key { + key: Qt.Key_O + text: "o" + } + Key { + key: Qt.Key_P + text: "p" + } + Key { + key: Qt.Key_Ccedilla + text: "ç" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Key { + key: Qt.Key_A + text: "a" + } + Key { + key: Qt.Key_S + text: "s" + } + Key { + key: Qt.Key_D + text: "d" + } + Key { + key: Qt.Key_F + text: "f" + } + Key { + key: Qt.Key_G + text: "g" + } + Key { + key: Qt.Key_H + text: "h" + } + Key { + key: Qt.Key_J + text: "j" + } + Key { + key: Qt.Key_K + text: "k" + } + Key { + key: Qt.Key_L + text: "l" + } + Key { + key: Qt.Key_Ediaeresis + text: "ë" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + ShiftKey {} + Key { + key: Qt.Key_Y + text: "y" + } + Key { + key: Qt.Key_X + text: "x" + } + Key { + key: Qt.Key_C + text: "c" + } + Key { + key: Qt.Key_V + text: "v" + } + Key { + key: Qt.Key_B + text: "b" + } + Key { + key: Qt.Key_N + text: "n" + } + Key { + key: Qt.Key_M + text: "m" + } + Key { + key: Qt.Key_Comma + text: "," + } + Key { + key: Qt.Key_Period + text: "." + } + Key { + key: Qt.Key_Minus + text: "-" + } + ShiftKey { + weight: 244 + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Apostrophe + text: "'" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/sq_AL/numbers.fallback b/virtualkeyboard_layouts_koriolan/layouts/sq_AL/numbers.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/sq_AL/symbols.fallback b/virtualkeyboard_layouts_koriolan/layouts/sq_AL/symbols.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/sr_SP/dialpad.fallback b/virtualkeyboard_layouts_koriolan/layouts/sr_SP/dialpad.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/sr_SP/digits.fallback b/virtualkeyboard_layouts_koriolan/layouts/sr_SP/digits.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/sr_SP/handwriting.qml b/virtualkeyboard_layouts_koriolan/layouts/sr_SP/handwriting.qml new file mode 100755 index 0000000..6f9cbb9 --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/sr_SP/handwriting.qml @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Layouts 1.0 +import QtQuick.VirtualKeyboard 2.3 + +KeyboardLayout { + function createInputMethod() { + return Qt.createQmlObject('import QtQuick 2.0; import QtQuick.VirtualKeyboard.Plugins 2.3; HandwritingInputMethod {}', parent) + } + sharedLayouts: ['symbols'] + + KeyboardRow { + Layout.preferredHeight: 3 + KeyboardColumn { + Layout.preferredWidth: bottomRow.width - hideKeyboardKey.width + KeyboardRow { + TraceInputKey { + objectName: "hwrInputArea" + patternRecognitionMode: InputEngine.PatternRecognitionMode.Handwriting + horizontalRulers: + InputContext.inputEngine.inputMode !== InputEngine.InputMode.Cyrillic ? [] : + [Math.round(boundingBox.height / 4), Math.round(boundingBox.height / 4) * 2, Math.round(boundingBox.height / 4) * 3] + } + } + } + KeyboardColumn { + Layout.preferredWidth: hideKeyboardKey.width + KeyboardRow { + BackspaceKey {} + } + KeyboardRow { + EnterKey {} + } + KeyboardRow { + ShiftKey { } + } + } + } + KeyboardRow { + id: bottomRow + Layout.preferredHeight: 1 + keyWeight: 154 + InputModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + customLayoutsOnly: true + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Minus + text: "-" + alternativeKeys: "<>()#%&*/\\\"'=+-_" + } + Key { + key: Qt.Key_Period + text: "." + alternativeKeys: ":;,.?!" + } + HideKeyboardKey { + id: hideKeyboardKey + weight: 204 + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/sr_SP/main.qml b/virtualkeyboard_layouts_koriolan/layouts/sr_SP/main.qml new file mode 100755 index 0000000..acd381a --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/sr_SP/main.qml @@ -0,0 +1,363 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.VirtualKeyboard 2.3 + +KeyboardLayoutLoader { + sharedLayouts: ['symbols'] + sourceComponent: InputContext.inputEngine.inputMode === InputEngine.InputMode.Cyrillic ? cyrillicLayout : latinLayout + Component { + id: cyrillicLayout + KeyboardLayout { + keyWeight: 160 + KeyboardRow { + Key { + text: "љ" + } + Key { + text: "њ" + } + Key { + text: "е" + } + Key { + text: "р" + } + Key { + text: "т" + } + Key { + text: "з" + } + Key { + text: "у" + } + Key { + text: "и" + } + Key { + text: "о" + } + Key { + text: "п" + } + Key { + text: "ш" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Key { + text: "а" + } + Key { + text: "с" + } + Key { + text: "д" + } + Key { + text: "ф" + } + Key { + text: "г" + } + Key { + text: "х" + } + Key { + text: "ј" + } + Key { + text: "к" + } + Key { + text: "л" + } + Key { + text: "ч" + } + Key { + text: "ћ" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + InputModeKey { + inputModes: [InputEngine.InputMode.Cyrillic, InputEngine.InputMode.Latin] + } + Key { + text: "ѕ" + } + Key { + text: "џ" + } + Key { + text: "ц" + } + Key { + text: "в" + } + Key { + text: "б" + } + Key { + text: "н" + } + Key { + text: "м" + } + Key { + text: "ђ" + } + Key { + text: "ж" + } + Key { + key: Qt.Key_Comma + text: "," + } + Key { + key: Qt.Key_Period + text: "." + alternativeKeys: "!.;?" + } + ShiftKey { + weight: 204 + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Apostrophe + text: "'" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } + } + } + Component { + id: latinLayout + KeyboardLayout { + keyWeight: 160 + KeyboardRow { + Key { + key: Qt.Key_Q + text: "q" + } + Key { + key: Qt.Key_W + text: "w" + } + Key { + key: Qt.Key_E + text: "e" + } + Key { + key: Qt.Key_R + text: "r" + } + Key { + key: Qt.Key_T + text: "t" + } + Key { + key: Qt.Key_Z + text: "z" + alternativeKeys: "zž" + } + Key { + key: Qt.Key_U + text: "u" + } + Key { + key: Qt.Key_I + text: "i" + } + Key { + key: Qt.Key_O + text: "o" + alternativeKeys: "oö" + } + Key { + key: Qt.Key_P + text: "p" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Key { + key: Qt.Key_A + text: "a" + alternativeKeys: "aåä" + } + Key { + key: Qt.Key_S + text: "s" + alternativeKeys: "sš" + } + Key { + key: Qt.Key_D + text: "d" + alternativeKeys: "dđ" + } + Key { + key: Qt.Key_F + text: "f" + } + Key { + key: Qt.Key_G + text: "g" + } + Key { + key: Qt.Key_H + text: "h" + } + Key { + key: Qt.Key_J + text: "j" + } + Key { + key: Qt.Key_K + text: "k" + } + Key { + key: Qt.Key_L + text: "l" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + InputModeKey { + inputModes: [InputEngine.InputMode.Cyrillic, InputEngine.InputMode.Latin] + } + Key { + key: Qt.Key_Y + text: "y" + } + Key { + key: Qt.Key_X + text: "x" + } + Key { + key: Qt.Key_C + text: "c" + alternativeKeys: "ćcč" + } + Key { + key: Qt.Key_V + text: "v" + } + Key { + key: Qt.Key_B + text: "b" + } + Key { + key: Qt.Key_N + text: "n" + } + Key { + key: Qt.Key_M + text: "m" + } + Key { + key: Qt.Key_Comma + text: "," + } + Key { + key: Qt.Key_Period + text: "." + } + ShiftKey { + weight: 204 + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Minus + text: "-" + alternativeKeys: "-\"'" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/sr_SP/numbers.fallback b/virtualkeyboard_layouts_koriolan/layouts/sr_SP/numbers.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/sr_SP/symbols.fallback b/virtualkeyboard_layouts_koriolan/layouts/sr_SP/symbols.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/sv_SE/dialpad.fallback b/virtualkeyboard_layouts_koriolan/layouts/sv_SE/dialpad.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/sv_SE/digits.fallback b/virtualkeyboard_layouts_koriolan/layouts/sv_SE/digits.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/sv_SE/handwriting.fallback b/virtualkeyboard_layouts_koriolan/layouts/sv_SE/handwriting.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/sv_SE/main.qml b/virtualkeyboard_layouts_koriolan/layouts/sv_SE/main.qml new file mode 100755 index 0000000..a3a8a86 --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/sv_SE/main.qml @@ -0,0 +1,209 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.VirtualKeyboard 2.1 + +KeyboardLayout { + inputMode: InputEngine.InputMode.Latin + keyWeight: 160 + KeyboardRow { + Key { + key: Qt.Key_Q + text: "q" + } + Key { + key: Qt.Key_W + text: "w" + } + Key { + key: Qt.Key_E + text: "e" + } + Key { + key: Qt.Key_R + text: "r" + } + Key { + key: Qt.Key_T + text: "t" + } + Key { + key: Qt.Key_Y + text: "y" + } + Key { + key: Qt.Key_U + text: "u" + } + Key { + key: Qt.Key_I + text: "i" + } + Key { + key: Qt.Key_O + text: "o" + } + Key { + key: Qt.Key_P + text: "p" + } + Key { + key: Qt.Key_Aring + text: "å" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 66 + } + Key { + key: Qt.Key_A + text: "a" + } + Key { + key: Qt.Key_S + text: "s" + } + Key { + key: Qt.Key_D + text: "d" + } + Key { + key: Qt.Key_F + text: "f" + } + Key { + key: Qt.Key_G + text: "g" + } + Key { + key: Qt.Key_H + text: "h" + } + Key { + key: Qt.Key_J + text: "j" + } + Key { + key: Qt.Key_K + text: "k" + } + Key { + key: Qt.Key_L + text: "l" + } + Key { + key: Qt.Key_Odiaeresis + text: "ö" + } + Key { + key: Qt.Key_Adiaeresis + text: "ä" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + ShiftKey { } + Key { + key: Qt.Key_Z + text: "z" + } + Key { + key: Qt.Key_X + text: "x" + } + Key { + key: Qt.Key_C + text: "c" + } + Key { + key: Qt.Key_V + text: "v" + } + Key { + key: Qt.Key_B + text: "b" + } + Key { + key: Qt.Key_N + text: "n" + } + Key { + key: Qt.Key_M + text: "m" + } + Key { + key: Qt.Key_Comma + text: "," + } + Key { + key: Qt.Key_Period + text: "." + } + Key { + key: Qt.Key_Minus + text: "-" + } + ShiftKey { + weight: 264 + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Apostrophe + text: "'" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/sv_SE/numbers.fallback b/virtualkeyboard_layouts_koriolan/layouts/sv_SE/numbers.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/sv_SE/symbols.fallback b/virtualkeyboard_layouts_koriolan/layouts/sv_SE/symbols.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/th_TH/dialpad.fallback b/virtualkeyboard_layouts_koriolan/layouts/th_TH/dialpad.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/th_TH/digits.fallback b/virtualkeyboard_layouts_koriolan/layouts/th_TH/digits.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/th_TH/handwriting.fallback b/virtualkeyboard_layouts_koriolan/layouts/th_TH/handwriting.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/th_TH/handwriting.qml b/virtualkeyboard_layouts_koriolan/layouts/th_TH/handwriting.qml new file mode 100755 index 0000000..428f29f --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/th_TH/handwriting.qml @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Layouts 1.0 +import QtQuick.VirtualKeyboard 2.3 + +KeyboardLayout { + function createInputMethod() { + return Qt.createQmlObject('import QtQuick 2.0; import QtQuick.VirtualKeyboard.Plugins 2.3; HandwritingInputMethod {}', parent) + } + sharedLayouts: ['symbols'] + + KeyboardRow { + Layout.preferredHeight: 3 + KeyboardColumn { + Layout.preferredWidth: bottomRow.width - hideKeyboardKey.width + KeyboardRow { + TraceInputKey { + objectName: "hwrInputArea" + patternRecognitionMode: InputEngine.PatternRecognitionMode.Handwriting + horizontalRulers: + InputContext.inputEngine.inputMode !== InputEngine.InputMode.Thai ? [] : + [Math.round(boundingBox.height / 4), Math.round(boundingBox.height / 4) * 3] + } + } + } + KeyboardColumn { + Layout.preferredWidth: hideKeyboardKey.width + KeyboardRow { + BackspaceKey {} + } + KeyboardRow { + EnterKey {} + } + KeyboardRow { + ShiftKey { } + } + } + } + KeyboardRow { + id: bottomRow + Layout.preferredHeight: 1 + keyWeight: 154 + InputModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + customLayoutsOnly: true + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_QuoteDbl + text: "\"" + alternativeKeys: "<>()#%&*/\\\"'=+-_" + } + Key { + key: Qt.Key_Period + text: "." + alternativeKeys: ":;,.?!" + } + HideKeyboardKey { + id: hideKeyboardKey + weight: 204 + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/th_TH/main.qml b/virtualkeyboard_layouts_koriolan/layouts/th_TH/main.qml new file mode 100755 index 0000000..60a8ebc --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/th_TH/main.qml @@ -0,0 +1,489 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Layouts 1.0 +import QtQuick.VirtualKeyboard 2.3 + +KeyboardLayoutLoader { + inputMode: InputEngine.InputMode.Latin + function createInputMethod() { + return Qt.createQmlObject('import QtQuick 2.0; import QtQuick.VirtualKeyboard.Plugins 2.3; ThaiInputMethod {}', parent, "thaiInputMethod") + } + sharedLayouts: [ "symbols" ] + sourceComponent: InputContext.shiftActive ? page2 : page1 + Component { + id: page1 + KeyboardLayout { + keyWeight: 160 + KeyboardRow { + Layout.preferredHeight: 3 + smallTextVisible: true + KeyboardColumn { + Layout.preferredWidth: bottomRow.width - hideKeyboardKey.width + KeyboardRow { + Key { + text: "ๆ" + alternativeKeys: "ๆ๑" + } + Key { + text: "ๅ" + alternativeKeys: "ๅ๒" + } + Key { + text: "ภ" + alternativeKeys: "ภ๓" + } + Key { + text: "ถ" + alternativeKeys: "ถ๔" + } + Key { + text: "\u0E38" + displayText: " \u0E38" + alternativeKeys: [ "\u0E38", " \u0E39" ] + } + Key { + text: "\u0E36" + displayText: " \u0E36" + } + Key { + text: "ค" + alternativeKeys: "ค๕" + } + Key { + text: "ต" + alternativeKeys: "ต๖" + } + Key { + text: "จ" + alternativeKeys: "จ๗" + } + Key { + text: "ข" + alternativeKeys: "ข๘" + } + Key { + text: "ช" + alternativeKeys: "ช๙" + } + } + KeyboardRow { + Key { + text: "ไ" + alternativeKeys: "ไ฿" + } + Key { + text: " ำ" + alternativeKeys: " ำฎ" + } + Key { + text: "พ" + alternativeKeys: "พฑ" + } + Key { + text: "ะ" + alternativeKeys: "ะธ" + } + Key { + text: "\u0E31" + displayText: " \u0E31" + alternativeKeys: "\u0E31。" + } + Key { + text: "\u0E35" + displayText: " \u0E35" + alternativeKeys: [ "\u0E35", " \u0E4A" ] + } + Key { + text: "ร" + alternativeKeys: "รณ" + } + Key { + text: "น" + alternativeKeys: "นฯ" + } + Key { + text: "ย" + alternativeKeys: "ยญ" + } + Key { + text: "บ" + alternativeKeys: "บฐ" + } + Key { + text: "ล" + } + } + KeyboardRow { + Key { + text: "ฟ" + alternativeKeys: "ฟฤ" + } + Key { + text: "ห" + alternativeKeys: "หฆ" + } + Key { + text: "ก" + alternativeKeys: "กฏ" + } + Key { + text: "ด" + alternativeKeys: "ดโ" + } + Key { + text: "เ" + alternativeKeys: "เฌ" + } + Key { + text: "\u0E49" + displayText: " \u0E49" + alternativeKeys: [ "\u0E49", " \u0E47" ] + } + Key { + text: "\u0E48" + displayText: " \u0E48" + alternativeKeys: [ "\u0E48", " \u0E4B" ] + } + Key { + text: "า" + alternativeKeys: "าษ" + } + Key { + text: "ส" + alternativeKeys: "สศ" + } + Key { + text: "ว" + alternativeKeys: "วซ" + } + Key { + text: "ง" + } + } + KeyboardRow { + FillerKey { + weight: 80 + } + Key { + text: "ผ" + } + Key { + text: "ป" + } + Key { + text: "แ" + alternativeKeys: "แฉ" + } + Key { + text: "อ" + alternativeKeys: "อฮ" + } + Key { + text: "\u0E34" + displayText: " \u0E34" + alternativeKeys: [ "\u0E34", " \u0E3A" ] + } + Key { + text: "\u0E37" + displayText: " \u0E37" + alternativeKeys: [ "\u0E37", " \u0E4C" ] + } + Key { + text: "ท" + } + Key { + text: "ม" + alternativeKeys: "มฒ" + } + Key { + text: "ใ" + alternativeKeys: "ใฬ" + } + Key { + text: "ฝ" + alternativeKeys: "ฝฦ" + } + FillerKey { + weight: 80 + } + } + } + KeyboardColumn { + Layout.preferredWidth: hideKeyboardKey.width + KeyboardRow { + BackspaceKey {} + } + KeyboardRow { + EnterKey {} + } + KeyboardRow { + ShiftKey { } + } + } + } + KeyboardRow { + id: bottomRow + keyWeight: 154 + SymbolModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Period + text: "." + alternativeKeys: "!?.," + smallTextVisible: true + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + id: hideKeyboardKey + weight: 204 + } + } + } + } + Component { + id: page2 + KeyboardLayout { + keyWeight: 160 + KeyboardRow { + Layout.preferredHeight: 3 + smallTextVisible: true + KeyboardColumn { + Layout.preferredWidth: bottomRow.width - hideKeyboardKey.width + KeyboardRow { + Key { + text: "๑" + } + Key { + text: "๒" + } + Key { + text: "๓" + } + Key { + text: "๔" + } + Key { + text: "\u0E39" + displayText: " \u0E39" + } + Key { + enabled: false + } + Key { + text: "๕" + } + Key { + text: "๖" + } + Key { + text: "๗" + } + Key { + text: "๘" + } + Key { + text: "๙" + } + } + KeyboardRow { + Key { + text: "฿" + } + Key { + text: "ฎ" + } + Key { + text: "ฑ" + } + Key { + text: "ธ" + } + Key { + text: "。" + } + Key { + text: "\u0E4A" + displayText: " \u0E4A" + } + Key { + text: "ณ" + } + Key { + text: "ฯ" + } + Key { + text: "ญ" + } + Key { + text: "ฐ" + } + Key { + enabled: false + } + } + KeyboardRow { + Key { + text: "ฤ" + } + Key { + text: "ฆ" + } + Key { + text: "ฏ" + } + Key { + text: "โ" + } + Key { + text: "ฌ" + } + Key { + text: "\u0E47" + displayText: " \u0E47" + } + Key { + text: "\u0E4B" + displayText: " \u0E4B" + } + Key { + text: "ษ" + } + Key { + text: "ศ" + } + Key { + text: "ซ" + } + Key { + enabled: false + } + } + KeyboardRow { + FillerKey { + weight: 80 + } + Key { + enabled: false + } + Key { + enabled: false + } + Key { + text: "ฉ" + } + Key { + text: "ฮ" + } + Key { + text: "\u0E3A" + displayText: " \u0E3A" + } + Key { + text: "\u0E4C" + displayText: " \u0E4C" + } + Key { + enabled: false + } + Key { + text: "ฒ" + } + Key { + text: "ฬ" + } + Key { + text: "ฦ" + } + FillerKey { + weight: 80 + } + } + } + KeyboardColumn { + Layout.preferredWidth: hideKeyboardKey.width + KeyboardRow { + BackspaceKey {} + } + KeyboardRow { + EnterKey {} + } + KeyboardRow { + ShiftKey { } + } + } + } + KeyboardRow { + id: bottomRow + keyWeight: 154 + SymbolModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Comma + text: "," + alternativeKeys: "!?," + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + id: hideKeyboardKey + weight: 204 + } + } + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/th_TH/numbers.fallback b/virtualkeyboard_layouts_koriolan/layouts/th_TH/numbers.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/th_TH/symbols.qml b/virtualkeyboard_layouts_koriolan/layouts/th_TH/symbols.qml new file mode 100755 index 0000000..53fdcd6 --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/th_TH/symbols.qml @@ -0,0 +1,376 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Layouts 1.0 +import QtQuick.VirtualKeyboard 2.1 + +KeyboardLayoutLoader { + property bool secondPage + onVisibleChanged: if (!visible) secondPage = false + sourceComponent: secondPage ? page2 : page1 + Component { + id: page1 + KeyboardLayout { + keyWeight: 160 + KeyboardRow { + Key { + key: Qt.Key_1 + text: "1" + } + Key { + key: Qt.Key_2 + text: "2" + } + Key { + key: Qt.Key_3 + text: "3" + } + Key { + key: Qt.Key_4 + text: "4" + } + Key { + key: Qt.Key_5 + text: "5" + } + Key { + key: Qt.Key_6 + text: "6" + } + Key { + key: Qt.Key_7 + text: "7" + } + Key { + key: Qt.Key_8 + text: "8" + } + Key { + key: Qt.Key_9 + text: "9" + } + Key { + key: Qt.Key_0 + text: "0" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Key { + key: Qt.Key_At + text: "@" + } + Key { + key: Qt.Key_NumberSign + text: "#" + } + Key { + key: Qt.Key_Percent + text: "%" + } + Key { + key: Qt.Key_Ampersand + text: "&" + } + Key { + key: Qt.Key_Asterisk + text: "*" + } + Key { + key: Qt.Key_Minus + text: "-" + } + Key { + key: Qt.Key_Plus + text: "+" + } + Key { + key: Qt.Key_ParenLeft + text: "(" + } + Key { + key: Qt.Key_ParenRight + text: ")" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + Key { + displayText: "1/2" + functionKey: true + onClicked: secondPage = !secondPage + } + Key { + key: Qt.Key_Exclam + text: "!" + } + Key { + key: Qt.Key_QuoteDbl + text: '"' + } + Key { + key: Qt.Key_Less + text: "<" + } + Key { + key: Qt.Key_Greater + text: ">" + } + Key { + key: Qt.Key_Apostrophe + text: "'" + } + Key { + key: Qt.Key_Colon + text: ":" + } + Key { + key: Qt.Key_Semicolon + text: ";" + } + Key { + key: Qt.Key_Slash + text: "/" + } + Key { + key: Qt.Key_Question + text: "?" + } + Key { + weight: 204 + displayText: "1/2" + functionKey: true + onClicked: secondPage = !secondPage + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + displayText: "กขค" + } + ChangeLanguageKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Period + text: "." + alternativeKeys: "!?.," + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } + } + } + Component { + id: page2 + KeyboardLayout { + keyWeight: 160 + KeyboardRow { + Key { + key: Qt.Key_AsciiTilde + text: "~" + } + Key { + key: Qt.Key_Agrave + text: "`" + } + Key { + key: Qt.Key_Bar + text: "|" + } + Key { + key: 0x7B + text: "·" + } + Key { + key: 0x221A + text: "√" + } + Key { + key: Qt.Key_division + text: "÷" + } + Key { + key: Qt.Key_multiply + text: "×" + } + Key { + key: Qt.Key_onehalf + text: "½" + alternativeKeys: "¼⅓½¾⅞" + } + Key { + key: Qt.Key_BraceLeft + text: "{" + } + Key { + key: Qt.Key_BraceRight + text: "}" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Key { + key: Qt.Key_Dollar + text: "$" + } + Key { + key: 0x20AC + text: "€" + } + Key { + key: 0xC2 + text: "£" + } + Key { + key: 0xA2 + text: "¢" + } + Key { + key: 0xA5 + text: "¥" + } + Key { + key: Qt.Key_Equal + text: "=" + } + Key { + key: Qt.Key_section + text: "§" + } + Key { + key: Qt.Key_BracketLeft + text: "[" + } + Key { + key: Qt.Key_BracketRight + text: "]" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + Key { + displayText: "2/2" + functionKey: true + onClicked: secondPage = !secondPage + } + Key { + key: Qt.Key_Underscore + text: "_" + } + Key { + key: 0x2122 + text: '™' + } + Key { + key: 0x00AE + text: '®' + } + Key { + key: Qt.Key_guillemotleft + text: '«' + } + Key { + key: Qt.Key_guillemotright + text: '»' + } + Key { + key: 0x201C + text: '“' + } + Key { + key: 0x201D + text: '”' + } + Key { + key: Qt.Key_Backslash + text: "\\" + } + Key { + key: Qt.Key_AsciiCircum + text: "^" + } + Key { + weight: 204 + displayText: "2/2" + functionKey: true + onClicked: secondPage = !secondPage + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + displayText: "กขค" + } + ChangeLanguageKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: 0x2026 + text: "\u2026" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/tr_TR/dialpad.fallback b/virtualkeyboard_layouts_koriolan/layouts/tr_TR/dialpad.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/tr_TR/digits.fallback b/virtualkeyboard_layouts_koriolan/layouts/tr_TR/digits.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/tr_TR/handwriting.fallback b/virtualkeyboard_layouts_koriolan/layouts/tr_TR/handwriting.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/tr_TR/main.qml b/virtualkeyboard_layouts_koriolan/layouts/tr_TR/main.qml new file mode 100755 index 0000000..31bf0dc --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/tr_TR/main.qml @@ -0,0 +1,221 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.VirtualKeyboard 2.3 + +KeyboardLayout { + inputMode: InputEngine.InputMode.Latin + keyWeight: 160 + KeyboardRow { + Key { + key: Qt.Key_Q + text: "q" + } + Key { + key: Qt.Key_W + text: "w" + } + Key { + key: Qt.Key_E + text: "e" + } + Key { + key: Qt.Key_R + text: "r" + } + Key { + key: Qt.Key_T + text: "t" + } + Key { + key: Qt.Key_Y + text: "y" + } + Key { + key: Qt.Key_U + text: "u" + } + Key { + text: "\u0131" + } + Key { + key: Qt.Key_O + text: "o" + } + Key { + key: Qt.Key_P + text: "p" + } + Key { + text: "\u011F" + } + Key { + key: Qt.Key_Udiaeresis + text: "ü" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 66 + } + Key { + key: Qt.Key_A + text: "a" + alternativeKeys: "aåä" + } + Key { + key: Qt.Key_S + text: "s" + alternativeKeys: "sš" + } + Key { + key: Qt.Key_D + text: "d" + } + Key { + key: Qt.Key_F + text: "f" + } + Key { + key: Qt.Key_G + text: "g" + } + Key { + key: Qt.Key_H + text: "h" + } + Key { + key: Qt.Key_J + text: "j" + } + Key { + key: Qt.Key_K + text: "k" + } + Key { + key: Qt.Key_L + text: "l" + } + Key { + text: "ş" + } + Key { + key: Qt.Key_I + text: "i" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + ShiftKey { } + Key { + key: Qt.Key_Z + text: "z" + alternativeKeys: "zž" + } + Key { + key: Qt.Key_X + text: "x" + alternativeKeys: "$¢x₺€¥£" + smallTextVisible: true + } + Key { + key: Qt.Key_C + text: "c" + } + Key { + key: Qt.Key_V + text: "v" + } + Key { + key: Qt.Key_B + text: "b" + } + Key { + key: Qt.Key_N + text: "n" + } + Key { + key: Qt.Key_M + text: "m" + } + Key { + key: Qt.Key_Odiaeresis + text: "ö" + } + Key { + key: Qt.Key_Ccedilla + text: "ç" + } + Key { + key: Qt.Key_Comma + text: "," + } + Key { + key: Qt.Key_Period + text: "." + alternativeKeys: "!?." + smallTextVisible: true + } + ShiftKey { + weight: 264 + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Apostrophe + text: "'" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/tr_TR/numbers.fallback b/virtualkeyboard_layouts_koriolan/layouts/tr_TR/numbers.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/tr_TR/symbols.fallback b/virtualkeyboard_layouts_koriolan/layouts/tr_TR/symbols.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/uk_UA/dialpad.fallback b/virtualkeyboard_layouts_koriolan/layouts/uk_UA/dialpad.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/uk_UA/digits.fallback b/virtualkeyboard_layouts_koriolan/layouts/uk_UA/digits.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/uk_UA/handwriting.fallback b/virtualkeyboard_layouts_koriolan/layouts/uk_UA/handwriting.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/uk_UA/main.qml b/virtualkeyboard_layouts_koriolan/layouts/uk_UA/main.qml new file mode 100755 index 0000000..c273145 --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/uk_UA/main.qml @@ -0,0 +1,373 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.VirtualKeyboard 2.3 + +KeyboardLayoutLoader { + sharedLayouts: ['symbols'] + sourceComponent: InputContext.inputEngine.inputMode === InputEngine.InputMode.Cyrillic ? cyrillicLayout : latinLayout + Component { + id: cyrillicLayout + KeyboardLayout { + keyWeight: 160 + KeyboardRow { + Key { + text: "й" + } + Key { + text: "ц" + } + Key { + text: "у" + } + Key { + text: "к" + } + Key { + text: "е" + } + Key { + text: "н" + } + Key { + text: "г" + } + Key { + text: "ш" + } + Key { + text: "щ" + } + Key { + text: "з" + } + Key { + text: "х" + } + Key { + text: "ї" + } + BackspaceKey { + weight: 180 + } + } + KeyboardRow { + FillerKey { + weight: 40 + } + Key { + text: "ф" + } + Key { + text: "і" + } + Key { + text: "в" + } + Key { + text: "а" + } + Key { + text: "п" + } + Key { + text: "р" + } + Key { + text: "о" + } + Key { + text: "л" + } + Key { + text: "д" + } + Key { + text: "ж" + } + Key { + text: "є" + } + EnterKey { + weight: 280 + } + } + KeyboardRow { + InputModeKey { + inputModes: [InputEngine.InputMode.Cyrillic, InputEngine.InputMode.Latin] + } + Key { + text: "ґ" + } + Key { + text: "я" + alternativeKeys: "$¢я₴€¥£" + smallTextVisible: true + } + Key { + text: "ч" + } + Key { + text: "с" + } + Key { + text: "м" + } + Key { + text: "и" + } + Key { + text: "т" + } + Key { + text: "ь" + } + Key { + text: "б" + } + Key { + text: "ю" + } + Key { + key: Qt.Key_Apostrophe + text: "'" + } + ShiftKey { + weight: 272 + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Period + text: "." + alternativeKeys: ";:!?.," + smallTextVisible: true + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } + } + } + Component { + id: latinLayout + KeyboardLayout { + keyWeight: 160 + KeyboardRow { + Key { + key: Qt.Key_Q + text: "q" + } + Key { + key: Qt.Key_W + text: "w" + } + Key { + key: Qt.Key_E + text: "e" + } + Key { + key: Qt.Key_R + text: "r" + } + Key { + key: Qt.Key_T + text: "t" + } + Key { + key: Qt.Key_Y + text: "y" + } + Key { + key: Qt.Key_U + text: "u" + } + Key { + key: Qt.Key_I + text: "i" + } + Key { + key: Qt.Key_O + text: "o" + alternativeKeys: "oö" + } + Key { + key: Qt.Key_P + text: "p" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Key { + key: Qt.Key_A + text: "a" + alternativeKeys: "aåä" + } + Key { + key: Qt.Key_S + text: "s" + alternativeKeys: "sš" + } + Key { + key: Qt.Key_D + text: "d" + alternativeKeys: "dđ" + } + Key { + key: Qt.Key_F + text: "f" + } + Key { + key: Qt.Key_G + text: "g" + } + Key { + key: Qt.Key_H + text: "h" + } + Key { + key: Qt.Key_J + text: "j" + } + Key { + key: Qt.Key_K + text: "k" + } + Key { + key: Qt.Key_L + text: "l" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + InputModeKey { + inputModes: [InputEngine.InputMode.Cyrillic, InputEngine.InputMode.Latin] + } + Key { + key: Qt.Key_Z + text: "z" + alternativeKeys: "zž" + } + Key { + key: Qt.Key_X + text: "x" + alternativeKeys: "$¢x₴€¥£" + smallTextVisible: true + } + Key { + key: Qt.Key_C + text: "c" + alternativeKeys: "ćcč" + } + Key { + key: Qt.Key_V + text: "v" + } + Key { + key: Qt.Key_B + text: "b" + } + Key { + key: Qt.Key_N + text: "n" + } + Key { + key: Qt.Key_M + text: "m" + } + Key { + key: Qt.Key_Minus + text: "-" + alternativeKeys: "-\"'" + } + Key { + key: Qt.Key_Apostrophe + text: "'" + } + ShiftKey { + weight: 204 + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Period + text: "." + alternativeKeys: ";:!?.," + smallTextVisible: true + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/uk_UA/numbers.fallback b/virtualkeyboard_layouts_koriolan/layouts/uk_UA/numbers.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/uk_UA/symbols.fallback b/virtualkeyboard_layouts_koriolan/layouts/uk_UA/symbols.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/vi_VN/dialpad.fallback b/virtualkeyboard_layouts_koriolan/layouts/vi_VN/dialpad.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/vi_VN/digits.fallback b/virtualkeyboard_layouts_koriolan/layouts/vi_VN/digits.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/vi_VN/handwriting.fallback b/virtualkeyboard_layouts_koriolan/layouts/vi_VN/handwriting.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/vi_VN/main.qml b/virtualkeyboard_layouts_koriolan/layouts/vi_VN/main.qml new file mode 100755 index 0000000..9a5c7e3 --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/vi_VN/main.qml @@ -0,0 +1,205 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.VirtualKeyboard 2.3 + +KeyboardLayout { + inputMode: InputEngine.InputMode.Latin + sharedLayouts: ["numbers", "digits"] + keyWeight: 160 + KeyboardRow { + Key { + key: Qt.Key_Q + text: "q" + } + Key { + key: Qt.Key_W + text: "w" + } + Key { + key: Qt.Key_E + text: "e" + alternativeKeys: "eèéẻẽẹêềếểễệ" + } + Key { + key: Qt.Key_R + text: "r" + } + Key { + key: Qt.Key_T + text: "t" + } + Key { + key: Qt.Key_Y + text: "y" + alternativeKeys: "yỳýỷỹỵ" + } + Key { + key: Qt.Key_U + text: "u" + alternativeKeys: "ưừứửữựuùúủũụ" + } + Key { + key: Qt.Key_I + text: "i" + alternativeKeys: "iìíỉĩị" + } + Key { + key: Qt.Key_O + text: "o" + alternativeKeys: "ơờớởỡợòóỏõọoôồốổỗộ" + } + Key { + key: Qt.Key_P + text: "p" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Key { + key: Qt.Key_A + text: "a" + alternativeKeys: "aàáảãạăằắẳẵặâầấẩẫậ" + } + Key { + key: Qt.Key_S + text: "s" + alternativeKeys: "sš" + } + Key { + key: Qt.Key_D + text: "d" + alternativeKeys: "dđ" + } + Key { + key: Qt.Key_F + text: "f" + } + Key { + key: Qt.Key_G + text: "g" + } + Key { + key: Qt.Key_H + text: "h" + } + Key { + key: Qt.Key_J + text: "j" + } + Key { + key: Qt.Key_K + text: "k" + } + Key { + key: Qt.Key_L + text: "l" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + ShiftKey {} + Key { + key: Qt.Key_Z + text: "z" + alternativeKeys: "zž" + } + Key { + key: Qt.Key_X + text: "x" + } + Key { + key: Qt.Key_C + text: "c" + } + Key { + key: Qt.Key_V + text: "v" + } + Key { + key: Qt.Key_B + text: "b" + } + Key { + key: Qt.Key_N + text: "n" + alternativeKeys: "nñ" + } + Key { + key: Qt.Key_M + text: "m" + } + Key { + key: Qt.Key_Comma + text: "," + } + Key { + key: Qt.Key_Period + text: "." + alternativeKeys: "!,.?" + } + ShiftKey { + weight: 204 + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Apostrophe + text: "'" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/vi_VN/numbers.fallback b/virtualkeyboard_layouts_koriolan/layouts/vi_VN/numbers.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/vi_VN/symbols.qml b/virtualkeyboard_layouts_koriolan/layouts/vi_VN/symbols.qml new file mode 100755 index 0000000..da5281b --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/vi_VN/symbols.qml @@ -0,0 +1,376 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Layouts 1.0 +import QtQuick.VirtualKeyboard 2.3 + +KeyboardLayoutLoader { + property bool secondPage + onVisibleChanged: if (!visible) secondPage = false + sourceComponent: secondPage ? page2 : page1 + Component { + id: page1 + KeyboardLayout { + keyWeight: 160 + KeyboardRow { + Key { + key: Qt.Key_1 + text: "1" + } + Key { + key: Qt.Key_2 + text: "2" + } + Key { + key: Qt.Key_3 + text: "3" + } + Key { + key: Qt.Key_4 + text: "4" + } + Key { + key: Qt.Key_5 + text: "5" + } + Key { + key: Qt.Key_6 + text: "6" + } + Key { + key: Qt.Key_7 + text: "7" + } + Key { + key: Qt.Key_8 + text: "8" + } + Key { + key: Qt.Key_9 + text: "9" + } + Key { + key: Qt.Key_0 + text: "0" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Key { + key: Qt.Key_At + text: "@" + } + Key { + key: Qt.Key_NumberSign + text: "#" + } + Key { + key: Qt.Key_Percent + text: "%" + } + Key { + key: Qt.Key_Ampersand + text: "&" + } + Key { + key: Qt.Key_Asterisk + text: "*" + } + Key { + key: Qt.Key_Minus + text: "-" + } + Key { + key: Qt.Key_Plus + text: "+" + } + Key { + key: Qt.Key_ParenLeft + text: "(" + } + Key { + key: Qt.Key_ParenRight + text: ")" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + Key { + displayText: "1/2" + functionKey: true + onClicked: secondPage = !secondPage + } + Key { + key: Qt.Key_Exclam + text: "!" + } + Key { + key: Qt.Key_QuoteDbl + text: '"' + } + Key { + key: Qt.Key_Less + text: "<" + } + Key { + key: Qt.Key_Greater + text: ">" + } + Key { + key: Qt.Key_Apostrophe + text: "'" + } + Key { + key: Qt.Key_Colon + text: ":" + } + Key { + key: Qt.Key_Semicolon + text: ";" + } + Key { + key: Qt.Key_Slash + text: "/" + } + Key { + key: Qt.Key_Question + text: "?" + } + Key { + weight: 204 + displayText: "1/2" + functionKey: true + onClicked: secondPage = !secondPage + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + displayText: "ABC" + } + ChangeLanguageKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Period + text: "." + alternativeKeys: ".," + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } + } + } + Component { + id: page2 + KeyboardLayout { + keyWeight: 160 + KeyboardRow { + Key { + key: Qt.Key_AsciiTilde + text: "~" + } + Key { + key: Qt.Key_Agrave + text: "`" + } + Key { + key: Qt.Key_Bar + text: "|" + } + Key { + key: 0x7B + text: "·" + } + Key { + key: 0x221A + text: "√" + } + Key { + key: Qt.Key_division + text: "÷" + } + Key { + key: Qt.Key_multiply + text: "×" + } + Key { + key: Qt.Key_onehalf + text: "½" + alternativeKeys: "¼⅓½¾⅞" + } + Key { + key: Qt.Key_BraceLeft + text: "{" + } + Key { + key: Qt.Key_BraceRight + text: "}" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Key { + key: Qt.Key_Dollar + text: "$" + } + Key { + key: 0x20AC + text: "€" + } + Key { + key: 0xC2 + text: "£" + } + Key { + key: 0xA2 + text: "¢" + } + Key { + key: 0x20AB + text: "₫" + } + Key { + key: Qt.Key_Equal + text: "=" + } + Key { + key: Qt.Key_section + text: "§" + } + Key { + key: Qt.Key_BracketLeft + text: "[" + } + Key { + key: Qt.Key_BracketRight + text: "]" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + Key { + displayText: "2/2" + functionKey: true + onClicked: secondPage = !secondPage + } + Key { + key: Qt.Key_Underscore + text: "_" + } + Key { + key: 0x2122 + text: '™' + } + Key { + key: 0x00AE + text: '®' + } + Key { + key: Qt.Key_guillemotleft + text: '«' + } + Key { + key: Qt.Key_guillemotright + text: '»' + } + Key { + key: 0x201C + text: '“' + } + Key { + key: 0x201D + text: '”' + } + Key { + key: Qt.Key_Backslash + text: "\\" + } + Key { + key: Qt.Key_AsciiCircum + text: "^" + } + Key { + weight: 204 + displayText: "2/2" + functionKey: true + onClicked: secondPage = !secondPage + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + displayText: "ABC" + } + ChangeLanguageKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: 0x2026 + text: "\u2026" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/zh_CN/dialpad.fallback b/virtualkeyboard_layouts_koriolan/layouts/zh_CN/dialpad.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/zh_CN/digits.fallback b/virtualkeyboard_layouts_koriolan/layouts/zh_CN/digits.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/zh_CN/handwriting.qml b/virtualkeyboard_layouts_koriolan/layouts/zh_CN/handwriting.qml new file mode 100755 index 0000000..fee0432 --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/zh_CN/handwriting.qml @@ -0,0 +1,116 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Layouts 1.0 +import QtQuick.VirtualKeyboard 2.3 + +KeyboardLayout { + function createInputMethod() { + return Qt.createQmlObject('import QtQuick 2.0; import QtQuick.VirtualKeyboard.Plugins 2.3; HandwritingInputMethod {}', parent) + } + sharedLayouts: ['symbols'] + inputMode: preferredInputMode() + + Connections { + target: InputContext + onInputMethodHintsChanged: { + var newInputMode = preferredInputMode() + if (InputContext.inputEngine.inputModes.indexOf(newInputMode) !== -1) + InputContext.inputEngine.inputMode = newInputMode + } + } + + function preferredInputMode() { + return InputContext.inputMethodHints & + (Qt.ImhPreferLatin | Qt.ImhEmailCharactersOnly | Qt.ImhUrlCharactersOnly | + Qt.ImhLatinOnly) ? InputEngine.InputMode.Latin : InputEngine.InputMode.ChineseHandwriting + } + + KeyboardRow { + Layout.preferredHeight: 3 + KeyboardColumn { + Layout.preferredWidth: bottomRow.width - hideKeyboardKey.width + KeyboardRow { + TraceInputKey { + objectName: "hwrInputArea" + patternRecognitionMode: InputEngine.PatternRecognitionMode.Handwriting + horizontalRulers: + InputContext.inputEngine.inputMode !== InputEngine.InputMode.ChineseHandwriting ? [] : + [Math.round(boundingBox.height / 4), Math.round(boundingBox.height / 4) * 2, Math.round(boundingBox.height / 4) * 3] + + } + } + } + KeyboardColumn { + Layout.preferredWidth: hideKeyboardKey.width + KeyboardRow { + BackspaceKey {} + } + KeyboardRow { + EnterKey {} + } + KeyboardRow { + ShiftKey { } + } + } + } + KeyboardRow { + id: bottomRow + Layout.preferredHeight: 1 + keyWeight: 154 + InputModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + customLayoutsOnly: true + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Apostrophe + text: "‘" + alternativeKeys: "《》〈〉•…々〆‘’“”「」¥" + } + Key { + key: Qt.Key_Period + text: "." + alternativeKeys: ":;,.、。?!" + } + HideKeyboardKey { + id: hideKeyboardKey + weight: 204 + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/zh_CN/main.qml b/virtualkeyboard_layouts_koriolan/layouts/zh_CN/main.qml new file mode 100755 index 0000000..349a14c --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/zh_CN/main.qml @@ -0,0 +1,204 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Layouts 1.0 +import QtQuick.VirtualKeyboard 2.1 + +KeyboardLayout { + function createInputMethod() { + return Qt.createQmlObject('import QtQuick 2.0; import QtQuick.VirtualKeyboard.Plugins 2.1; PinyinInputMethod {}', parent, "pinyinInputMethod") + } + sharedLayouts: ['symbols'] + keyWeight: 160 + KeyboardRow { + Key { + key: Qt.Key_Q + text: "q" + } + Key { + key: Qt.Key_W + text: "w" + } + Key { + key: Qt.Key_E + text: "e" + } + Key { + key: Qt.Key_R + text: "r" + } + Key { + key: Qt.Key_T + text: "t" + } + Key { + key: Qt.Key_Y + text: "y" + } + Key { + key: Qt.Key_U + text: "u" + } + Key { + key: Qt.Key_I + text: "i" + } + Key { + key: Qt.Key_O + text: "o" + } + Key { + key: Qt.Key_P + text: "p" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Key { + key: Qt.Key_A + text: "a" + } + Key { + key: Qt.Key_S + text: "s" + } + Key { + key: Qt.Key_D + text: "d" + } + Key { + key: Qt.Key_F + text: "f" + } + Key { + key: Qt.Key_G + text: "g" + } + Key { + key: Qt.Key_H + text: "h" + } + Key { + key: Qt.Key_J + text: "j" + } + Key { + key: Qt.Key_K + text: "k" + } + Key { + key: Qt.Key_L + text: "l" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + Key { + enabled: InputContext.preeditText.length > 0 + key: Qt.Key_Apostrophe + text: "'" + } + Key { + key: Qt.Key_Z + text: "z" + } + Key { + key: Qt.Key_X + text: "x" + } + Key { + key: Qt.Key_C + text: "c" + } + Key { + key: Qt.Key_V + text: "v" + } + Key { + key: Qt.Key_B + text: "b" + } + Key { + key: Qt.Key_N + text: "n" + } + Key { + key: Qt.Key_M + text: "m" + } + Key { + key: Qt.Key_Comma + text: "\uFF0C" + alternativeKeys: "\uFF0C\uFF1B\u3001" + } + Key { + key: Qt.Key_Period + text: "\uFF0E" + alternativeKeys: "\uFF0E\uFF1A\u3002" + } + ShiftKey { + weight: 204 + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Question + text: "?" + alternativeKeys: "?!" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/zh_CN/numbers.fallback b/virtualkeyboard_layouts_koriolan/layouts/zh_CN/numbers.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/zh_CN/symbols.qml b/virtualkeyboard_layouts_koriolan/layouts/zh_CN/symbols.qml new file mode 100755 index 0000000..4ad06ba --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/zh_CN/symbols.qml @@ -0,0 +1,294 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Layouts 1.0 +import QtQuick.VirtualKeyboard 2.1 + +KeyboardLayoutLoader { + function createInputMethod() { + return Qt.createQmlObject('import QtQuick 2.0; import QtQuick.VirtualKeyboard.Plugins 2.1; PinyinInputMethod {}', parent, "pinyinInputMethod") + } + sharedLayouts: ['main'] + property int page + readonly property int numPages: 3 + property var keysPage1: [ + "1234567890", + "@#$%^&*()", + "“”、=:;!?~" + ] + property var keysPage2: [ + "-+/\\|[]{}·", + "<>,.:;!?~", + "/\"'_§¥€£¢" + ] + property var keysPage3: [ + "()〔〕〈〉《》【】", + "→←↑↓↔■□●○", + "\『』「」★☆◆◇" + ] + sourceComponent: { + switch (page) { + case 2: return page3 + case 1: return page2 + default: return page1 + } + } + Component { + id: page1 + KeyboardLayout { + keyWeight: 160 + KeyboardRow { + Repeater { + model: keysPage1[0].length + Key { + key: keysPage1[0][index].charCodeAt(0) + text: keysPage1[0][index] + } + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Repeater { + model: keysPage1[1].length + Key { + key: keysPage1[1][index].charCodeAt(0) + text: keysPage1[1][index] + } + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + Key { + displayText: (page + 1) + "/" + numPages + functionKey: true + onClicked: page = (page + 1) % numPages + } + Repeater { + model: keysPage1[2].length + Key { + key: keysPage1[2][index].charCodeAt(0) + text: keysPage1[2][index] + } + } + Key { + weight: 204 + displayText: (page + 1) + "/" + numPages + functionKey: true + onClicked: page = (page + 1) % numPages + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + displayText: "ABC" + } + ChangeLanguageKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: 0x2014 + text: "—" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } + } + } + Component { + id: page2 + KeyboardLayout { + keyWeight: 160 + KeyboardRow { + Repeater { + model: keysPage2[0].length + Key { + key: keysPage2[0][index].charCodeAt(0) + text: keysPage2[0][index] + } + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Repeater { + model: keysPage2[1].length + Key { + key: keysPage2[1][index].charCodeAt(0) + text: keysPage2[1][index] + } + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + Key { + displayText: (page + 1) + "/" + numPages + functionKey: true + onClicked: page = (page + 1) % numPages + } + Repeater { + model: keysPage2[2].length + Key { + key: keysPage2[2][index].charCodeAt(0) + text: keysPage2[2][index] + } + } + Key { + weight: 204 + displayText: (page + 1) + "/" + numPages + functionKey: true + onClicked: page = (page + 1) % numPages + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + displayText: "ABC" + } + ChangeLanguageKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: 0x3002 + text: "。" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } + } + } + Component { + id: page3 + KeyboardLayout { + keyWeight: 160 + KeyboardRow { + Repeater { + model: keysPage3[0].length + Key { + key: keysPage3[0][index].charCodeAt(0) + text: keysPage3[0][index] + } + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Repeater { + model: keysPage3[1].length + Key { + key: keysPage3[1][index].charCodeAt(0) + text: keysPage3[1][index] + } + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + Key { + displayText: (page + 1) + "/" + numPages + functionKey: true + onClicked: page = (page + 1) % numPages + } + Repeater { + model: keysPage3[2].length + Key { + key: keysPage3[2][index].charCodeAt(0) + text: keysPage3[2][index] + } + } + Key { + weight: 204 + displayText: (page + 1) + "/" + numPages + functionKey: true + onClicked: page = (page + 1) % numPages + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + displayText: "ABC" + } + ChangeLanguageKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: 0x2026 + text: "…" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/zh_TW/dialpad.fallback b/virtualkeyboard_layouts_koriolan/layouts/zh_TW/dialpad.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/zh_TW/digits.fallback b/virtualkeyboard_layouts_koriolan/layouts/zh_TW/digits.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/zh_TW/handwriting.qml b/virtualkeyboard_layouts_koriolan/layouts/zh_TW/handwriting.qml new file mode 100755 index 0000000..fee0432 --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/zh_TW/handwriting.qml @@ -0,0 +1,116 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Layouts 1.0 +import QtQuick.VirtualKeyboard 2.3 + +KeyboardLayout { + function createInputMethod() { + return Qt.createQmlObject('import QtQuick 2.0; import QtQuick.VirtualKeyboard.Plugins 2.3; HandwritingInputMethod {}', parent) + } + sharedLayouts: ['symbols'] + inputMode: preferredInputMode() + + Connections { + target: InputContext + onInputMethodHintsChanged: { + var newInputMode = preferredInputMode() + if (InputContext.inputEngine.inputModes.indexOf(newInputMode) !== -1) + InputContext.inputEngine.inputMode = newInputMode + } + } + + function preferredInputMode() { + return InputContext.inputMethodHints & + (Qt.ImhPreferLatin | Qt.ImhEmailCharactersOnly | Qt.ImhUrlCharactersOnly | + Qt.ImhLatinOnly) ? InputEngine.InputMode.Latin : InputEngine.InputMode.ChineseHandwriting + } + + KeyboardRow { + Layout.preferredHeight: 3 + KeyboardColumn { + Layout.preferredWidth: bottomRow.width - hideKeyboardKey.width + KeyboardRow { + TraceInputKey { + objectName: "hwrInputArea" + patternRecognitionMode: InputEngine.PatternRecognitionMode.Handwriting + horizontalRulers: + InputContext.inputEngine.inputMode !== InputEngine.InputMode.ChineseHandwriting ? [] : + [Math.round(boundingBox.height / 4), Math.round(boundingBox.height / 4) * 2, Math.round(boundingBox.height / 4) * 3] + + } + } + } + KeyboardColumn { + Layout.preferredWidth: hideKeyboardKey.width + KeyboardRow { + BackspaceKey {} + } + KeyboardRow { + EnterKey {} + } + KeyboardRow { + ShiftKey { } + } + } + } + KeyboardRow { + id: bottomRow + Layout.preferredHeight: 1 + keyWeight: 154 + InputModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + customLayoutsOnly: true + } + HandwritingModeKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Apostrophe + text: "‘" + alternativeKeys: "《》〈〉•…々〆‘’“”「」¥" + } + Key { + key: Qt.Key_Period + text: "." + alternativeKeys: ":;,.、。?!" + } + HideKeyboardKey { + id: hideKeyboardKey + weight: 204 + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/zh_TW/main.qml b/virtualkeyboard_layouts_koriolan/layouts/zh_TW/main.qml new file mode 100755 index 0000000..bd9c145 --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/zh_TW/main.qml @@ -0,0 +1,458 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Layouts 1.0 +import QtQuick.VirtualKeyboard 2.3 + +KeyboardLayoutLoader { + function createInputMethod() { + return Qt.createQmlObject('import QtQuick 2.0; import QtQuick.VirtualKeyboard.Plugins 2.3; TCInputMethod {}', parent, "tcInputMethod") + } + sharedLayouts: ['symbols'] + sourceComponent: InputContext.inputEngine.inputMode === InputEngine.InputMode.Cangjie ? pageCangjie : pageZhuyin + Component { + id: pageCangjie + KeyboardLayout { + keyWeight: 160 + smallTextVisible: true + KeyboardRow { + Key { + text: "\u624B" + alternativeKeys: "\u624Bq" + } + Key { + text: "\u7530" + alternativeKeys: "\u7530w" + } + Key { + text: "\u6C34" + alternativeKeys: "\u6C34e" + } + Key { + text: "\u53E3" + alternativeKeys: "\u53E3r" + } + Key { + text: "\u5EFF" + alternativeKeys: "\u5EFFt" + } + Key { + text: "\u535C" + alternativeKeys: "\u535Cy" + } + Key { + text: "\u5C71" + alternativeKeys: "\u5C71u" + } + Key { + text: "\u6208" + alternativeKeys: "\u6208i" + } + Key { + text: "\u4EBA" + alternativeKeys: "\u4EBAo" + } + Key { + text: "\u5FC3" + alternativeKeys: "\u5FC3p" + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Key { + text: "\u65E5" + alternativeKeys: "\u65E5a" + } + Key { + text: "\u5C38" + alternativeKeys: "\u5C38s" + } + Key { + text: "\u6728" + alternativeKeys: "\u6728d" + } + Key { + text: "\u706B" + alternativeKeys: "\u706Bf" + } + Key { + text: "\u571F" + alternativeKeys: "\u571Fg" + } + Key { + text: "\u7AF9" + alternativeKeys: "\u7AF9h" + } + Key { + text: "\u5341" + alternativeKeys: "\u5341j" + } + Key { + text: "\u5927" + alternativeKeys: "\u5927k" + } + Key { + text: "\u4E2D" + alternativeKeys: "\u4E2Dl" + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + ModeKey { + id: simplifiedModeKey + key: Qt.Key_Mode_switch + displayText: "速成" + Component.onCompleted: updateBinding() + Connections { + target: InputContext.inputEngine + onInputMethodChanged: simplifiedModeKey.updateBinding() + } + function updateBinding() { + if (InputContext.inputEngine.inputMethod && InputContext.inputEngine.inputMethod.hasOwnProperty("simplified")) { + simplifiedModeKey.mode = InputContext.inputEngine.inputMethod.simplified + InputContext.inputEngine.inputMethod.simplified = Qt.binding(function() { return simplifiedModeKey.mode }) + } + } + } + Key { + text: "\u91CD" + alternativeKeys: "\u91CDz" + } + Key { + text: "\u96E3" + alternativeKeys: "\u96E3x" + } + Key { + text: "\u91D1" + alternativeKeys: "\u91D1c" + } + Key { + text: "\u5973" + alternativeKeys: "\u5973v" + } + Key { + text: "\u6708" + alternativeKeys: "\u6708b" + } + Key { + text: "\u5F13" + alternativeKeys: "\u5F13n" + } + Key { + text: "\u4E00" + alternativeKeys: "\u4E00m" + } + Key { + key: Qt.Key_Comma + text: "\uFF0C" + alternativeKeys: "\uFF0C\uFF1B\u3001" + } + Key { + key: Qt.Key_Period + text: "\uFF0E" + alternativeKeys: "\uFF0E\uFF1A\u3002" + } + ShiftKey { + weight: 204 + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + } + HandwritingModeKey { + weight: 154 + } + InputModeKey { + visible: InputContext.inputEngine.inputModes.indexOf(InputEngine.InputMode.Zhuyin) !== -1 + } + SpaceKey { + weight: 864 + } + Key { + key: Qt.Key_Question + text: "\uFF1F" + alternativeKeys: "\uFF1F\uFF01" + } + Key { + key: 0xE000 + text: ":-)" + smallTextVisible: false + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } + } + } + Component { + id: pageZhuyin + KeyboardLayout { + smallTextVisible: true + KeyboardRow { + Layout.preferredHeight: 3 + KeyboardColumn { + Layout.preferredWidth: bottomRow.width - hideKeyboardKey.width + KeyboardRow { + Key { + text: "\u3105" + alternativeKeys: "\u31051" + } + Key { + text: "\u3109" + alternativeKeys: "\u31092" + } + Key { + text: "\u02C7" + alternativeKeys: "\u02C73" + } + Key { + text: "\u02CB" + alternativeKeys: "4" + displayText: "`" + } + Key { + text: "\u3113" + alternativeKeys: "\u31135" + } + Key { + text: "\u02CA" + alternativeKeys: "6" + displayText: "´" + } + Key { + text: "\u02D9" + alternativeKeys: "\u02D97" + } + Key { + text: "\u311A" + alternativeKeys: "\u311A8" + } + Key { + text: "\u311E" + alternativeKeys: "\u311E9" + } + Key { + text: "\u3122" + alternativeKeys: "\u31220" + } + } + KeyboardRow { + Key { + text: "\u3106" + alternativeKeys: "\u3106q" + } + Key { + text: "\u310A" + alternativeKeys: "\u310Aw" + } + Key { + text: "\u310D" + alternativeKeys: "\u310De" + } + Key { + text: "\u3110" + alternativeKeys: "\u3110r" + } + Key { + text: "\u3114" + alternativeKeys: "\u3114t" + } + Key { + text: "\u3117" + alternativeKeys: "\u3117y" + } + Key { + text: "\u3127" + alternativeKeys: "\u3127u" + } + Key { + text: "\u311B" + alternativeKeys: "\u311Bi" + } + Key { + text: "\u311F" + alternativeKeys: "\u311Fo" + } + Key { + text: "\u3123" + alternativeKeys: "\u3123p" + } + } + KeyboardRow { + Key { + text: "\u3107" + alternativeKeys: "\u3107a" + } + Key { + text: "\u310B" + alternativeKeys: "\u310Bs" + } + Key { + text: "\u310E" + alternativeKeys: "\u310Ed" + } + Key { + text: "\u3111" + alternativeKeys: "\u3111f" + } + Key { + text: "\u3115" + alternativeKeys: "\u3115g" + } + Key { + text: "\u3118" + alternativeKeys: "\u3118h" + } + Key { + text: "\u3128" + alternativeKeys: "\u3128j" + } + Key { + text: "\u311C" + alternativeKeys: "\u311Ck" + } + Key { + text: "\u3120" + alternativeKeys: "\u3120l" + } + Key { + text: "\u3124" + alternativeKeys: "\u3124…" + } + } + KeyboardRow { + Key { + text: "\u3108" + alternativeKeys: "\u3108z" + } + Key { + text: "\u310C" + alternativeKeys: "\u310Cx" + } + Key { + text: "\u310F" + alternativeKeys: "\u310Fc" + } + Key { + text: "\u3112" + alternativeKeys: "\u3112v" + } + Key { + text: "\u3116" + alternativeKeys: "\u3116b" + } + Key { + text: "\u3119" + alternativeKeys: "\u3119n" + } + Key { + text: "\u3129" + alternativeKeys: "\u3129m" + } + Key { + text: "\u311D" + alternativeKeys: "、\u311D," + } + Key { + text: "\u3121" + alternativeKeys: "。\u3121." + } + Key { + text: "\u3125" + alternativeKeys: ";\u3125:" + } + } + } + KeyboardColumn { + Layout.preferredWidth: hideKeyboardKey.width + KeyboardRow { + BackspaceKey {} + } + KeyboardRow { + EnterKey {} + } + KeyboardRow { + ShiftKey { } + } + } + } + KeyboardRow { + id: bottomRow + Layout.preferredHeight: 1 + keyWeight: 154 + SymbolModeKey { + weight: 217 + } + ChangeLanguageKey { + weight: 154 + } + HandwritingModeKey { + weight: 154 + } + InputModeKey { + visible: InputContext.inputEngine.inputModes.indexOf(InputEngine.InputMode.Cangjie) !== -1 + } + SpaceKey { + weight: 864 + } + Key { + text: "\u3126" + } + Key { + key: Qt.Key_Question + text: "\uFF1F" + alternativeKeys: "\uFF1F\uFF01" + } + Key { + key: 0xE000 + text: ":-)" + smallTextVisible: false + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + id: hideKeyboardKey + weight: 204 + } + } + } + } +} diff --git a/virtualkeyboard_layouts_koriolan/layouts/zh_TW/numbers.fallback b/virtualkeyboard_layouts_koriolan/layouts/zh_TW/numbers.fallback new file mode 100755 index 0000000..e69de29 diff --git a/virtualkeyboard_layouts_koriolan/layouts/zh_TW/symbols.qml b/virtualkeyboard_layouts_koriolan/layouts/zh_TW/symbols.qml new file mode 100755 index 0000000..3d43ae6 --- /dev/null +++ b/virtualkeyboard_layouts_koriolan/layouts/zh_TW/symbols.qml @@ -0,0 +1,294 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Virtual Keyboard module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Layouts 1.0 +import QtQuick.VirtualKeyboard 2.1 + +KeyboardLayoutLoader { + function createInputMethod() { + return Qt.createQmlObject('import QtQuick 2.0; import QtQuick.VirtualKeyboard.Plugins 2.1; TCInputMethod {}', parent, "tcInputMethod") + } + sharedLayouts: ['main'] + property int page + readonly property int numPages: 3 + property var keysPage1: [ + "1234567890", + "@#$%^&*()", + "“”、=:;!?~" + ] + property var keysPage2: [ + "-+/\\|[]{}·", + "<>,.:;!?~", + "/\"'_§¥€£¢" + ] + property var keysPage3: [ + "()〔〕〈〉《》【】", + "→←↑↓↔■□●○", + "\『』「」★☆◆◇" + ] + sourceComponent: { + switch (page) { + case 2: return page3 + case 1: return page2 + default: return page1 + } + } + Component { + id: page1 + KeyboardLayout { + keyWeight: 160 + KeyboardRow { + Repeater { + model: keysPage1[0].length + Key { + key: keysPage1[0][index].charCodeAt(0) + text: keysPage1[0][index] + } + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Repeater { + model: keysPage1[1].length + Key { + key: keysPage1[1][index].charCodeAt(0) + text: keysPage1[1][index] + } + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + Key { + displayText: (page + 1) + "/" + numPages + functionKey: true + onClicked: page = (page + 1) % numPages + } + Repeater { + model: keysPage1[2].length + Key { + key: keysPage1[2][index].charCodeAt(0) + text: keysPage1[2][index] + } + } + Key { + weight: 204 + displayText: (page + 1) + "/" + numPages + functionKey: true + onClicked: page = (page + 1) % numPages + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + displayText: "ABC" + } + ChangeLanguageKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: 0x2014 + text: "—" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } + } + } + Component { + id: page2 + KeyboardLayout { + keyWeight: 160 + KeyboardRow { + Repeater { + model: keysPage2[0].length + Key { + key: keysPage2[0][index].charCodeAt(0) + text: keysPage2[0][index] + } + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Repeater { + model: keysPage2[1].length + Key { + key: keysPage2[1][index].charCodeAt(0) + text: keysPage2[1][index] + } + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + Key { + displayText: (page + 1) + "/" + numPages + functionKey: true + onClicked: page = (page + 1) % numPages + } + Repeater { + model: keysPage2[2].length + Key { + key: keysPage2[2][index].charCodeAt(0) + text: keysPage2[2][index] + } + } + Key { + weight: 204 + displayText: (page + 1) + "/" + numPages + functionKey: true + onClicked: page = (page + 1) % numPages + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + displayText: "ABC" + } + ChangeLanguageKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: 0x3002 + text: "。" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } + } + } + Component { + id: page3 + KeyboardLayout { + keyWeight: 160 + KeyboardRow { + Repeater { + model: keysPage3[0].length + Key { + key: keysPage3[0][index].charCodeAt(0) + text: keysPage3[0][index] + } + } + BackspaceKey {} + } + KeyboardRow { + FillerKey { + weight: 56 + } + Repeater { + model: keysPage3[1].length + Key { + key: keysPage3[1][index].charCodeAt(0) + text: keysPage3[1][index] + } + } + EnterKey { + weight: 283 + } + } + KeyboardRow { + keyWeight: 156 + Key { + displayText: (page + 1) + "/" + numPages + functionKey: true + onClicked: page = (page + 1) % numPages + } + Repeater { + model: keysPage3[2].length + Key { + key: keysPage3[2][index].charCodeAt(0) + text: keysPage3[2][index] + } + } + Key { + weight: 204 + displayText: (page + 1) + "/" + numPages + functionKey: true + onClicked: page = (page + 1) % numPages + } + } + KeyboardRow { + keyWeight: 154 + SymbolModeKey { + weight: 217 + displayText: "ABC" + } + ChangeLanguageKey { + weight: 154 + } + SpaceKey { + weight: 864 + } + Key { + key: 0x2026 + text: "…" + } + Key { + key: 0xE000 + text: ":-)" + alternativeKeys: [ ";-)", ":-)", ":-D", ":-(", "<3" ] + } + HideKeyboardKey { + weight: 204 + } + } + } + } +}