Mercurial > ~darius > hgwebdir.cgi > OverviewJD
diff main.qml @ 0:57ffb39f29d4
First commit of new carousel page to allow battery charging current to
be adjusted.
author | Daniel O'Connor <darius@dons.net.au> |
---|---|
date | Mon, 13 Dec 2021 23:05:38 +1030 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.qml Mon Dec 13 23:05:38 2021 +1030 @@ -0,0 +1,369 @@ +import QtQuick 1.1 + +import Qt.labs.components.native 1.0 +import com.victron.velib 1.0 +import "utils.js" as Utils + +PageStackWindow { + id: rootWindow + + gpsConnected: gpsFix.value === 1 + onCompletedChanged: checkAlarm() + initialPage: PageMain {} + + property VeQuickItem gpsService: VeQuickItem { uid: "dbus/com.victronenergy.system/GpsService" } + property VeQuickItem gpsFix: VeQuickItem { uid: Utils.path("dbus/", gpsService.value, "/Fix") } + property bool completed: false + property bool showAlert: NotificationCenter.alert + property bool alarm: NotificationCenter.alarm + property bool overviewsLoaded: defaultOverview.valid && generatorOverview.valid && mobileOverview.valid && tanksOverview.valid && startWithMenu.valid + property string bindPrefix: "com.victronenergy.settings" + + property bool isNotificationPage: pageStack.currentPage && pageStack.currentPage.title === qsTr("Notifications") + property bool isOverviewPage: pageStack.currentPage && pageStack.currentPage.model === overviewModel; + property bool isOfflineFwUpdatePage: pageStack.currentPage && pageStack.currentPage.objectName === "offlineFwUpdatePage"; + + + property string hubOverviewType: theSystem.systemType.valid ? + withoutGridMeter.value === 1 ? "Hub" : theSystem.systemType.value : "" + + // Keep track of the current view (menu/overview) to show as default next time the + // CCGX is restarted + onIsOverviewPageChanged: startWithMenu.setValue(isOverviewPage ? 0 : 1) + + // Add the correct OverviewHub page + onHubOverviewTypeChanged: { + switch(hubOverviewType){ + case "Hub": + case "Hub-1": + case "Hub-2": + case "Hub-3": + replaceOverview("OverviewGridParallel.qml", "OverviewHub.qml"); + break; + case "Hub-4": + case "ESS": + replaceOverview("OverviewHub.qml", "OverviewGridParallel.qml"); + break; + default: + break; + } + // Workaround the QTBUG-17012 (only the first sentence in each case of Switch Statement can be executed) + // by adding a return statement + return + } + + VBusItem { + id: generatorOverview + bind: "com.victronenergy.settings/Settings/Relay/Function" + onValueChanged: extraOverview("OverviewGeneratorRelay.qml", value === 1) + } + + VBusItem { + id: fischerPandaGenOverview + bind: "com.victronenergy.settings/Settings/Services/FischerPandaAutoStartStop" + onValueChanged: extraOverview("OverviewGeneratorFp.qml", value === 1) + } + + VBusItem { + id: mobileOverview + bind: "com.victronenergy.settings/Settings/Gui/MobileOverview" + onValueChanged:{ + extraOverview("OverviewMobile.qml", value === 1) + } + } + VBusItem { + id: tanksOverview + bind: "com.victronenergy.settings/Settings/Gui/TanksOverview" + onValueChanged:{ + extraOverview("OverviewTanks.qml", value === 1) + } + } + + VBusItem { + id: startWithMenu + bind: "com.victronenergy.settings/Settings/Gui/StartWithMenuView" + } + + VBusItem { + id: withoutGridMeter + bind: "com.victronenergy.settings/Settings/CGwacs/RunWithoutGridMeter" + } + + + VBusItem { + id: defaultOverview + bind: "com.victronenergy.settings/Settings/Gui/DefaultOverview" + } + + // Note: finding a firmware image on the storage device is error 4 for vrm storage + // since it should not be used for logging. That fact is used here to determine if + // there is a firmware image. + Connections { + target: storageEvents + onVrmStorageError: { + if (error === 4) { + setTopPage(offlineFwUpdates) + } + } + } + + onAlarmChanged: { + if (completed) + checkAlarm() + } + + // always keep track of system information + HubData { + id: theSystem + } + + // note: used for leaving the overviews as well + function backToMainMenu() + { + pageStack.pop(initialPage); + } + + Toast { + id: toast + transform: Scale { + xScale: screen.scaleX + yScale: screen.scaleY + origin.x: toast.width / 2 + origin.y: toast.height / 2 + } + } + + SignalToaster {} + + ToolbarHandlerPages { + id: mainToolbarHandler + isDefault: true + } + + ToolBarLayout { + id: mbTools + height: parent.height + + Item { + anchors.verticalCenter: parent.verticalCenter + anchors.left: mbTools.left + height: mbTools.height + width: 200 + + MouseArea { + anchors.fill: parent + onClicked: { + if (pageStack.currentPage) + pageStack.currentPage.toolbarHandler.leftAction(true) + } + } + + Row { + anchors.centerIn: parent + + MbIcon { + anchors.verticalCenter: parent.verticalCenter + iconId: pageStack.currentPage ? pageStack.currentPage.leftIcon : "" + } + + Text { + anchors.verticalCenter: parent.verticalCenter + text: pageStack.currentPage ? pageStack.currentPage.leftText : "" + color: "white" + font.bold: true + font.pixelSize: 16 + } + } + } + + MbIcon { + id: centerScrollIndicator + + anchors { + horizontalCenter: parent.horizontalCenter + verticalCenter: mbTools.verticalCenter + } + iconId: pageStack.currentPage ? pageStack.currentPage.scrollIndicator : "" + } + + Item { + anchors.verticalCenter: parent.verticalCenter + height: mbTools.height + anchors.right: mbTools.right + width: 200 + + MouseArea { + anchors.fill: parent + onClicked: { + if (pageStack.currentPage) + pageStack.currentPage.toolbarHandler.rightAction(true) + } + } + + Row { + anchors.centerIn: parent + + MbIcon { + iconId: pageStack.currentPage ? pageStack.currentPage.rightIcon : "" + anchors.verticalCenter: parent.verticalCenter + } + + Text { + text: pageStack.currentPage ? pageStack.currentPage.rightText : "" + anchors.verticalCenter: parent.verticalCenter + color: "white" + font.bold: true + font.pixelSize: 16 + } + } + } + } + + Component.onCompleted: { + completed = true + } + + ListModel { + id: overviewModel + ListElement { + pageSource: "OverviewHub.qml" + } + ListElement { + pageSource: "OverviewTiles.qml" + } + // ---> OverviewJD sentinel + ListElement { + pageSource: "OverviewJD.qml" + } + // <--- OverviewJD trailer + } + + Component { + id: overviewComponent + PageFlow { + // Display default overview when loaded + defaultIndex: getDefaultOverviewIndex() + // Store the current overview page as default + onCurrentIndexChanged: if (active) defaultOverview.setValue(overviewModel.get(currentIndex).pageSource.replace(".qml", "")) + model: overviewModel + } + } + + // When all the related settings items are valid, show the overview page if was the last oppened page + // before restarting + Timer { + interval: 2000 + running: completed && overviewsLoaded && startWithMenu.valid + onTriggered: if (startWithMenu.value === 0) showOverview() + } + + function getDefaultOverviewIndex() + { + if(!defaultOverview.valid) + return 0 + for (var i = 0; i < overviewModel.count; i++){ + if (overviewModel.get(i).pageSource.replace(".qml", "") === defaultOverview.value) { + return i + } + } + return 0 + } + + Component { + id: noticationsComponent + PageNotifications {} + } + + Component { + id: offlineFwUpdates + PageSettingsFirmwareOffline { checkOnCompleted: true} + + } + + // Add or remove extra overviews. for example, generator overview + // shouldn't be shown if the start/stop functionality is not enabled. + // Index parameter is optional, usefull to keep an order. + function extraOverview(name, show, index) + { + var i = 0 + if (show) { + if (index !== undefined) { + if (overviewModel.get(index).pageSource === name) + return + // First append the page + overviewModel.append({"pageSource": name}) + // Then move all the pages behind index + overviewModel.move(index, overviewModel.count - 2, overviewModel.count - 2) + } else { + for (i = 0; i < overviewModel.count; i++) + if (overviewModel.get(i).pageSource === name) + // Don't append if already exists + return + overviewModel.append({"pageSource": name}) + } + } else { + for (i = 0; i < overviewModel.count; i++) + if (overviewModel.get(i).pageSource === name) + overviewModel.remove(i) + } + } + + function replaceOverview(oldPage, newPage) + { + for (var i = 0; i < overviewModel.count; i++) + if (overviewModel.get(i).pageSource === oldPage) + overviewModel.get(i).pageSource = newPage + } + + // Central mover for the ball animation on the overviews + // Instead of using a timer per line, using a central one + // reduces the CPU usage a little bit and makes the animations + // smoother. + Timer { + id: mover + property double pos: _counter / _loops + property int _counter + property int _loops: 13 + + interval: 100 + running: true + repeat: true + onTriggered: if (_counter >= (_loops - 1)) _counter = 0; else _counter++ + } + + // If an overview or notifications is active, the new page will replace it + // instead to be pushed. This way we prevent an unwanted stackpage depth + // increment everytime another page wants to be on top. + function setTopPage(page) + { + if (isNotificationPage || isOverviewPage || isOfflineFwUpdatePage) + rootWindow.pageStack.replace(page); + else + rootWindow.pageStack.push(page); + } + + function spuriousKeyPress() + { + return !pageStack.currentPage || !pageStack.currentPage.active + } + + function showOverview() + { + if (spuriousKeyPress() || isOverviewPage) + return + setTopPage(overviewComponent) + } + + function showPageNotifications() + { + if (spuriousKeyPress() || isNotificationPage) + return + setTopPage(noticationsComponent) + } + + function checkAlarm() + { + if (alarm) + showPageNotifications() + } +}