on 20f7e61 help sign in
unity8/qml/Components/Lockscreen.qml
276 lines 8.5 kB history raw
1/*
2 * Copyright (C) 2013 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 */
17import QtQuick 2.0
18import Ubuntu.Components 1.0
19import Ubuntu.Components.Popups 1.0
21Showable {
22 id: root
24 // Determine if a numeric or alphanumeric pad is used.
25 property bool alphaNumeric: false
27 // Placeholder text
28 property string placeholderText: ""
29 // Placeholder text while shaking (e.g. Incorrect passprase)
30 property string wrongPlaceholderText: ""
31 // Retries text (e.g. 3 retries left)
32 property string retryText: ""
34 // Informational text. (e.g. some text to tell which domain this is pin is entered for.
35 property string infoText: ""
37 // In case the Lockscreen can show a greeter message, this is the username
38 property string username: ""
40 // Set those to a value greater 0 to restrict the pin length.
41 // If both are unset, the Lockscreen will show a confirm button and allow typing any length of pin before
42 // confirming. If minPinLength is set to a value > 0, the confirm button will only become active when the
43 // entered pin is at least that long. If maxPinLength is set, the lockscreen won't allow entering any
44 // more numbers than that. If both are set to the same value, the lockscreen will enter auto confirming
45 // behavior, hiding the confirmation button and triggering that automatically when the entered pin reached
46 // that length. This is ignored by the alphaNumeric lockscreen as that one is always confirmed by pressing
47 // enter on the OSK.
48 property int minPinLength: -1
49 property int maxPinLength: -1
51 property url background: ""
53 signal entered(string passphrase)
54 signal cancel()
55 signal emergencyCall()
56 signal infoPopupConfirmed()
58 onRequiredChanged: {
59 if (required && pinPadLoader.item) {
60 clear(false)
61 }
62 }
64 function forceDelay(delay) {
65 forcedDelayTimer.interval = delay
66 forcedDelayTimer.start()
67 }
69 function reset() {
70 // This causes the loader below to destry and recreate the source
71 pinPadLoader.resetting = true;
72 pinPadLoader.resetting = false;
73 }
75 function clear(showAnimation) {
76 if (pinPadLoader.item) {
77 pinPadLoader.item.clear(showAnimation);
78 }
79 pinPadLoader.showWrongText = showAnimation
80 pinPadLoader.waiting = false
81 }
83 function showInfoPopup(title, text) {
84 PopupUtils.open(infoPopupComponent, root, {title: title, text: text})
85 }
87 Timer {
88 id: forcedDelayTimer
89 onTriggered: pinPadLoader.showWrongText = false
90 }
92 Rectangle {
93 // In case background fails to load or is undefined
94 id: backgroundBackup
95 anchors.fill: parent
96 color: "black"
97 }
99 Image {
100 id: backgroundImage
101 objectName: "lockscreenBackground"
102 anchors {
103 fill: parent
104 }
105 source: root.required ? root.background : ""
106 fillMode: Image.PreserveAspectCrop
107 }
109 MouseArea {
110 anchors.fill: root
111 }
113 Column {
114 spacing: units.gu(2)
115 anchors {
116 left: parent.left
117 right: parent.right
118 bottom: pinPadLoader.top
119 bottomMargin: units.gu(2)
120 }
121 Label {
122 objectName: "retryCountLabel"
123 anchors {
124 left: parent.left
125 right: parent.right
126 }
127 text: root.retryText
128 horizontalAlignment: Text.AlignHCenter
129 color: "#f3f3e7"
130 opacity: 0.6
131 visible: root.retryText.length > 0
132 }
133 Label {
134 id: infoTextLabel
135 objectName: "infoTextLabel"
136 anchors {
137 left: parent.left
138 right: parent.right
139 }
140 text: root.infoText
141 horizontalAlignment: Text.AlignHCenter
142 color: "#f3f3e7"
143 opacity: 0.6
144 visible: root.infoText.length > 0
145 }
146 }
148 Loader {
149 id: pinPadLoader
150 objectName: "pinPadLoader"
151 anchors {
152 left: parent.left
153 right: parent.right
154 verticalCenter: parent.verticalCenter
155 verticalCenterOffset: root.alphaNumeric ? -units.gu(10) : -units.gu(4)
156 }
157 property bool resetting: false
158 property bool waiting: false
159 property bool showWrongText: false
161 readonly property string forcedDelayText: i18n.tr("Too many incorrect attempts") +
162 "\n" +
163 i18n.tr("Please wait")
165 source: (!resetting && root.required) ? (root.alphaNumeric ? "PassphraseLockscreen.qml" : "PinLockscreen.qml") : ""
166 onSourceChanged: {
167 waiting = false
168 showWrongText = false
169 }
171 Connections {
172 target: pinPadLoader.item
174 onEntered: {
175 pinPadLoader.waiting = true
176 root.entered(passphrase);
177 }
179 onCancel: {
180 root.cancel()
181 }
182 }
184 Binding {
185 target: pinPadLoader.item
186 property: "minPinLength"
187 value: root.minPinLength
188 }
189 Binding {
190 target: pinPadLoader.item
191 property: "maxPinLength"
192 value: root.maxPinLength
193 }
194 Binding {
195 target: pinPadLoader.item
196 property: "placeholderText"
197 value: forcedDelayTimer.running ? pinPadLoader.forcedDelayText :
198 (pinPadLoader.showWrongText ? root.wrongPlaceholderText :
199 root.placeholderText)
200 }
201 Binding {
202 target: pinPadLoader.item
203 property: "username"
204 value: root.username
205 }
206 Binding {
207 target: pinPadLoader.item
208 property: "entryEnabled"
209 value: !pinPadLoader.waiting && !forcedDelayTimer.running
210 }
211 }
213 Column {
214 id: emergencyCallColumn
216 // FIXME: We *should* show emergency dialer if there is a SIM present,
217 // regardless of whether the side stage is enabled. But right now,
218 // the assumption is that narrow screens are phones which have SIMs
219 // and wider screens are tablets which don't. When we do allow this
220 // on devices with a side stage and a SIM, work should be done to
221 // ensure that the main stage is disabled while the dialer is present
222 // in the side stage.
223 visible: !shell.sideStageEnabled
225 anchors {
226 left: parent.left
227 bottom: parent.bottom
228 bottomMargin: units.gu(4)
229 right: parent.right
230 }
231 height: childrenRect.height
232 spacing: units.gu(1)
234 Icon {
235 objectName: "emergencyCallIcon"
236 height: units.gu(3)
237 width: height
238 anchors.horizontalCenter: parent.horizontalCenter
239 name: "phone-app-call-symbolic"
240 color: "#f3f3e7"
241 opacity: 0.6
242 }
244 Label {
245 text: i18n.tr("Emergency Call")
246 color: "#f3f3e7"
247 opacity: 0.6
248 fontSize: "medium"
249 anchors.horizontalCenter: parent.horizontalCenter
250 }
251 }
253 MouseArea {
254 anchors.fill: emergencyCallColumn
255 onClicked: root.emergencyCall()
256 enabled: emergencyCallColumn.visible
257 }
259 Component {
260 id: infoPopupComponent
261 Dialog {
262 id: dialog
263 objectName: "infoPopup"
264 modal: true
266 Button {
267 objectName: "infoPopupOkButton"
268 text: i18n.tr("OK")
269 onClicked: {
270 PopupUtils.close(dialog)
271 root.infoPopupConfirmed();
272 }
273 }
274 }
275 }