comparison main.qml.orig @ 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
comparison
equal deleted inserted replaced
-1:000000000000 0:57ffb39f29d4
1 import QtQuick 1.1
2
3 import Qt.labs.components.native 1.0
4 import com.victron.velib 1.0
5 import "utils.js" as Utils
6
7 PageStackWindow {
8 id: rootWindow
9
10 gpsConnected: gpsFix.value === 1
11 onCompletedChanged: checkAlarm()
12 initialPage: PageMain {}
13
14 property VeQuickItem gpsService: VeQuickItem { uid: "dbus/com.victronenergy.system/GpsService" }
15 property VeQuickItem gpsFix: VeQuickItem { uid: Utils.path("dbus/", gpsService.value, "/Fix") }
16 property bool completed: false
17 property bool showAlert: NotificationCenter.alert
18 property bool alarm: NotificationCenter.alarm
19 property bool overviewsLoaded: defaultOverview.valid && generatorOverview.valid && mobileOverview.valid && tanksOverview.valid && startWithMenu.valid
20 property string bindPrefix: "com.victronenergy.settings"
21
22 property bool isNotificationPage: pageStack.currentPage && pageStack.currentPage.title === qsTr("Notifications")
23 property bool isOverviewPage: pageStack.currentPage && pageStack.currentPage.model === overviewModel;
24 property bool isOfflineFwUpdatePage: pageStack.currentPage && pageStack.currentPage.objectName === "offlineFwUpdatePage";
25
26
27 property string hubOverviewType: theSystem.systemType.valid ?
28 withoutGridMeter.value === 1 ? "Hub" : theSystem.systemType.value : ""
29
30 // Keep track of the current view (menu/overview) to show as default next time the
31 // CCGX is restarted
32 onIsOverviewPageChanged: startWithMenu.setValue(isOverviewPage ? 0 : 1)
33
34 // Add the correct OverviewHub page
35 onHubOverviewTypeChanged: {
36 switch(hubOverviewType){
37 case "Hub":
38 case "Hub-1":
39 case "Hub-2":
40 case "Hub-3":
41 replaceOverview("OverviewGridParallel.qml", "OverviewHub.qml");
42 break;
43 case "Hub-4":
44 case "ESS":
45 replaceOverview("OverviewHub.qml", "OverviewGridParallel.qml");
46 break;
47 default:
48 break;
49 }
50 // Workaround the QTBUG-17012 (only the first sentence in each case of Switch Statement can be executed)
51 // by adding a return statement
52 return
53 }
54
55 VBusItem {
56 id: generatorOverview
57 bind: "com.victronenergy.settings/Settings/Relay/Function"
58 onValueChanged: extraOverview("OverviewGeneratorRelay.qml", value === 1)
59 }
60
61 VBusItem {
62 id: fischerPandaGenOverview
63 bind: "com.victronenergy.settings/Settings/Services/FischerPandaAutoStartStop"
64 onValueChanged: extraOverview("OverviewGeneratorFp.qml", value === 1)
65 }
66
67 VBusItem {
68 id: mobileOverview
69 bind: "com.victronenergy.settings/Settings/Gui/MobileOverview"
70 onValueChanged:{
71 extraOverview("OverviewMobile.qml", value === 1)
72 }
73 }
74 VBusItem {
75 id: tanksOverview
76 bind: "com.victronenergy.settings/Settings/Gui/TanksOverview"
77 onValueChanged:{
78 extraOverview("OverviewTanks.qml", value === 1)
79 }
80 }
81
82 VBusItem {
83 id: startWithMenu
84 bind: "com.victronenergy.settings/Settings/Gui/StartWithMenuView"
85 }
86
87 VBusItem {
88 id: withoutGridMeter
89 bind: "com.victronenergy.settings/Settings/CGwacs/RunWithoutGridMeter"
90 }
91
92
93 VBusItem {
94 id: defaultOverview
95 bind: "com.victronenergy.settings/Settings/Gui/DefaultOverview"
96 }
97
98 // Note: finding a firmware image on the storage device is error 4 for vrm storage
99 // since it should not be used for logging. That fact is used here to determine if
100 // there is a firmware image.
101 Connections {
102 target: storageEvents
103 onVrmStorageError: {
104 if (error === 4) {
105 setTopPage(offlineFwUpdates)
106 }
107 }
108 }
109
110 onAlarmChanged: {
111 if (completed)
112 checkAlarm()
113 }
114
115 // always keep track of system information
116 HubData {
117 id: theSystem
118 }
119
120 // note: used for leaving the overviews as well
121 function backToMainMenu()
122 {
123 pageStack.pop(initialPage);
124 }
125
126 Toast {
127 id: toast
128 transform: Scale {
129 xScale: screen.scaleX
130 yScale: screen.scaleY
131 origin.x: toast.width / 2
132 origin.y: toast.height / 2
133 }
134 }
135
136 SignalToaster {}
137
138 ToolbarHandlerPages {
139 id: mainToolbarHandler
140 isDefault: true
141 }
142
143 ToolBarLayout {
144 id: mbTools
145 height: parent.height
146
147 Item {
148 anchors.verticalCenter: parent.verticalCenter
149 anchors.left: mbTools.left
150 height: mbTools.height
151 width: 200
152
153 MouseArea {
154 anchors.fill: parent
155 onClicked: {
156 if (pageStack.currentPage)
157 pageStack.currentPage.toolbarHandler.leftAction(true)
158 }
159 }
160
161 Row {
162 anchors.centerIn: parent
163
164 MbIcon {
165 anchors.verticalCenter: parent.verticalCenter
166 iconId: pageStack.currentPage ? pageStack.currentPage.leftIcon : ""
167 }
168
169 Text {
170 anchors.verticalCenter: parent.verticalCenter
171 text: pageStack.currentPage ? pageStack.currentPage.leftText : ""
172 color: "white"
173 font.bold: true
174 font.pixelSize: 16
175 }
176 }
177 }
178
179 MbIcon {
180 id: centerScrollIndicator
181
182 anchors {
183 horizontalCenter: parent.horizontalCenter
184 verticalCenter: mbTools.verticalCenter
185 }
186 iconId: pageStack.currentPage ? pageStack.currentPage.scrollIndicator : ""
187 }
188
189 Item {
190 anchors.verticalCenter: parent.verticalCenter
191 height: mbTools.height
192 anchors.right: mbTools.right
193 width: 200
194
195 MouseArea {
196 anchors.fill: parent
197 onClicked: {
198 if (pageStack.currentPage)
199 pageStack.currentPage.toolbarHandler.rightAction(true)
200 }
201 }
202
203 Row {
204 anchors.centerIn: parent
205
206 MbIcon {
207 iconId: pageStack.currentPage ? pageStack.currentPage.rightIcon : ""
208 anchors.verticalCenter: parent.verticalCenter
209 }
210
211 Text {
212 text: pageStack.currentPage ? pageStack.currentPage.rightText : ""
213 anchors.verticalCenter: parent.verticalCenter
214 color: "white"
215 font.bold: true
216 font.pixelSize: 16
217 }
218 }
219 }
220 }
221
222 Component.onCompleted: {
223 completed = true
224 }
225
226 ListModel {
227 id: overviewModel
228 ListElement {
229 pageSource: "OverviewHub.qml"
230 }
231 ListElement {
232 pageSource: "OverviewTiles.qml"
233 }
234 }
235
236 Component {
237 id: overviewComponent
238 PageFlow {
239 // Display default overview when loaded
240 defaultIndex: getDefaultOverviewIndex()
241 // Store the current overview page as default
242 onCurrentIndexChanged: if (active) defaultOverview.setValue(overviewModel.get(currentIndex).pageSource.replace(".qml", ""))
243 model: overviewModel
244 }
245 }
246
247 // When all the related settings items are valid, show the overview page if was the last oppened page
248 // before restarting
249 Timer {
250 interval: 2000
251 running: completed && overviewsLoaded && startWithMenu.valid
252 onTriggered: if (startWithMenu.value === 0) showOverview()
253 }
254
255 function getDefaultOverviewIndex()
256 {
257 if(!defaultOverview.valid)
258 return 0
259 for (var i = 0; i < overviewModel.count; i++){
260 if (overviewModel.get(i).pageSource.replace(".qml", "") === defaultOverview.value) {
261 return i
262 }
263 }
264 return 0
265 }
266
267 Component {
268 id: noticationsComponent
269 PageNotifications {}
270 }
271
272 Component {
273 id: offlineFwUpdates
274 PageSettingsFirmwareOffline { checkOnCompleted: true}
275
276 }
277
278 // Add or remove extra overviews. for example, generator overview
279 // shouldn't be shown if the start/stop functionality is not enabled.
280 // Index parameter is optional, usefull to keep an order.
281 function extraOverview(name, show, index)
282 {
283 var i = 0
284 if (show) {
285 if (index !== undefined) {
286 if (overviewModel.get(index).pageSource === name)
287 return
288 // First append the page
289 overviewModel.append({"pageSource": name})
290 // Then move all the pages behind index
291 overviewModel.move(index, overviewModel.count - 2, overviewModel.count - 2)
292 } else {
293 for (i = 0; i < overviewModel.count; i++)
294 if (overviewModel.get(i).pageSource === name)
295 // Don't append if already exists
296 return
297 overviewModel.append({"pageSource": name})
298 }
299 } else {
300 for (i = 0; i < overviewModel.count; i++)
301 if (overviewModel.get(i).pageSource === name)
302 overviewModel.remove(i)
303 }
304 }
305
306 function replaceOverview(oldPage, newPage)
307 {
308 for (var i = 0; i < overviewModel.count; i++)
309 if (overviewModel.get(i).pageSource === oldPage)
310 overviewModel.get(i).pageSource = newPage
311 }
312
313 // Central mover for the ball animation on the overviews
314 // Instead of using a timer per line, using a central one
315 // reduces the CPU usage a little bit and makes the animations
316 // smoother.
317 Timer {
318 id: mover
319 property double pos: _counter / _loops
320 property int _counter
321 property int _loops: 13
322
323 interval: 100
324 running: true
325 repeat: true
326 onTriggered: if (_counter >= (_loops - 1)) _counter = 0; else _counter++
327 }
328
329 // If an overview or notifications is active, the new page will replace it
330 // instead to be pushed. This way we prevent an unwanted stackpage depth
331 // increment everytime another page wants to be on top.
332 function setTopPage(page)
333 {
334 if (isNotificationPage || isOverviewPage || isOfflineFwUpdatePage)
335 rootWindow.pageStack.replace(page);
336 else
337 rootWindow.pageStack.push(page);
338 }
339
340 function spuriousKeyPress()
341 {
342 return !pageStack.currentPage || !pageStack.currentPage.active
343 }
344
345 function showOverview()
346 {
347 if (spuriousKeyPress() || isOverviewPage)
348 return
349 setTopPage(overviewComponent)
350 }
351
352 function showPageNotifications()
353 {
354 if (spuriousKeyPress() || isNotificationPage)
355 return
356 setTopPage(noticationsComponent)
357 }
358
359 function checkAlarm()
360 {
361 if (alarm)
362 showPageNotifications()
363 }
364 }