Mercurial > ~darius > hgwebdir.cgi > OverviewJD
comparison 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 |
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 // ---> OverviewJD sentinel | |
235 ListElement { | |
236 pageSource: "OverviewJD.qml" | |
237 } | |
238 // <--- OverviewJD trailer | |
239 } | |
240 | |
241 Component { | |
242 id: overviewComponent | |
243 PageFlow { | |
244 // Display default overview when loaded | |
245 defaultIndex: getDefaultOverviewIndex() | |
246 // Store the current overview page as default | |
247 onCurrentIndexChanged: if (active) defaultOverview.setValue(overviewModel.get(currentIndex).pageSource.replace(".qml", "")) | |
248 model: overviewModel | |
249 } | |
250 } | |
251 | |
252 // When all the related settings items are valid, show the overview page if was the last oppened page | |
253 // before restarting | |
254 Timer { | |
255 interval: 2000 | |
256 running: completed && overviewsLoaded && startWithMenu.valid | |
257 onTriggered: if (startWithMenu.value === 0) showOverview() | |
258 } | |
259 | |
260 function getDefaultOverviewIndex() | |
261 { | |
262 if(!defaultOverview.valid) | |
263 return 0 | |
264 for (var i = 0; i < overviewModel.count; i++){ | |
265 if (overviewModel.get(i).pageSource.replace(".qml", "") === defaultOverview.value) { | |
266 return i | |
267 } | |
268 } | |
269 return 0 | |
270 } | |
271 | |
272 Component { | |
273 id: noticationsComponent | |
274 PageNotifications {} | |
275 } | |
276 | |
277 Component { | |
278 id: offlineFwUpdates | |
279 PageSettingsFirmwareOffline { checkOnCompleted: true} | |
280 | |
281 } | |
282 | |
283 // Add or remove extra overviews. for example, generator overview | |
284 // shouldn't be shown if the start/stop functionality is not enabled. | |
285 // Index parameter is optional, usefull to keep an order. | |
286 function extraOverview(name, show, index) | |
287 { | |
288 var i = 0 | |
289 if (show) { | |
290 if (index !== undefined) { | |
291 if (overviewModel.get(index).pageSource === name) | |
292 return | |
293 // First append the page | |
294 overviewModel.append({"pageSource": name}) | |
295 // Then move all the pages behind index | |
296 overviewModel.move(index, overviewModel.count - 2, overviewModel.count - 2) | |
297 } else { | |
298 for (i = 0; i < overviewModel.count; i++) | |
299 if (overviewModel.get(i).pageSource === name) | |
300 // Don't append if already exists | |
301 return | |
302 overviewModel.append({"pageSource": name}) | |
303 } | |
304 } else { | |
305 for (i = 0; i < overviewModel.count; i++) | |
306 if (overviewModel.get(i).pageSource === name) | |
307 overviewModel.remove(i) | |
308 } | |
309 } | |
310 | |
311 function replaceOverview(oldPage, newPage) | |
312 { | |
313 for (var i = 0; i < overviewModel.count; i++) | |
314 if (overviewModel.get(i).pageSource === oldPage) | |
315 overviewModel.get(i).pageSource = newPage | |
316 } | |
317 | |
318 // Central mover for the ball animation on the overviews | |
319 // Instead of using a timer per line, using a central one | |
320 // reduces the CPU usage a little bit and makes the animations | |
321 // smoother. | |
322 Timer { | |
323 id: mover | |
324 property double pos: _counter / _loops | |
325 property int _counter | |
326 property int _loops: 13 | |
327 | |
328 interval: 100 | |
329 running: true | |
330 repeat: true | |
331 onTriggered: if (_counter >= (_loops - 1)) _counter = 0; else _counter++ | |
332 } | |
333 | |
334 // If an overview or notifications is active, the new page will replace it | |
335 // instead to be pushed. This way we prevent an unwanted stackpage depth | |
336 // increment everytime another page wants to be on top. | |
337 function setTopPage(page) | |
338 { | |
339 if (isNotificationPage || isOverviewPage || isOfflineFwUpdatePage) | |
340 rootWindow.pageStack.replace(page); | |
341 else | |
342 rootWindow.pageStack.push(page); | |
343 } | |
344 | |
345 function spuriousKeyPress() | |
346 { | |
347 return !pageStack.currentPage || !pageStack.currentPage.active | |
348 } | |
349 | |
350 function showOverview() | |
351 { | |
352 if (spuriousKeyPress() || isOverviewPage) | |
353 return | |
354 setTopPage(overviewComponent) | |
355 } | |
356 | |
357 function showPageNotifications() | |
358 { | |
359 if (spuriousKeyPress() || isNotificationPage) | |
360 return | |
361 setTopPage(noticationsComponent) | |
362 } | |
363 | |
364 function checkAlarm() | |
365 { | |
366 if (alarm) | |
367 showPageNotifications() | |
368 } | |
369 } |