diff --git a/README.it.md b/README.it.md index 0482b90..1969bf2 100644 --- a/README.it.md +++ b/README.it.md @@ -27,6 +27,8 @@ e ripiega sull'inglese; la si può scegliere anche nelle impostazioni dell'app. in Home scorre da 30:00 a 00:00 e in copertina prende il posto dell'obiettivo dell'acqua. I secondi vengono dalla fine del boost letta dall'impianto: il conto è giusto anche se il boost l'ha avviato qualcun altro +- **Il tasto del boost diventa *Stop*** mentre il boost è in corso, in Home e in + copertina: un tocco lo ferma, invece di farne ripartire un altro - **Assenza con le date**: toccando *Assenza* si apre una finestra dove si scelgono il primo e l'ultimo giorno (calendario, un tocco ciascuno). In quel periodo la casa resta a 15 °C e riprende il programma normale il giorno scelto diff --git a/README.md b/README.md index e9aab5c..d0d2aa3 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,9 @@ status, domestic hot water, and the house target temperature per zone. it ticking down from 30:00 to 00:00, and the cover page shows it in place of the hot water target. The seconds come from the plant's own boost end time, so the count is right even if the boost was started from somewhere else +- **The boost button turns into *Stop*** while a boost is running, on the home + screen and on the cover: tapping it stops the boost instead of starting + another one - **Away mode with dates**: tapping *Away* opens a dialog where you pick the first and the last day (calendar, one tap each). The house is kept at 15 °C for that period and resumes its normal programme on the day you chose as the diff --git a/docs/PIANO.md b/docs/PIANO.md index e920025..b4a0808 100644 --- a/docs/PIANO.md +++ b/docs/PIANO.md @@ -435,7 +435,36 @@ la scatola, cioe' **sopra** l'etichetta che sporge. Da li' l'impressione che si 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) +## 13. Il tasto del boost diventa Stop, e la riga che spostava i tasti — v0.7.2 + +Carlo: *"Il boost funziona ma la scritta sposta in basso i pulsanti facendoli +coprire. Il pulsante di avvio boost dovrebbe diventare stop boost se il boost e' +attivo"*. + +Due cose distinte, e la prima va detta perche' evita confusione: la riga che +**copriva** i tasti era il difetto di 0.7.1 (il tasto piu' basso del contenuto), +che al momento della segnalazione non era ancora installata sul telefono -- il +bridge si aggiorna da solo sul server, l'app no. La riga che invece li +**spostava** era nuova e vera: il conto alla rovescia prendeva il posto del +suggerimento ma con un carattere piu' grande (`fontSizeSmall` contro +`fontSizeExtraSmall`), quindi la Home cresceva di una decina di pixel e tutto +scendeva. Ora e' una riga sola, di altezza fissa, con il carattere del +suggerimento: sostituirsi non sposta piu' niente. + +**Come è stato fatto (0.7.2).** +- tasto del boost condizionale (`Stop` con il glifo di stop quando `boostActive`) + **anche in copertina**: una copertina che riavvia il boost quando vuoi fermarlo + e' peggio di un tasto che non fa niente; +- `quick-boost-stop.png` disegnato in casa con `scripts/make_glyphs.py`, come gli + altri tre glifi; +- "Stop boost" per intero non ci sta accanto all'icona (92 px contro 73): resta + `Stop`, il senso lo porta il glifo. E' `tests/label_fit_check.py` a dirlo, che + adesso legge anche le etichette condizionali; +- `tests/cover_action_check.py` legge tutti i comandi dell'azione e tutte le + icone citate: prima si aspettava un solo letterale e su un invio condizionale + segnalava un problema inesistente. + +## 14. Conseguenze dell'uso reale (0.7.0) Deciso con l'uso, non in anticipo: diff --git a/qml/cover/CoverPage.qml b/qml/cover/CoverPage.qml index e0f3549..00d7c1f 100644 --- a/qml/cover/CoverPage.qml +++ b/qml/cover/CoverPage.qml @@ -176,8 +176,12 @@ CoverBackground { // Il componente e' in Sailfish.Silica 1.0 (verificato nella guida dell'SDK). CoverActionList { CoverAction { - iconSource: "../icons/quick-boost.png" - onTriggered: api.sendCommand("hot_water_boost_on") + // Anche dalla copertina il tasto ferma quando il boost e' in corso: + // altrimenti un tocco per fermarlo ne farebbe ripartire un altro. + iconSource: api.boostActive ? "../icons/quick-boost-stop.png" + : "../icons/quick-boost.png" + onTriggered: api.sendCommand(api.boostActive ? "hot_water_boost_off" + : "hot_water_boost_on") } } } diff --git a/qml/icons/quick-boost-stop.png b/qml/icons/quick-boost-stop.png new file mode 100644 index 0000000..ca4de32 Binary files /dev/null and b/qml/icons/quick-boost-stop.png differ diff --git a/qml/pages/MainPage.qml b/qml/pages/MainPage.qml index 46babd9..37b4245 100644 --- a/qml/pages/MainPage.qml +++ b/qml/pages/MainPage.qml @@ -223,27 +223,38 @@ Page { } } - // Conto alla rovescia del boost, da 30:00 a 00:00 (richiesta - // dell'utente): si vede solo mentre il boost e' in corso. - Label { - visible: api.configured && api.boostActive - x: Theme.horizontalPageMargin - width: parent.width - 2 * Theme.horizontalPageMargin - text: qsTr("Boost · %1").arg(api.boostCountdown) - color: Theme.highlightColor - font.pixelSize: Theme.fontSizeSmall - font.bold: true - } + // Una sola riga, sempre della stessa altezza: mentre il boost corre + // il conto alla rovescia prende il posto del suggerimento senza + // spostare niente sotto. Il carattere e' quello del suggerimento + // (fontSizeExtraSmall): se fosse piu' grande, la riga piu' alta + // spingerebbe giu' i pulsanti e la riga di contorno finirebbe loro + // addosso (segnalato da Carlo). + Item { + visible: api.configured + width: parent.width + height: Math.max(contoRovescia.implicitHeight, + suggerimento.implicitHeight) - Label { - // Con il boost in corso questa riga sparisce: al suo posto c'e' - // il conto alla rovescia, cosi' la Home resta di una schermata. - visible: api.configured && !api.boostActive - x: Theme.horizontalPageMargin - width: parent.width - 2 * Theme.horizontalPageMargin - text: qsTr("Tap a value to adjust it") - color: Theme.secondaryColor - font.pixelSize: Theme.fontSizeExtraSmall + Label { + id: contoRovescia + visible: api.boostActive + x: Theme.horizontalPageMargin + width: parent.width - 2 * Theme.horizontalPageMargin + text: qsTr("Boost · %1").arg(api.boostCountdown) + color: Theme.highlightColor + font.pixelSize: Theme.fontSizeExtraSmall + font.bold: true + } + + Label { + id: suggerimento + visible: !api.boostActive + x: Theme.horizontalPageMargin + width: parent.width - 2 * Theme.horizontalPageMargin + text: qsTr("Tap a value to adjust it") + color: Theme.secondaryColor + font.pixelSize: Theme.fontSizeExtraSmall + } } // ---- azioni rapide --------------------------------------------- // @@ -268,14 +279,26 @@ Page { // sopra (segnalato da Carlo: "la riga sotto copre i // pulsanti"). Vedi tests/label_fit_check.py. height: Theme.itemSizeMedium - text: qsTr("Boost") + // Mentre il boost e' in corso il tasto ferma invece di + // avviare: dice cosa succede premendolo, come il tasto + // dell'assenza. "Stop boost" per intero non ci sta accanto + // all'icona (92 px contro 73 disponibili): resta "Stop", + // che il glifo di stop rende inequivocabile. + text: api.boostActive ? qsTr("Stop") : qsTr("Boost") // La casella dell'icona la decide il tema: senza, l'Image // prende la misura del file e si mangia il testo. - icon.source: "../icons/quick-boost.png" + icon.source: api.boostActive ? "../icons/quick-boost-stop.png" + : "../icons/quick-boost.png" icon.width: Theme.iconSizeExtraSmall icon.height: Theme.iconSizeExtraSmall - onClicked: remorse.execute(boostBtn, qsTr("Starting DHW boost"), - function() { api.sendCommand("hot_water_boost_on") }) + onClicked: remorse.execute( + boostBtn, + api.boostActive ? qsTr("Stopping DHW boost") + : qsTr("Starting DHW boost"), + function() { + api.sendCommand(api.boostActive ? "hot_water_boost_off" + : "hot_water_boost_on") + }) } Button { diff --git a/rpm/harbour-aira.spec b/rpm/harbour-aira.spec index 384767d..c66d095 100644 --- a/rpm/harbour-aira.spec +++ b/rpm/harbour-aira.spec @@ -1,6 +1,6 @@ Name: harbour-aira Summary: Control your Aira heat pump through a local bridge -Version: 0.7.1 +Version: 0.7.2 Release: 1 Group: Qt/Qt License: MIT @@ -37,6 +37,15 @@ 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 - 0.7.2-1 +- il tasto del boost diventa "Stop" (con glifo di stop) mentre il boost e' in + corso, in Home e in copertina: prima un tocco dalla copertina ne faceva + ripartire un altro invece di fermarlo. +- il conto alla rovescia prende il posto del suggerimento nella stessa riga e + con la stessa misura del carattere: essendo piu' alto spingeva giu' i tasti + delle azioni rapide. +- tests/cover_action_check.py controlla tutti i comandi dell'azione (anche + condizionali) e tutte le icone citate. * Sun Oct 11 2026 Carlo - 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, diff --git a/scripts/make_glyphs.py b/scripts/make_glyphs.py index 8c49a59..9cd482c 100644 --- a/scripts/make_glyphs.py +++ b/scripts/make_glyphs.py @@ -72,12 +72,22 @@ def comandi(d, cx, cy, w, h): d.ellipse([kx - r, y - r, kx + r, y + r], fill=BIANCO) +def stop(d, cx, cy, w, h): + """Ferma il boost: quadrato pieno dentro un anello (il segno universale).""" + r = min(w, h) / 2 + d.ellipse([cx - r, cy - r, cx + r, cy + r], outline=BIANCO, + width=max(2, int(h * 0.12))) + q = r * 0.46 + d.rectangle([cx - q, cy - q, cx + q, cy + q], fill=BIANCO) + + def main(): DEST.mkdir(parents=True, exist_ok=True) disegni = ( ("quick-boost.png", fiamma, 0.62), ("quick-away.png", casa, 0.80), ("quick-commands.png", comandi, 0.90), + ("quick-boost-stop.png", stop, 0.90), ) # il glifo riempie il suo riquadro (un filo di margine): la misura sul # telefono la decide Theme.iconSizeExtraSmall nel pulsante, non il file diff --git a/src/main.cpp b/src/main.cpp index ea82147..f75548f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -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.1")); + app->setApplicationVersion(QStringLiteral("0.7.2")); 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.1 build" << __DATE__ << __TIME__; + qDebug() << "harbour-aira v0.7.2 build" << __DATE__ << __TIME__; view->rootContext()->setContextProperty(QStringLiteral("appSettings"), &settings); view->rootContext()->setContextProperty(QStringLiteral("api"), &api); diff --git a/tests/cover_action_check.py b/tests/cover_action_check.py index fb69e96..208e8ca 100644 --- a/tests/cover_action_check.py +++ b/tests/cover_action_check.py @@ -62,7 +62,7 @@ def main(): problemi.append("usa `iconSource`, non `icon.source`: `icon.source` e' del " "pulsante Button e qui non darebbe errore, solo nessuna icona") - for m in re.finditer(r'iconSource\s*:\s*"([^"]+)"', testo): + for m in re.finditer(r'"(\.\./icons/[^"]+\.png)"', testo): icona = (COPERTINA.parent / m.group(1)).resolve() if not icona.exists(): problemi.append("l'icona %s non esiste (risolta da %s)" @@ -70,9 +70,17 @@ def main(): else: print("icona: %s -> %s" % (m.group(1), icona.relative_to(RADICE))) - comandi = re.findall(r'sendCommand\("([^"]+)"', testo) + # L'invio puo' essere condizionale (il tasto del boost avvia o ferma) e + # scritto su piu' righe: si prende tutto il testo fra sendCommand( e la + # parentesi di chiusura, poi tutti i letterali che sembrano un id. + comandi = [] + for m in re.finditer(r"sendCommand\(([^)]*)\)", testo, re.S): + comandi += [s for s in re.findall(r'"([^"]+)"', m.group(1)) + if re.match(r"^[a-z][a-z_]*$", s)] if not comandi: problemi.append("l'azione non invia nessun comando: a che serve?") + else: + print("comandi inviati: %s" % ", ".join(comandi)) for c in comandi: if not BRIDGE.exists(): print("salto il controllo del comando %r: manca %s" % (c, BRIDGE)) diff --git a/translations/harbour-aira-it.ts b/translations/harbour-aira-it.ts index 0a27ec9..19d0b87 100644 --- a/translations/harbour-aira-it.ts +++ b/translations/harbour-aira-it.ts @@ -563,47 +563,57 @@ Acqua calda - + Boost · %1 Boost · %1 - + Tap a value to adjust it Tocca un valore per regolarlo - + Quick actions Azioni rapide - + Boost Boost - + + Stop + Stop + + + + Stopping DHW boost + Fermo il boost + + + Home Torna - + Away Assenza - + Away mode off Assenza disattivata - + More Altro - + Outside %1 °C · Thermostat %2 °C · Zones %3 Esterno %1 °C · Termostato %2 °C · Zone %3 @@ -618,7 +628,7 @@ Bridge non configurato. Apri le impostazioni e inserisci l'indirizzo del server e il token. - + Starting DHW boost Avvio del boost ACS