Lomiri
Loading...
Searching...
No Matches
IndicatorsLight.qml
1/*
2 * Copyright 2014 Canonical Ltd.
3 * Copyright 2019 UBports Foundation
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public License as published by
7 * the Free Software Foundation; version 3.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 * Authors:
18 * Renato Araujo Oliveira Filho <renato@canonical.com>
19 */
20
21import QtQuick 2.15
22import QtQml 2.15
23import Powerd 0.1
24import Hfd 0.1
25import QMenuModel 1.0 as QMenuModel
26import Lomiri.Indicators 0.1 as Indicators
27import Wizard 0.1
28
29import "../../.."
30
31Item {
32 id: root
33
34 property bool supportsMultiColorLed: true
35
36 property string indicatorState: "INDICATOR_OFF"
37
38 property color color: "darkgreen"
39 property int onMillisec: 1000
40 property int offMillisec: 3000
41
42 property double batteryLevel: 0
43 property string deviceState: ""
44 property alias hasMessages: _rootState.hasMessages
45
46 property string batteryIconName: Status.batteryIcon
47 property string displayStatus: Powerd.status
48
49 onSupportsMultiColorLedChanged: {
50 updateLightState("onSupportsMultiColorLedChanged")
51 }
52
53 onDisplayStatusChanged: {
54 updateLightState("onDisplayStatusChanged")
55 }
56
57 onBatteryIconNameChanged: {
58 updateLightState("onBatteryIconNameChanged")
59 }
60
61 function updateLightState(msg) {
62 console.log("updateLightState: " + msg
63 + ", indicatorState: " + indicatorState
64 + ", supportsMultiColorLed: " + supportsMultiColorLed
65 + ", hasMessages: " + hasMessages
66 + ", icon: " + batteryIconName
67 + ", displayStatus: " + displayStatus
68 + ", deviceState: " + deviceState
69 + ", batteryLevel: " + batteryLevel)
70
71 //
72 // priorities:
73 // unread messsages (highest), full&charging, charging, low
74 //
75 // Icons: (see device.s from indicator-power)
76 // %s-empty-symbolic empty
77 // %s-caution-charging-symbolic charging [ 0..10)
78 // %s-low-charging-symbolic charging [10..30)
79 // %s-good-charging-symbolic charging [30..60)
80 // %s-full-charging-symbolic charging [60..100]
81 // %s-full-charged-symbolic fully charged
82 // %s-low-symbolic ?
83 // %s-full-symbolic ?
84 //
85 // device-state: (see system-settings\plugins\battery)
86 // fully-charged
87 // charging
88 // discharging
89 //
90 // Indicators:
91 // unread notifications : darkgreen pulsing (1000/3000)
92 // charging : white continuously
93 // battery full : green continuously
94 // battery low : orangered pulsing (500/3000)
95 //
96 // Notes:
97 // Icon name 'full-charged' comes late (45m after 100%)
98 // so also check device-state and battery-level
99 //
100 // Battery low warning dialog on screen shows up at 10%
101 // but 'caution' icon at 9%.
102 //
103
104 // only show led when display is off
105 if (displayStatus == Powerd.On) {
106 indicatorState = "INDICATOR_OFF"
107 return
108 }
109
110 // unread messsages have highest priority
111 if (hasMessages) {
112 indicatorState = "HAS_MESSAGES"
113 return
114 }
115
116 // if device does not support a multi color led set led off
117 if(!supportsMultiColorLed) {
118console.log("no support for Multicolor LED. " + indicatorState)
119 indicatorState = "INDICATOR_OFF"
120 return
121 }
122
123 var isCharging = batteryIconName.indexOf("charging") >= 0
124 || deviceState == "charging"
125 || deviceState == "fully-charged"
126
127 var isFull = batteryIconName.indexOf("full-charged") >= 0
128 || deviceState == "fully-charged"
129 || batteryLevel >= 100
130
131 if (isCharging && isFull) {
132 indicatorState = "BATTERY_FULL"
133 } else if (isCharging) {
134 indicatorState = "BATTERY_CHARGING"
135 } else if (batteryIconName.indexOf("caution") >= 0
136 || batteryIconName.indexOf("empty") >= 0) {
137 indicatorState = "BATTERY_LOW"
138 } else {
139 indicatorState = "INDICATOR_OFF"
140 }
141 }
142
143 onIndicatorStateChanged: {
144 console.log("onIndicatorStateChange: " + indicatorState)
145
146 switch (indicatorState) {
147 case "INDICATOR_OFF":
148 break;
149 case "HAS_MESSAGES":
150 color = "darkgreen"
151 onMillisec = 1000
152 offMillisec = 3000
153 break;
154 case "BATTERY_FULL":
155 color = "green"
156 onMillisec = 1000
157 offMillisec = 0
158 break;
159 case "BATTERY_CHARGING":
160 color = "white"
161 onMillisec = 1000
162 offMillisec = 0
163 break;
164 case "BATTERY_LOW":
165 color = "orangered"
166 onMillisec = 500
167 offMillisec = 3000
168 break;
169 default:
170 console.log("ERROR onIndicatorStateChange: unknown state: " + indicatorState)
171 break;
172 }
173
174 // HACK: led is only updated after turn on so first always turn off
175 Leds.state = Leds.Off
176 if (indicatorState != "INDICATOR_OFF")
177 Leds.state = Leds.On
178 }
179
180 // Existence of unread notifications is determined by checking for a specific icon name in a dbus signal.
181 property var _actionGroup: QMenuModel.QDBusActionGroup {
182 busType: 1
183 busName: "org.ayatana.indicator.messages"
184 objectPath: "/org/ayatana/indicator/messages"
185 }
186
187 Indicators.ActionRootState {
188 id: _rootState
189 actionGroup: _actionGroup
190 actionName: "messages"
191 Component.onCompleted: actionGroup.start()
192 property bool hasMessages: (String(icons).indexOf("indicator-messages-new") != -1) && valid
193 onHasMessagesChanged: updateLightState("onHasMessagesChanged")
194 }
195
196 // Charging state and battery level are determined by listening to dbus signals from upower.
197 // See also system-settings battery plugin.
198 property var _ipag: QMenuModel.QDBusActionGroup {
199 busType: 1
200 busName: "org.ayatana.indicator.power"
201 objectPath: "/org/ayatana/indicator/power"
202 property variant batteryLevel: action("battery-level").state
203 property variant deviceState: action("device-state").state
204 Component.onCompleted: start()
205 onBatteryLevelChanged: {
206 root.batteryLevel = batteryLevel ? batteryLevel : 0.00
207 updateLightState("onBatteryLevelChanged")
208 }
209 onDeviceStateChanged: {
210 root.deviceState = deviceState ? deviceState : "unknown"
211 updateLightState("onDeviceStateChanged")
212 }
213 }
214
215 Component.onCompleted: Leds.state = Leds.Off
216 Component.onDestruction: Leds.state = Leds.Off
217
218 property var _colorBinding: Binding {
219 target: Leds
220 restoreMode: Binding.RestoreBinding
221 property: "color"
222 value: root.color
223 }
224
225 property var _onMillisecBinding: Binding {
226 target: Leds
227 restoreMode: Binding.RestoreBinding
228 property: "onMillisec"
229 value: root.onMillisec
230 }
231
232 property var _offMillisecBinding: Binding {
233 target: Leds
234 restoreMode: Binding.RestoreBinding
235 property: "offMillisec"
236 value: root.offMillisec
237 }
238}