Lomiri
Loading...
Searching...
No Matches
PromptList.qml
1/*
2 * Copyright (C) 2017 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 */
16
17import QtQuick 2.12
18import Lomiri.Components 1.3
19import AccountsService 0.1
20import "../Components"
21import "." 0.1
22
23FocusScope {
24 id: root
25 height: childrenRect.height
26
27 property bool isLandscape
28 property string usageMode
29 property bool alphanumeric: true
30 property bool interactive: true
31 property bool loginError: false
32 property bool hasKeyboard: false
33 property int maxHeight: units.gu(5)
34 // don't allow custom pincode prompt for multi user in phone context as it will hide the login list
35 readonly property string pinCodeManager: LightDMService.users.count > 1 && root.usageMode === "phone" && root.isLandscape ? AccountsService.defaultPinCodePromptManager : AccountsService.pinCodePromptManager
36
37 property real defaultPromptWidth: units.gu(20)
38 property real maxPromptHeight: isLandscape ? root.width - units.gu(10) : maxHeight
39
40 signal responded(string text)
41 signal clicked()
42 signal canceled()
43
44 function showFakePassword() {
45 for (var i = 0; i < repeater.count; i++) {
46 var item = repeater.itemAt(i).item;
47 if (item.isPrompt) {
48 item.showFakePassword();
49 }
50 }
51 }
52
53 QtObject {
54 id: d
55
56 function sendResponse() {
57 for (var i = 0; i < repeater.count; i++) {
58 var item = repeater.itemAt(i).item;
59 if (item.isPrompt) {
60 root.responded(item.enteredText);
61 }
62 }
63 }
64 }
65
66 Column {
67 width: parent.width
68 spacing: units.gu(0.5)
69
70 Repeater {
71 id: repeater
72 model: LightDMService.prompts
73
74 delegate: Loader {
75 id: loader
76
77 readonly property bool isLabel: model.type == LightDMService.prompts.Message ||
78 model.type == LightDMService.prompts.Error
79 // we want to have properties set at component loading time
80 readonly property var modelText: model.text
81 readonly property var modelType: model.type
82 readonly property var modelIndex: model.index
83
84 sourceComponent: isLabel ? infoLabel : greeterPrompt
85 anchors.horizontalCenter: parent.horizontalCenter
86
87 active: root.visible
88
89 onLoaded: {
90 for (var i = 0; i < repeater.count; i++) {
91 var item = repeater.itemAt(i);
92 if (item && !item.isLabel) {
93 item.focus = true;
94 break;
95 }
96 }
97 loader.item.opacity = 1;
98 }
99 }
100 }
101 }
102
103 Component {
104 id: infoLabel
105
106 FadingLabel {
107 objectName: "infoLabel" + modelIndex
108 width: root.defaultPromptWidth
109
110 readonly property bool isPrompt: false
111
112 color: modelType === LightDMService.prompts.Message ? theme.palette.normal.raisedSecondaryText
113 : theme.palette.normal.negative
114 fontSize: "small"
115 textFormat: Text.PlainText
116 text: modelText
117
118 visible: modelType === LightDMService.prompts.Message
119
120 Behavior on opacity { LomiriNumberAnimation {} }
121 opacity: 0
122 }
123 }
124
125 Component {
126 id: greeterPrompt
127
128 GreeterPrompt {
129 objectName: "greeterPrompt" + modelIndex
130 width: isAlternativePinPrompt ? root.width : root.defaultPromptWidth
131 implicitHeight: isAlternativePinPrompt ? root.maxPromptHeight : units.gu(5)
132
133 property bool isAlphanumeric: modelText !== "" || root.alphanumeric
134 property bool isAlternativePinPrompt: (isPinPrompt && pinCodeManager !== AccountsService.defaultPinCodePromptManager)
135
136 interactive: root.interactive
137 pinCodeManager: root.pinCodeManager
138 isPrompt: modelType !== LightDMService.prompts.Button
139 isSecret: modelType === LightDMService.prompts.Secret
140 isPinPrompt: isPrompt && !isAlphanumeric && isSecret
141 loginError: root.loginError
142 hasKeyboard: root.hasKeyboard
143 text: modelText ? modelText : (isAlphanumeric ? i18n.tr("Passphrase") : i18n.tr("Passcode"))
144
145 onClicked: root.clicked()
146 onAccepted: {
147 // If there is another GreeterPrompt, focus it.
148 for (var i = modelIndex + 1; i < repeater.count; i++) {
149 var item = repeater.itemAt(i).item;
150 if (item.isPrompt) {
151 item.forceActiveFocus();
152 return;
153 }
154 }
155
156 // Nope we're the last one; just send our response.
157 d.sendResponse();
158 }
159
160 onLoginErrorChanged: {
161 // provide a fallback to password prompt in case of 5 failed attempts
162 if (loginError && isPinPrompt && AccountsService.failedLogins === 5) {
163 isPrompt = true
164 root.alphanumeric = true
165 }
166 }
167 onCanceled: root.canceled()
168
169 Behavior on opacity { LomiriNumberAnimation {} }
170 opacity: 0
171 }
172 }
173}