on bedf8bc help sign in
unity8/qml/Greeter/GreeterPrompt.qml
197 lines 6.8 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
31 signal clicked()
32 signal canceled()
33 signal responded(string text)
35 function reset() {
36 passwordInput.text = "";
37 fakeLabel.text = "";
38 d.enabled = true;
39 }
41 StyledItem {
42 id: d
44 property bool enabled: true
45 readonly property color textColor: passwordInput.enabled ? theme.palette.normal.raisedText
46 : theme.palette.disabled.raisedText
47 readonly property color selectedColor: passwordInput.enabled ? theme.palette.normal.raised
48 : theme.palette.disabled.raised
49 readonly property color drawColor: passwordInput.enabled ? theme.palette.normal.raisedSecondaryText
50 : theme.palette.disabled.raisedSecondaryText
51 readonly property color errorColor: passwordInput.enabled ? theme.palette.normal.negative
52 : theme.palette.disabled.negative
53 }
55 Rectangle {
56 anchors.fill: parent
57 border.width: units.dp(1)
58 border.color: d.drawColor
59 radius: units.gu(0.5)
60 color: "transparent"
61 }
63 Component.onCompleted: updateFocus()
64 onIsPromptChanged: updateFocus()
65 function updateFocus() {
66 if (root.isPrompt) {
67 passwordInput.focus = true;
68 } else {
69 promptButton.focus = true;
70 }
71 }
73 AbstractButton {
74 id: promptButton
75 objectName: "promptButton"
76 anchors.fill: parent
77 visible: !root.isPrompt
79 onClicked: {
80 if (d.enabled) {
81 d.enabled = false;
82 root.clicked();
83 }
84 }
86 Label {
87 anchors.centerIn: parent
88 color: d.textColor
89 text: root.text
90 }
91 }
93 TextField {
94 id: passwordInput
95 objectName: "promptField"
96 anchors.fill: parent
97 visible: root.isPrompt
98 opacity: fakeLabel.visible ? 0 : 1
100 validator: RegExpValidator {
101 regExp: root.isAlphanumeric ? /^.*$/ : /^\d{4}$/
102 }
104 inputMethodHints: Qt.ImhSensitiveData | Qt.ImhNoPredictiveText |
105 Qt.ImhMultiLine | // so OSK doesn't close on Enter
106 (root.isAlphanumeric ? Qt.ImhNone : Qt.ImhDigitsOnly)
107 echoMode: root.isSecret ? TextInput.Password : TextInput.Normal
108 hasClearButton: false
110 readonly property real frameSpacing: units.gu(0.5)
112 style: Item {
113 property color color: d.textColor
114 property color selectedTextColor: d.selectedColor
115 property color selectionColor: d.textColor
116 property color borderColor: "transparent"
117 property color backgroundColor: "transparent"
118 property color errorColor: d.errorColor
119 property real frameSpacing: passwordInput.frameSpacing
120 anchors.fill: parent
121 }
123 secondaryItem: [
124 Icon {
125 id: capsIcon
126 name: "keyboard-caps-enabled"
127 height: units.gu(3)
128 width: units.gu(3)
129 color: d.textColor
130 visible: root.isSecret && false // TODO: detect when caps lock is on
131 readonly property real visibleWidth: visible ? width + passwordInput.frameSpacing : 0
132 }
133 ]
135 onDisplayTextChanged: {
136 // We use onDisplayTextChanged instead of onTextChanged because
137 // displayText changes after text and if we did this before it
138 // updated, we would use the wrong displayText for fakeLabel.
139 if (!isAlphanumeric && text.length >= 4) {
140 // hard limit of 4 for passcodes right now
141 respond();
142 }
143 }
145 onAccepted: {
146 if (d.enabled)
147 respond();
148 }
150 function respond() {
151 d.enabled = false;
152 fakeLabel.text = displayText;
153 root.responded(text);
154 }
156 Keys.onEscapePressed: {
157 root.canceled();
158 event.accepted = true;
159 }
161 // We use our own custom placeholder label instead of the standard
162 // TextField one because the standard one hardcodes baseText as the
163 // palette color, whereas we want raisedSecondaryText.
164 Label {
165 id: hint
166 anchors {
167 left: parent.left
168 right: parent.right
169 verticalCenter: parent.verticalCenter
170 leftMargin: units.gu(1.5)
171 rightMargin: anchors.leftMargin + capsIcon.visibleWidth
172 }
173 text: root.text
174 visible: passwordInput.text == "" && !passwordInput.inputMethodComposing
175 color: d.drawColor
176 elide: Text.ElideRight
177 }
178 }
180 // Have a fake label that covers the text field after the user presses
181 // enter. What we *really* want is a disabled mode that doesn't lose OSK
182 // focus. Because our goal here is simply to keep the OSK up while
183 // we wait for PAM to get back to us, and while waiting, we don't want
184 // the user to be able to edit the field (simply because it would look
185 // weird if we allowed that). But until we have such a disabled mode,
186 // we'll fake it by covering the real text field with a label.
187 FadingLabel {
188 id: fakeLabel
189 anchors.verticalCenter: parent.verticalCenter
190 anchors.left: parent.left
191 anchors.right: parent.right
192 anchors.leftMargin: passwordInput.frameSpacing * 2
193 anchors.rightMargin: passwordInput.frameSpacing * 2 + capsIcon.visibleWidth
194 color: d.drawColor
195 visible: root.isPrompt && !d.enabled
196 }