Unity 8
Lockscreen.qml
1 /*
2  * Copyright (C) 2013-2017 Canonical, Ltd.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; version 3.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program. If not, see <http://www.gnu.org/licenses/>.
15  */
16 
17 import QtQuick 2.4
18 import Ubuntu.Components 1.3
19 import Ubuntu.Components.Popups 1.3
20 import Ubuntu.Telephony 0.1 as Telephony
21 
22 Showable {
23  id: root
24 
25  // Determine if a numeric or alphanumeric pad is used.
26  property bool alphaNumeric: false
27 
28  // Whether to show an emergency call button
29  property bool showEmergencyCallButton: true
30 
31  // Whether to show a cancel button (not all lockscreen types normally do anyway)
32  property bool showCancelButton: true
33 
34  // Informational text. (e.g. some text to tell which domain this is pin is entered for)
35  property string infoText: ""
36 
37  // Retries text (e.g. 3 retries left)
38  // (This is not currently used, but will be necessary for SIM unlock screen)
39  property string retryText: ""
40 
41  // The text to be displayed in case the login failed
42  property string errorText: ""
43 
44  // Set those to a value greater 0 to restrict the pin length.
45  // If both are unset, the Lockscreen will show a confirm button and allow typing any length of pin before
46  // confirming. If minPinLength is set to a value > 0, the confirm button will only become active when the
47  // entered pin is at least that long. If maxPinLength is set, the lockscreen won't allow entering any
48  // more numbers than that. If both are set to the same value, the lockscreen will enter auto confirming
49  // behavior, hiding the confirmation button and triggering that automatically when the entered pin reached
50  // that length. This is ignored by the alphaNumeric lockscreen as that one is always confirmed by pressing
51  // enter on the OSK.
52  property int minPinLength: -1
53  property int maxPinLength: -1
54 
55  property url background: ""
56  // Use this to put a black overlay above the background
57  // 0: normal background, 1: black background
58  property real darkenBackground: 0
59 
60  property color foregroundColor: "#f3f3e7"
61 
62  readonly property string passphrase: (pinPadLoader.item && pinPadLoader.item.passphrase) ? pinPadLoader.item.passphrase : ""
63 
64  signal entered(string passphrase)
65  signal cancel()
66  signal emergencyCall()
67  signal infoPopupConfirmed()
68 
69  onActiveFocusChanged: if (activeFocus && pinPadLoader.item) pinPadLoader.item.forceActiveFocus()
70 
71  function reset() {
72  // This causes the loader below to destry and recreate the source
73  pinPadLoader.resetting = true;
74  pinPadLoader.resetting = false;
75  }
76 
77  function clear(showAnimation) {
78  if (pinPadLoader.item) {
79  pinPadLoader.item.clear(showAnimation);
80  }
81  pinPadLoader.showWrongText = showAnimation
82  pinPadLoader.waiting = false
83  }
84 
85  function showInfoPopup(title, text) {
86  var popup = PopupUtils.open(infoPopupComponent, root, {title: title, text: text})
87  // FIXME: SDK will do this internally soonish
88  popup.z = Number.MAX_VALUE
89  }
90 
91  Rectangle {
92  // In case background fails to load
93  id: backgroundBackup
94  anchors.fill: parent
95  color: "black"
96  visible: root.background.toString() !== ""
97  }
98 
99  Wallpaper {
100  id: backgroundImage
101  objectName: "lockscreenBackground"
102  anchors {
103  fill: parent
104  }
105  source: root.required ? root.background : ""
106  }
107 
108  // This is to
109  // a) align it with the greeter and
110  // b) keep the white fonts readable on bright backgrounds
111  Rectangle {
112  anchors.fill: parent
113  color: "black"
114  opacity: root.darkenBackground
115  }
116 
117  Loader {
118  id: pinPadLoader
119  objectName: "pinPadLoader"
120  anchors.fill: parent
121  property bool resetting: false
122  property bool waiting: false
123  property bool showWrongText: false
124  focus: true
125 
126  source: {
127  if (resetting || !root.required) {
128  return ""
129  } else if (root.alphaNumeric) {
130  return "PassphraseLockscreen.qml"
131  } else {
132  return "PinLockscreen.qml"
133  }
134  }
135  onSourceChanged: {
136  waiting = false
137  showWrongText = false
138  }
139 
140  Connections {
141  target: pinPadLoader.item
142 
143  onEntered: {
144  pinPadLoader.waiting = true
145  root.entered(passphrase);
146  }
147 
148  onCancel: {
149  root.cancel()
150  }
151  }
152 
153  Binding {
154  target: pinPadLoader.item
155  property: "minPinLength"
156  value: root.minPinLength
157  }
158  Binding {
159  target: pinPadLoader.item
160  property: "maxPinLength"
161  value: root.maxPinLength
162  }
163  Binding {
164  target: pinPadLoader.item
165  property: "infoText"
166  value: root.infoText
167  }
168  Binding {
169  target: pinPadLoader.item
170  property: "retryText"
171  value: root.retryText
172  }
173  Binding {
174  target: pinPadLoader.item
175  property: "errorText"
176  value: pinPadLoader.showWrongText ? root.errorText : ""
177  }
178  Binding {
179  target: pinPadLoader.item
180  property: "entryEnabled"
181  value: !pinPadLoader.waiting
182  }
183  Binding {
184  target: pinPadLoader.item
185  property: "showCancelButton"
186  value: root.showCancelButton
187  }
188  Binding {
189  target: pinPadLoader.item
190  property: "foregroundColor"
191  value: root.foregroundColor
192  }
193  }
194 
195  Item {
196  id: emergencyCallRow
197 
198  visible: showEmergencyCallButton
199 
200  anchors {
201  bottom: parent.bottom
202  bottomMargin: units.gu(7) + (Qt.inputMethod.visible ? Qt.inputMethod.keyboardRectangle.height : 0)
203  left: parent.left
204  right: parent.right
205  }
206 
207  Label {
208  id: emergencyCallLabel
209  objectName: "emergencyCallLabel"
210  anchors.horizontalCenter: parent.horizontalCenter
211 
212  text: callManager.hasCalls ? i18n.tr("Return to Call") : i18n.tr("Emergency Call")
213  color: root.foregroundColor
214  }
215 
216  Icon {
217  id: emergencyCallIcon
218  anchors.left: emergencyCallLabel.right
219  anchors.leftMargin: units.gu(1)
220  width: emergencyCallLabel.height
221  height: emergencyCallLabel.height
222  name: "call-start"
223  color: root.foregroundColor
224  }
225 
226  MouseArea {
227  anchors.top: emergencyCallLabel.top
228  anchors.bottom: emergencyCallLabel.bottom
229  anchors.left: emergencyCallLabel.left
230  anchors.right: emergencyCallIcon.right
231  onClicked: root.emergencyCall()
232  }
233  }
234 
235  Component {
236  id: infoPopupComponent
237  ShellDialog {
238  id: dialog
239  objectName: "infoPopup"
240  property var dialogLoader // dummy to satisfy ShellDialog's context dependent prop
241 
242  Button {
243  width: parent.width
244  objectName: "infoPopupOkButton"
245  text: i18n.tr("OK")
246  focus: true
247  onClicked: {
248  PopupUtils.close(dialog)
249  root.infoPopupConfirmed();
250  }
251  }
252  }
253  }
254 }