diff --git a/qml.qrc b/qml.qrc
index 0555682..aa4e73f 100644
--- a/qml.qrc
+++ b/qml.qrc
@@ -9,6 +9,7 @@
qml/detail_reservoir.qml
qml/detail_circuit.qml
qml/detail_batterie.qml
+ qml/responsive.js
images/4g_lte_off.png
images/4g_lte_on_1.png
images/4g_lte_on_2.png
diff --git a/qml/detail_batterie.qml b/qml/detail_batterie.qml
index 4931004..26239d7 100644
--- a/qml/detail_batterie.qml
+++ b/qml/detail_batterie.qml
@@ -4,6 +4,8 @@ import QtQuick.Layouts 1.12
import qt.koriolan.shipheart 1.0
+import "responsive.js" as Responsive
+
// ============================================================================
// detail_batterie.qml - page de détail d'une batterie (valeur + historique).
// ----------------------------------------------------------------------------
@@ -110,15 +112,16 @@ Shipheart_page {
Text {
text: nomElement
- font.pixelSize: 22
+ font.pixelSize: Responsive.police(22, page_detail_batterie.width)
font.bold: true
color: couleur_gris_pale
}
- // Sélecteur de variable (8 valeurs simples + énergie) :
+ // Sélecteur de variable (8 valeurs simples + énergie) - 4 colonnes
+ // normalement, 2 si écran étroit :
GridLayout {
Layout.fillWidth: true
- columns: 4
+ columns: Responsive.colonnesSelonLargeur(page_detail_batterie.width, variablesLibelles.length)
columnSpacing: 8
rowSpacing: 8
@@ -126,7 +129,7 @@ Shipheart_page {
model: variablesLibelles
delegate: Rectangle {
Layout.fillWidth: true
- height: 34
+ height: Math.max(34, Responsive.HAUTEUR_MIN_TACTILE)
radius: 8
color: (index === variableIndex) ? shipheart_couleur_fond_bouton_actif : shipheart_couleur_fond_bouton
@@ -134,7 +137,7 @@ Shipheart_page {
anchors.centerIn: parent
text: modelData
color: couleur_blanc_casse
- font.pixelSize: 12
+ font.pixelSize: Responsive.police(12, page_detail_batterie.width)
font.bold: (index === variableIndex)
}
@@ -161,13 +164,13 @@ Shipheart_page {
text: modeEnergie
? (totalWh >= 1000 ? (totalWh / 1000).toFixed(2) : totalWh.toFixed(1))
: valeurActuelle.toFixed(precisionAffichage)
- font.pixelSize: 64
+ font.pixelSize: Responsive.police(64, page_detail_batterie.width)
font.bold: true
color: couleur_blanc_casse
}
Text {
text: modeEnergie ? (totalWh >= 1000 ? "kWh" : "Wh") : uniteAffichage
- font.pixelSize: 20
+ font.pixelSize: Responsive.police(20, page_detail_batterie.width)
color: couleur_gris_pale
Layout.alignment: Qt.AlignTop
}
@@ -179,22 +182,22 @@ Shipheart_page {
visible: !modeEnergie
spacing: 10
RowLayout {
- Text { text: qsTr("Max"); color: couleur_gris_pale; Layout.preferredWidth: 90 }
- Text { text: valeurMax.toFixed(precisionAffichage) + " " + uniteAffichage; color: couleur_blanc_casse; Layout.preferredWidth: 100 }
- Text { text: "[" + formater_date(tempsMax) + "]"; color: couleur_gris_moyen }
+ Text { text: qsTr("Max"); color: couleur_gris_pale; font.pixelSize: Responsive.police(13, page_detail_batterie.width); Layout.preferredWidth: 90 }
+ Text { text: valeurMax.toFixed(precisionAffichage) + " " + uniteAffichage; color: couleur_blanc_casse; font.pixelSize: Responsive.police(13, page_detail_batterie.width); Layout.preferredWidth: 100 }
+ Text { text: "[" + formater_date(tempsMax) + "]"; color: couleur_gris_moyen; font.pixelSize: Responsive.police(13, page_detail_batterie.width) }
}
RowLayout {
- Text { text: qsTr("Moyen"); color: couleur_gris_pale; Layout.preferredWidth: 90 }
- Text { text: valeurMoyenne.toFixed(precisionAffichage) + " " + uniteAffichage; color: couleur_blanc_casse; Layout.preferredWidth: 100 }
+ Text { text: qsTr("Moyen"); color: couleur_gris_pale; font.pixelSize: Responsive.police(13, page_detail_batterie.width); Layout.preferredWidth: 90 }
+ Text { text: valeurMoyenne.toFixed(precisionAffichage) + " " + uniteAffichage; color: couleur_blanc_casse; font.pixelSize: Responsive.police(13, page_detail_batterie.width); Layout.preferredWidth: 100 }
}
RowLayout {
- Text { text: qsTr("Min"); color: couleur_gris_pale; Layout.preferredWidth: 90 }
- Text { text: valeurMin.toFixed(precisionAffichage) + " " + uniteAffichage; color: couleur_blanc_casse; Layout.preferredWidth: 100 }
- Text { text: "[" + formater_date(tempsMin) + "]"; color: couleur_gris_moyen }
+ Text { text: qsTr("Min"); color: couleur_gris_pale; font.pixelSize: Responsive.police(13, page_detail_batterie.width); Layout.preferredWidth: 90 }
+ Text { text: valeurMin.toFixed(precisionAffichage) + " " + uniteAffichage; color: couleur_blanc_casse; font.pixelSize: Responsive.police(13, page_detail_batterie.width); Layout.preferredWidth: 100 }
+ Text { text: "[" + formater_date(tempsMin) + "]"; color: couleur_gris_moyen; font.pixelSize: Responsive.police(13, page_detail_batterie.width) }
}
RowLayout {
- Text { text: qsTr("Delta (Max - Min)"); color: couleur_gris_pale; Layout.preferredWidth: 160 }
- Text { text: (valeurMax - valeurMin).toFixed(precisionAffichage + 1) + " " + uniteAffichage; color: couleur_blanc_casse }
+ Text { text: qsTr("Delta (Max - Min)"); color: couleur_gris_pale; font.pixelSize: Responsive.police(13, page_detail_batterie.width); Layout.preferredWidth: 160 }
+ Text { text: (valeurMax - valeurMin).toFixed(precisionAffichage + 1) + " " + uniteAffichage; color: couleur_blanc_casse; font.pixelSize: Responsive.police(13, page_detail_batterie.width) }
}
}
@@ -202,7 +205,7 @@ Shipheart_page {
visible: modeEnergie
text: qsTr("Consommation totale sur la période - détail par circuit ci-dessous")
color: couleur_gris_pale
- font.pixelSize: 13
+ font.pixelSize: Responsive.police(13, page_detail_batterie.width)
}
}
@@ -412,20 +415,20 @@ Shipheart_page {
Text {
text: modelData.nom
color: (modelData.consigne > 0) ? couleur_blanc_casse : couleur_gris_moyen
- font.pixelSize: 13
+ font.pixelSize: Responsive.police(13, page_detail_batterie.width)
Layout.preferredWidth: parent.width * 0.4
elide: Text.ElideRight
}
Text {
text: modelData.energie_wh.toFixed(2) + " Wh"
color: couleur_blanc_casse
- font.pixelSize: 13
+ font.pixelSize: Responsive.police(13, page_detail_batterie.width)
Layout.preferredWidth: parent.width * 0.3
}
Text {
text: modelData.pourcentage.toFixed(1) + " %"
color: couleur_gris_pale
- font.pixelSize: 13
+ font.pixelSize: Responsive.police(13, page_detail_batterie.width)
Layout.fillWidth: true
}
}
@@ -439,7 +442,7 @@ Shipheart_page {
model: periodesLibelles
delegate: Rectangle {
Layout.preferredWidth: 140
- Layout.preferredHeight: 40
+ Layout.preferredHeight: Math.max(40, Responsive.HAUTEUR_MIN_TACTILE)
radius: 8
color: (index === periodeIndex) ? shipheart_couleur_fond_bouton_actif : shipheart_couleur_fond_bouton
@@ -447,6 +450,7 @@ Shipheart_page {
anchors.centerIn: parent
text: modelData
color: couleur_blanc_casse
+ font.pixelSize: Responsive.police(14, page_detail_batterie.width)
font.bold: (index === periodeIndex)
}
@@ -465,14 +469,14 @@ Shipheart_page {
// Bouton retour :
Rectangle {
Layout.fillWidth: true
- Layout.preferredHeight: 44
+ Layout.preferredHeight: Math.max(44, Responsive.HAUTEUR_MIN_TACTILE)
radius: 8
color: shipheart_couleur_fond_bouton
Text {
anchors.centerIn: parent
text: "↩"
- font.pixelSize: 20
+ font.pixelSize: Responsive.police(20, page_detail_batterie.width)
color: couleur_blanc_casse
}
diff --git a/qml/detail_capteur.qml b/qml/detail_capteur.qml
index f6c2702..319c525 100644
--- a/qml/detail_capteur.qml
+++ b/qml/detail_capteur.qml
@@ -4,6 +4,8 @@ import QtQuick.Layouts 1.12
import qt.koriolan.shipheart 1.0
+import "responsive.js" as Responsive
+
// ============================================================================
// detail_capteur.qml - page de détail d'un capteur (valeur + historique).
// ----------------------------------------------------------------------------
@@ -99,7 +101,7 @@ Shipheart_page {
Text {
text: nomElement
- font.pixelSize: 22
+ font.pixelSize: Responsive.police(22, page_detail_capteur.width)
font.bold: true
color: couleur_gris_pale
}
@@ -114,13 +116,13 @@ Shipheart_page {
spacing: 4
Text {
text: valeurActuelle.toFixed(precisionAffichage)
- font.pixelSize: 64
+ font.pixelSize: Responsive.police(64, page_detail_capteur.width)
font.bold: true
color: couleur_blanc_casse
}
Text {
text: uniteAffichage
- font.pixelSize: 20
+ font.pixelSize: Responsive.police(20, page_detail_capteur.width)
color: couleur_gris_pale
Layout.alignment: Qt.AlignTop
}
@@ -131,22 +133,22 @@ Shipheart_page {
ColumnLayout {
spacing: 10
RowLayout {
- Text { text: qsTr("Max"); color: couleur_gris_pale; Layout.preferredWidth: 90 }
- Text { text: valeurMax.toFixed(precisionAffichage) + " " + uniteAffichage; color: couleur_blanc_casse; Layout.preferredWidth: 100 }
- Text { text: "[" + formater_date(tempsMax) + "]"; color: couleur_gris_moyen }
+ Text { text: qsTr("Max"); color: couleur_gris_pale; font.pixelSize: Responsive.police(13, page_detail_capteur.width); Layout.preferredWidth: 90 }
+ Text { text: valeurMax.toFixed(precisionAffichage) + " " + uniteAffichage; color: couleur_blanc_casse; font.pixelSize: Responsive.police(13, page_detail_capteur.width); Layout.preferredWidth: 100 }
+ Text { text: "[" + formater_date(tempsMax) + "]"; color: couleur_gris_moyen; font.pixelSize: Responsive.police(13, page_detail_capteur.width) }
}
RowLayout {
- Text { text: qsTr("Moyen"); color: couleur_gris_pale; Layout.preferredWidth: 90 }
- Text { text: valeurMoyenne.toFixed(precisionAffichage) + " " + uniteAffichage; color: couleur_blanc_casse; Layout.preferredWidth: 100 }
+ Text { text: qsTr("Moyen"); color: couleur_gris_pale; font.pixelSize: Responsive.police(13, page_detail_capteur.width); Layout.preferredWidth: 90 }
+ Text { text: valeurMoyenne.toFixed(precisionAffichage) + " " + uniteAffichage; color: couleur_blanc_casse; font.pixelSize: Responsive.police(13, page_detail_capteur.width); Layout.preferredWidth: 100 }
}
RowLayout {
- Text { text: qsTr("Min"); color: couleur_gris_pale; Layout.preferredWidth: 90 }
- Text { text: valeurMin.toFixed(precisionAffichage) + " " + uniteAffichage; color: couleur_blanc_casse; Layout.preferredWidth: 100 }
- Text { text: "[" + formater_date(tempsMin) + "]"; color: couleur_gris_moyen }
+ Text { text: qsTr("Min"); color: couleur_gris_pale; font.pixelSize: Responsive.police(13, page_detail_capteur.width); Layout.preferredWidth: 90 }
+ Text { text: valeurMin.toFixed(precisionAffichage) + " " + uniteAffichage; color: couleur_blanc_casse; font.pixelSize: Responsive.police(13, page_detail_capteur.width); Layout.preferredWidth: 100 }
+ Text { text: "[" + formater_date(tempsMin) + "]"; color: couleur_gris_moyen; font.pixelSize: Responsive.police(13, page_detail_capteur.width) }
}
RowLayout {
- Text { text: qsTr("Delta (Max - Min)"); color: couleur_gris_pale; Layout.preferredWidth: 160 }
- Text { text: (valeurMax - valeurMin).toFixed(precisionAffichage + 1) + " " + uniteAffichage; color: couleur_blanc_casse }
+ Text { text: qsTr("Delta (Max - Min)"); color: couleur_gris_pale; font.pixelSize: Responsive.police(13, page_detail_capteur.width); Layout.preferredWidth: 160 }
+ Text { text: (valeurMax - valeurMin).toFixed(precisionAffichage + 1) + " " + uniteAffichage; color: couleur_blanc_casse; font.pixelSize: Responsive.police(13, page_detail_capteur.width) }
}
}
}
@@ -271,7 +273,7 @@ Shipheart_page {
model: periodesLibelles
delegate: Rectangle {
Layout.preferredWidth: 140
- Layout.preferredHeight: 40
+ Layout.preferredHeight: Math.max(40, Responsive.HAUTEUR_MIN_TACTILE)
radius: 8
color: (index === periodeIndex) ? shipheart_couleur_fond_bouton_actif : shipheart_couleur_fond_bouton
@@ -279,6 +281,7 @@ Shipheart_page {
anchors.centerIn: parent
text: modelData
color: couleur_blanc_casse
+ font.pixelSize: Responsive.police(14, page_detail_capteur.width)
font.bold: (index === periodeIndex)
}
@@ -297,14 +300,14 @@ Shipheart_page {
// Bouton retour :
Rectangle {
Layout.fillWidth: true
- Layout.preferredHeight: 44
+ Layout.preferredHeight: Math.max(44, Responsive.HAUTEUR_MIN_TACTILE)
radius: 8
color: shipheart_couleur_fond_bouton
Text {
anchors.centerIn: parent
text: "↩"
- font.pixelSize: 20
+ font.pixelSize: Responsive.police(20, page_detail_capteur.width)
color: couleur_blanc_casse
}
diff --git a/qml/detail_circuit.qml b/qml/detail_circuit.qml
index 4c78bf1..c8c8bca 100644
--- a/qml/detail_circuit.qml
+++ b/qml/detail_circuit.qml
@@ -4,6 +4,8 @@ import QtQuick.Layouts 1.12
import qt.koriolan.shipheart 1.0
+import "responsive.js" as Responsive
+
// ============================================================================
// detail_circuit.qml - page de détail d'un circuit (valeur + historique).
// ----------------------------------------------------------------------------
@@ -93,20 +95,24 @@ Shipheart_page {
Text {
text: nomElement
- font.pixelSize: 22
+ font.pixelSize: Responsive.police(22, page_detail_circuit.width)
font.bold: true
color: couleur_gris_pale
}
- // Sélecteur de variable (propre aux circuits/batteries) :
- Row {
+ // Sélecteur de variable (propre aux circuits/batteries) - 4 colonnes
+ // normalement, 2x2 si écran étroit :
+ GridLayout {
Layout.fillWidth: true
- spacing: 8
+ columns: Responsive.colonnesSelonLargeur(page_detail_circuit.width, variablesLibelles.length)
+ rowSpacing: 8
+ columnSpacing: 8
+
Repeater {
model: variablesLibelles
delegate: Rectangle {
- width: (page_detail_circuit.width - 40 - 3 * 8) / 4
- height: 36
+ Layout.fillWidth: true
+ Layout.preferredHeight: Responsive.HAUTEUR_MIN_TACTILE
radius: 8
color: (index === variableIndex) ? shipheart_couleur_fond_bouton_actif : shipheart_couleur_fond_bouton
@@ -114,7 +120,7 @@ Shipheart_page {
anchors.centerIn: parent
text: modelData
color: couleur_blanc_casse
- font.pixelSize: 13
+ font.pixelSize: Responsive.police(13, page_detail_circuit.width)
font.bold: (index === variableIndex)
}
@@ -139,13 +145,13 @@ Shipheart_page {
spacing: 4
Text {
text: valeurActuelle.toFixed(precisionAffichage)
- font.pixelSize: 64
+ font.pixelSize: Responsive.police(64, page_detail_circuit.width)
font.bold: true
color: couleur_blanc_casse
}
Text {
text: uniteAffichage
- font.pixelSize: 20
+ font.pixelSize: Responsive.police(20, page_detail_circuit.width)
color: couleur_gris_pale
Layout.alignment: Qt.AlignTop
}
@@ -156,22 +162,22 @@ Shipheart_page {
ColumnLayout {
spacing: 10
RowLayout {
- Text { text: qsTr("Max"); color: couleur_gris_pale; Layout.preferredWidth: 90 }
- Text { text: valeurMax.toFixed(precisionAffichage) + " " + uniteAffichage; color: couleur_blanc_casse; Layout.preferredWidth: 100 }
- Text { text: "[" + formater_date(tempsMax) + "]"; color: couleur_gris_moyen }
+ Text { text: qsTr("Max"); color: couleur_gris_pale; font.pixelSize: Responsive.police(13, page_detail_circuit.width); Layout.preferredWidth: 90 }
+ Text { text: valeurMax.toFixed(precisionAffichage) + " " + uniteAffichage; color: couleur_blanc_casse; font.pixelSize: Responsive.police(13, page_detail_circuit.width); Layout.preferredWidth: 100 }
+ Text { text: "[" + formater_date(tempsMax) + "]"; color: couleur_gris_moyen; font.pixelSize: Responsive.police(13, page_detail_circuit.width) }
}
RowLayout {
- Text { text: qsTr("Moyen"); color: couleur_gris_pale; Layout.preferredWidth: 90 }
- Text { text: valeurMoyenne.toFixed(precisionAffichage) + " " + uniteAffichage; color: couleur_blanc_casse; Layout.preferredWidth: 100 }
+ Text { text: qsTr("Moyen"); color: couleur_gris_pale; font.pixelSize: Responsive.police(13, page_detail_circuit.width); Layout.preferredWidth: 90 }
+ Text { text: valeurMoyenne.toFixed(precisionAffichage) + " " + uniteAffichage; color: couleur_blanc_casse; font.pixelSize: Responsive.police(13, page_detail_circuit.width); Layout.preferredWidth: 100 }
}
RowLayout {
- Text { text: qsTr("Min"); color: couleur_gris_pale; Layout.preferredWidth: 90 }
- Text { text: valeurMin.toFixed(precisionAffichage) + " " + uniteAffichage; color: couleur_blanc_casse; Layout.preferredWidth: 100 }
- Text { text: "[" + formater_date(tempsMin) + "]"; color: couleur_gris_moyen }
+ Text { text: qsTr("Min"); color: couleur_gris_pale; font.pixelSize: Responsive.police(13, page_detail_circuit.width); Layout.preferredWidth: 90 }
+ Text { text: valeurMin.toFixed(precisionAffichage) + " " + uniteAffichage; color: couleur_blanc_casse; font.pixelSize: Responsive.police(13, page_detail_circuit.width); Layout.preferredWidth: 100 }
+ Text { text: "[" + formater_date(tempsMin) + "]"; color: couleur_gris_moyen; font.pixelSize: Responsive.police(13, page_detail_circuit.width) }
}
RowLayout {
- Text { text: qsTr("Delta (Max - Min)"); color: couleur_gris_pale; Layout.preferredWidth: 160 }
- Text { text: (valeurMax - valeurMin).toFixed(precisionAffichage + 1) + " " + uniteAffichage; color: couleur_blanc_casse }
+ Text { text: qsTr("Delta (Max - Min)"); color: couleur_gris_pale; font.pixelSize: Responsive.police(13, page_detail_circuit.width); Layout.preferredWidth: 160 }
+ Text { text: (valeurMax - valeurMin).toFixed(precisionAffichage + 1) + " " + uniteAffichage; color: couleur_blanc_casse; font.pixelSize: Responsive.police(13, page_detail_circuit.width) }
}
}
}
@@ -293,7 +299,7 @@ Shipheart_page {
model: periodesLibelles
delegate: Rectangle {
Layout.preferredWidth: 140
- Layout.preferredHeight: 40
+ Layout.preferredHeight: Math.max(40, Responsive.HAUTEUR_MIN_TACTILE)
radius: 8
color: (index === periodeIndex) ? shipheart_couleur_fond_bouton_actif : shipheart_couleur_fond_bouton
@@ -301,6 +307,7 @@ Shipheart_page {
anchors.centerIn: parent
text: modelData
color: couleur_blanc_casse
+ font.pixelSize: Responsive.police(14, page_detail_circuit.width)
font.bold: (index === periodeIndex)
}
@@ -319,14 +326,14 @@ Shipheart_page {
// Bouton retour :
Rectangle {
Layout.fillWidth: true
- Layout.preferredHeight: 44
+ Layout.preferredHeight: Math.max(44, Responsive.HAUTEUR_MIN_TACTILE)
radius: 8
color: shipheart_couleur_fond_bouton
Text {
anchors.centerIn: parent
text: "↩"
- font.pixelSize: 20
+ font.pixelSize: Responsive.police(20, page_detail_circuit.width)
color: couleur_blanc_casse
}
diff --git a/qml/detail_reservoir.qml b/qml/detail_reservoir.qml
index 146fbf9..1cb1063 100644
--- a/qml/detail_reservoir.qml
+++ b/qml/detail_reservoir.qml
@@ -4,6 +4,8 @@ import QtQuick.Layouts 1.12
import qt.koriolan.shipheart 1.0
+import "responsive.js" as Responsive
+
// ============================================================================
// detail_reservoir.qml - page de détail d'un réservoir (valeur + historique).
// ----------------------------------------------------------------------------
@@ -90,7 +92,7 @@ Shipheart_page {
Text {
text: nomElement
- font.pixelSize: 22
+ font.pixelSize: Responsive.police(22, page_detail_reservoir.width)
font.bold: true
color: couleur_gris_pale
}
@@ -105,13 +107,13 @@ Shipheart_page {
spacing: 4
Text {
text: valeurActuelle.toFixed(precisionAffichage)
- font.pixelSize: 64
+ font.pixelSize: Responsive.police(64, page_detail_reservoir.width)
font.bold: true
color: couleur_blanc_casse
}
Text {
text: uniteAffichage
- font.pixelSize: 20
+ font.pixelSize: Responsive.police(20, page_detail_reservoir.width)
color: couleur_gris_pale
Layout.alignment: Qt.AlignTop
}
@@ -122,22 +124,22 @@ Shipheart_page {
ColumnLayout {
spacing: 10
RowLayout {
- Text { text: qsTr("Max"); color: couleur_gris_pale; Layout.preferredWidth: 90 }
- Text { text: valeurMax.toFixed(precisionAffichage) + " " + uniteAffichage; color: couleur_blanc_casse; Layout.preferredWidth: 100 }
- Text { text: "[" + formater_date(tempsMax) + "]"; color: couleur_gris_moyen }
+ Text { text: qsTr("Max"); color: couleur_gris_pale; font.pixelSize: Responsive.police(13, page_detail_reservoir.width); Layout.preferredWidth: 90 }
+ Text { text: valeurMax.toFixed(precisionAffichage) + " " + uniteAffichage; color: couleur_blanc_casse; font.pixelSize: Responsive.police(13, page_detail_reservoir.width); Layout.preferredWidth: 100 }
+ Text { text: "[" + formater_date(tempsMax) + "]"; color: couleur_gris_moyen; font.pixelSize: Responsive.police(13, page_detail_reservoir.width) }
}
RowLayout {
- Text { text: qsTr("Moyen"); color: couleur_gris_pale; Layout.preferredWidth: 90 }
- Text { text: valeurMoyenne.toFixed(precisionAffichage) + " " + uniteAffichage; color: couleur_blanc_casse; Layout.preferredWidth: 100 }
+ Text { text: qsTr("Moyen"); color: couleur_gris_pale; font.pixelSize: Responsive.police(13, page_detail_reservoir.width); Layout.preferredWidth: 90 }
+ Text { text: valeurMoyenne.toFixed(precisionAffichage) + " " + uniteAffichage; color: couleur_blanc_casse; font.pixelSize: Responsive.police(13, page_detail_reservoir.width); Layout.preferredWidth: 100 }
}
RowLayout {
- Text { text: qsTr("Min"); color: couleur_gris_pale; Layout.preferredWidth: 90 }
- Text { text: valeurMin.toFixed(precisionAffichage) + " " + uniteAffichage; color: couleur_blanc_casse; Layout.preferredWidth: 100 }
- Text { text: "[" + formater_date(tempsMin) + "]"; color: couleur_gris_moyen }
+ Text { text: qsTr("Min"); color: couleur_gris_pale; font.pixelSize: Responsive.police(13, page_detail_reservoir.width); Layout.preferredWidth: 90 }
+ Text { text: valeurMin.toFixed(precisionAffichage) + " " + uniteAffichage; color: couleur_blanc_casse; font.pixelSize: Responsive.police(13, page_detail_reservoir.width); Layout.preferredWidth: 100 }
+ Text { text: "[" + formater_date(tempsMin) + "]"; color: couleur_gris_moyen; font.pixelSize: Responsive.police(13, page_detail_reservoir.width) }
}
RowLayout {
- Text { text: qsTr("Delta (Max - Min)"); color: couleur_gris_pale; Layout.preferredWidth: 160 }
- Text { text: (valeurMax - valeurMin).toFixed(precisionAffichage + 1) + " " + uniteAffichage; color: couleur_blanc_casse }
+ Text { text: qsTr("Delta (Max - Min)"); color: couleur_gris_pale; font.pixelSize: Responsive.police(13, page_detail_reservoir.width); Layout.preferredWidth: 160 }
+ Text { text: (valeurMax - valeurMin).toFixed(precisionAffichage + 1) + " " + uniteAffichage; color: couleur_blanc_casse; font.pixelSize: Responsive.police(13, page_detail_reservoir.width) }
}
}
}
@@ -262,7 +264,7 @@ Shipheart_page {
model: periodesLibelles
delegate: Rectangle {
Layout.preferredWidth: 140
- Layout.preferredHeight: 40
+ Layout.preferredHeight: Math.max(40, Responsive.HAUTEUR_MIN_TACTILE)
radius: 8
color: (index === periodeIndex) ? shipheart_couleur_fond_bouton_actif : shipheart_couleur_fond_bouton
@@ -270,6 +272,7 @@ Shipheart_page {
anchors.centerIn: parent
text: modelData
color: couleur_blanc_casse
+ font.pixelSize: Responsive.police(14, page_detail_reservoir.width)
font.bold: (index === periodeIndex)
}
@@ -288,14 +291,14 @@ Shipheart_page {
// Bouton retour :
Rectangle {
Layout.fillWidth: true
- Layout.preferredHeight: 44
+ Layout.preferredHeight: Math.max(44, Responsive.HAUTEUR_MIN_TACTILE)
radius: 8
color: shipheart_couleur_fond_bouton
Text {
anchors.centerIn: parent
text: "↩"
- font.pixelSize: 20
+ font.pixelSize: Responsive.police(20, page_detail_reservoir.width)
color: couleur_blanc_casse
}
diff --git a/qml/home.qml b/qml/home.qml
index 4f1accb..1b460fb 100644
--- a/qml/home.qml
+++ b/qml/home.qml
@@ -4,6 +4,8 @@ import QtQuick.Layouts 1.12
import qt.koriolan.shipheart 1.0
+import "responsive.js" as Responsive
+
// ============================================================================
// home.qml (client shipheart_wasm) - 4 domaines (circuit/batterie/capteur/
// reservoir), via l'API réelle (DataProvider). Écriture (consigne) sur
@@ -210,7 +212,7 @@ Shipheart_page {
Text {
anchors.centerIn: parent
color: couleur_orange
- font.pixelSize: 13
+ font.pixelSize: Responsive.police(13, page_accueil.width)
font.bold: true
text: dataProvider.aDejaEteConnecte
? qsTr("⚠ Bateau non connecté depuis le %1").arg(
@@ -220,17 +222,19 @@ Shipheart_page {
}
//-----------------------------------------------------------
- // Sélecteur de domaine :
- Row {
+ // Sélecteur de domaine - 4 colonnes normalement, 2x2 si écran étroit
+ // (téléphone en portrait, typiquement) :
+ GridLayout {
Layout.fillWidth: true
- height: shipheart_hauteur_bandeau_haut
- spacing: espace_onglets
+ columns: Responsive.colonnesSelonLargeur(page_accueil.width, domaines_libelles.length)
+ rowSpacing: espace_onglets
+ columnSpacing: espace_onglets
Repeater {
model: domaines_libelles
delegate: Rectangle {
- width: (page_accueil.width - 3 * espace_onglets) / 4
- height: shipheart_hauteur_bandeau_haut
+ Layout.fillWidth: true
+ Layout.preferredHeight: Math.max(shipheart_hauteur_bandeau_haut, Responsive.HAUTEUR_MIN_TACTILE)
radius: rayon_onglets
color: (index === domaine_actif_index) ? shipheart_couleur_fond_bouton_actif : shipheart_couleur_fond_bouton
@@ -238,7 +242,7 @@ Shipheart_page {
anchors.centerIn: parent
text: modelData
color: couleur_blanc_casse
- font.pixelSize: 13
+ font.pixelSize: Responsive.police(13, page_accueil.width)
font.bold: (index === domaine_actif_index)
}
@@ -253,18 +257,25 @@ Shipheart_page {
}
//-----------------------------------------------------------
- // Onglets (familles du domaine actif) :
+ // Onglets (familles du domaine actif) - nombre de colonnes limité
+ // selon la largeur d'écran (2 si étroit, 5 sinon), hauteur du
+ // conteneur calculée pour s'adapter au nombre de lignes nécessaires
+ // (peut donc passer sur 2+ lignes sur un écran étroit) :
Rectangle {
+ id: zone_onglets_familles
+ readonly property int colonnesOnglets: Responsive.colonnesSelonLargeur(page_accueil.width, modele_onglets_actuel.count)
+ readonly property int lignesOnglets: Math.ceil(modele_onglets_actuel.count / colonnesOnglets)
+
Layout.fillWidth: true
- height: shipheart_hauteur_bandeau_haut
+ Layout.preferredHeight: lignesOnglets * Math.max(shipheart_hauteur_bandeau_haut, Responsive.HAUTEUR_MIN_TACTILE)
color: "transparent"
visible: modele_onglets_actuel.count > 1
GridView {
id: grille_onglets
anchors.fill: parent
- cellWidth: width / Math.max(1, Math.min(modele_onglets_actuel.count, 5))
- cellHeight: shipheart_hauteur_bandeau_haut
+ cellWidth: width / zone_onglets_familles.colonnesOnglets
+ cellHeight: Math.max(shipheart_hauteur_bandeau_haut, Responsive.HAUTEUR_MIN_TACTILE)
model: modele_onglets_actuel
clip: true
@@ -280,7 +291,7 @@ Shipheart_page {
text: model.libelle
anchors.centerIn: parent
color: couleur_blanc_casse
- font.pixelSize: 14
+ font.pixelSize: Responsive.police(14, page_accueil.width)
font.bold: model.actif
}
@@ -333,7 +344,7 @@ Shipheart_page {
Text {
text: model.nom
color: couleur_blanc_casse
- font.pixelSize: 16
+ font.pixelSize: Responsive.police(16, page_accueil.width)
font.bold: true
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
@@ -362,7 +373,7 @@ Shipheart_page {
}
}
color: couleur_blanc_casse
- font.pixelSize: 12
+ font.pixelSize: Responsive.police(12, page_accueil.width)
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
}
@@ -378,7 +389,7 @@ Shipheart_page {
text: (model.consigne > 0) ? qsTr("On") : qsTr("Off")
color: (model.consigne > 0) ? couleur_green_yellow : couleur_blanc_casse
- font.pixelSize: 18
+ font.pixelSize: Responsive.police(18, page_accueil.width)
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
}
diff --git a/qml/responsive.js b/qml/responsive.js
new file mode 100644
index 0000000..e29274f
--- /dev/null
+++ b/qml/responsive.js
@@ -0,0 +1,47 @@
+.pragma library
+
+// ============================================================================
+// responsive.js - fonctions utilitaires pour un affichage adaptatif (PC,
+// tablette, téléphone). Même principe que fonctions.js/fonctions_date_heure.js
+// côté natif (bibliothèque JS partagée, importée par les pages qui en ont
+// besoin) - cf synthèse, chantier "responsive".
+// ============================================================================
+
+// Seuil en dessous duquel l'écran est considéré "étroit" (bascule en mise en
+// page compacte - typiquement un téléphone en portrait) :
+var SEUIL_ECRAN_ETROIT = 700;
+
+function estEtroit(largeur) {
+ return largeur < SEUIL_ECRAN_ETROIT;
+}
+
+// Taille de police proportionnelle à la largeur d'écran disponible, avec un
+// plancher et un plafond pour rester lisible sur petit écran et raisonnable
+// sur grand écran PC. 'base' est la taille pensée pour un écran de référence
+// (~950px de large, l'ordre de grandeur habituel de test de ce projet).
+function police(base, largeur) {
+ var largeurReference = 950;
+ var taille = base * (largeur / largeurReference);
+ var plancher = base * 0.6;
+ var plafond = base * 1.3;
+ if (taille < plancher) taille = plancher;
+ if (taille > plafond) taille = plafond;
+ return Math.round(taille);
+}
+
+// Nombre de colonnes adapté à la largeur RÉELLEMENT disponible et au nombre
+// d'éléments à afficher, plutôt qu'un simple seuil binaire "écran étroit/
+// large" - chaque bouton reste au moins 'largeurMinBouton' de large, quel que
+// soit le nombre d'éléments (qui peut varier dynamiquement - ex: familles
+// créées/supprimées par l'utilisateur, différent d'un domaine à l'autre) :
+var LARGEUR_MIN_BOUTON = 130;
+
+function colonnesSelonLargeur(largeurDisponible, nombreElements, largeurMinBouton) {
+ if (largeurMinBouton === undefined) largeurMinBouton = LARGEUR_MIN_BOUTON;
+ var colonnesPossibles = Math.max(1, Math.floor(largeurDisponible / largeurMinBouton));
+ return Math.max(1, Math.min(nombreElements, colonnesPossibles));
+}
+
+// Hauteur minimale garantie pour une cible tactile (bouton), quelle que soit
+// l'échelle par ailleurs - recommandation usuelle d'accessibilité (~44px) :
+var HAUTEUR_MIN_TACTILE = 44;