Unity 8
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 
21 import QtQuick 2.4
22 import Powerd 0.1
23 import Lights 0.1
24 import QMenuModel 0.1 as QMenuModel
25 import Unity.Indicators 0.1 as Indicators
26 import Wizard 0.1
27 
28 import "../../.."
29 
30 QtObject {
31  id: root
32 
33  property bool supportsMultiColorLed: true
34 
35  property string indicatorState: "INDICATOR_OFF"
36 
37  property color color: "darkgreen"
38  property int onMillisec: 1000
39  property int offMillisec: 3000
40 
41  property double batteryLevel: 0
42  property string deviceState: ""
43  property bool hasMessages: false
44 
45  property string batteryIconName: Status.batteryIcon
46  property string displayStatus: Powerd.status
47 
48  onSupportsMultiColorLedChanged: {
49  updateLightState("onSupportsMultiColorLedChanged")
50  }
51 
52  onDisplayStatusChanged: {
53  updateLightState("onDisplayStatusChanged")
54  }
55 
56  onBatteryIconNameChanged: {
57  updateLightState("onBatteryIconNameChanged")
58  }
59 
60  function updateLightState(msg) {
61  console.log("updateLightState: " + msg
62  + ", indicatorState: " + indicatorState
63  + ", supportsMultiColorLed: " + supportsMultiColorLed
64  + ", hasMessages: " + hasMessages
65  + ", icon: " + batteryIconName
66  + ", displayStatus: " + displayStatus
67  + ", deviceState: " + deviceState
68  + ", batteryLevel: " + batteryLevel)
69 
70  //
71  // priorities:
72  // unread messsages (highest), full&charging, charging, low
73  //
74  // Icons: (see device.s from indicator-power)
75  // %s-empty-symbolic empty
76  // %s-caution-charging-symbolic charging [ 0..10)
77  // %s-low-charging-symbolic charging [10..30)
78  // %s-good-charging-symbolic charging [30..60)
79  // %s-full-charging-symbolic charging [60..100]
80  // %s-full-charged-symbolic fully charged
81  // %s-low-symbolic ?
82  // %s-full-symbolic ?
83  //
84  // device-state: (see system-settings\plugins\battery)
85  // fully-charged
86  // charging
87  // discharging
88  //
89  // Indicators:
90  // unread notifications : darkgreen pulsing (1000/3000)
91  // charging : white continuously
92  // battery full : green continuously
93  // battery low : orangered pulsing (500/3000)
94  //
95  // Notes:
96  // Icon name 'full-charged' comes late (45m after 100%)
97  // so also check device-state and battery-level
98  //
99  // Battery low warning dialog on screen shows up at 10%
100  // but 'caution' icon at 9%.
101  //
102 
103  // only show led when display is off
104  if (displayStatus == Powerd.On) {
105  indicatorState = "INDICATOR_OFF"
106  return
107  }
108 
109  // unread messsages have highest priority
110  if (hasMessages) {
111  indicatorState = "HAS_MESSAGES"
112  return
113  }
114 
115  // if device does not support a multi color led set led off
116  if(!supportsMultiColorLed) {
117 console.log("no support for Multicolor LED. " + indicatorState)
118  indicatorState = "INDICATOR_OFF"
119  return
120  }
121 
122  var isCharging = batteryIconName.indexOf("charging") >= 0
123  || deviceState == "charging"
124  || deviceState == "fully-charged"
125 
126  var isFull = batteryIconName.indexOf("full-charged") >= 0
127  || deviceState == "fully-charged"
128  || batteryLevel >= 100
129 
130  if (isCharging && isFull) {
131  indicatorState = "BATTERY_FULL"
132  } else if (isCharging) {
133  indicatorState = "BATTERY_CHARGING"
134  } else if (batteryIconName.indexOf("caution") >= 0
135  || batteryIconName.indexOf("empty") >= 0) {
136  indicatorState = "BATTERY_LOW"
137  } else {
138  indicatorState = "INDICATOR_OFF"
139  }
140  }
141 
142  onIndicatorStateChanged: {
143  console.log("onIndicatorStateChange: " + indicatorState)
144 
145  switch (indicatorState) {
146  case "INDICATOR_OFF":
147  break;
148  case "HAS_MESSAGES":
149  color = "darkgreen"
150  onMillisec = 1000
151  offMillisec = 3000
152  break;
153  case "BATTERY_FULL":
154  color = "green"
155  onMillisec = 1000
156  offMillisec = 0
157  break;
158  case "BATTERY_CHARGING":
159  color = "white"
160  onMillisec = 1000
161  offMillisec = 0
162  break;
163  case "BATTERY_LOW":
164  color = "orangered"
165  onMillisec = 500
166  offMillisec = 3000
167  break;
168  default:
169  console.log("ERROR onIndicatorStateChange: unknown state: " + indicatorState)
170  break;
171  }
172 
173  // HACK: led is only updated after turn on so first always turn off
174  Lights.state = Lights.Off
175  if (indicatorState != "INDICATOR_OFF")
176  Lights.state = Lights.On
177  }
178 
179  // Existence of unread notifications is determined by checking for a specific icon name in a dbus signal.
180  property var _actionGroup: QMenuModel.QDBusActionGroup {
181  busType: 1
182  busName: "com.canonical.indicator.messages"
183  objectPath: "/com/canonical/indicator/messages"
184  }
185 
186  property var _rootState: Indicators.ActionRootState {
187  actionGroup: _actionGroup
188  actionName: "messages"
189  Component.onCompleted: actionGroup.start()
190  property bool hasMessages: valid && (String(icons).indexOf("indicator-messages-new") != -1)
191  onHasMessagesChanged: {
192  root.hasMessages = hasMessages
193  updateLightState("onHasMessagesChanged")
194  }
195  }
196 
197  // Charging state and battery level are determined by listening to dbus signals from upower.
198  // See also system-settings battery plugin.
199  property var _ipag: QMenuModel.QDBusActionGroup {
200  busType: 1
201  busName: "com.canonical.indicator.power"
202  objectPath: "/com/canonical/indicator/power"
203  property variant batteryLevel: action("battery-level").state
204  property variant deviceState: action("device-state").state
205  Component.onCompleted: start()
206  onBatteryLevelChanged: {
207  root.batteryLevel = batteryLevel ? batteryLevel : 0.00
208  updateLightState("onBatteryLevelChanged")
209  }
210  onDeviceStateChanged: {
211  root.deviceState = deviceState ? deviceState : "unknown"
212  updateLightState("onDeviceStateChanged")
213  }
214  }
215 
216  Component.onCompleted: Lights.state = Lights.Off
217  Component.onDestruction: Lights.state = Lights.Off
218 
219  property var _colorBinding: Binding {
220  target: Lights
221  property: "color"
222  value: root.color
223  }
224 
225  property var _onMillisecBinding: Binding {
226  target: Lights
227  property: "onMillisec"
228  value: root.onMillisec
229  }
230 
231  property var _offMillisecBinding: Binding {
232  target: Lights
233  property: "offMillisec"
234  value: root.offMillisec
235  }
236 }