0.7.1: i tasti delle azioni rapide dichiarano la loro altezza
In Silica il tasto piglia l'altezza dal tema (itemSizeExtraSmall, ~56 px) e non dal contenuto: con icona e etichetta (~110) il testo usciva dalla scatola e la riga di contorno della colonna finiva sopra le etichette. Ora height: Theme.itemSizeMedium. Aggiunto il controllo in tests/label_fit_check.py e il registro di posizione e altezza di ogni riga della Home.
This commit is contained in:
@@ -58,7 +58,7 @@ CREDS = BASE / "aira.json"
|
||||
TOKENS = BASE / "aira_tokens.json"
|
||||
POOL_CFG = BASE / "aira_config.json"
|
||||
|
||||
VERSION = "0.7.0"
|
||||
VERSION = "0.7.1"
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------- #
|
||||
@@ -693,6 +693,12 @@ def boost_restanti(st: dict) -> int:
|
||||
quando = datetime.fromisoformat(fine.replace("Z", "+00:00"))
|
||||
except ValueError:
|
||||
return 0
|
||||
# L'impianto manda la fine del boost ora con il fuso, ora senza (ora
|
||||
# locale): senza, va letta nel fuso dell'IMPIANTO, altrimenti la
|
||||
# sottrazione con "adesso" (che il fuso ce l'ha) solleva TypeError e
|
||||
# /summary risponde 502 -- l'app resta senza dati ("Nessun dato").
|
||||
if quando.tzinfo is None:
|
||||
quando = quando.replace(tzinfo=PLANT_TZ)
|
||||
return max(0, int((quando - datetime.now(timezone.utc)).total_seconds()))
|
||||
|
||||
|
||||
|
||||
@@ -231,6 +231,18 @@ check("boost in corso: restano ~1200 secondi",
|
||||
check("boost finito: zero secondi",
|
||||
b.boost_restanti({"hot_water_boost": {"end_time": "2026-01-01T00:00:00Z"}}) == 0)
|
||||
check("boost mai avviato: zero secondi", b.boost_restanti({}) == 0)
|
||||
|
||||
# L'impianto puo' mandare la fine del boost SENZA fuso (ora locale). E' la forma
|
||||
# che ha fatto rispondere 502 a /summary: la sottrazione con "adesso" (che il
|
||||
# fuso ce l'ha) solleva TypeError, e l'app resta senza dati ("Nessun dato").
|
||||
# Il conto alla rovescia deve reggere entrambe le forme.
|
||||
_fine_naive = (datetime.now(b.PLANT_TZ) + timedelta(seconds=1200)).strftime("%Y-%m-%dT%H:%M:%S")
|
||||
check("boost con fine senza fuso (ora dell'impianto)",
|
||||
abs(b.boost_restanti({"hot_water_boost": {"end_time": _fine_naive}}) - 1200) <= 3)
|
||||
check("riassunto con fine senza fuso (la forma che dava 502)",
|
||||
(b.summarize({"hot_water_boost": {"end_time": _fine_naive}}) or {}).get("boost_active") is True)
|
||||
check("boost con fine fuori orario (fuso diverso)",
|
||||
b.boost_restanti({"hot_water_boost": {"end_time": "2020-01-01T00:00:00"}}) == 0)
|
||||
riassunto = b.summarize({"hot_water_boost": {"end_time": fra}})
|
||||
check("riassunto: dice che il boost e' in corso", riassunto.get("boost_active") is True)
|
||||
check("riassunto: porta i secondi del boost",
|
||||
|
||||
+26
-1
@@ -410,7 +410,32 @@ respinto con 400 **prima** di partire.
|
||||
4. mentre il boost è in corso si deve vedere un **conto alla rovescia da 30:00 a
|
||||
00:00**.
|
||||
|
||||
## 12. Conseguenze dell'uso reale (0.7.0)
|
||||
## 12. I tasti delle azioni rapide e la riga che li copriva — v0.7.1
|
||||
|
||||
Carlo: *"Quando premo un bottone la riga sotto si disallinea coprendo i
|
||||
pulsanti"*.
|
||||
|
||||
Non era la riga a spostarsi: era il **tasto** a essere piu' basso del suo
|
||||
contenuto. In Silica `Button` dichiara `height: implicitHeight` e
|
||||
`implicitHeight: Theme.itemSizeExtraSmall` (~56 px), un'altezza pensata per
|
||||
un'icona *accanto* a un'etichetta corta. I tre tasti delle azioni rapide hanno
|
||||
icona **e** etichetta (ingombro visibile ~110-160 px, quello che io avevo
|
||||
misurato come "tasto 161 px"): il contenuto esce dalla scatola, e la riga
|
||||
successiva della colonna -- le letture di contorno -- viene messa subito sotto
|
||||
la scatola, cioe' **sopra** l'etichetta che sporge. Da li' l'impressione che si
|
||||
"disallinei".
|
||||
|
||||
**Come è stato fatto (0.7.1).**
|
||||
- i tre tasti dichiarano `height: Theme.itemSizeMedium` (`Button.qml` del target
|
||||
Sailfish letto dentro il motore di build, non indovinato);
|
||||
- `tests/label_fit_check.py` adesso pretende l'altezza dichiarata su ogni tasto
|
||||
che porta icona e testo: senza, il tema ne da' ~56 px contro ~110 di
|
||||
contenuto;
|
||||
- il registro dell'avvio (dopo un secondo) elenca **posizione e altezza di ogni
|
||||
riga della Home**, cosi' se la disposizione non torna si legge dal registro
|
||||
quale riga finisce dove invece di dedurlo da uno screenshot.
|
||||
|
||||
## 13. Conseguenze dell'uso reale (0.7.0)
|
||||
|
||||
Deciso con l'uso, non in anticipo:
|
||||
|
||||
|
||||
+23
-1
@@ -261,6 +261,13 @@ Page {
|
||||
Button {
|
||||
id: boostBtn
|
||||
width: (parent.width - 2 * parent.spacing) / 3
|
||||
// In Silica il tasto piglia l'altezza dal tema
|
||||
// (itemSizeExtraSmall ~56 px), ma icona E etichetta ne
|
||||
// occupano ~110: senza questa riga l'etichetta esce dalla
|
||||
// scatola e la riga successiva della colonna le finisce
|
||||
// sopra (segnalato da Carlo: "la riga sotto copre i
|
||||
// pulsanti"). Vedi tests/label_fit_check.py.
|
||||
height: Theme.itemSizeMedium
|
||||
text: qsTr("Boost")
|
||||
// La casella dell'icona la decide il tema: senza, l'Image
|
||||
// prende la misura del file e si mangia il testo.
|
||||
@@ -274,6 +281,7 @@ Page {
|
||||
Button {
|
||||
id: assenzaBtn
|
||||
width: (parent.width - 2 * parent.spacing) / 3
|
||||
height: Theme.itemSizeMedium
|
||||
// Il pulsante dice cosa succede premendolo, non lo stato.
|
||||
// Etichette corte: nel tasto, largo un terzo di schermo,
|
||||
// icona e testo devono starci insieme.
|
||||
@@ -302,6 +310,7 @@ Page {
|
||||
|
||||
Button {
|
||||
width: (parent.width - 2 * parent.spacing) / 3
|
||||
height: Theme.itemSizeMedium
|
||||
// "Comandi" (8 lettere) non ci sta accanto a un'icona in un
|
||||
// terzo di schermo: la pagina resta "Comandi impianto".
|
||||
text: qsTr("More")
|
||||
@@ -350,7 +359,20 @@ Page {
|
||||
Timer {
|
||||
id: misura
|
||||
interval: 1000
|
||||
onTriggered: console.log("harbour-aira home: contenuto", flick.contentHeight,
|
||||
onTriggered: {
|
||||
console.log("harbour-aira home: contenuto", flick.contentHeight,
|
||||
"schermo", height)
|
||||
// Ogni riga della Home con la sua posizione: se una riga finisce
|
||||
// addosso a un'altra, qui si legge quale e di quanto. E' la riga da
|
||||
// mandare al primo avvio se la disposizione non torna.
|
||||
for (var i = 0; i < col.children.length; ++i) {
|
||||
var r = col.children[i]
|
||||
if (r.height === undefined)
|
||||
continue
|
||||
console.log("harbour-aira riga", i, "y", Math.round(r.y),
|
||||
"h", Math.round(r.height),
|
||||
r.text !== undefined ? JSON.stringify(r.text) : "")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Name: harbour-aira
|
||||
Summary: Control your Aira heat pump through a local bridge
|
||||
Version: 0.7.0
|
||||
Version: 0.7.1
|
||||
Release: 1
|
||||
Group: Qt/Qt
|
||||
License: MIT
|
||||
@@ -37,6 +37,13 @@ Address and token of the bridge live in the app settings (AppConfigLocation);
|
||||
no personal data is stored in the binary.
|
||||
|
||||
%changelog
|
||||
* Sun Oct 11 2026 Carlo <carlo@carlobaratto.it> - 0.7.1-1
|
||||
- i tre tasti delle azioni rapide dichiarano la loro altezza: in Silica il tasto
|
||||
la piglia dal tema (Theme.itemSizeExtraSmall, ~56 px) e non dal contenuto,
|
||||
quindi con icona E etichetta il testo (~110 px) usciva dalla scatola e la riga
|
||||
di contorno finiva sopra le etichette (segnalato: "la riga sotto si disallinea
|
||||
coprendo i pulsanti").
|
||||
- il registro dell'avvio elenca posizione e altezza di ogni riga della Home.
|
||||
* Sun Oct 11 2026 Carlo <carlo@carlobaratto.it> - 0.7.0-1
|
||||
- assenza con le date: popup con inizio e fine (DatePickerDialog, componenti
|
||||
verificati nella guida Silica dell'SDK). Il bridge manda inizio e fine come
|
||||
|
||||
+2
-2
@@ -21,7 +21,7 @@ Q_DECL_EXPORT int main(int argc, char *argv[])
|
||||
|
||||
app->setOrganizationName(QStringLiteral("harbour"));
|
||||
app->setApplicationName(QStringLiteral("aira"));
|
||||
app->setApplicationVersion(QStringLiteral("0.7.0"));
|
||||
app->setApplicationVersion(QStringLiteral("0.7.1"));
|
||||
|
||||
Settings settings;
|
||||
ApiClient api(&settings);
|
||||
@@ -36,7 +36,7 @@ Q_DECL_EXPORT int main(int argc, char *argv[])
|
||||
|
||||
// Prima riga del log: dice subito se il device sta girando la build nuova
|
||||
// o una stale (trappola nota del build engine).
|
||||
qDebug() << "harbour-aira v0.7.0 build" << __DATE__ << __TIME__;
|
||||
qDebug() << "harbour-aira v0.7.1 build" << __DATE__ << __TIME__;
|
||||
|
||||
view->rootContext()->setContextProperty(QStringLiteral("appSettings"), &settings);
|
||||
view->rootContext()->setContextProperty(QStringLiteral("api"), &api);
|
||||
|
||||
@@ -31,7 +31,7 @@ FONT = "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf"
|
||||
|
||||
|
||||
def testi_dei_tasti(qml: str):
|
||||
"""I testi dei tasti che hanno un'icona, nell'ordine in cui appaiono."""
|
||||
"""I tasti con icona: (testo, altezza dichiarata o None), in ordine."""
|
||||
fuori = []
|
||||
for blocco in re.finditer(r"Button\s*\{(.*?)\n\s*\}", qml, re.S):
|
||||
corpo = blocco.group(1)
|
||||
@@ -40,7 +40,11 @@ def testi_dei_tasti(qml: str):
|
||||
riga = re.search(r"text:\s*(.+)", corpo)
|
||||
if not riga:
|
||||
continue
|
||||
fuori.extend(re.findall(r'qsTr\("([^"]+)"\)', riga.group(1)))
|
||||
testo = re.findall(r'qsTr\("([^"]+)"\)', riga.group(1))
|
||||
if not testo:
|
||||
continue
|
||||
alt = re.search(r"^\s*height:\s*(.+)$", corpo, re.M)
|
||||
fuori.append((testo[0], alt.group(1).strip() if alt else None))
|
||||
return fuori
|
||||
|
||||
|
||||
@@ -62,13 +66,24 @@ def main():
|
||||
qml = (RADICE / "qml" / "pages" / "MainPage.qml").read_text(encoding="utf-8")
|
||||
ts = (RADICE / "translations" / "harbour-aira-it.ts").read_text(encoding="utf-8")
|
||||
it = traduzioni(ts)
|
||||
sorgenti = testi_dei_tasti(qml)
|
||||
if len(sorgenti) < 3:
|
||||
print("ESITO: trovati %d testi con icona, ne servono 3" % len(sorgenti))
|
||||
origine = testi_dei_tasti(qml)
|
||||
if len(origine) < 3:
|
||||
print("ESITO: trovati %d testi con icona, ne servono 3" % len(origine))
|
||||
return 1
|
||||
sorgenti = [t for t, _ in origine]
|
||||
|
||||
disponibile = TASTO - 2 * RIENTRO - ICONA - DISTACCO
|
||||
problema = 0
|
||||
|
||||
# 1. L'altezza. In Silica il tasto la piglia dal tema
|
||||
# (Theme.itemSizeExtraSmall, ~56 px) e non dal contenuto: con icona E
|
||||
# etichetta il contenuto ne occupa ~110, esce dalla scatola, e la riga
|
||||
# successiva della colonna viene messa sopra la scatola -- cioe' sopra
|
||||
# l'etichetta che sporge. Chi ha entrambi deve dichiarare l'altezza.
|
||||
for testo, alt in origine:
|
||||
if not alt:
|
||||
print(" %-9s nessuna altezza dichiarata: il tema ne da' ~56 px, il contenuto ~110" % testo)
|
||||
problema += 1
|
||||
disponibile = TASTO - 2 * RIENTRO - ICONA - DISTACCO
|
||||
f = ImageFont.truetype(FONT, CARATTERE)
|
||||
|
||||
def largo(testo):
|
||||
|
||||
Reference in New Issue
Block a user