on 19a9ecd help sign in
unity8/qml/Greeter/GreeterPrompt.qml
229 lines 8.0 kB history raw
1/*
2 * Copyright (C) 2016 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.4
18import Ubuntu.Components 1.3
19import "../Components"
21FocusScope {
22 id: root
23 implicitHeight: units.gu(5)
24 focus: true
26 property bool isPrompt
27 property bool isAlphanumeric
28 property string text
29 property bool isSecret
30 property bool interactive: true
31 readonly property alias enteredText: passwordInput.text
33 signal clicked()
34 signal canceled()
35 signal accepted()
37 function showFakePassword() {
38 // Just a silly hack for looking like 4 pin numbers got entered, if
39 // a fingerprint was used and we happen to be using a pin. This was
40 // a request from Design.
41 if (isSecret && isPrompt && !isAlphanumeric) {
42 passwordInput.text = "...."; // actual text doesn't matter
43 }
44 }
46 StyledItem {
47 id: d
49 readonly property color textColor: passwordInput.enabled ? theme.palette.normal.raisedText
50 : theme.palette.disabled.raisedText
51 readonly property color selectedColor: passwordInput.enabled ? theme.palette.normal.raised
52 : theme.palette.disabled.raised
53 readonly property color drawColor: passwordInput.enabled ? theme.palette.normal.raisedSecondaryText
54 : theme.palette.disabled.raisedSecondaryText
55 readonly property color errorColor: passwordInput.enabled ? theme.palette.normal.negative
56 : theme.palette.disabled.negative
57 }
59 Rectangle {
60 anchors.fill: parent
61 border.width: units.dp(1)
62 border.color: d.drawColor
63 radius: units.gu(0.5)
64 color: "transparent"
65 }
67 Component.onCompleted: updateFocus()
68 onIsPromptChanged: updateFocus()
69 function updateFocus() {
70 if (root.isPrompt) {
71 passwordInput.focus = true;
72 } else {
73 promptButton.focus = true;
74 }
75 }
77 StyledItem {
78 id: promptButton
79 objectName: "promptButton"
80 anchors.fill: parent
81 visible: !root.isPrompt
82 activeFocusOnTab: true
84 styleName: "FocusShape"
86 function triggered() {
87 if (root.interactive) {
88 root.clicked();
89 }
90 }
92 Rectangle {
93 height: parent.height;
94 width: parent.width
95 color: "transparent"
96 border {
97 color: d.textColor
98 width: units.dp(1)
99 }
100 }
102 Keys.onSpacePressed: triggered();
103 Keys.onReturnPressed: triggered();
104 Keys.onEnterPressed: triggered();
105 MouseArea {
106 anchors.fill: parent
107 onClicked: parent.triggered();
108 }
110 Label {
111 anchors.centerIn: parent
112 color: d.textColor
113 text: root.text
114 }
115 }
117 TextField {
118 id: passwordInput
119 objectName: "promptField"
120 anchors.fill: parent
121 visible: root.isPrompt
122 opacity: fakeLabel.visible ? 0 : 1
123 activeFocusOnTab: true
125 validator: RegExpValidator {
126 regExp: root.isAlphanumeric ? /^.*$/ : /^\d{4}$/
127 }
129 inputMethodHints: Qt.ImhSensitiveData | Qt.ImhNoPredictiveText |
130 Qt.ImhMultiLine | // so OSK doesn't close on Enter
131 (root.isAlphanumeric ? Qt.ImhNone : Qt.ImhDigitsOnly)
132 echoMode: root.isSecret ? TextInput.Password : TextInput.Normal
133 hasClearButton: false
135 readonly property real frameSpacing: units.gu(0.5)
137 style: StyledItem {
138 anchors.fill: parent
139 styleName: "FocusShape"
141 // Properties needed by TextField
142 readonly property color color: d.textColor
143 readonly property color selectedTextColor: d.selectedColor
144 readonly property color selectionColor: d.textColor
145 readonly property color borderColor: "transparent"
146 readonly property color backgroundColor: "transparent"
147 readonly property color errorColor: d.errorColor
148 readonly property real frameSpacing: styledItem.frameSpacing
150 // Properties needed by FocusShape
151 readonly property bool enabled: styledItem.enabled
152 readonly property bool keyNavigationFocus: styledItem.keyNavigationFocus
153 property bool activeFocusOnTab
154 }
156 secondaryItem: [
157 Icon {
158 id: capsIcon
159 name: "keyboard-caps-enabled"
160 height: units.gu(3)
161 width: units.gu(3)
162 color: d.textColor
163 visible: root.isSecret && false // TODO: detect when caps lock is on
164 readonly property real visibleWidth: visible ? width + passwordInput.frameSpacing : 0
165 }
166 ]
168 onDisplayTextChanged: {
169 // We use onDisplayTextChanged instead of onTextChanged because
170 // displayText changes after text and if we did this before it
171 // updated, we would use the wrong displayText for fakeLabel.
172 if (!isAlphanumeric && text.length >= 4) {
173 // hard limit of 4 for passcodes right now
174 respond();
175 }
176 }
178 onAccepted: respond()
180 function respond() {
181 if (root.interactive) {
182 root.accepted();
183 }
184 }
186 Keys.onEscapePressed: {
187 root.canceled();
188 event.accepted = true;
189 }
191 // We use our own custom placeholder label instead of the standard
192 // TextField one because the standard one hardcodes baseText as the
193 // palette color, whereas we want raisedSecondaryText.
194 Label {
195 id: hint
196 objectName: "promptHint"
197 anchors {
198 left: parent.left
199 right: parent.right
200 verticalCenter: parent.verticalCenter
201 leftMargin: units.gu(1.5)
202 rightMargin: anchors.leftMargin + capsIcon.visibleWidth
203 }
204 text: root.text
205 visible: passwordInput.text == "" && !passwordInput.inputMethodComposing
206 color: d.drawColor
207 elide: Text.ElideRight
208 }
209 }
211 // Have a fake label that covers the text field after the user presses
212 // enter. What we *really* want is a disabled mode that doesn't lose OSK
213 // focus. Because our goal here is simply to keep the OSK up while
214 // we wait for PAM to get back to us, and while waiting, we don't want
215 // the user to be able to edit the field (simply because it would look
216 // weird if we allowed that). But until we have such a disabled mode,
217 // we'll fake it by covering the real text field with a label.
218 FadingLabel {
219 id: fakeLabel
220 anchors.verticalCenter: parent.verticalCenter
221 anchors.left: parent.left
222 anchors.right: parent.right
223 anchors.leftMargin: passwordInput.frameSpacing * 2
224 anchors.rightMargin: passwordInput.frameSpacing * 2 + capsIcon.visibleWidth
225 color: d.drawColor
226 text: passwordInput.displayText
227 visible: root.isPrompt && !root.interactive
228 }