Kirigami-addons

FormPasswordFieldDelegate.qml
1/*
2 * Copyright 2022 Carl Schwan <carl@carlschwan.eu>
3 * SPDX-License-Identifier: LGPL-2.0-or-later
4 */
5
6import QtQuick
7import QtQuick.Controls
8import QtQuick.Layouts
9
10import org.kde.kirigami as Kirigami
11
12/**
13 * @brief A Form delegate that corresponds to a password field.
14 *
15 * ```qml
16 * FormCard.FormHeader {
17 * title: "Information"
18 * }
19 *
20 * FormCard.FormCard {
21 * FormCard.FormTextFieldDelegate {
22 * label: "Account name"
23 * }
24 *
25 * FormCard.FormPasswordFieldDelegate {
26 * label: "Password"
27 * statusMessage: "Password incorrect"
28 * status: Kirigami.MessageType.Error
29 * text: "666666666"
30 * }
31 *
32 * FormCard.FormPasswordFieldDelegate {
33 * label: "Password repeat"
34 * statusMessage: "Password match"
35 * text: "4242424242"
36 * status: Kirigami.MessageType.Positive
37 * echoMode: TextInput.Password
38 * }
39 * }
40 * ```
41 *
42 * @since KirigamiAddons 0.11.0
43 *
44 * @inherit AbstractFormDelegate
45 */
46AbstractFormDelegate {
47 id: root
48
49 /**
50 * @brief A label containing primary text that appears above and
51 * to the left the text field.
52 */
53 required property string label
54
55 /**
56 * @brief set the maximum length of the text inside the TextField if maxLength > 0
57 */
58 property alias maximumLength: textField.maximumLength
59
60 /**
61 * @brief This hold the activeFocus state of the internal TextField.
62 */
63 property alias fieldActiveFocus: textField.activeFocus
64
65 /**
66 * @brief This hold the `readOnly` state of the internal TextField.
67 */
68 property alias readOnly: textField.readOnly
69
70 /**
71 * @brief This property holds the `echoMode` of the internal TextField.
72 *
73 * This consists of how the text inside the text field will be
74 * displayed to the user.
75 *
76 * @see <a href="https://doc.qt.io/qt-6/qml-qtquick-textinput.html#echoMode-prop">TextInput.echoMode</a>
77 */
78 property alias echoMode: textField.echoMode
79
80 /**
81 * @brief This property holds the `inputMethodHints` of the
82 * internal TextField.
83 *
84 * This consists of hints on the expected content or behavior of
85 * the text field, be it sensitive data, in a date format, or whether
86 * the characters will be hidden, for example.
87 *
88 * @see <a href="https://doc.qt.io/qt-6/qml-qtquick-textinput.html#inputMethodHints-prop">TextInput.inputMethodHints</a>
89 */
90 property alias inputMethodHints: textField.inputMethodHints
91
92 /**
93 * @brief This property holds the `placeholderText` of the
94 * internal TextField.
95 *
96 * This consists of secondary text shown by default on the text field
97 * if no text has been written in it.
98 */
99 property alias placeholderText: textField.placeholderText
100
101 /**
102 * @brief This property holds the `validator` of the internal TextField.
103 */
104 property alias validator: textField.validator
105
106 /**
107 * @brief This property holds the `acceptableInput` of the internal TextField.
108 */
109 property alias acceptableInput: textField.acceptableInput
110
111 /**
112 * @brief This property holds the current status message type of
113 * the text field.
114 *
115 * This consists of an inline message with a colorful background
116 * and an appropriate icon.
117 *
118 * The status property will affect the color of ::statusMessage used.
119 *
120 * Accepted values:
121 * - `Kirigami.MessageType.Information` (blue color)
122 * - `Kirigami.MessageType.Positive` (green color)
123 * - `Kirigami.MessageType.Warning` (orange color)
124 * - `Kirigami.MessageType.Error` (red color)
126 * default: `Kirigami.MessageType.Information` if ::statusMessage is set,
127 * nothing otherwise.
128 *
129 * @see Kirigami.MessageType
130 */
131 property var status: Kirigami.MessageType.Information
133 /**
134 * @brief This property holds the current status message of
135 * the text field.
136 *
137 * If this property is not set, no ::status will be shown.
138 */
139 property string statusMessage: ""
141 /**
142 * @brief This property hodls whether the password quality is shown.
143 *
144 * This is allow people to see whether heir password is secure when choosing
145 * a new password.
146 */
147 property bool showPasswordQuality: false
148
149 /**
150 * @This signal is emitted when the Return or Enter key is pressed.
151 *
152 * Note that if there is a validator or inputMask set on the text input,
153 * the signal will only be emitted if the input is in an acceptable
154 * state.
155 */
156 signal accepted();
157
158 /**
159 * @brief This signal is emitted when the Return or Enter key is pressed
160 * or the text input loses focus.
161 *
162 * Note that if there is a validator or inputMask set on the text input
163 * and enter/return is pressed, this signal will only be emitted if
164 * the input follows the inputMask and the validator returns an
165 * acceptable state.
166 */
167 signal editingFinished();
168
169 /**
170 * @brief This signal is emitted whenever the text is edited.
171 *
172 * Unlike textChanged(), this signal is not emitted when the text
173 * is changed programmatically, for example, by changing the
174 * value of the text property or by calling ::clear().
175 */
176 signal textEdited();
178 /**
179 * @brief Clears the contents of the text input and resets partial
180 * text input from an input method.
181 */
182 function clear(): void {
183 textField.clear();
184 }
185
186 /**
187 * Inserts text into the TextInput at position.
188 */
189 function insert(position: int, text: string): void {
190 textField.insert(position, text);
191 }
192
193 /**
194 * Causes all text to be selected.
195 * @since Kirigami Addons 1.4.0
196 */
197 function selectAll(): void {
198 textField.selectAll();
199 }
200
201 /**
202 * Causes the text from start to end to be selected.
203 * @since Kirigami Addons 1.4.0
204 */
205 function select(start: int, end: int): void {
206 textField.select(start, end);
207 }
208
209 onActiveFocusChanged: { // propagate focus to the text field
210 if (activeFocus) {
211 textField.forceActiveFocus();
212 }
213 }
214
215 onClicked: textField.forceActiveFocus()
216 background: null
217 Accessible.role: Accessible.EditableText
218
219 contentItem: ColumnLayout {
220 spacing: Kirigami.Units.smallSpacing
221 RowLayout {
222 spacing: Kirigami.Units.largeSpacing
223 Label {
224 Layout.fillWidth: true
225 text: label
226 elide: Text.ElideRight
227 color: root.enabled ? Kirigami.Theme.textColor : Kirigami.Theme.disabledTextColor
228 wrapMode: Text.Wrap
229 maximumLineCount: 2
230 }
231 Label {
232 TextMetrics {
233 id: metrics
234 text: label(root.maximumLength, root.maximumLength)
235 font: Kirigami.Theme.smallFont
236
237 function label(current: int, maximum: int): string {
238 return i18ndc("kirigami-addons6", "@label %1 is current text length, %2 is maximum length of text field", "%1/%2", current, maximum)
239 }
240 }
241 // 32767 is the default value for TextField.maximumLength
242 visible: root.maximumLength < 32767
243 text: metrics.label(textField.text.length, root.maximumLength)
244 font: Kirigami.Theme.smallFont
245 color: textField.text.length === root.maximumLength
246 ? Kirigami.Theme.neutralTextColor
247 : Kirigami.Theme.textColor
248 horizontalAlignment: Text.AlignRight
249
250 Layout.margins: Kirigami.Units.smallSpacing
251 Layout.preferredWidth: metrics.advanceWidth
252 }
253 }
254
255 Kirigami.PasswordField {
256 id: textField
257 Accessible.description: label
258 Layout.fillWidth: true
259 placeholderText: root.placeholderText
260 text: root.text
261 onTextChanged: root.text = text
262 onAccepted: root.accepted()
263 onEditingFinished: root.editingFinished()
264 onTextEdited: root.textEdited()
265 activeFocusOnTab: false
266 }
267
268 Loader {
269 active: root.showPasswordQuality
270 Layout.fillWidth: true
271 sourceComponent: RowLayout {
272 spacing: 2
273
274 PasswordHealth {
275 id: passwordHealth
276 password: textField.text
277 }
278
279 Repeater {
280 model: 4
281
282 Rectangle {
283 id: rect
284
285 required property int index
286
287 height: Kirigami.Units.smallSpacing
288
289 radius: 1
290
291 color: switch (passwordHealth.quality) {
292 case PasswordHealth.Bad:
293 case PasswordHealth.Poor:
294 return Kirigami.Theme.negativeBackgroundColor;
295 case PasswordHealth.Weak:
296 return Kirigami.Theme.neutralBackgroundColor;
297 case PasswordHealth.Good:
298 case PasswordHealth.Excellent:
299 return Kirigami.Theme.positiveBackgroundColor;
300 }
301
302 Layout.fillWidth: true
303
304 Rectangle {
305 height: Kirigami.Units.smallSpacing
306 width: {
307 const entropy = Math.min(passwordHealth.entropy, 200);
308 if (entropy > (index + 1) * 50) {
309 return parent.width;
310 } else if (entropy < (index) * 50) {
311 return 0;
312 }
313 const percent = entropy / 200;
314 return Math.max(0, parent.width * (percent * 4 - index))
315 }
316
317 radius: 1
318
319 color: switch (passwordHealth.quality) {
320 case PasswordHealth.Bad:
321 case PasswordHealth.Poor:
322 return Kirigami.Theme.negativeTextColor;
323 case PasswordHealth.Weak:
324 return Kirigami.Theme.neutralTextColor;
325 case PasswordHealth.Good:
326 case PasswordHealth.Excellent:
327 return Kirigami.Theme.positiveTextColor;
328 }
329 }
330 }
331 }
332 }
333 }
334
335 Kirigami.InlineMessage {
336 id: formErrorHandler
337 visible: root.statusMessage.length > 0
338 Layout.topMargin: visible ? Kirigami.Units.smallSpacing : 0
339 Layout.fillWidth: true
340 text: root.statusMessage
341 type: root.status
342 }
343 }
344}
345
string label
A label containing primary text that appears above and to the left the text field.
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri Feb 21 2025 11:53:19 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.