@@ -24,17 +24,24 @@ Showable {
2424 // Determine if a numeric or alphanumeric pad is used.
2525 property bool alphaNumeric: false
2626
27+ // Whether to show an emergency call button
28+ property bool showEmergencyCallButton: true
29+
30+ // Whether to show a cancel button (not all lockscreen types normally do anyway)
31+ property bool showCancelButton: true
32+
2733 // Informational text. (e.g. some text to tell which domain this is pin is entered for)
2834 property string infoText: ""
2935
3036 // Retries text (e.g. 3 retries left)
37+ // (This is not currently used, but will be necessary for SIM unlock screen)
3138 property string retryText: ""
3239
3340 // The text to be displayed in case the login failed
3441 property string errorText: ""
3542
36− // In case the Lockscreen can show a greeter message, this is the username
37− property string username: ""
43+ // If > 0, a forced delay is happening
44+ property int delayMinutes: 0
3845
3946 // Set those to a value greater 0 to restrict the pin length.
4047 // If both are unset, the Lockscreen will show a confirm button and allow typing any length of pin before
@@ -54,16 +61,7 @@ Showable {
5461 signal emergencyCall()
5562 signal infoPopupConfirmed()
5663
57− onRequiredChanged: {
58− if (required && pinPadLoader.item) {
59− clear(false)
60− }
61− }
62−
63− function forceDelay(delay) {
64− forcedDelayTimer.interval = delay
65− forcedDelayTimer.start()
66− }
64+ onActiveFocusChanged: if (activeFocus && pinPadLoader.item) pinPadLoader.item.forceActiveFocus()
6765
6866 function reset() {
6967 // This causes the loader below to destry and recreate the source
@@ -83,16 +81,12 @@ Showable {
8381 PopupUtils.open(infoPopupComponent, root, {title: title, text: text})
8482 }
8583
86− Timer {
87− id: forcedDelayTimer
88− onTriggered: pinPadLoader.showWrongText = false
89− }
90−
9184 Rectangle {
92− // In case background fails to load or is undefined
85+ // In case background fails to load
9386 id: backgroundBackup
9487 anchors.fill: parent
9588 color: "black"
89+ visible: root.background.toString() !== ""
9690 }
9791
9892 Image {
@@ -107,111 +101,141 @@ Showable {
107101
108102 MouseArea {
109103 anchors.fill: root
104+ onClicked: {
105+ if (pinPadLoader.item)
106+ pinPadLoader.item.forceActiveFocus()
107+ }
110108 }
111109
112− Loader {
113− id: pinPadLoader
114− objectName: "pinPadLoader"
115− anchors {
116− left: parent.left
117− right: parent.right
118− verticalCenter: parent.verticalCenter
119− verticalCenterOffset: root.alphaNumeric ? -units.gu(10) : 0
120− }
121− property bool resetting: false
122− property bool waiting: false
123− property bool showWrongText: false
124−
125− source: (!resetting && root.required) ? (root.alphaNumeric ? "PassphraseLockscreen.qml" : "PinLockscreen.qml") : ""
126− onSourceChanged: {
127− waiting = false
128− showWrongText = false
129− }
130− onLoaded: {
131− if (forcedDelayTimer.running) {
132− pinPadLoader.item.clear(true)
110+ FocusScope {
111+ id: loaderScope
112+ anchors.fill: parent
113+
114+ Loader {
115+ id: pinPadLoader
116+ objectName: "pinPadLoader"
117+ anchors.fill: parent
118+ property bool resetting: false
119+ property bool waiting: false
120+ property bool showWrongText: false
121+
122+ source: {
123+ if (resetting || !root.required) {
124+ return ""
125+ } else if (root.delayMinutes > 0) {
126+ return "DelayedLockscreen.qml"
127+ } else if (root.alphaNumeric) {
128+ return "PassphraseLockscreen.qml"
129+ } else {
130+ return "PinLockscreen.qml"
131+ }
132+ }
133+ onSourceChanged: {
134+ waiting = false
135+ showWrongText = false
136+ if (loaderScope.activeFocus && pinPadLoader.item)
137+ pinPadLoader.item.forceActiveFocus()
133138 }
134− }
135139
136− Connections {
137− target: pinPadLoader.item
140+ Connections {
141+ target: pinPadLoader.item
138142
139− onEntered: {
140− pinPadLoader.waiting = true
141− root.entered(passphrase);
142− }
143+ onEntered: {
144+ pinPadLoader.waiting = true
145+ root.entered(passphrase);
146+ }
143147
144− onCancel: {
145− root.cancel()
148+ onCancel: {
149+ root.cancel()
150+ }
146151 }
147− }
148152
149− Binding {
150− target: pinPadLoader.item
151− property: "minPinLength"
152− value: root.minPinLength
153− }
154− Binding {
155− target: pinPadLoader.item
156− property: "maxPinLength"
157− value: root.maxPinLength
158− }
159− Binding {
160− target: pinPadLoader.item
161− property: "infoText"
162− value: root.infoText
163− }
164− Binding {
165− target: pinPadLoader.item
166− property: "retryText"
167− value: forcedDelayTimer.running ? i18n.tr("Please wait") : root.retryText
168− }
169− Binding {
170− target: pinPadLoader.item
171− property: "errorText"
172− value: forcedDelayTimer.running ? i18n.tr("Too many incorrect attempts") :
173− (pinPadLoader.showWrongText ? root.errorText : "")
174− }
175− Binding {
176− target: pinPadLoader.item
177− property: "username"
178− value: root.username
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: "alphaNumeric"
186+ value: root.alphaNumeric
187+ }
188+ Binding {
189+ target: pinPadLoader.item
190+ property: "delayMinutes"
191+ value: root.delayMinutes
192+ }
179193 }
180194 Binding {
181195 target: pinPadLoader.item
182− property: "entryEnabled"
183− value: !pinPadLoader.waiting && !forcedDelayTimer.running
196+ property: "showCancelButton"
197+ value: root.showCancelButton
184198 }
185199 }
186200
187− Label {
188− id: emergencyCallLabel
189− objectName: "emergencyCallLabel"
201+ Item {
202+ id: emergencyCallRow
190203
191− // FIXME: We *should* show emergency dialer if there is a SIM present,
192− // regardless of whether the side stage is enabled. But right now,
193− // the assumption is that narrow screens are phones which have SIMs
194− // and wider screens are tablets which don't. When we do allow this
195− // on devices with a side stage and a SIM, work should be done to
196− // ensure that the main stage is disabled while the dialer is present
197− // in the side stage.
198− visible: !shell.sideStageEnabled
204+ visible: showEmergencyCallButton
199205
200206 anchors {
201207 bottom: parent.bottom
202− bottomMargin: units.gu(4)
203− horizontalCenter: parent.horizontalCenter
208+ bottomMargin: units.gu(7) + (Qt.inputMethod.visible ? Qt.inputMethod.keyboardRectangle.height : 0)
209+ left: parent.left
210+ right: parent.right
204211 }
205212
206− text: i18n.tr("Emergency Call")
207− color: "#f3f3e7"
208− opacity: 0.6
209− }
213+ Label {
214+ id: emergencyCallLabel
215+ objectName: "emergencyCallLabel"
216+ anchors.horizontalCenter: parent.horizontalCenter
210217
211− MouseArea {
212− anchors.fill: emergencyCallLabel
213− onClicked: root.emergencyCall()
214− enabled: emergencyCallLabel.visible
218+ text: i18n.tr("Emergency Call")
219+ color: "#f3f3e7"
220+ }
221+
222+ Icon {
223+ id: emergencyCallIcon
224+ anchors.left: emergencyCallLabel.right
225+ anchors.leftMargin: units.gu(1)
226+ width: emergencyCallLabel.height
227+ height: emergencyCallLabel.height
228+ name: "call-start"
229+ color: "#f3f3e7"
230+ }
231+
232+ MouseArea {
233+ anchors.top: emergencyCallLabel.top
234+ anchors.bottom: emergencyCallLabel.bottom
235+ anchors.left: emergencyCallLabel.left
236+ anchors.right: emergencyCallIcon.right
237+ onClicked: root.emergencyCall()
238+ }
215239 }
216240
217241 Component {