From 3c1596f0f6cb474699ee9f4d2a3fe752ceb2e61a Mon Sep 17 00:00:00 2001 From: Luuk Visser Date: Thu, 6 Aug 2026 16:22:12 +0200 Subject: [PATCH 1/2] Apply qmlformat to all QML files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Runs pyside6-qmlformat over the four QML files so the repository is clean against the qmlformat hook and the PR Lint workflow, instead of leaving the reformat to whichever change happens to touch a file first. Whitespace only: tabs become four spaces, single-line anchors/width/height blocks expand onto their own lines, single-statement if bodies drop their braces, and the stray semicolon after "import qb.base 1.0" is removed. Verified no semantic change — with whitespace and semicolons stripped, all four files are byte-identical to their previous versions. qmllint passes. Co-Authored-By: Claude Opus 5 --- TscClockApp.qml | 540 ++++++++------- TscClockSettings.qml | 397 ++++++----- TscClockTile.qml | 292 ++++---- TscClockTravelSettings.qml | 1288 ++++++++++++++++++++++-------------- 4 files changed, 1411 insertions(+), 1106 deletions(-) diff --git a/TscClockApp.qml b/TscClockApp.qml index fe87d2c..0d4d376 100644 --- a/TscClockApp.qml +++ b/TscClockApp.qml @@ -1,284 +1,318 @@ import QtQuick 2.1 import qb.components 1.0 -import qb.base 1.0; +import qb.base 1.0 import FileIO 1.0 App { - id: tscClockApp + id: tscClockApp - property url tileUrl : "TscClockTile.qml"; - property url settingsUrl : "TscClockSettings.qml"; - property url travelSettingsUrl : "TscClockTravelSettings.qml"; - property url thumbnailIcon : "drawables/clock.svg"; + property url tileUrl: "TscClockTile.qml" + property url settingsUrl: "TscClockSettings.qml" + property url travelSettingsUrl: "TscClockTravelSettings.qml" + property url thumbnailIcon: "drawables/clock.svg" - property TscClockSettings tscClockSettings - property TscClockTravelSettings tscClockTravelSettings + property TscClockSettings tscClockSettings + property TscClockTravelSettings tscClockTravelSettings - property string timeStr - property string timeSeconds - property string dateStr - property int leftMarginTime : 10 - property bool showSeconds : true - property bool showDate : true - property bool showMonthInText : true - property bool showDayOfWeek : true - property bool centerLayout : false - property bool showDayOnDate : false + property string timeStr + property string timeSeconds + property string dateStr + property int leftMarginTime: 10 + property bool showSeconds: true + property bool showDate: true + property bool showMonthInText: true + property bool showDayOfWeek: true + property bool centerLayout: false + property bool showDayOnDate: false - // Route 1 - property string route1Start : "06:30" - property string route1End : "09:00" - property string route1Label : "Thuis-Werk:" - property string route1FromLat : "" - property string route1FromLon : "" - property string route1ToLat : "" - property string route1ToLon : "" - property bool route1WorkdaysOnly : false - property bool route1WindowEnabled : false // false = ignore time window, always active + // Route 1 + property string route1Start: "06:30" + property string route1End: "09:00" + property string route1Label: "Thuis-Werk:" + property string route1FromLat: "" + property string route1FromLon: "" + property string route1ToLat: "" + property string route1ToLon: "" + property bool route1WorkdaysOnly: false + property bool route1WindowEnabled: false // false = ignore time window, always active - // Route 2 - property string route2Start : "16:00" - property string route2End : "18:30" - property string route2Label : "Werk-Thuis:" - property string route2FromLat : "" - property string route2FromLon : "" - property string route2ToLat : "" - property string route2ToLon : "" - property bool route2WorkdaysOnly : false - property bool route2WindowEnabled : false // false = ignore time window, always active + // Route 2 + property string route2Start: "16:00" + property string route2End: "18:30" + property string route2Label: "Werk-Thuis:" + property string route2FromLat: "" + property string route2FromLon: "" + property string route2ToLat: "" + property string route2ToLon: "" + property bool route2WorkdaysOnly: false + property bool route2WindowEnabled: false // false = ignore time window, always active - // Runtime — not persisted - property string travelTime1Str : "" - property string travelTime2Str : "" - property bool route1Active : false - property bool route2Active : false + // Runtime — not persisted + property string travelTime1Str: "" + property string travelTime2Str: "" + property bool route1Active: false + property bool route2Active: false + FileIO { + id: tscClockSettingsFile + source: "file:///mnt/data/tsc/tscClock.userSettings.json" + } - FileIO { - id: tscClockSettingsFile - source: "file:///mnt/data/tsc/tscClock.userSettings.json" - } + Component.onCompleted: { + try { + var settingsString = tscClockSettingsFile.read(); + var settings = JSON.parse(settingsString); + if (settings['showSeconds']) + showSeconds = (settings['showSeconds'] == "true"); + if (settings['showDate']) + showDate = (settings['showDate'] == "true"); + if (settings['showMonthInText']) + showMonthInText = (settings['showMonthInText'] == "true"); + if (settings['showDayOfWeek']) + showDayOfWeek = (settings['showDayOfWeek'] == "true"); + if (settings['centerLayout']) + centerLayout = (settings['centerLayout'] == "true"); + if (settings['showDayOnDate']) + showDayOnDate = (settings['showDayOnDate'] == "true"); + if (settings['route1Start']) + route1Start = settings['route1Start']; + if (settings['route1End']) + route1End = settings['route1End']; + if (settings['route1Label']) + route1Label = settings['route1Label']; + if (settings['route1FromLat']) + route1FromLat = settings['route1FromLat']; + if (settings['route1FromLon']) + route1FromLon = settings['route1FromLon']; + if (settings['route1ToLat']) + route1ToLat = settings['route1ToLat']; + if (settings['route1ToLon']) + route1ToLon = settings['route1ToLon']; + if (settings['route2Start']) + route2Start = settings['route2Start']; + if (settings['route2End']) + route2End = settings['route2End']; + if (settings['route2Label']) + route2Label = settings['route2Label']; + if (settings['route2FromLat']) + route2FromLat = settings['route2FromLat']; + if (settings['route2FromLon']) + route2FromLon = settings['route2FromLon']; + if (settings['route2ToLat']) + route2ToLat = settings['route2ToLat']; + if (settings['route2ToLon']) + route2ToLon = settings['route2ToLon']; + if (settings['route1WorkdaysOnly']) + route1WorkdaysOnly = (settings['route1WorkdaysOnly'] == "true"); + if (settings['route2WorkdaysOnly']) + route2WorkdaysOnly = (settings['route2WorkdaysOnly'] == "true"); + if (settings['route1WindowEnabled']) + route1WindowEnabled = (settings['route1WindowEnabled'] == "true"); + if (settings['route2WindowEnabled']) + route2WindowEnabled = (settings['route2WindowEnabled'] == "true"); + } catch (e) {} + } - Component.onCompleted: { - try { - var settingsString = tscClockSettingsFile.read(); - var settings = JSON.parse(settingsString); - if (settings['showSeconds']) showSeconds = (settings['showSeconds'] == "true"); - if (settings['showDate']) showDate = (settings['showDate'] == "true"); - if (settings['showMonthInText']) showMonthInText = (settings['showMonthInText'] == "true"); - if (settings['showDayOfWeek']) showDayOfWeek = (settings['showDayOfWeek'] == "true"); - if (settings['centerLayout']) centerLayout = (settings['centerLayout'] == "true"); - if (settings['showDayOnDate']) showDayOnDate = (settings['showDayOnDate'] == "true"); - if (settings['route1Start']) route1Start = settings['route1Start']; - if (settings['route1End']) route1End = settings['route1End']; - if (settings['route1Label']) route1Label = settings['route1Label']; - if (settings['route1FromLat']) route1FromLat = settings['route1FromLat']; - if (settings['route1FromLon']) route1FromLon = settings['route1FromLon']; - if (settings['route1ToLat']) route1ToLat = settings['route1ToLat']; - if (settings['route1ToLon']) route1ToLon = settings['route1ToLon']; - if (settings['route2Start']) route2Start = settings['route2Start']; - if (settings['route2End']) route2End = settings['route2End']; - if (settings['route2Label']) route2Label = settings['route2Label']; - if (settings['route2FromLat']) route2FromLat = settings['route2FromLat']; - if (settings['route2FromLon']) route2FromLon = settings['route2FromLon']; - if (settings['route2ToLat']) route2ToLat = settings['route2ToLat']; - if (settings['route2ToLon']) route2ToLon = settings['route2ToLon']; - if (settings['route1WorkdaysOnly']) route1WorkdaysOnly = (settings['route1WorkdaysOnly'] == "true"); - if (settings['route2WorkdaysOnly']) route2WorkdaysOnly = (settings['route2WorkdaysOnly'] == "true"); - if (settings['route1WindowEnabled']) route1WindowEnabled = (settings['route1WindowEnabled'] == "true"); - if (settings['route2WindowEnabled']) route2WindowEnabled = (settings['route2WindowEnabled'] == "true"); - } catch(e) { - } - } + function init() { + registry.registerWidget("tile", tileUrl, this, null, { + thumbLabel: qsTr("Klok-TSC"), + thumbIcon: thumbnailIcon, + thumbCategory: "general", + thumbWeight: 30, + baseTileWeight: 10, + thumbIconVAlignment: "center" + }); + registry.registerWidget("screen", settingsUrl, this, "tscClockSettings"); + registry.registerWidget("screen", travelSettingsUrl, this, "tscClockTravelSettings"); + } - function init() { - registry.registerWidget("tile", tileUrl, this, null, {thumbLabel: qsTr("Klok-TSC"), thumbIcon: thumbnailIcon, thumbCategory: "general", thumbWeight: 30, baseTileWeight: 10, thumbIconVAlignment: "center"}); - registry.registerWidget("screen", settingsUrl, this, "tscClockSettings"); - registry.registerWidget("screen", travelSettingsUrl, this, "tscClockTravelSettings"); - } + function updateClockTiles() { + var now = new Date().getTime(); + timeSeconds = new Date().getSeconds(); + if (timeSeconds.length == 1) + timeSeconds = "0" + timeSeconds; - function updateClockTiles() { - var now = new Date().getTime(); - timeSeconds = new Date().getSeconds(); - if (timeSeconds.length == 1) timeSeconds = "0" + timeSeconds; + if (showDayOfWeek && !showDayOnDate) { + timeStr = i18n.dateTime(now, i18n.dow_full).substring(0, 2).toLowerCase() + " " + i18n.dateTime(now, i18n.time_yes); + leftMarginTime = isNxt ? 8 : 6; + } else { + timeStr = i18n.dateTime(now, i18n.time_yes); + leftMarginTime = isNxt ? 60 : 48; + if (showSeconds) + leftMarginTime = leftMarginTime - 15; + } - if (showDayOfWeek && !showDayOnDate) { - timeStr = i18n.dateTime(now, i18n.dow_full).substring(0,2).toLowerCase() + " " + i18n.dateTime(now, i18n.time_yes); - leftMarginTime = isNxt ? 8 : 6; - } else { - timeStr = i18n.dateTime(now, i18n.time_yes); - leftMarginTime = isNxt ? 60 : 48; - if (showSeconds) leftMarginTime = leftMarginTime - 15; - } + var dateBase = showMonthInText ? i18n.dateTime(now, i18n.mon_full) : i18n.dateTime(now, i18n.mon_num); + if (showDayOfWeek && showDayOnDate) { + dateStr = i18n.dateTime(now, i18n.dow_full).substring(0, 2).toLowerCase() + " " + dateBase; + } else { + dateStr = dateBase; + } - var dateBase = showMonthInText ? i18n.dateTime(now, i18n.mon_full) : i18n.dateTime(now, i18n.mon_num); - if (showDayOfWeek && showDayOnDate) { - dateStr = i18n.dateTime(now, i18n.dow_full).substring(0,2).toLowerCase() + " " + dateBase; - } else { - dateStr = dateBase; - } + checkTravelTimeWindow(); + } - checkTravelTimeWindow(); - } + function minutesOfDay(timeStr) { + var parts = timeStr.split(":"); + if (parts.length !== 2) + return -1; + return parseInt(parts[0]) * 60 + parseInt(parts[1]); + } - function minutesOfDay(timeStr) { - var parts = timeStr.split(":"); - if (parts.length !== 2) return -1; - return parseInt(parts[0]) * 60 + parseInt(parts[1]); - } + function setTravelTime(slot, str) { + if (slot === 1) + travelTime1Str = str; + else + travelTime2Str = str; + } - function setTravelTime(slot, str) { - if (slot === 1) travelTime1Str = str; - else travelTime2Str = str; - } + function fetchTravelTime(slot, fromLat, fromLon, toLat, toLon, label) { + if (!fromLat || !fromLon || !toLat || !toLon) { + console.log("Waze: skipping fetch, missing coordinates"); + return; + } + // Accept Dutch decimal commas and stray whitespace + fromLat = String(fromLat).trim().replace(",", "."); + fromLon = String(fromLon).trim().replace(",", "."); + toLat = String(toLat).trim().replace(",", "."); + toLon = String(toLon).trim().replace(",", "."); + var lbl = label || ""; + var url = "https://routing-livemap-row.waze.com/RoutingManager/routingRequest" + "?from=x%3A" + fromLon + "+y%3A" + fromLat + "&to=x%3A" + toLon + "+y%3A" + toLat + "&at=0&returnJSON=true&returnGeometries=false" + "&returnInstructions=false&timeout=60000&nPaths=1"; + console.log("Waze: GET " + url); + var xhr = new XMLHttpRequest(); + xhr.onreadystatechange = function () { + if (xhr.readyState !== XMLHttpRequest.DONE) + return; + // Break the xhr <-> handler reference cycle so the request object + // (and its closure) can be garbage-collected instead of leaking. + xhr.onreadystatechange = null; + if (xhr.status !== 200) { + console.log("Waze: HTTP " + xhr.status + " — " + (xhr.responseText || "").substring(0, 200)); + return; + } + try { + var data = JSON.parse(xhr.responseText); + // nPaths=1 returns data.response.results; multi-path returns data.alternatives[]. + var results = data.alternatives ? data.alternatives[0].response.results : data.response.results; + var secs = 0; + for (var i = 0; i < results.length; i++) + secs += results[i].crossTime; + var str = (lbl ? lbl + " " : "") + Math.round(secs / 60) + " min"; + setTravelTime(slot, str); + console.log("Waze: ok — " + str); + } catch (e) { + console.log("Waze: parse error — " + e + " — body: " + (xhr.responseText || "").substring(0, 200)); + } + }; + xhr.open("GET", url); + xhr.send(); + } - function fetchTravelTime(slot, fromLat, fromLon, toLat, toLon, label) { - if (!fromLat || !fromLon || !toLat || !toLon) { - console.log("Waze: skipping fetch, missing coordinates"); - return; - } - // Accept Dutch decimal commas and stray whitespace - fromLat = String(fromLat).trim().replace(",", "."); - fromLon = String(fromLon).trim().replace(",", "."); - toLat = String(toLat).trim().replace(",", "."); - toLon = String(toLon).trim().replace(",", "."); - var lbl = label || ""; - var url = "https://routing-livemap-row.waze.com/RoutingManager/routingRequest" + - "?from=x%3A" + fromLon + "+y%3A" + fromLat + - "&to=x%3A" + toLon + "+y%3A" + toLat + - "&at=0&returnJSON=true&returnGeometries=false" + - "&returnInstructions=false&timeout=60000&nPaths=1"; - console.log("Waze: GET " + url); - var xhr = new XMLHttpRequest(); - xhr.onreadystatechange = function() { - if (xhr.readyState !== XMLHttpRequest.DONE) return; - // Break the xhr <-> handler reference cycle so the request object - // (and its closure) can be garbage-collected instead of leaking. - xhr.onreadystatechange = null; - if (xhr.status !== 200) { - console.log("Waze: HTTP " + xhr.status + " — " + (xhr.responseText || "").substring(0, 200)); - return; - } - try { - var data = JSON.parse(xhr.responseText); - // nPaths=1 returns data.response.results; multi-path returns data.alternatives[]. - var results = data.alternatives - ? data.alternatives[0].response.results - : data.response.results; - var secs = 0; - for (var i = 0; i < results.length; i++) secs += results[i].crossTime; - var str = (lbl ? lbl + " " : "") + Math.round(secs / 60) + " min"; - setTravelTime(slot, str); - console.log("Waze: ok — " + str); - } catch(e) { - console.log("Waze: parse error — " + e + " — body: " + (xhr.responseText || "").substring(0, 200)); - } - }; - xhr.open("GET", url); - xhr.send(); - } + // Whether a route should currently be shown. When its time window is + // disabled the route is always active (still subject to workdays-only); + // otherwise the current time must fall inside [start, end). + function routeIsActive(rs, re, windowEnabled, workdaysOnly, current, isWorkday) { + if (workdaysOnly && !isWorkday) + return false; + if (!windowEnabled) + return true; + return rs >= 0 && re > rs && current >= rs && current < re; + } - // Whether a route should currently be shown. When its time window is - // disabled the route is always active (still subject to workdays-only); - // otherwise the current time must fall inside [start, end). - function routeIsActive(rs, re, windowEnabled, workdaysOnly, current, isWorkday) { - if (workdaysOnly && !isWorkday) return false; - if (!windowEnabled) return true; - return rs >= 0 && re > rs && current >= rs && current < re; - } + function checkTravelTimeWindow() { + var now = new Date(); + var current = now.getHours() * 60 + now.getMinutes(); + var dow = now.getDay(); // 0=Sunday … 6=Saturday + var isWorkday = dow >= 1 && dow <= 5; + var r1s = minutesOfDay(route1Start), r1e = minutesOfDay(route1End); + var r2s = minutesOfDay(route2Start), r2e = minutesOfDay(route2End); - function checkTravelTimeWindow() { - var now = new Date(); - var current = now.getHours() * 60 + now.getMinutes(); - var dow = now.getDay(); // 0=Sunday … 6=Saturday - var isWorkday = dow >= 1 && dow <= 5; - var r1s = minutesOfDay(route1Start), r1e = minutesOfDay(route1End); - var r2s = minutesOfDay(route2Start), r2e = minutesOfDay(route2End); + // Each route is evaluated independently so overlapping windows show both. + var a1 = routeIsActive(r1s, r1e, route1WindowEnabled, route1WorkdaysOnly, current, isWorkday); + var a2 = routeIsActive(r2s, r2e, route2WindowEnabled, route2WorkdaysOnly, current, isWorkday); - // Each route is evaluated independently so overlapping windows show both. - var a1 = routeIsActive(r1s, r1e, route1WindowEnabled, route1WorkdaysOnly, current, isWorkday); - var a2 = routeIsActive(r2s, r2e, route2WindowEnabled, route2WorkdaysOnly, current, isWorkday); + // Fetch only on the transition into the active state (so we don't refetch + // every tick), but always clear when inactive so a stale value can never + // linger — e.g. after a settings change flips a route to inactive. + if (a1) { + if (!route1Active) { + route1Active = true; + fetchTravelTime(1, route1FromLat, route1FromLon, route1ToLat, route1ToLon, route1Label); + } + } else { + route1Active = false; + travelTime1Str = ""; + } + if (a2) { + if (!route2Active) { + route2Active = true; + fetchTravelTime(2, route2FromLat, route2FromLon, route2ToLat, route2ToLon, route2Label); + } + } else { + route2Active = false; + travelTime2Str = ""; + } + } - // Fetch only on the transition into the active state (so we don't refetch - // every tick), but always clear when inactive so a stale value can never - // linger — e.g. after a settings change flips a route to inactive. - if (a1) { - if (!route1Active) { - route1Active = true; - fetchTravelTime(1, route1FromLat, route1FromLon, route1ToLat, route1ToLon, route1Label); - } - } else { - route1Active = false; - travelTime1Str = ""; - } - if (a2) { - if (!route2Active) { - route2Active = true; - fetchTravelTime(2, route2FromLat, route2FromLon, route2ToLat, route2ToLon, route2Label); - } - } else { - route2Active = false; - travelTime2Str = ""; - } - } + function saveSettings() { + var tmpshowSeconds = showSeconds ? "true" : "false"; + var tmpshowDate = showDate ? "true" : "false"; + var tmpshowMonthInText = showMonthInText ? "true" : "false"; + var tmpshowDayOfWeek = showDayOfWeek ? "true" : "false"; + var tmpCenterLayout = centerLayout ? "true" : "false"; + var tmpshowDayOnDate = showDayOnDate ? "true" : "false"; - function saveSettings() { - var tmpshowSeconds = showSeconds ? "true" : "false"; - var tmpshowDate = showDate ? "true" : "false"; - var tmpshowMonthInText = showMonthInText ? "true" : "false"; - var tmpshowDayOfWeek = showDayOfWeek ? "true" : "false"; - var tmpCenterLayout = centerLayout ? "true" : "false"; - var tmpshowDayOnDate = showDayOnDate ? "true" : "false"; + var tscClockSettingsJson = { + "showSeconds": tmpshowSeconds, + "showDate": tmpshowDate, + "showMonthInText": tmpshowMonthInText, + "showDayOfWeek": tmpshowDayOfWeek, + "centerLayout": tmpCenterLayout, + "showDayOnDate": tmpshowDayOnDate, + "route1Start": route1Start, + "route1End": route1End, + "route1Label": route1Label, + "route1FromLat": route1FromLat, + "route1FromLon": route1FromLon, + "route1ToLat": route1ToLat, + "route1ToLon": route1ToLon, + "route2Start": route2Start, + "route2End": route2End, + "route2Label": route2Label, + "route2FromLat": route2FromLat, + "route2FromLon": route2FromLon, + "route2ToLat": route2ToLat, + "route2ToLon": route2ToLon, + "route1WorkdaysOnly": route1WorkdaysOnly ? "true" : "false", + "route2WorkdaysOnly": route2WorkdaysOnly ? "true" : "false", + "route1WindowEnabled": route1WindowEnabled ? "true" : "false", + "route2WindowEnabled": route2WindowEnabled ? "true" : "false" + }; - var tscClockSettingsJson = { - "showSeconds" : tmpshowSeconds, - "showDate" : tmpshowDate, - "showMonthInText": tmpshowMonthInText, - "showDayOfWeek" : tmpshowDayOfWeek, - "centerLayout" : tmpCenterLayout, - "showDayOnDate" : tmpshowDayOnDate, - "route1Start" : route1Start, - "route1End" : route1End, - "route1Label" : route1Label, - "route1FromLat" : route1FromLat, - "route1FromLon" : route1FromLon, - "route1ToLat" : route1ToLat, - "route1ToLon" : route1ToLon, - "route2Start" : route2Start, - "route2End" : route2End, - "route2Label" : route2Label, - "route2FromLat" : route2FromLat, - "route2FromLon" : route2FromLon, - "route2ToLat" : route2ToLat, - "route2ToLon" : route2ToLon, - "route1WorkdaysOnly" : route1WorkdaysOnly ? "true" : "false", - "route2WorkdaysOnly" : route2WorkdaysOnly ? "true" : "false", - "route1WindowEnabled" : route1WindowEnabled ? "true" : "false", - "route2WindowEnabled" : route2WindowEnabled ? "true" : "false" - } + var doc3 = new XMLHttpRequest(); + doc3.open("PUT", "file:///mnt/data/tsc/tscClock.userSettings.json"); + doc3.send(JSON.stringify(tscClockSettingsJson)); + } - var doc3 = new XMLHttpRequest(); - doc3.open("PUT", "file:///mnt/data/tsc/tscClock.userSettings.json"); - doc3.send(JSON.stringify(tscClockSettingsJson)); - } + Timer { + id: datetimeTimer + interval: 1000 + triggeredOnStart: true + running: true + repeat: true + onTriggered: updateClockTiles() + } - Timer { - id: datetimeTimer - interval: 1000 - triggeredOnStart: true - running: true - repeat: true - onTriggered: updateClockTiles() - } - - Timer { - id: travelTimeRefreshTimer - interval: 300000 // 5 minutes - running: true - repeat: true - onTriggered: { - if (route1Active) fetchTravelTime(1, route1FromLat, route1FromLon, route1ToLat, route1ToLon, route1Label); - if (route2Active) fetchTravelTime(2, route2FromLat, route2FromLon, route2ToLat, route2ToLon, route2Label); - } - } + Timer { + id: travelTimeRefreshTimer + interval: 300000 // 5 minutes + running: true + repeat: true + onTriggered: { + if (route1Active) + fetchTravelTime(1, route1FromLat, route1FromLon, route1ToLat, route1ToLon, route1Label); + if (route2Active) + fetchTravelTime(2, route2FromLat, route2FromLon, route2ToLat, route2ToLon, route2Label); + } + } } diff --git a/TscClockSettings.qml b/TscClockSettings.qml index b3eaa7d..f3b6ade 100644 --- a/TscClockSettings.qml +++ b/TscClockSettings.qml @@ -3,204 +3,201 @@ import qb.components 1.0 import BxtClient 1.0 Screen { - id: tscClockSettingsScreen - - - screenTitle: "TSC Klok configuratie" - - onShown: { - addCustomTopRightButton("Opslaan"); - showDateToggle.isSwitchedOn = app.showDate; - showSecondsToggle.isSwitchedOn = app.showSeconds; - showMonthInTextToggle.isSwitchedOn = app.showMonthInText; - showDayOfWeekToggle.isSwitchedOn = app.showDayOfWeek; - centerLayoutToggle.isSwitchedOn = app.centerLayout; - showDayOnDateToggle.isSwitchedOn = app.showDayOnDate; - } - - onCustomButtonClicked: { - app.saveSettings(); - app.updateClockTiles(); - hide(); - } - - - Text { - id: showDateText - x: isNxt ? 36 : 30 - y: isNxt ? 60 : 50 - width: isNxt ? 500 : 400 - font.pixelSize: isNxt ? 20 : 16 - font.family: qfont.semiBold.name - text: "Toon datum" - } - - OnOffToggle { - id: showDateToggle - height: isNxt ? 45 : 36 - anchors.left: showDateText.right - anchors.leftMargin: isNxt ? 25 : 20 - anchors.top: showDateText.top - leftIsSwitchedOn: false - onSelectedChangedByUser: { - if (isSwitchedOn) { - app.showDate = true; - } else { - app.showDate = false; - } - } - } - - - Text { - id: showSecondsText - anchors { - top: showDateText.bottom - topMargin: isNxt ? 25 : 20 - left: showDateText.left - } - font.pixelSize: isNxt ? 20 : 16 - font.family: qfont.semiBold.name - text: "Toon seconden in de tijd" - } - - OnOffToggle { - id: showSecondsToggle - height: isNxt ? 45 : 36 - anchors.left: showDateToggle.left - anchors.top: showSecondsText.top - leftIsSwitchedOn: false - onSelectedChangedByUser: { - if (isSwitchedOn) { - app.showSeconds = true - } else { - app.showSeconds = false - } - } - } - - Text { - id: showMonthInTextText - anchors { - top: showSecondsText.bottom - topMargin: isNxt ? 25 : 20 - left: showSecondsText.left - } - font.pixelSize: isNxt ? 20 : 16 - font.family: qfont.semiBold.name - text: "Maand in datum voluit geschreven" - opacity: app.showDate ? 1.0 : 0.35 - } - - OnOffToggle { - id: showMonthInTextToggle - height: isNxt ? 45 : 36 - anchors.left: showSecondsToggle.left - anchors.top: showMonthInTextText.top - leftIsSwitchedOn: false - enabled: app.showDate - opacity: app.showDate ? 1.0 : 0.35 - onSelectedChangedByUser: { - if (isSwitchedOn) { - app.showMonthInText = true; - } else { - app.showMonthInText = false; - } - } - } - - Text { - id: showDayOfWeekText - anchors { - top: showMonthInTextText.bottom - topMargin: isNxt ? 25 : 20 - left: showSecondsText.left - } - font.pixelSize: isNxt ? 20 : 16 - font.family: qfont.semiBold.name - text: "Toon dag van de week" - } - - OnOffToggle { - id: showDayOfWeekToggle - height: isNxt ? 45 : 36 - anchors.left: showSecondsToggle.left - anchors.top: showDayOfWeekText.top - leftIsSwitchedOn: false - onSelectedChangedByUser: { - if (isSwitchedOn) { - app.showDayOfWeek = true; - } else { - app.showDayOfWeek = false; - } - } - } - - Text { - id: centerLayoutText - anchors { - top: showDayOfWeekText.bottom - topMargin: isNxt ? 25 : 20 - left: showDayOfWeekText.left - } - font.pixelSize: isNxt ? 20 : 16 - font.family: qfont.semiBold.name - text: "Verticaal gecentreerde weergave" - } - - OnOffToggle { - id: centerLayoutToggle - height: isNxt ? 45 : 36 - anchors.left: showDayOfWeekToggle.left - anchors.top: centerLayoutText.top - leftIsSwitchedOn: false - onSelectedChangedByUser: { - app.centerLayout = isSwitchedOn; - } - } - - Text { - id: showDayOnDateText - anchors { - top: centerLayoutText.bottom - topMargin: isNxt ? 25 : 20 - left: centerLayoutText.left - } - font.pixelSize: isNxt ? 20 : 16 - font.family: qfont.semiBold.name - text: "Dag voor datum (i.p.v. voor tijd)" - visible: app.showDayOfWeek - opacity: app.showDate ? 1.0 : 0.35 - } - - OnOffToggle { - id: showDayOnDateToggle - height: isNxt ? 45 : 36 - anchors.left: centerLayoutToggle.left - anchors.top: showDayOnDateText.top - leftIsSwitchedOn: false - visible: app.showDayOfWeek - enabled: app.showDate - opacity: app.showDate ? 1.0 : 0.35 - onSelectedChangedByUser: { - app.showDayOnDate = isSwitchedOn; - } - } - - Text { - id: travelSettingsNavText - anchors { - top: showDayOnDateText.bottom - topMargin: isNxt ? 30 : 22 - left: showDayOnDateText.left - } - font.pixelSize: isNxt ? 20 : 16 - font.family: qfont.semiBold.name - text: "Waze reistijd »" - - MouseArea { - anchors.fill: parent - onClicked: app.tscClockTravelSettings.show() - } - } + id: tscClockSettingsScreen + + screenTitle: "TSC Klok configuratie" + + onShown: { + addCustomTopRightButton("Opslaan"); + showDateToggle.isSwitchedOn = app.showDate; + showSecondsToggle.isSwitchedOn = app.showSeconds; + showMonthInTextToggle.isSwitchedOn = app.showMonthInText; + showDayOfWeekToggle.isSwitchedOn = app.showDayOfWeek; + centerLayoutToggle.isSwitchedOn = app.centerLayout; + showDayOnDateToggle.isSwitchedOn = app.showDayOnDate; + } + + onCustomButtonClicked: { + app.saveSettings(); + app.updateClockTiles(); + hide(); + } + + Text { + id: showDateText + x: isNxt ? 36 : 30 + y: isNxt ? 60 : 50 + width: isNxt ? 500 : 400 + font.pixelSize: isNxt ? 20 : 16 + font.family: qfont.semiBold.name + text: "Toon datum" + } + + OnOffToggle { + id: showDateToggle + height: isNxt ? 45 : 36 + anchors.left: showDateText.right + anchors.leftMargin: isNxt ? 25 : 20 + anchors.top: showDateText.top + leftIsSwitchedOn: false + onSelectedChangedByUser: { + if (isSwitchedOn) { + app.showDate = true; + } else { + app.showDate = false; + } + } + } + + Text { + id: showSecondsText + anchors { + top: showDateText.bottom + topMargin: isNxt ? 25 : 20 + left: showDateText.left + } + font.pixelSize: isNxt ? 20 : 16 + font.family: qfont.semiBold.name + text: "Toon seconden in de tijd" + } + + OnOffToggle { + id: showSecondsToggle + height: isNxt ? 45 : 36 + anchors.left: showDateToggle.left + anchors.top: showSecondsText.top + leftIsSwitchedOn: false + onSelectedChangedByUser: { + if (isSwitchedOn) { + app.showSeconds = true; + } else { + app.showSeconds = false; + } + } + } + + Text { + id: showMonthInTextText + anchors { + top: showSecondsText.bottom + topMargin: isNxt ? 25 : 20 + left: showSecondsText.left + } + font.pixelSize: isNxt ? 20 : 16 + font.family: qfont.semiBold.name + text: "Maand in datum voluit geschreven" + opacity: app.showDate ? 1.0 : 0.35 + } + + OnOffToggle { + id: showMonthInTextToggle + height: isNxt ? 45 : 36 + anchors.left: showSecondsToggle.left + anchors.top: showMonthInTextText.top + leftIsSwitchedOn: false + enabled: app.showDate + opacity: app.showDate ? 1.0 : 0.35 + onSelectedChangedByUser: { + if (isSwitchedOn) { + app.showMonthInText = true; + } else { + app.showMonthInText = false; + } + } + } + + Text { + id: showDayOfWeekText + anchors { + top: showMonthInTextText.bottom + topMargin: isNxt ? 25 : 20 + left: showSecondsText.left + } + font.pixelSize: isNxt ? 20 : 16 + font.family: qfont.semiBold.name + text: "Toon dag van de week" + } + + OnOffToggle { + id: showDayOfWeekToggle + height: isNxt ? 45 : 36 + anchors.left: showSecondsToggle.left + anchors.top: showDayOfWeekText.top + leftIsSwitchedOn: false + onSelectedChangedByUser: { + if (isSwitchedOn) { + app.showDayOfWeek = true; + } else { + app.showDayOfWeek = false; + } + } + } + + Text { + id: centerLayoutText + anchors { + top: showDayOfWeekText.bottom + topMargin: isNxt ? 25 : 20 + left: showDayOfWeekText.left + } + font.pixelSize: isNxt ? 20 : 16 + font.family: qfont.semiBold.name + text: "Verticaal gecentreerde weergave" + } + + OnOffToggle { + id: centerLayoutToggle + height: isNxt ? 45 : 36 + anchors.left: showDayOfWeekToggle.left + anchors.top: centerLayoutText.top + leftIsSwitchedOn: false + onSelectedChangedByUser: { + app.centerLayout = isSwitchedOn; + } + } + + Text { + id: showDayOnDateText + anchors { + top: centerLayoutText.bottom + topMargin: isNxt ? 25 : 20 + left: centerLayoutText.left + } + font.pixelSize: isNxt ? 20 : 16 + font.family: qfont.semiBold.name + text: "Dag voor datum (i.p.v. voor tijd)" + visible: app.showDayOfWeek + opacity: app.showDate ? 1.0 : 0.35 + } + + OnOffToggle { + id: showDayOnDateToggle + height: isNxt ? 45 : 36 + anchors.left: centerLayoutToggle.left + anchors.top: showDayOnDateText.top + leftIsSwitchedOn: false + visible: app.showDayOfWeek + enabled: app.showDate + opacity: app.showDate ? 1.0 : 0.35 + onSelectedChangedByUser: { + app.showDayOnDate = isSwitchedOn; + } + } + + Text { + id: travelSettingsNavText + anchors { + top: showDayOnDateText.bottom + topMargin: isNxt ? 30 : 22 + left: showDayOnDateText.left + } + font.pixelSize: isNxt ? 20 : 16 + font.family: qfont.semiBold.name + text: "Waze reistijd »" + + MouseArea { + anchors.fill: parent + onClicked: app.tscClockTravelSettings.show() + } + } } diff --git a/TscClockTile.qml b/TscClockTile.qml index 51efcff..23f3d92 100644 --- a/TscClockTile.qml +++ b/TscClockTile.qml @@ -3,164 +3,164 @@ import QtQuick 2.1 import qb.components 1.0 Tile { - id: tscClockTile + id: tscClockTile - onClicked: { - if (app.tscClockSettings) - app.tscClockSettings.show(); - } + onClicked: { + if (app.tscClockSettings) + app.tscClockSettings.show(); + } - // --- CENTRED LAYOUT --- - Column { - width: parent.width - anchors.verticalCenter: parent.verticalCenter - spacing: isNxt ? 8 : 6 - visible: app.centerLayout + // --- CENTRED LAYOUT --- + Column { + width: parent.width + anchors.verticalCenter: parent.verticalCenter + spacing: isNxt ? 8 : 6 + visible: app.centerLayout - Item { - width: parent.width - height: txtTimeBigCentered.implicitHeight + Item { + width: parent.width + height: txtTimeBigCentered.implicitHeight - Text { - id: txtTimeBigCentered - text: app.timeStr - color: (typeof dimmableColors !== 'undefined') ? dimmableColors.clockTileColor : colors.clockTileColor - anchors.horizontalCenter: parent.horizontalCenter - anchors.horizontalCenterOffset: app.showSeconds ? -Math.round((txtSecondsCentered.implicitWidth + (isNxt ? 5 : 4)) / 2) : 0 - font.pixelSize: app.showDayOnDate ? (isNxt ? 75 : 58) : (isNxt ? 65 : 50) - font.family: qfont.regular.name - } + Text { + id: txtTimeBigCentered + text: app.timeStr + color: (typeof dimmableColors !== 'undefined') ? dimmableColors.clockTileColor : colors.clockTileColor + anchors.horizontalCenter: parent.horizontalCenter + anchors.horizontalCenterOffset: app.showSeconds ? -Math.round((txtSecondsCentered.implicitWidth + (isNxt ? 5 : 4)) / 2) : 0 + font.pixelSize: app.showDayOnDate ? (isNxt ? 75 : 58) : (isNxt ? 65 : 50) + font.family: qfont.regular.name + } - Text { - id: txtSecondsCentered - text: app.timeSeconds - color: (typeof dimmableColors !== 'undefined') ? dimmableColors.clockTileColor : colors.clockTileColor - anchors { - bottom: txtTimeBigCentered.bottom - bottomMargin: isNxt ? 11 : 9 - left: txtTimeBigCentered.right - leftMargin: isNxt ? 5 : 4 - } - font.pixelSize: isNxt ? 30 : 24 - font.family: qfont.regular.name - visible: app.showSeconds - } - } + Text { + id: txtSecondsCentered + text: app.timeSeconds + color: (typeof dimmableColors !== 'undefined') ? dimmableColors.clockTileColor : colors.clockTileColor + anchors { + bottom: txtTimeBigCentered.bottom + bottomMargin: isNxt ? 11 : 9 + left: txtTimeBigCentered.right + leftMargin: isNxt ? 5 : 4 + } + font.pixelSize: isNxt ? 30 : 24 + font.family: qfont.regular.name + visible: app.showSeconds + } + } - Text { - id: txtDateCentered - text: app.dateStr - color: (typeof dimmableColors !== 'undefined') ? dimmableColors.clockTileColor : colors.clockTileColor - anchors.horizontalCenter: parent.horizontalCenter - horizontalAlignment: Text.AlignHCenter - font.pixelSize: isNxt ? 32 : 25 - font.family: qfont.regular.name - visible: app.showDate - height: app.showDate ? implicitHeight : 0 - } + Text { + id: txtDateCentered + text: app.dateStr + color: (typeof dimmableColors !== 'undefined') ? dimmableColors.clockTileColor : colors.clockTileColor + anchors.horizontalCenter: parent.horizontalCenter + horizontalAlignment: Text.AlignHCenter + font.pixelSize: isNxt ? 32 : 25 + font.family: qfont.regular.name + visible: app.showDate + height: app.showDate ? implicitHeight : 0 + } - Text { - id: txtTravel1Centered - text: app.travelTime1Str - color: (typeof dimmableColors !== 'undefined') ? dimmableColors.clockTileColor : colors.clockTileColor - anchors.horizontalCenter: parent.horizontalCenter - font.pixelSize: isNxt ? 20 : 16 - font.family: qfont.regular.name - visible: app.travelTime1Str !== "" - height: app.travelTime1Str !== "" ? implicitHeight : 0 - } + Text { + id: txtTravel1Centered + text: app.travelTime1Str + color: (typeof dimmableColors !== 'undefined') ? dimmableColors.clockTileColor : colors.clockTileColor + anchors.horizontalCenter: parent.horizontalCenter + font.pixelSize: isNxt ? 20 : 16 + font.family: qfont.regular.name + visible: app.travelTime1Str !== "" + height: app.travelTime1Str !== "" ? implicitHeight : 0 + } - Text { - id: txtTravel2Centered - text: app.travelTime2Str - color: (typeof dimmableColors !== 'undefined') ? dimmableColors.clockTileColor : colors.clockTileColor - anchors.horizontalCenter: parent.horizontalCenter - font.pixelSize: isNxt ? 20 : 16 - font.family: qfont.regular.name - visible: app.travelTime2Str !== "" - height: app.travelTime2Str !== "" ? implicitHeight : 0 - } - } + Text { + id: txtTravel2Centered + text: app.travelTime2Str + color: (typeof dimmableColors !== 'undefined') ? dimmableColors.clockTileColor : colors.clockTileColor + anchors.horizontalCenter: parent.horizontalCenter + font.pixelSize: isNxt ? 20 : 16 + font.family: qfont.regular.name + visible: app.travelTime2Str !== "" + height: app.travelTime2Str !== "" ? implicitHeight : 0 + } + } - // --- ORIGINAL LAYOUT --- - Text { - id: txtTimeBig - text: app.timeStr - color: (typeof dimmableColors !== 'undefined') ? dimmableColors.clockTileColor: colors.clockTileColor - anchors { - baseline: parent.top - baselineOffset: isNxt ? 70 : 55 - left: parent.left - leftMargin: app.leftMarginTime - } - font.pixelSize: app.showDayOnDate ? (isNxt ? 75 : 58) : (isNxt ? 65 : 50) - font.family: qfont.regular.name - visible: !app.centerLayout - } + // --- ORIGINAL LAYOUT --- + Text { + id: txtTimeBig + text: app.timeStr + color: (typeof dimmableColors !== 'undefined') ? dimmableColors.clockTileColor : colors.clockTileColor + anchors { + baseline: parent.top + baselineOffset: isNxt ? 70 : 55 + left: parent.left + leftMargin: app.leftMarginTime + } + font.pixelSize: app.showDayOnDate ? (isNxt ? 75 : 58) : (isNxt ? 65 : 50) + font.family: qfont.regular.name + visible: !app.centerLayout + } - Text { - id: txtSeconds - text: app.timeSeconds - color: (typeof dimmableColors !== 'undefined') ? dimmableColors.clockTileColor: colors.clockTileColor - anchors { - bottom: txtTimeBig.bottom - bottomMargin: isNxt ? 11 : 9 - left: txtTimeBig.right - leftMargin: isNxt ? 5 : 4 - } - font.pixelSize: isNxt ? 30 : 24 - font.family: qfont.regular.name - visible: app.showSeconds && !app.centerLayout - } + Text { + id: txtSeconds + text: app.timeSeconds + color: (typeof dimmableColors !== 'undefined') ? dimmableColors.clockTileColor : colors.clockTileColor + anchors { + bottom: txtTimeBig.bottom + bottomMargin: isNxt ? 11 : 9 + left: txtTimeBig.right + leftMargin: isNxt ? 5 : 4 + } + font.pixelSize: isNxt ? 30 : 24 + font.family: qfont.regular.name + visible: app.showSeconds && !app.centerLayout + } - Text { - id: txtDate - text: app.dateStr - color: (typeof dimmableColors !== 'undefined') ? dimmableColors.clockTileColor: colors.clockTileColor - anchors { - baseline: parent.top - baselineOffset: isNxt ? 120 : 95 - horizontalCenter: parent.horizontalCenter - } - horizontalAlignment: Text.AlignHCenter - font.pixelSize: isNxt ? 32 : 25 - font.family: qfont.regular.name - visible: app.showDate && !app.centerLayout - } + Text { + id: txtDate + text: app.dateStr + color: (typeof dimmableColors !== 'undefined') ? dimmableColors.clockTileColor : colors.clockTileColor + anchors { + baseline: parent.top + baselineOffset: isNxt ? 120 : 95 + horizontalCenter: parent.horizontalCenter + } + horizontalAlignment: Text.AlignHCenter + font.pixelSize: isNxt ? 32 : 25 + font.family: qfont.regular.name + visible: app.showDate && !app.centerLayout + } - Column { - id: travelColumn - anchors { - // Approximate the old single-line baseline (158/125) as a top offset; - // the first line's ascent (~16/13 px) puts its baseline at that spot. - top: parent.top - topMargin: isNxt ? 142 : 112 - horizontalCenter: parent.horizontalCenter - } - visible: !app.centerLayout + Column { + id: travelColumn + anchors { + // Approximate the old single-line baseline (158/125) as a top offset; + // the first line's ascent (~16/13 px) puts its baseline at that spot. + top: parent.top + topMargin: isNxt ? 142 : 112 + horizontalCenter: parent.horizontalCenter + } + visible: !app.centerLayout - Text { - id: txtTravelTime1 - text: app.travelTime1Str - color: (typeof dimmableColors !== 'undefined') ? dimmableColors.clockTileColor: colors.clockTileColor - anchors.horizontalCenter: parent.horizontalCenter - horizontalAlignment: Text.AlignHCenter - font.pixelSize: isNxt ? 20 : 16 - font.family: qfont.regular.name - visible: app.travelTime1Str !== "" - height: app.travelTime1Str !== "" ? implicitHeight : 0 - } + Text { + id: txtTravelTime1 + text: app.travelTime1Str + color: (typeof dimmableColors !== 'undefined') ? dimmableColors.clockTileColor : colors.clockTileColor + anchors.horizontalCenter: parent.horizontalCenter + horizontalAlignment: Text.AlignHCenter + font.pixelSize: isNxt ? 20 : 16 + font.family: qfont.regular.name + visible: app.travelTime1Str !== "" + height: app.travelTime1Str !== "" ? implicitHeight : 0 + } - Text { - id: txtTravelTime2 - text: app.travelTime2Str - color: (typeof dimmableColors !== 'undefined') ? dimmableColors.clockTileColor: colors.clockTileColor - anchors.horizontalCenter: parent.horizontalCenter - horizontalAlignment: Text.AlignHCenter - font.pixelSize: isNxt ? 20 : 16 - font.family: qfont.regular.name - visible: app.travelTime2Str !== "" - height: app.travelTime2Str !== "" ? implicitHeight : 0 - } - } + Text { + id: txtTravelTime2 + text: app.travelTime2Str + color: (typeof dimmableColors !== 'undefined') ? dimmableColors.clockTileColor : colors.clockTileColor + anchors.horizontalCenter: parent.horizontalCenter + horizontalAlignment: Text.AlignHCenter + font.pixelSize: isNxt ? 20 : 16 + font.family: qfont.regular.name + visible: app.travelTime2Str !== "" + height: app.travelTime2Str !== "" ? implicitHeight : 0 + } + } } diff --git a/TscClockTravelSettings.qml b/TscClockTravelSettings.qml index adc0b67..2769024 100644 --- a/TscClockTravelSettings.qml +++ b/TscClockTravelSettings.qml @@ -2,534 +2,808 @@ import QtQuick 2.1 import qb.components 1.0 Screen { - id: tscClockTravelSettingsScreen + id: tscClockTravelSettingsScreen - screenTitle: "Waze reistijd configuratie" + screenTitle: "Waze reistijd configuratie" - onShown: { - addCustomTopRightButton("Opslaan"); - r1StartInput.text = app.route1Start; - r1EndInput.text = app.route1End; - r1FromLatInput.text = app.route1FromLat; - r1FromLonInput.text = app.route1FromLon; - r1ToLatInput.text = app.route1ToLat; - r1ToLonInput.text = app.route1ToLon; - r1LabelInput.text = app.route1Label; - r1WorkdaysToggle.isSwitchedOn = app.route1WorkdaysOnly; - r1WindowToggle.isSwitchedOn = app.route1WindowEnabled; - r2StartInput.text = app.route2Start; - r2EndInput.text = app.route2End; - r2FromLatInput.text = app.route2FromLat; - r2FromLonInput.text = app.route2FromLon; - r2ToLatInput.text = app.route2ToLat; - r2ToLonInput.text = app.route2ToLon; - r2LabelInput.text = app.route2Label; - r2WorkdaysToggle.isSwitchedOn = app.route2WorkdaysOnly; - r2WindowToggle.isSwitchedOn = app.route2WindowEnabled; - } + onShown: { + addCustomTopRightButton("Opslaan"); + r1StartInput.text = app.route1Start; + r1EndInput.text = app.route1End; + r1FromLatInput.text = app.route1FromLat; + r1FromLonInput.text = app.route1FromLon; + r1ToLatInput.text = app.route1ToLat; + r1ToLonInput.text = app.route1ToLon; + r1LabelInput.text = app.route1Label; + r1WorkdaysToggle.isSwitchedOn = app.route1WorkdaysOnly; + r1WindowToggle.isSwitchedOn = app.route1WindowEnabled; + r2StartInput.text = app.route2Start; + r2EndInput.text = app.route2End; + r2FromLatInput.text = app.route2FromLat; + r2FromLonInput.text = app.route2FromLon; + r2ToLatInput.text = app.route2ToLat; + r2ToLonInput.text = app.route2ToLon; + r2LabelInput.text = app.route2Label; + r2WorkdaysToggle.isSwitchedOn = app.route2WorkdaysOnly; + r2WindowToggle.isSwitchedOn = app.route2WindowEnabled; + } - onCustomButtonClicked: { - app.route1Start = r1StartInput.text; - app.route1End = r1EndInput.text; - app.route1Label = r1LabelInput.text; - app.route1FromLat = r1FromLatInput.text; - app.route1FromLon = r1FromLonInput.text; - app.route1ToLat = r1ToLatInput.text; - app.route1ToLon = r1ToLonInput.text; - app.route1WorkdaysOnly = r1WorkdaysToggle.isSwitchedOn; - app.route1WindowEnabled = r1WindowToggle.isSwitchedOn; - app.route2Start = r2StartInput.text; - app.route2End = r2EndInput.text; - app.route2Label = r2LabelInput.text; - app.route2FromLat = r2FromLatInput.text; - app.route2FromLon = r2FromLonInput.text; - app.route2ToLat = r2ToLatInput.text; - app.route2ToLon = r2ToLonInput.text; - app.route2WorkdaysOnly = r2WorkdaysToggle.isSwitchedOn; - app.route2WindowEnabled = r2WindowToggle.isSwitchedOn; - app.saveSettings(); - // Re-evaluate right now so the tile reflects the new settings immediately - // (clearing routes that are no longer active, fetching ones that are), - // instead of waiting for the next 1-second tick. Resetting the active - // flags forces a re-fetch for routes that stay active with new coords. - app.route1Active = false; - app.route2Active = false; - app.checkTravelTimeWindow(); - hide(); - } + onCustomButtonClicked: { + app.route1Start = r1StartInput.text; + app.route1End = r1EndInput.text; + app.route1Label = r1LabelInput.text; + app.route1FromLat = r1FromLatInput.text; + app.route1FromLon = r1FromLonInput.text; + app.route1ToLat = r1ToLatInput.text; + app.route1ToLon = r1ToLonInput.text; + app.route1WorkdaysOnly = r1WorkdaysToggle.isSwitchedOn; + app.route1WindowEnabled = r1WindowToggle.isSwitchedOn; + app.route2Start = r2StartInput.text; + app.route2End = r2EndInput.text; + app.route2Label = r2LabelInput.text; + app.route2FromLat = r2FromLatInput.text; + app.route2FromLon = r2FromLonInput.text; + app.route2ToLat = r2ToLatInput.text; + app.route2ToLon = r2ToLonInput.text; + app.route2WorkdaysOnly = r2WorkdaysToggle.isSwitchedOn; + app.route2WindowEnabled = r2WindowToggle.isSwitchedOn; + app.saveSettings(); + // Re-evaluate right now so the tile reflects the new settings immediately + // (clearing routes that are no longer active, fetching ones that are), + // instead of waiting for the next 1-second tick. Resetting the active + // flags forces a re-fetch for routes that stay active with new coords. + app.route1Active = false; + app.route2Active = false; + app.checkTravelTimeWindow(); + hide(); + } - // ── Route 1 ────────────────────────────────────────────────────────────── + // ── Route 1 ────────────────────────────────────────────────────────────── - Text { - id: route1Header - x: isNxt ? 36 : 30 - y: isNxt ? 60 : 50 - font.pixelSize: isNxt ? 22 : 18 - font.family: qfont.semiBold.name - text: "Route 1" - } + Text { + id: route1Header + x: isNxt ? 36 : 30 + y: isNxt ? 60 : 50 + font.pixelSize: isNxt ? 22 : 18 + font.family: qfont.semiBold.name + text: "Route 1" + } - Text { - id: r1PeriodeLabel - anchors { top: route1Header.bottom; topMargin: isNxt ? 18 : 14; left: route1Header.left } - width: isNxt ? 100 : 80 - height: isNxt ? 36 : 28 - font.pixelSize: isNxt ? 18 : 14 - font.family: qfont.regular.name - text: "Periode:" - verticalAlignment: Text.AlignVCenter - } - Rectangle { - id: r1StartBox - anchors { left: r1PeriodeLabel.right; leftMargin: isNxt ? 10 : 8; verticalCenter: r1PeriodeLabel.verticalCenter } - opacity: r1WindowToggle.isSwitchedOn ? 1.0 : 0.35 - width: isNxt ? 90 : 70; height: isNxt ? 36 : 28 - border.color: "#aaaaaa"; border.width: 1; radius: 2; color: "white" - TextInput { - id: r1StartInput - anchors { fill: parent; margins: isNxt ? 6 : 4 } - font.pixelSize: isNxt ? 18 : 14 - font.family: qfont.regular.name - color: "#333333" - } - } - Text { - id: r1TotLabel - anchors { left: r1StartBox.right; leftMargin: isNxt ? 10 : 8; verticalCenter: r1PeriodeLabel.verticalCenter } - opacity: r1WindowToggle.isSwitchedOn ? 1.0 : 0.35 - height: isNxt ? 36 : 28 - font.pixelSize: isNxt ? 18 : 14 - font.family: qfont.regular.name - text: "tot" - verticalAlignment: Text.AlignVCenter - } - Rectangle { - id: r1EndBox - anchors { left: r1TotLabel.right; leftMargin: isNxt ? 10 : 8; verticalCenter: r1PeriodeLabel.verticalCenter } - opacity: r1WindowToggle.isSwitchedOn ? 1.0 : 0.35 - width: isNxt ? 90 : 70; height: isNxt ? 36 : 28 - border.color: "#aaaaaa"; border.width: 1; radius: 2; color: "white" - TextInput { - id: r1EndInput - anchors { fill: parent; margins: isNxt ? 6 : 4 } - font.pixelSize: isNxt ? 18 : 14 - font.family: qfont.regular.name - color: "#333333" - } - } + Text { + id: r1PeriodeLabel + anchors { + top: route1Header.bottom + topMargin: isNxt ? 18 : 14 + left: route1Header.left + } + width: isNxt ? 100 : 80 + height: isNxt ? 36 : 28 + font.pixelSize: isNxt ? 18 : 14 + font.family: qfont.regular.name + text: "Periode:" + verticalAlignment: Text.AlignVCenter + } + Rectangle { + id: r1StartBox + anchors { + left: r1PeriodeLabel.right + leftMargin: isNxt ? 10 : 8 + verticalCenter: r1PeriodeLabel.verticalCenter + } + opacity: r1WindowToggle.isSwitchedOn ? 1.0 : 0.35 + width: isNxt ? 90 : 70 + height: isNxt ? 36 : 28 + border.color: "#aaaaaa" + border.width: 1 + radius: 2 + color: "white" + TextInput { + id: r1StartInput + anchors { + fill: parent + margins: isNxt ? 6 : 4 + } + font.pixelSize: isNxt ? 18 : 14 + font.family: qfont.regular.name + color: "#333333" + } + } + Text { + id: r1TotLabel + anchors { + left: r1StartBox.right + leftMargin: isNxt ? 10 : 8 + verticalCenter: r1PeriodeLabel.verticalCenter + } + opacity: r1WindowToggle.isSwitchedOn ? 1.0 : 0.35 + height: isNxt ? 36 : 28 + font.pixelSize: isNxt ? 18 : 14 + font.family: qfont.regular.name + text: "tot" + verticalAlignment: Text.AlignVCenter + } + Rectangle { + id: r1EndBox + anchors { + left: r1TotLabel.right + leftMargin: isNxt ? 10 : 8 + verticalCenter: r1PeriodeLabel.verticalCenter + } + opacity: r1WindowToggle.isSwitchedOn ? 1.0 : 0.35 + width: isNxt ? 90 : 70 + height: isNxt ? 36 : 28 + border.color: "#aaaaaa" + border.width: 1 + radius: 2 + color: "white" + TextInput { + id: r1EndInput + anchors { + fill: parent + margins: isNxt ? 6 : 4 + } + font.pixelSize: isNxt ? 18 : 14 + font.family: qfont.regular.name + color: "#333333" + } + } - Text { - id: r1LabelText - anchors { top: r1PeriodeLabel.bottom; topMargin: isNxt ? 12 : 9; left: r1PeriodeLabel.left } - width: isNxt ? 100 : 80 - height: isNxt ? 36 : 28 - font.pixelSize: isNxt ? 18 : 14 - font.family: qfont.regular.name - text: "Label:" - verticalAlignment: Text.AlignVCenter - } - Rectangle { - id: r1LabelBox - anchors { left: r1LabelText.right; leftMargin: isNxt ? 10 : 8; verticalCenter: r1LabelText.verticalCenter } - width: isNxt ? 250 : 200; height: isNxt ? 36 : 28 - border.color: "#aaaaaa"; border.width: 1; radius: 2; color: "white" - TextInput { - id: r1LabelInput - anchors { fill: parent; margins: isNxt ? 6 : 4 } - font.pixelSize: isNxt ? 18 : 14 - font.family: qfont.regular.name - color: "#333333" - } - } + Text { + id: r1LabelText + anchors { + top: r1PeriodeLabel.bottom + topMargin: isNxt ? 12 : 9 + left: r1PeriodeLabel.left + } + width: isNxt ? 100 : 80 + height: isNxt ? 36 : 28 + font.pixelSize: isNxt ? 18 : 14 + font.family: qfont.regular.name + text: "Label:" + verticalAlignment: Text.AlignVCenter + } + Rectangle { + id: r1LabelBox + anchors { + left: r1LabelText.right + leftMargin: isNxt ? 10 : 8 + verticalCenter: r1LabelText.verticalCenter + } + width: isNxt ? 250 : 200 + height: isNxt ? 36 : 28 + border.color: "#aaaaaa" + border.width: 1 + radius: 2 + color: "white" + TextInput { + id: r1LabelInput + anchors { + fill: parent + margins: isNxt ? 6 : 4 + } + font.pixelSize: isNxt ? 18 : 14 + font.family: qfont.regular.name + color: "#333333" + } + } - Text { - id: r1VanLabel - anchors { top: r1LabelText.bottom; topMargin: isNxt ? 12 : 9; left: r1LabelText.left } - width: isNxt ? 100 : 80 - height: isNxt ? 36 : 28 - font.pixelSize: isNxt ? 18 : 14 - font.family: qfont.regular.name - text: "Van:" - verticalAlignment: Text.AlignVCenter - } - Rectangle { - id: r1FromLatBox - anchors { left: r1FromLatLabel.right; leftMargin: isNxt ? 6 : 5; verticalCenter: r1VanLabel.verticalCenter } - width: isNxt ? 105 : 85; height: isNxt ? 36 : 28 - border.color: "#aaaaaa"; border.width: 1; radius: 2; color: "white" - TextInput { - id: r1FromLatInput - anchors { fill: parent; margins: isNxt ? 6 : 4 } - font.pixelSize: isNxt ? 18 : 14 - font.family: qfont.regular.name - color: "#333333" - } - } - Rectangle { - id: r1FromLonBox - anchors { left: r1FromLonLabel.right; leftMargin: isNxt ? 6 : 5; verticalCenter: r1VanLabel.verticalCenter } - width: isNxt ? 105 : 85; height: isNxt ? 36 : 28 - border.color: "#aaaaaa"; border.width: 1; radius: 2; color: "white" - TextInput { - id: r1FromLonInput - anchors { fill: parent; margins: isNxt ? 6 : 4 } - font.pixelSize: isNxt ? 18 : 14 - font.family: qfont.regular.name - color: "#333333" - } - } + Text { + id: r1VanLabel + anchors { + top: r1LabelText.bottom + topMargin: isNxt ? 12 : 9 + left: r1LabelText.left + } + width: isNxt ? 100 : 80 + height: isNxt ? 36 : 28 + font.pixelSize: isNxt ? 18 : 14 + font.family: qfont.regular.name + text: "Van:" + verticalAlignment: Text.AlignVCenter + } + Rectangle { + id: r1FromLatBox + anchors { + left: r1FromLatLabel.right + leftMargin: isNxt ? 6 : 5 + verticalCenter: r1VanLabel.verticalCenter + } + width: isNxt ? 105 : 85 + height: isNxt ? 36 : 28 + border.color: "#aaaaaa" + border.width: 1 + radius: 2 + color: "white" + TextInput { + id: r1FromLatInput + anchors { + fill: parent + margins: isNxt ? 6 : 4 + } + font.pixelSize: isNxt ? 18 : 14 + font.family: qfont.regular.name + color: "#333333" + } + } + Rectangle { + id: r1FromLonBox + anchors { + left: r1FromLonLabel.right + leftMargin: isNxt ? 6 : 5 + verticalCenter: r1VanLabel.verticalCenter + } + width: isNxt ? 105 : 85 + height: isNxt ? 36 : 28 + border.color: "#aaaaaa" + border.width: 1 + radius: 2 + color: "white" + TextInput { + id: r1FromLonInput + anchors { + fill: parent + margins: isNxt ? 6 : 4 + } + font.pixelSize: isNxt ? 18 : 14 + font.family: qfont.regular.name + color: "#333333" + } + } - Text { - id: r1NaarLabel - anchors { top: r1VanLabel.bottom; topMargin: isNxt ? 12 : 9; left: r1VanLabel.left } - width: isNxt ? 100 : 80 - height: isNxt ? 36 : 28 - font.pixelSize: isNxt ? 18 : 14 - font.family: qfont.regular.name - text: "Naar:" - verticalAlignment: Text.AlignVCenter - } - Rectangle { - id: r1ToLatBox - anchors { left: r1ToLatLabel.right; leftMargin: isNxt ? 6 : 5; verticalCenter: r1NaarLabel.verticalCenter } - width: isNxt ? 105 : 85; height: isNxt ? 36 : 28 - border.color: "#aaaaaa"; border.width: 1; radius: 2; color: "white" - TextInput { - id: r1ToLatInput - anchors { fill: parent; margins: isNxt ? 6 : 4 } - font.pixelSize: isNxt ? 18 : 14 - font.family: qfont.regular.name - color: "#333333" - } - } - Rectangle { - id: r1ToLonBox - anchors { left: r1ToLonLabel.right; leftMargin: isNxt ? 6 : 5; verticalCenter: r1NaarLabel.verticalCenter } - width: isNxt ? 105 : 85; height: isNxt ? 36 : 28 - border.color: "#aaaaaa"; border.width: 1; radius: 2; color: "white" - TextInput { - id: r1ToLonInput - anchors { fill: parent; margins: isNxt ? 6 : 4 } - font.pixelSize: isNxt ? 18 : 14 - font.family: qfont.regular.name - color: "#333333" - } - } + Text { + id: r1NaarLabel + anchors { + top: r1VanLabel.bottom + topMargin: isNxt ? 12 : 9 + left: r1VanLabel.left + } + width: isNxt ? 100 : 80 + height: isNxt ? 36 : 28 + font.pixelSize: isNxt ? 18 : 14 + font.family: qfont.regular.name + text: "Naar:" + verticalAlignment: Text.AlignVCenter + } + Rectangle { + id: r1ToLatBox + anchors { + left: r1ToLatLabel.right + leftMargin: isNxt ? 6 : 5 + verticalCenter: r1NaarLabel.verticalCenter + } + width: isNxt ? 105 : 85 + height: isNxt ? 36 : 28 + border.color: "#aaaaaa" + border.width: 1 + radius: 2 + color: "white" + TextInput { + id: r1ToLatInput + anchors { + fill: parent + margins: isNxt ? 6 : 4 + } + font.pixelSize: isNxt ? 18 : 14 + font.family: qfont.regular.name + color: "#333333" + } + } + Rectangle { + id: r1ToLonBox + anchors { + left: r1ToLonLabel.right + leftMargin: isNxt ? 6 : 5 + verticalCenter: r1NaarLabel.verticalCenter + } + width: isNxt ? 105 : 85 + height: isNxt ? 36 : 28 + border.color: "#aaaaaa" + border.width: 1 + radius: 2 + color: "white" + TextInput { + id: r1ToLonInput + anchors { + fill: parent + margins: isNxt ? 6 : 4 + } + font.pixelSize: isNxt ? 18 : 14 + font.family: qfont.regular.name + color: "#333333" + } + } - Text { - id: r1WorkdaysLabel - anchors { top: r1WindowLabel.bottom; topMargin: isNxt ? 12 : 9; left: route1Header.left } - height: isNxt ? 36 : 28 - font.pixelSize: isNxt ? 18 : 14 - font.family: qfont.regular.name - text: "Alleen op werkdagen" - verticalAlignment: Text.AlignVCenter - } - OnOffToggle { - id: r1WorkdaysToggle - height: isNxt ? 36 : 28 - anchors { left: r1WorkdaysLabel.right; leftMargin: isNxt ? 12 : 10; verticalCenter: r1WorkdaysLabel.verticalCenter } - leftIsSwitchedOn: false - } + Text { + id: r1WorkdaysLabel + anchors { + top: r1WindowLabel.bottom + topMargin: isNxt ? 12 : 9 + left: route1Header.left + } + height: isNxt ? 36 : 28 + font.pixelSize: isNxt ? 18 : 14 + font.family: qfont.regular.name + text: "Alleen op werkdagen" + verticalAlignment: Text.AlignVCenter + } + OnOffToggle { + id: r1WorkdaysToggle + height: isNxt ? 36 : 28 + anchors { + left: r1WorkdaysLabel.right + leftMargin: isNxt ? 12 : 10 + verticalCenter: r1WorkdaysLabel.verticalCenter + } + leftIsSwitchedOn: false + } - // ── Route 2 ────────────────────────────────────────────────────────────── + // ── Route 2 ────────────────────────────────────────────────────────────── - Text { - id: route2Header - // Second column: aligned to Route 1's top, starting at the screen's - // horizontal centre so it adapts to the available width. - anchors { top: route1Header.top; left: parent.horizontalCenter; leftMargin: isNxt ? 20 : 16 } - font.pixelSize: isNxt ? 22 : 18 - font.family: qfont.semiBold.name - text: "Route 2" - } + Text { + id: route2Header + // Second column: aligned to Route 1's top, starting at the screen's + // horizontal centre so it adapts to the available width. + anchors { + top: route1Header.top + left: parent.horizontalCenter + leftMargin: isNxt ? 20 : 16 + } + font.pixelSize: isNxt ? 22 : 18 + font.family: qfont.semiBold.name + text: "Route 2" + } - Text { - id: r2PeriodeLabel - anchors { top: route2Header.bottom; topMargin: isNxt ? 18 : 14; left: route2Header.left } - width: isNxt ? 100 : 80 - height: isNxt ? 36 : 28 - font.pixelSize: isNxt ? 18 : 14 - font.family: qfont.regular.name - text: "Periode:" - verticalAlignment: Text.AlignVCenter - } - Rectangle { - id: r2StartBox - anchors { left: r2PeriodeLabel.right; leftMargin: isNxt ? 10 : 8; verticalCenter: r2PeriodeLabel.verticalCenter } - opacity: r2WindowToggle.isSwitchedOn ? 1.0 : 0.35 - width: isNxt ? 90 : 70; height: isNxt ? 36 : 28 - border.color: "#aaaaaa"; border.width: 1; radius: 2; color: "white" - TextInput { - id: r2StartInput - anchors { fill: parent; margins: isNxt ? 6 : 4 } - font.pixelSize: isNxt ? 18 : 14 - font.family: qfont.regular.name - color: "#333333" - } - } - Text { - id: r2TotLabel - anchors { left: r2StartBox.right; leftMargin: isNxt ? 10 : 8; verticalCenter: r2PeriodeLabel.verticalCenter } - opacity: r2WindowToggle.isSwitchedOn ? 1.0 : 0.35 - height: isNxt ? 36 : 28 - font.pixelSize: isNxt ? 18 : 14 - font.family: qfont.regular.name - text: "tot" - verticalAlignment: Text.AlignVCenter - } - Rectangle { - id: r2EndBox - anchors { left: r2TotLabel.right; leftMargin: isNxt ? 10 : 8; verticalCenter: r2PeriodeLabel.verticalCenter } - opacity: r2WindowToggle.isSwitchedOn ? 1.0 : 0.35 - width: isNxt ? 90 : 70; height: isNxt ? 36 : 28 - border.color: "#aaaaaa"; border.width: 1; radius: 2; color: "white" - TextInput { - id: r2EndInput - anchors { fill: parent; margins: isNxt ? 6 : 4 } - font.pixelSize: isNxt ? 18 : 14 - font.family: qfont.regular.name - color: "#333333" - } - } + Text { + id: r2PeriodeLabel + anchors { + top: route2Header.bottom + topMargin: isNxt ? 18 : 14 + left: route2Header.left + } + width: isNxt ? 100 : 80 + height: isNxt ? 36 : 28 + font.pixelSize: isNxt ? 18 : 14 + font.family: qfont.regular.name + text: "Periode:" + verticalAlignment: Text.AlignVCenter + } + Rectangle { + id: r2StartBox + anchors { + left: r2PeriodeLabel.right + leftMargin: isNxt ? 10 : 8 + verticalCenter: r2PeriodeLabel.verticalCenter + } + opacity: r2WindowToggle.isSwitchedOn ? 1.0 : 0.35 + width: isNxt ? 90 : 70 + height: isNxt ? 36 : 28 + border.color: "#aaaaaa" + border.width: 1 + radius: 2 + color: "white" + TextInput { + id: r2StartInput + anchors { + fill: parent + margins: isNxt ? 6 : 4 + } + font.pixelSize: isNxt ? 18 : 14 + font.family: qfont.regular.name + color: "#333333" + } + } + Text { + id: r2TotLabel + anchors { + left: r2StartBox.right + leftMargin: isNxt ? 10 : 8 + verticalCenter: r2PeriodeLabel.verticalCenter + } + opacity: r2WindowToggle.isSwitchedOn ? 1.0 : 0.35 + height: isNxt ? 36 : 28 + font.pixelSize: isNxt ? 18 : 14 + font.family: qfont.regular.name + text: "tot" + verticalAlignment: Text.AlignVCenter + } + Rectangle { + id: r2EndBox + anchors { + left: r2TotLabel.right + leftMargin: isNxt ? 10 : 8 + verticalCenter: r2PeriodeLabel.verticalCenter + } + opacity: r2WindowToggle.isSwitchedOn ? 1.0 : 0.35 + width: isNxt ? 90 : 70 + height: isNxt ? 36 : 28 + border.color: "#aaaaaa" + border.width: 1 + radius: 2 + color: "white" + TextInput { + id: r2EndInput + anchors { + fill: parent + margins: isNxt ? 6 : 4 + } + font.pixelSize: isNxt ? 18 : 14 + font.family: qfont.regular.name + color: "#333333" + } + } - Text { - id: r2LabelText - anchors { top: r2PeriodeLabel.bottom; topMargin: isNxt ? 12 : 9; left: r2PeriodeLabel.left } - width: isNxt ? 100 : 80 - height: isNxt ? 36 : 28 - font.pixelSize: isNxt ? 18 : 14 - font.family: qfont.regular.name - text: "Label:" - verticalAlignment: Text.AlignVCenter - } - Rectangle { - id: r2LabelBox - anchors { left: r2LabelText.right; leftMargin: isNxt ? 10 : 8; verticalCenter: r2LabelText.verticalCenter } - width: isNxt ? 250 : 200; height: isNxt ? 36 : 28 - border.color: "#aaaaaa"; border.width: 1; radius: 2; color: "white" - TextInput { - id: r2LabelInput - anchors { fill: parent; margins: isNxt ? 6 : 4 } - font.pixelSize: isNxt ? 18 : 14 - font.family: qfont.regular.name - color: "#333333" - } - } + Text { + id: r2LabelText + anchors { + top: r2PeriodeLabel.bottom + topMargin: isNxt ? 12 : 9 + left: r2PeriodeLabel.left + } + width: isNxt ? 100 : 80 + height: isNxt ? 36 : 28 + font.pixelSize: isNxt ? 18 : 14 + font.family: qfont.regular.name + text: "Label:" + verticalAlignment: Text.AlignVCenter + } + Rectangle { + id: r2LabelBox + anchors { + left: r2LabelText.right + leftMargin: isNxt ? 10 : 8 + verticalCenter: r2LabelText.verticalCenter + } + width: isNxt ? 250 : 200 + height: isNxt ? 36 : 28 + border.color: "#aaaaaa" + border.width: 1 + radius: 2 + color: "white" + TextInput { + id: r2LabelInput + anchors { + fill: parent + margins: isNxt ? 6 : 4 + } + font.pixelSize: isNxt ? 18 : 14 + font.family: qfont.regular.name + color: "#333333" + } + } - Text { - id: r2VanLabel - anchors { top: r2LabelText.bottom; topMargin: isNxt ? 12 : 9; left: r2LabelText.left } - width: isNxt ? 100 : 80 - height: isNxt ? 36 : 28 - font.pixelSize: isNxt ? 18 : 14 - font.family: qfont.regular.name - text: "Van:" - verticalAlignment: Text.AlignVCenter - } - Rectangle { - id: r2FromLatBox - anchors { left: r2FromLatLabel.right; leftMargin: isNxt ? 6 : 5; verticalCenter: r2VanLabel.verticalCenter } - width: isNxt ? 105 : 85; height: isNxt ? 36 : 28 - border.color: "#aaaaaa"; border.width: 1; radius: 2; color: "white" - TextInput { - id: r2FromLatInput - anchors { fill: parent; margins: isNxt ? 6 : 4 } - font.pixelSize: isNxt ? 18 : 14 - font.family: qfont.regular.name - color: "#333333" - } - } - Rectangle { - id: r2FromLonBox - anchors { left: r2FromLonLabel.right; leftMargin: isNxt ? 6 : 5; verticalCenter: r2VanLabel.verticalCenter } - width: isNxt ? 105 : 85; height: isNxt ? 36 : 28 - border.color: "#aaaaaa"; border.width: 1; radius: 2; color: "white" - TextInput { - id: r2FromLonInput - anchors { fill: parent; margins: isNxt ? 6 : 4 } - font.pixelSize: isNxt ? 18 : 14 - font.family: qfont.regular.name - color: "#333333" - } - } + Text { + id: r2VanLabel + anchors { + top: r2LabelText.bottom + topMargin: isNxt ? 12 : 9 + left: r2LabelText.left + } + width: isNxt ? 100 : 80 + height: isNxt ? 36 : 28 + font.pixelSize: isNxt ? 18 : 14 + font.family: qfont.regular.name + text: "Van:" + verticalAlignment: Text.AlignVCenter + } + Rectangle { + id: r2FromLatBox + anchors { + left: r2FromLatLabel.right + leftMargin: isNxt ? 6 : 5 + verticalCenter: r2VanLabel.verticalCenter + } + width: isNxt ? 105 : 85 + height: isNxt ? 36 : 28 + border.color: "#aaaaaa" + border.width: 1 + radius: 2 + color: "white" + TextInput { + id: r2FromLatInput + anchors { + fill: parent + margins: isNxt ? 6 : 4 + } + font.pixelSize: isNxt ? 18 : 14 + font.family: qfont.regular.name + color: "#333333" + } + } + Rectangle { + id: r2FromLonBox + anchors { + left: r2FromLonLabel.right + leftMargin: isNxt ? 6 : 5 + verticalCenter: r2VanLabel.verticalCenter + } + width: isNxt ? 105 : 85 + height: isNxt ? 36 : 28 + border.color: "#aaaaaa" + border.width: 1 + radius: 2 + color: "white" + TextInput { + id: r2FromLonInput + anchors { + fill: parent + margins: isNxt ? 6 : 4 + } + font.pixelSize: isNxt ? 18 : 14 + font.family: qfont.regular.name + color: "#333333" + } + } - Text { - id: r2NaarLabel - anchors { top: r2VanLabel.bottom; topMargin: isNxt ? 12 : 9; left: r2VanLabel.left } - width: isNxt ? 100 : 80 - height: isNxt ? 36 : 28 - font.pixelSize: isNxt ? 18 : 14 - font.family: qfont.regular.name - text: "Naar:" - verticalAlignment: Text.AlignVCenter - } - Rectangle { - id: r2ToLatBox - anchors { left: r2ToLatLabel.right; leftMargin: isNxt ? 6 : 5; verticalCenter: r2NaarLabel.verticalCenter } - width: isNxt ? 105 : 85; height: isNxt ? 36 : 28 - border.color: "#aaaaaa"; border.width: 1; radius: 2; color: "white" - TextInput { - id: r2ToLatInput - anchors { fill: parent; margins: isNxt ? 6 : 4 } - font.pixelSize: isNxt ? 18 : 14 - font.family: qfont.regular.name - color: "#333333" - } - } - Rectangle { - id: r2ToLonBox - anchors { left: r2ToLonLabel.right; leftMargin: isNxt ? 6 : 5; verticalCenter: r2NaarLabel.verticalCenter } - width: isNxt ? 105 : 85; height: isNxt ? 36 : 28 - border.color: "#aaaaaa"; border.width: 1; radius: 2; color: "white" - TextInput { - id: r2ToLonInput - anchors { fill: parent; margins: isNxt ? 6 : 4 } - font.pixelSize: isNxt ? 18 : 14 - font.family: qfont.regular.name - color: "#333333" - } - } + Text { + id: r2NaarLabel + anchors { + top: r2VanLabel.bottom + topMargin: isNxt ? 12 : 9 + left: r2VanLabel.left + } + width: isNxt ? 100 : 80 + height: isNxt ? 36 : 28 + font.pixelSize: isNxt ? 18 : 14 + font.family: qfont.regular.name + text: "Naar:" + verticalAlignment: Text.AlignVCenter + } + Rectangle { + id: r2ToLatBox + anchors { + left: r2ToLatLabel.right + leftMargin: isNxt ? 6 : 5 + verticalCenter: r2NaarLabel.verticalCenter + } + width: isNxt ? 105 : 85 + height: isNxt ? 36 : 28 + border.color: "#aaaaaa" + border.width: 1 + radius: 2 + color: "white" + TextInput { + id: r2ToLatInput + anchors { + fill: parent + margins: isNxt ? 6 : 4 + } + font.pixelSize: isNxt ? 18 : 14 + font.family: qfont.regular.name + color: "#333333" + } + } + Rectangle { + id: r2ToLonBox + anchors { + left: r2ToLonLabel.right + leftMargin: isNxt ? 6 : 5 + verticalCenter: r2NaarLabel.verticalCenter + } + width: isNxt ? 105 : 85 + height: isNxt ? 36 : 28 + border.color: "#aaaaaa" + border.width: 1 + radius: 2 + color: "white" + TextInput { + id: r2ToLonInput + anchors { + fill: parent + margins: isNxt ? 6 : 4 + } + font.pixelSize: isNxt ? 18 : 14 + font.family: qfont.regular.name + color: "#333333" + } + } - Text { - id: r2WorkdaysLabel - anchors { top: r2WindowLabel.bottom; topMargin: isNxt ? 12 : 9; left: route2Header.left } - height: isNxt ? 36 : 28 - font.pixelSize: isNxt ? 18 : 14 - font.family: qfont.regular.name - text: "Alleen op werkdagen" - verticalAlignment: Text.AlignVCenter - } - OnOffToggle { - id: r2WorkdaysToggle - height: isNxt ? 36 : 28 - anchors { left: r2WorkdaysLabel.right; leftMargin: isNxt ? 12 : 10; verticalCenter: r2WorkdaysLabel.verticalCenter } - leftIsSwitchedOn: false - } + Text { + id: r2WorkdaysLabel + anchors { + top: r2WindowLabel.bottom + topMargin: isNxt ? 12 : 9 + left: route2Header.left + } + height: isNxt ? 36 : 28 + font.pixelSize: isNxt ? 18 : 14 + font.family: qfont.regular.name + text: "Alleen op werkdagen" + verticalAlignment: Text.AlignVCenter + } + OnOffToggle { + id: r2WorkdaysToggle + height: isNxt ? 36 : 28 + anchors { + left: r2WorkdaysLabel.right + leftMargin: isNxt ? 12 : 10 + verticalCenter: r2WorkdaysLabel.verticalCenter + } + leftIsSwitchedOn: false + } - // ── Lat/Lon prefix labels (anchored to the coordinate boxes above) ──────── + // ── Lat/Lon prefix labels (anchored to the coordinate boxes above) ──────── - Text { - id: r1FromLatLabel - anchors { left: r1VanLabel.right; leftMargin: isNxt ? 8 : 6; verticalCenter: r1VanLabel.verticalCenter } - width: isNxt ? 30 : 24; height: isNxt ? 36 : 28 - font.pixelSize: isNxt ? 18 : 14 - font.family: qfont.regular.name - color: "#555555" - text: "Lat" - verticalAlignment: Text.AlignVCenter - } - Text { - id: r1FromLonLabel - anchors { left: r1FromLatBox.right; leftMargin: isNxt ? 10 : 8; verticalCenter: r1VanLabel.verticalCenter } - width: isNxt ? 30 : 24; height: isNxt ? 36 : 28 - font.pixelSize: isNxt ? 18 : 14 - font.family: qfont.regular.name - color: "#555555" - text: "Lon" - verticalAlignment: Text.AlignVCenter - } - Text { - id: r1ToLatLabel - anchors { left: r1NaarLabel.right; leftMargin: isNxt ? 8 : 6; verticalCenter: r1NaarLabel.verticalCenter } - width: isNxt ? 30 : 24; height: isNxt ? 36 : 28 - font.pixelSize: isNxt ? 18 : 14 - font.family: qfont.regular.name - color: "#555555" - text: "Lat" - verticalAlignment: Text.AlignVCenter - } - Text { - id: r1ToLonLabel - anchors { left: r1ToLatBox.right; leftMargin: isNxt ? 10 : 8; verticalCenter: r1NaarLabel.verticalCenter } - width: isNxt ? 30 : 24; height: isNxt ? 36 : 28 - font.pixelSize: isNxt ? 18 : 14 - font.family: qfont.regular.name - color: "#555555" - text: "Lon" - verticalAlignment: Text.AlignVCenter - } - Text { - id: r2FromLatLabel - anchors { left: r2VanLabel.right; leftMargin: isNxt ? 8 : 6; verticalCenter: r2VanLabel.verticalCenter } - width: isNxt ? 30 : 24; height: isNxt ? 36 : 28 - font.pixelSize: isNxt ? 18 : 14 - font.family: qfont.regular.name - color: "#555555" - text: "Lat" - verticalAlignment: Text.AlignVCenter - } - Text { - id: r2FromLonLabel - anchors { left: r2FromLatBox.right; leftMargin: isNxt ? 10 : 8; verticalCenter: r2VanLabel.verticalCenter } - width: isNxt ? 30 : 24; height: isNxt ? 36 : 28 - font.pixelSize: isNxt ? 18 : 14 - font.family: qfont.regular.name - color: "#555555" - text: "Lon" - verticalAlignment: Text.AlignVCenter - } - Text { - id: r2ToLatLabel - anchors { left: r2NaarLabel.right; leftMargin: isNxt ? 8 : 6; verticalCenter: r2NaarLabel.verticalCenter } - width: isNxt ? 30 : 24; height: isNxt ? 36 : 28 - font.pixelSize: isNxt ? 18 : 14 - font.family: qfont.regular.name - color: "#555555" - text: "Lat" - verticalAlignment: Text.AlignVCenter - } - Text { - id: r2ToLonLabel - anchors { left: r2ToLatBox.right; leftMargin: isNxt ? 10 : 8; verticalCenter: r2NaarLabel.verticalCenter } - width: isNxt ? 30 : 24; height: isNxt ? 36 : 28 - font.pixelSize: isNxt ? 18 : 14 - font.family: qfont.regular.name - color: "#555555" - text: "Lon" - verticalAlignment: Text.AlignVCenter - } + Text { + id: r1FromLatLabel + anchors { + left: r1VanLabel.right + leftMargin: isNxt ? 8 : 6 + verticalCenter: r1VanLabel.verticalCenter + } + width: isNxt ? 30 : 24 + height: isNxt ? 36 : 28 + font.pixelSize: isNxt ? 18 : 14 + font.family: qfont.regular.name + color: "#555555" + text: "Lat" + verticalAlignment: Text.AlignVCenter + } + Text { + id: r1FromLonLabel + anchors { + left: r1FromLatBox.right + leftMargin: isNxt ? 10 : 8 + verticalCenter: r1VanLabel.verticalCenter + } + width: isNxt ? 30 : 24 + height: isNxt ? 36 : 28 + font.pixelSize: isNxt ? 18 : 14 + font.family: qfont.regular.name + color: "#555555" + text: "Lon" + verticalAlignment: Text.AlignVCenter + } + Text { + id: r1ToLatLabel + anchors { + left: r1NaarLabel.right + leftMargin: isNxt ? 8 : 6 + verticalCenter: r1NaarLabel.verticalCenter + } + width: isNxt ? 30 : 24 + height: isNxt ? 36 : 28 + font.pixelSize: isNxt ? 18 : 14 + font.family: qfont.regular.name + color: "#555555" + text: "Lat" + verticalAlignment: Text.AlignVCenter + } + Text { + id: r1ToLonLabel + anchors { + left: r1ToLatBox.right + leftMargin: isNxt ? 10 : 8 + verticalCenter: r1NaarLabel.verticalCenter + } + width: isNxt ? 30 : 24 + height: isNxt ? 36 : 28 + font.pixelSize: isNxt ? 18 : 14 + font.family: qfont.regular.name + color: "#555555" + text: "Lon" + verticalAlignment: Text.AlignVCenter + } + Text { + id: r2FromLatLabel + anchors { + left: r2VanLabel.right + leftMargin: isNxt ? 8 : 6 + verticalCenter: r2VanLabel.verticalCenter + } + width: isNxt ? 30 : 24 + height: isNxt ? 36 : 28 + font.pixelSize: isNxt ? 18 : 14 + font.family: qfont.regular.name + color: "#555555" + text: "Lat" + verticalAlignment: Text.AlignVCenter + } + Text { + id: r2FromLonLabel + anchors { + left: r2FromLatBox.right + leftMargin: isNxt ? 10 : 8 + verticalCenter: r2VanLabel.verticalCenter + } + width: isNxt ? 30 : 24 + height: isNxt ? 36 : 28 + font.pixelSize: isNxt ? 18 : 14 + font.family: qfont.regular.name + color: "#555555" + text: "Lon" + verticalAlignment: Text.AlignVCenter + } + Text { + id: r2ToLatLabel + anchors { + left: r2NaarLabel.right + leftMargin: isNxt ? 8 : 6 + verticalCenter: r2NaarLabel.verticalCenter + } + width: isNxt ? 30 : 24 + height: isNxt ? 36 : 28 + font.pixelSize: isNxt ? 18 : 14 + font.family: qfont.regular.name + color: "#555555" + text: "Lat" + verticalAlignment: Text.AlignVCenter + } + Text { + id: r2ToLonLabel + anchors { + left: r2ToLatBox.right + leftMargin: isNxt ? 10 : 8 + verticalCenter: r2NaarLabel.verticalCenter + } + width: isNxt ? 30 : 24 + height: isNxt ? 36 : 28 + font.pixelSize: isNxt ? 18 : 14 + font.family: qfont.regular.name + color: "#555555" + text: "Lon" + verticalAlignment: Text.AlignVCenter + } - // ── Time-window enable toggles (per route, own row under the coordinates) ── + // ── Time-window enable toggles (per route, own row under the coordinates) ── - Text { - id: r1WindowLabel - anchors { top: r1NaarLabel.bottom; topMargin: isNxt ? 12 : 9; left: route1Header.left } - height: isNxt ? 36 : 28 - font.pixelSize: isNxt ? 18 : 14 - font.family: qfont.regular.name - text: "Tijdvenster" - verticalAlignment: Text.AlignVCenter - } - OnOffToggle { - id: r1WindowToggle - height: isNxt ? 36 : 28 - anchors { left: r1WindowLabel.right; leftMargin: isNxt ? 12 : 10; verticalCenter: r1WindowLabel.verticalCenter } - leftIsSwitchedOn: false - } - Text { - id: r2WindowLabel - anchors { top: r2NaarLabel.bottom; topMargin: isNxt ? 12 : 9; left: route2Header.left } - height: isNxt ? 36 : 28 - font.pixelSize: isNxt ? 18 : 14 - font.family: qfont.regular.name - text: "Tijdvenster" - verticalAlignment: Text.AlignVCenter - } - OnOffToggle { - id: r2WindowToggle - height: isNxt ? 36 : 28 - anchors { left: r2WindowLabel.right; leftMargin: isNxt ? 12 : 10; verticalCenter: r2WindowLabel.verticalCenter } - leftIsSwitchedOn: false - } + Text { + id: r1WindowLabel + anchors { + top: r1NaarLabel.bottom + topMargin: isNxt ? 12 : 9 + left: route1Header.left + } + height: isNxt ? 36 : 28 + font.pixelSize: isNxt ? 18 : 14 + font.family: qfont.regular.name + text: "Tijdvenster" + verticalAlignment: Text.AlignVCenter + } + OnOffToggle { + id: r1WindowToggle + height: isNxt ? 36 : 28 + anchors { + left: r1WindowLabel.right + leftMargin: isNxt ? 12 : 10 + verticalCenter: r1WindowLabel.verticalCenter + } + leftIsSwitchedOn: false + } + Text { + id: r2WindowLabel + anchors { + top: r2NaarLabel.bottom + topMargin: isNxt ? 12 : 9 + left: route2Header.left + } + height: isNxt ? 36 : 28 + font.pixelSize: isNxt ? 18 : 14 + font.family: qfont.regular.name + text: "Tijdvenster" + verticalAlignment: Text.AlignVCenter + } + OnOffToggle { + id: r2WindowToggle + height: isNxt ? 36 : 28 + anchors { + left: r2WindowLabel.right + leftMargin: isNxt ? 12 : 10 + verticalCenter: r2WindowLabel.verticalCenter + } + leftIsSwitchedOn: false + } - // ── Hint ───────────────────────────────────────────────────────────────── + // ── Hint ───────────────────────────────────────────────────────────────── - Text { - anchors { top: r1WorkdaysLabel.bottom; topMargin: isNxt ? 18 : 12; left: route1Header.left } - font.pixelSize: isNxt ? 15 : 12 - font.family: qfont.regular.name - color: "#888888" - text: "Coördinaten in decimaal formaat (bijv. 52.3704 / 4.8952), tijd als HH:MM" - } + Text { + anchors { + top: r1WorkdaysLabel.bottom + topMargin: isNxt ? 18 : 12 + left: route1Header.left + } + font.pixelSize: isNxt ? 15 : 12 + font.family: qfont.regular.name + color: "#888888" + text: "Coördinaten in decimaal formaat (bijv. 52.3704 / 4.8952), tijd als HH:MM" + } } From 4e30ea5ff83d7ca7720126476cfbc6a5c40f1532 Mon Sep 17 00:00:00 2001 From: Luuk Visser Date: Thu, 6 Aug 2026 16:33:09 +0200 Subject: [PATCH 2/2] Time out stalled Waze requests, and add an English translation Addresses the two limitations the README listed. Request timeouts. Qt's QML XMLHttpRequest has no timeout property, so each request is now guarded by a Timer that aborts it after 15 seconds. A request that times out, returns a non-200 status or yields unparseable JSON replaces the duration with an em dash instead of leaving the previous value on the tile, so an unreachable Waze reads as unavailable rather than as a stale travel time. Only one request per route is in flight at a time: a refresh, a settings change or a route going inactive aborts the one before it. A route whose coordinates are blank now clears its row rather than keeping the last value. The guard is armed before send(), because a request that fails immediately runs its handler from inside send(). Translations. Every user-visible string now goes through qsTr(), with Dutch as the source language, and lang/lang_en_GB.qm translates the 27 of them to English. This follows the lang/lang_.qm convention the other ToonStore apps use. lang_en_GB.ts is kept as the editable source alongside the compiled catalog, and the README documents the lupdate/lrelease cycle. Verified pyside6-lupdate finds exactly the 27 strings in the catalog, with none missing and none stale, and that the compiled catalog loads through QTranslator and resolves every context. Co-Authored-By: Claude Opus 5 --- .gitattributes | 3 + Changelog.txt | 4 ++ README.md | 39 +++++++++--- TscClockApp.qml | 84 +++++++++++++++++++++++-- TscClockSettings.qml | 18 +++--- TscClockTravelSettings.qml | 54 ++++++++--------- lang/lang_en_GB.qm | Bin 0 -> 2493 bytes lang/lang_en_GB.ts | 121 +++++++++++++++++++++++++++++++++++++ version.txt | 2 +- 9 files changed, 276 insertions(+), 49 deletions(-) create mode 100644 lang/lang_en_GB.qm create mode 100644 lang/lang_en_GB.ts diff --git a/.gitattributes b/.gitattributes index 6313b56..4f9b388 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1,4 @@ * text=auto eol=lf + +# Compiled Qt translation catalogs +*.qm binary diff --git a/Changelog.txt b/Changelog.txt index f00bd87..43a0df0 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -1,3 +1,7 @@ +1.1.1 +- Abort Waze requests that stall, and show a dash instead of a stale travel time +- Mark user-visible strings with qsTr and add an English translation + 1.1.0 - Add new option for center layout - Add option to move the day text to the date row diff --git a/README.md b/README.md index 208f579..eb7e95a 100644 --- a/README.md +++ b/README.md @@ -102,8 +102,14 @@ duration can never linger on the tile. A second timer refreshes the active route Travel times come from Waze's public live-map routing endpoint (`routing-livemap-row.waze.com/RoutingManager/routingRequest`), summing `crossTime` over -the returned route segments. Failures are logged to the Toon's console and leave the -previous value in place. +the returned route segments. + +Each request is guarded by a 15-second `Timer` that aborts it — Qt's QML +`XMLHttpRequest` has no `timeout` property of its own. A request that times out, returns +a non-200 status or yields unparseable JSON logs the reason to the Toon's console and +replaces the duration with `—`, so an unreachable Waze reads as unavailable rather than +freezing on a stale number. Only one request per route is ever in flight; a refresh or a +settings change aborts the previous one. | File | Role | | ------------------------------ | ------------------------------------------------------------ | @@ -111,10 +117,30 @@ previous value in place. | `TscClockTile.qml` | The tile — both layouts, switched by `app.centerLayout` | | `TscClockSettings.qml` | Clock settings screen | | `TscClockTravelSettings.qml` | Two-column travel-time settings screen | +| `lang/` | Qt translation catalogs, one per locale | | `version.txt`, `Changelog.txt` | Read by the ToonStore to detect and describe updates | -`isNxt` selects the larger font and margin values for Toon 2 (NXT) hardware. The UI is in -Dutch, matching the rest of the Toon interface. +`isNxt` selects the larger font and margin values for Toon 2 (NXT) hardware. + +## Translations + +The source language is Dutch, matching the rest of the Toon interface. Every user-visible +string goes through `qsTr()`, and `lang/lang_en_GB.qm` translates them to English; the +Toon loads the catalog matching its own locale, following the same `lang/lang_.qm` +convention as the other ToonStore apps. Dutch needs no catalog, being the source language. + +`lang/lang_en_GB.ts` is the editable source and `lang/lang_en_GB.qm` the compiled form the +Toon actually reads, so **both must be committed**. After changing or adding a string: + +```sh +pip install PySide6 +pyside6-lupdate *.qml -ts lang/lang_en_GB.ts # pick up new strings +pyside6-lrelease lang/lang_en_GB.ts -qm lang/lang_en_GB.qm +``` + +`lupdate` merges rather than overwrites, marking new entries `type="unfinished"` for +translation and stale ones `type="vanished"`. Adding a language means copying the `.ts`, +changing its `language` attribute and compiling it to a matching `.qm`. ## Differences from upstream @@ -167,9 +193,8 @@ There is no way to run the app off-device: it depends on Toon-private QML module requests at any time, and every fetch sends your route coordinates to Waze. - `thumbnailIcon` points at `drawables/clock.svg`, which is not in this repository — inherited from upstream, where the file is likewise absent. -- Travel times are fetched over HTTP without a timeout; an unreachable Waze leaves the - last value on the tile until the route goes inactive. -- The settings screens are Dutch-only and not translated via `qsTr`. +- Only Dutch and English are provided. Any other locale falls back to the Dutch source + strings. ## License diff --git a/TscClockApp.qml b/TscClockApp.qml index 0d4d376..b347b89 100644 --- a/TscClockApp.qml +++ b/TscClockApp.qml @@ -28,7 +28,7 @@ App { // Route 1 property string route1Start: "06:30" property string route1End: "09:00" - property string route1Label: "Thuis-Werk:" + property string route1Label: qsTr("Thuis-Werk:") property string route1FromLat: "" property string route1FromLon: "" property string route1ToLat: "" @@ -39,7 +39,7 @@ App { // Route 2 property string route2Start: "16:00" property string route2End: "18:30" - property string route2Label: "Werk-Thuis:" + property string route2Label: qsTr("Werk-Thuis:") property string route2FromLat: "" property string route2FromLon: "" property string route2ToLat: "" @@ -53,6 +53,13 @@ App { property bool route1Active: false property bool route2Active: false + // The in-flight request per slot, kept so a stalled one can be aborted. + property var pendingXhr1: null + property var pendingXhr2: null + // Qt's QML XMLHttpRequest has no timeout property, so each request is + // guarded by a Timer that aborts it. + property int travelRequestTimeout: 15000 + FileIO { id: tscClockSettingsFile source: "file:///mnt/data/tsc/tscClock.userSettings.json" @@ -166,9 +173,54 @@ App { travelTime2Str = str; } + function setPendingXhr(slot, xhr) { + if (slot === 1) + pendingXhr1 = xhr; + else + pendingXhr2 = xhr; + } + + function travelTimeoutTimer(slot) { + return slot === 1 ? travelTimeout1 : travelTimeout2; + } + + function routeLabel(slot) { + return slot === 1 ? route1Label : route2Label; + } + + function clearTravelRequest(slot) { + travelTimeoutTimer(slot).stop(); + setPendingXhr(slot, null); + } + + // Replace the duration with a dash, so a route that cannot be reached reads + // as unavailable instead of silently freezing on its last known value. + function showTravelFailure(slot, reason) { + var lbl = routeLabel(slot); + setTravelTime(slot, (lbl ? lbl + " " : "") + "—"); + console.log("Waze: route " + slot + " unavailable — " + reason); + } + + // Drop the in-flight request for a slot. Pass an empty reason to abandon it + // silently (route switched off, or a new fetch supersedes it). + function abortTravelRequest(slot, reason) { + var xhr = slot === 1 ? pendingXhr1 : pendingXhr2; + if (xhr) { + // Detach first: abort() itself fires a final readyState change. + xhr.onreadystatechange = null; + xhr.abort(); + } + clearTravelRequest(slot); + if (reason) + showTravelFailure(slot, reason); + } + function fetchTravelTime(slot, fromLat, fromLon, toLat, toLon, label) { + // A refresh can land while the previous request is still open. + abortTravelRequest(slot, ""); if (!fromLat || !fromLon || !toLat || !toLon) { console.log("Waze: skipping fetch, missing coordinates"); + setTravelTime(slot, ""); return; } // Accept Dutch decimal commas and stray whitespace @@ -186,8 +238,9 @@ App { // Break the xhr <-> handler reference cycle so the request object // (and its closure) can be garbage-collected instead of leaking. xhr.onreadystatechange = null; + clearTravelRequest(slot); if (xhr.status !== 200) { - console.log("Waze: HTTP " + xhr.status + " — " + (xhr.responseText || "").substring(0, 200)); + showTravelFailure(slot, "HTTP " + xhr.status + " — " + (xhr.responseText || "").substring(0, 200)); return; } try { @@ -197,14 +250,19 @@ App { var secs = 0; for (var i = 0; i < results.length; i++) secs += results[i].crossTime; - var str = (lbl ? lbl + " " : "") + Math.round(secs / 60) + " min"; + var str = (lbl ? lbl + " " : "") + Math.round(secs / 60) + " " + qsTr("min"); setTravelTime(slot, str); console.log("Waze: ok — " + str); } catch (e) { - console.log("Waze: parse error — " + e + " — body: " + (xhr.responseText || "").substring(0, 200)); + showTravelFailure(slot, "parse error — " + e + " — body: " + (xhr.responseText || "").substring(0, 200)); } }; xhr.open("GET", url); + // Arm the guard before sending: a request that fails immediately calls + // the handler from inside send(), and that handler must be able to + // clear the pending request and stop the timer. + setPendingXhr(slot, xhr); + travelTimeoutTimer(slot).restart(); xhr.send(); } @@ -241,6 +299,7 @@ App { } } else { route1Active = false; + abortTravelRequest(1, ""); travelTime1Str = ""; } if (a2) { @@ -250,6 +309,7 @@ App { } } else { route2Active = false; + abortTravelRequest(2, ""); travelTime2Str = ""; } } @@ -303,6 +363,20 @@ App { onTriggered: updateClockTiles() } + Timer { + id: travelTimeout1 + interval: travelRequestTimeout + repeat: false + onTriggered: abortTravelRequest(1, "no response within " + travelRequestTimeout + " ms") + } + + Timer { + id: travelTimeout2 + interval: travelRequestTimeout + repeat: false + onTriggered: abortTravelRequest(2, "no response within " + travelRequestTimeout + " ms") + } + Timer { id: travelTimeRefreshTimer interval: 300000 // 5 minutes diff --git a/TscClockSettings.qml b/TscClockSettings.qml index f3b6ade..7eefc05 100644 --- a/TscClockSettings.qml +++ b/TscClockSettings.qml @@ -5,10 +5,10 @@ import BxtClient 1.0 Screen { id: tscClockSettingsScreen - screenTitle: "TSC Klok configuratie" + screenTitle: qsTr("TSC Klok configuratie") onShown: { - addCustomTopRightButton("Opslaan"); + addCustomTopRightButton(qsTr("Opslaan")); showDateToggle.isSwitchedOn = app.showDate; showSecondsToggle.isSwitchedOn = app.showSeconds; showMonthInTextToggle.isSwitchedOn = app.showMonthInText; @@ -30,7 +30,7 @@ Screen { width: isNxt ? 500 : 400 font.pixelSize: isNxt ? 20 : 16 font.family: qfont.semiBold.name - text: "Toon datum" + text: qsTr("Toon datum") } OnOffToggle { @@ -58,7 +58,7 @@ Screen { } font.pixelSize: isNxt ? 20 : 16 font.family: qfont.semiBold.name - text: "Toon seconden in de tijd" + text: qsTr("Toon seconden in de tijd") } OnOffToggle { @@ -85,7 +85,7 @@ Screen { } font.pixelSize: isNxt ? 20 : 16 font.family: qfont.semiBold.name - text: "Maand in datum voluit geschreven" + text: qsTr("Maand in datum voluit geschreven") opacity: app.showDate ? 1.0 : 0.35 } @@ -115,7 +115,7 @@ Screen { } font.pixelSize: isNxt ? 20 : 16 font.family: qfont.semiBold.name - text: "Toon dag van de week" + text: qsTr("Toon dag van de week") } OnOffToggle { @@ -142,7 +142,7 @@ Screen { } font.pixelSize: isNxt ? 20 : 16 font.family: qfont.semiBold.name - text: "Verticaal gecentreerde weergave" + text: qsTr("Verticaal gecentreerde weergave") } OnOffToggle { @@ -165,7 +165,7 @@ Screen { } font.pixelSize: isNxt ? 20 : 16 font.family: qfont.semiBold.name - text: "Dag voor datum (i.p.v. voor tijd)" + text: qsTr("Dag voor datum (i.p.v. voor tijd)") visible: app.showDayOfWeek opacity: app.showDate ? 1.0 : 0.35 } @@ -193,7 +193,7 @@ Screen { } font.pixelSize: isNxt ? 20 : 16 font.family: qfont.semiBold.name - text: "Waze reistijd »" + text: qsTr("Waze reistijd »") MouseArea { anchors.fill: parent diff --git a/TscClockTravelSettings.qml b/TscClockTravelSettings.qml index 2769024..80fd87b 100644 --- a/TscClockTravelSettings.qml +++ b/TscClockTravelSettings.qml @@ -4,10 +4,10 @@ import qb.components 1.0 Screen { id: tscClockTravelSettingsScreen - screenTitle: "Waze reistijd configuratie" + screenTitle: qsTr("Waze reistijd configuratie") onShown: { - addCustomTopRightButton("Opslaan"); + addCustomTopRightButton(qsTr("Opslaan")); r1StartInput.text = app.route1Start; r1EndInput.text = app.route1End; r1FromLatInput.text = app.route1FromLat; @@ -66,7 +66,7 @@ Screen { y: isNxt ? 60 : 50 font.pixelSize: isNxt ? 22 : 18 font.family: qfont.semiBold.name - text: "Route 1" + text: qsTr("Route 1") } Text { @@ -80,7 +80,7 @@ Screen { height: isNxt ? 36 : 28 font.pixelSize: isNxt ? 18 : 14 font.family: qfont.regular.name - text: "Periode:" + text: qsTr("Periode:") verticalAlignment: Text.AlignVCenter } Rectangle { @@ -119,7 +119,7 @@ Screen { height: isNxt ? 36 : 28 font.pixelSize: isNxt ? 18 : 14 font.family: qfont.regular.name - text: "tot" + text: qsTr("tot") verticalAlignment: Text.AlignVCenter } Rectangle { @@ -159,7 +159,7 @@ Screen { height: isNxt ? 36 : 28 font.pixelSize: isNxt ? 18 : 14 font.family: qfont.regular.name - text: "Label:" + text: qsTr("Label:") verticalAlignment: Text.AlignVCenter } Rectangle { @@ -198,7 +198,7 @@ Screen { height: isNxt ? 36 : 28 font.pixelSize: isNxt ? 18 : 14 font.family: qfont.regular.name - text: "Van:" + text: qsTr("Van:") verticalAlignment: Text.AlignVCenter } Rectangle { @@ -261,7 +261,7 @@ Screen { height: isNxt ? 36 : 28 font.pixelSize: isNxt ? 18 : 14 font.family: qfont.regular.name - text: "Naar:" + text: qsTr("Naar:") verticalAlignment: Text.AlignVCenter } Rectangle { @@ -323,7 +323,7 @@ Screen { height: isNxt ? 36 : 28 font.pixelSize: isNxt ? 18 : 14 font.family: qfont.regular.name - text: "Alleen op werkdagen" + text: qsTr("Alleen op werkdagen") verticalAlignment: Text.AlignVCenter } OnOffToggle { @@ -350,7 +350,7 @@ Screen { } font.pixelSize: isNxt ? 22 : 18 font.family: qfont.semiBold.name - text: "Route 2" + text: qsTr("Route 2") } Text { @@ -364,7 +364,7 @@ Screen { height: isNxt ? 36 : 28 font.pixelSize: isNxt ? 18 : 14 font.family: qfont.regular.name - text: "Periode:" + text: qsTr("Periode:") verticalAlignment: Text.AlignVCenter } Rectangle { @@ -403,7 +403,7 @@ Screen { height: isNxt ? 36 : 28 font.pixelSize: isNxt ? 18 : 14 font.family: qfont.regular.name - text: "tot" + text: qsTr("tot") verticalAlignment: Text.AlignVCenter } Rectangle { @@ -443,7 +443,7 @@ Screen { height: isNxt ? 36 : 28 font.pixelSize: isNxt ? 18 : 14 font.family: qfont.regular.name - text: "Label:" + text: qsTr("Label:") verticalAlignment: Text.AlignVCenter } Rectangle { @@ -482,7 +482,7 @@ Screen { height: isNxt ? 36 : 28 font.pixelSize: isNxt ? 18 : 14 font.family: qfont.regular.name - text: "Van:" + text: qsTr("Van:") verticalAlignment: Text.AlignVCenter } Rectangle { @@ -545,7 +545,7 @@ Screen { height: isNxt ? 36 : 28 font.pixelSize: isNxt ? 18 : 14 font.family: qfont.regular.name - text: "Naar:" + text: qsTr("Naar:") verticalAlignment: Text.AlignVCenter } Rectangle { @@ -607,7 +607,7 @@ Screen { height: isNxt ? 36 : 28 font.pixelSize: isNxt ? 18 : 14 font.family: qfont.regular.name - text: "Alleen op werkdagen" + text: qsTr("Alleen op werkdagen") verticalAlignment: Text.AlignVCenter } OnOffToggle { @@ -635,7 +635,7 @@ Screen { font.pixelSize: isNxt ? 18 : 14 font.family: qfont.regular.name color: "#555555" - text: "Lat" + text: qsTr("Lat") verticalAlignment: Text.AlignVCenter } Text { @@ -650,7 +650,7 @@ Screen { font.pixelSize: isNxt ? 18 : 14 font.family: qfont.regular.name color: "#555555" - text: "Lon" + text: qsTr("Lon") verticalAlignment: Text.AlignVCenter } Text { @@ -665,7 +665,7 @@ Screen { font.pixelSize: isNxt ? 18 : 14 font.family: qfont.regular.name color: "#555555" - text: "Lat" + text: qsTr("Lat") verticalAlignment: Text.AlignVCenter } Text { @@ -680,7 +680,7 @@ Screen { font.pixelSize: isNxt ? 18 : 14 font.family: qfont.regular.name color: "#555555" - text: "Lon" + text: qsTr("Lon") verticalAlignment: Text.AlignVCenter } Text { @@ -695,7 +695,7 @@ Screen { font.pixelSize: isNxt ? 18 : 14 font.family: qfont.regular.name color: "#555555" - text: "Lat" + text: qsTr("Lat") verticalAlignment: Text.AlignVCenter } Text { @@ -710,7 +710,7 @@ Screen { font.pixelSize: isNxt ? 18 : 14 font.family: qfont.regular.name color: "#555555" - text: "Lon" + text: qsTr("Lon") verticalAlignment: Text.AlignVCenter } Text { @@ -725,7 +725,7 @@ Screen { font.pixelSize: isNxt ? 18 : 14 font.family: qfont.regular.name color: "#555555" - text: "Lat" + text: qsTr("Lat") verticalAlignment: Text.AlignVCenter } Text { @@ -740,7 +740,7 @@ Screen { font.pixelSize: isNxt ? 18 : 14 font.family: qfont.regular.name color: "#555555" - text: "Lon" + text: qsTr("Lon") verticalAlignment: Text.AlignVCenter } @@ -756,7 +756,7 @@ Screen { height: isNxt ? 36 : 28 font.pixelSize: isNxt ? 18 : 14 font.family: qfont.regular.name - text: "Tijdvenster" + text: qsTr("Tijdvenster") verticalAlignment: Text.AlignVCenter } OnOffToggle { @@ -779,7 +779,7 @@ Screen { height: isNxt ? 36 : 28 font.pixelSize: isNxt ? 18 : 14 font.family: qfont.regular.name - text: "Tijdvenster" + text: qsTr("Tijdvenster") verticalAlignment: Text.AlignVCenter } OnOffToggle { @@ -804,6 +804,6 @@ Screen { font.pixelSize: isNxt ? 15 : 12 font.family: qfont.regular.name color: "#888888" - text: "Coördinaten in decimaal formaat (bijv. 52.3704 / 4.8952), tijd als HH:MM" + text: qsTr("Coördinaten in decimaal formaat (bijv. 52.3704 / 4.8952), tijd als HH:MM") } } diff --git a/lang/lang_en_GB.qm b/lang/lang_en_GB.qm new file mode 100644 index 0000000000000000000000000000000000000000..2e70c206c63880fa9c80e6db44cd2e4a1d030a48 GIT binary patch literal 2493 zcma)7QD|FL82*zqX|}eb&UK6`cm`u_p~<=|wOdhP?a(?CSDMg*gUyqBPm{ac+*8iI zNnH0N?4hU+iufStgAX$BS;p8DL0`n7Z-asC!3SS_8O%NTF#OI*bJNx)k&>R=bI<>M z|Ns5p`SZ#h``9m!zxeFe<1ha3?pNPGx!Ce>=YX-~rx$8m~Tm0XR1k&Fo)zJ)hW|NCWRlYfXGI z_;_xFXy9)0;&-oMEgf)gapWOxjokn{j3zY@`R0jZpW)2kDUV;^W!8{VF`EbV8k=;|8|g;6 zwG}wm>?xhlXj`{}2m;3|`$oK%A(;YVD}#V4CX*VNJ?vFX4t0EECO3wB>S&W2a3xi|=DQaOn zDw7}LjlnWZdxu%lTX)KJ#RErlN1sGS6_nltzHWfkmMI@ldxW(R<-+A@u@p+LJq?M%0A62c!d@Vi| zPL`onP$(m;1v$`nBZ-Aw?GA-iyVNyONjM`2>0VkDDsU{$U3kF~UZ8|fEqzp(H+nST z1RTj}6WGjf7>j^IKee3C=w8S(y2dvJQ^N6eE$qj8-OCvVu<71*Z?$IH<|rzJd;YxZ z3dkcj&`DKAV_ObB+P*wRh2-5`S7-}fl=xG?)edZ3=T1j#uv#W{Eup?b`fSad)0bXQ z8m>*_%`9cGo}oFKp)8(H;giMASvqIlP0=)VIx=w6_a%(2dCF5htm4f@`O|G>J01_( zt+t$+?!~%PSOYd$a;{-Q%x2PO=4P_&6w9X1o}0}~O&d!v?)q$LX+EFVYWAvqm~yB? z4>Whj%uVEYNw{WS_6kmz;ErcvIUe*Q)G=sUSZXXM&A8~zQ$$Q>rpMprT=mVa_ju~X zcZilDh@Pqvmgw*%mxXeqE&5U)q7{Vdv8yk^>9E+r6L2XHu%SPPldhHzgP1H Tpt=kzjRmr&CAV-tqLIkIq+=`` literal 0 HcmV?d00001 diff --git a/lang/lang_en_GB.ts b/lang/lang_en_GB.ts new file mode 100644 index 0000000..c73f8ec --- /dev/null +++ b/lang/lang_en_GB.ts @@ -0,0 +1,121 @@ + + + + + TscClockApp + + Klok-TSC + Clock-TSC + + + Thuis-Werk: + Home-Work: + + + Werk-Thuis: + Work-Home: + + + min + min + + + + TscClockSettings + + TSC Klok configuratie + TSC Clock settings + + + Opslaan + Save + + + Toon datum + Show date + + + Toon seconden in de tijd + Show seconds in the time + + + Maand in datum voluit geschreven + Write the month out in full + + + Toon dag van de week + Show day of the week + + + Verticaal gecentreerde weergave + Vertically centred layout + + + Dag voor datum (i.p.v. voor tijd) + Day before date (instead of before time) + + + Waze reistijd » + Waze travel time » + + + + TscClockTravelSettings + + Waze reistijd configuratie + Waze travel time settings + + + Opslaan + Save + + + Route 1 + Route 1 + + + Route 2 + Route 2 + + + Periode: + Period: + + + tot + to + + + Label: + Label: + + + Van: + From: + + + Naar: + To: + + + Lat + Lat + + + Lon + Lon + + + Tijdvenster + Time window + + + Alleen op werkdagen + Weekdays only + + + Coördinaten in decimaal formaat (bijv. 52.3704 / 4.8952), tijd als HH:MM + Coordinates in decimal format (e.g. 52.3704 / 4.8952), time as HH:MM + + + diff --git a/version.txt b/version.txt index 9084fa2..524cb55 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.1.0 +1.1.1