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