1/* === This file is part of Calamares - <https://calamares.io> === 2 * 3 * SPDX-FileCopyrightText: 2020 - 2021 Anke Boersma <demm@kaosx.us> 4 * SPDX-FileCopyrightText: 2021 Adriaan de Groot <groot@kde.org> 5 * SPDX-License-Identifier: GPL-3.0-or-later 6 * 7 * Calamares is Free Software: see the License-Identifier above. 8 * 9 */ 10 11import io.calamares.core 1.0 12import io.calamares.ui 1.0 13 14import QtQuick 2.15 15import QtQuick.Controls 2.10 16import QtQuick.Layouts 1.3 17import org.kde.kirigami 2.7 as Kirigami 18import QtGraphicalEffects 1.0 19import QtQuick.Window 2.3 20 21Kirigami.ScrollablePage { 22 // You can hard-code a color here, or bind to a Kirigami theme color, 23 // or use a color from Calamares branding, or .. 24 readonly property color unfilledFieldColor: "#FBFBFB" //Kirigami.Theme.backgroundColor 25 readonly property color positiveFieldColor: "#F0FFF0" //Kirigami.Theme.positiveBackgroundColor 26 readonly property color negativeFieldColor: "#EBCED1" //Kirigami.Theme.negativeBackgroundColor 27 readonly property color unfilledFieldOutlineColor: "#F1F1F1" 28 readonly property color positiveFieldOutlineColor: "#DCFFDC" 29 readonly property color negativeFieldOutlineColor: "#BE5F68" 30 readonly property color headerTextColor: "#1F1F1F" 31 readonly property color commentsColor: "#6D6D6D" 32 33 width: parent.width 34 height: parent.height 35 36 header: Kirigami.Heading { 37 Layout.fillWidth: true 38 height: 50 39 horizontalAlignment: Qt.AlignHCenter 40 color: headerTextColor 41 font.weight: Font.Medium 42 font.pointSize: 12 43 text: qsTr("Pick your user name and credentials to login and perform admin tasks") 44 } 45 46 ColumnLayout { 47 id: _formLayout 48 spacing: Kirigami.Units.smallSpacing 49 50 Column { 51 Layout.fillWidth: true 52 spacing: Kirigami.Units.smallSpacing 53 54 Label { 55 width: parent.width 56 text: qsTr("What is your name?") 57 } 58 59 TextField { 60 id: _userNameField 61 width: parent.width 62 enabled: config.isEditable("fullName") 63 placeholderText: qsTr("Your Full Name") 64 text: config.fullName 65 onTextChanged: config.setFullName(text) 66 67 palette.base: _userNameField.text.length 68 ? positiveFieldColor : unfilledFieldColor 69 palette.highlight : _userNameField.text.length 70 ? positiveFieldOutlineColor : unfilledFieldOutlineColor 71 } 72 } 73 74 Column { 75 Layout.fillWidth: true 76 spacing: Kirigami.Units.smallSpacing 77 78 Label { 79 width: parent.width 80 text: qsTr("What name do you want to use to log in?") 81 } 82 83 TextField { 84 id: _userLoginField 85 width: parent.width 86 enabled: config.isEditable("loginName") 87 placeholderText: qsTr("Login Name") 88 text: config.loginName 89 validator: RegularExpressionValidator { regularExpression: /[a-z_][a-z0-9_-]*[$]?$/ } 90 91 onTextChanged: acceptableInput 92 ? ( _userLoginField.text === "root" 93 ? forbiddenMessage.visible=true 94 : ( config.setLoginName(text), 95 userMessage.visible = false,forbiddenMessage.visible=false ) ) 96 : ( userMessage.visible = true,console.log("Invalid") ) 97 98 palette.base: _userLoginField.text.length 99 ? ( acceptableInput 100 ? ( _userLoginField.text === "root" 101 ? negativeFieldColor 102 : positiveFieldColor ) 103 : negativeFieldColor ) 104 : unfilledFieldColor 105 palette.highlight : _userLoginField.text.length 106 ? ( acceptableInput 107 ? ( _userLoginField.text === "root" 108 ? negativeFieldOutlineColor 109 : positiveFieldOutlineColor ) 110 : negativeFieldOutlineColor ) 111 : unfilledFieldOutlineColor 112 } 113 114 Label { 115 width: parent.width 116 text: qsTr("If more than one person will use this computer, you can create multiple accounts after installation.") 117 font.weight: Font.Thin 118 font.pointSize: 8 119 color: commentsColor 120 } 121 } 122 123 Kirigami.InlineMessage { 124 id: userMessage 125 Layout.fillWidth: true 126 visible: false 127 type: Kirigami.MessageType.Error 128 text: qsTr("Only lowercase letters, numbers, underscore and hyphen are allowed.") 129 } 130 131 Kirigami.InlineMessage { 132 id: forbiddenMessage 133 Layout.fillWidth: true 134 visible: false 135 type: Kirigami.MessageType.Error 136 text: qsTr("root is not allowed as username.") 137 } 138 139 Column { 140 Layout.fillWidth: true 141 spacing: Kirigami.Units.smallSpacing 142 143 Label { 144 width: parent.width 145 text: qsTr("What is the name of this computer?") 146 } 147 148 TextField { 149 id: _hostName 150 width: parent.width 151 placeholderText: qsTr("Computer Name") 152 text: config.hostName 153 validator: RegularExpressionValidator { regularExpression: /[a-zA-Z0-9][-a-zA-Z0-9_]+/ } 154 155 onTextChanged: acceptableInput 156 ? ( _hostName.text === "localhost" 157 ? forbiddenHost.visible=true 158 : ( config.setHostName(text), 159 hostMessage.visible = false,forbiddenHost.visible = false ) ) 160 : hostMessage.visible = true 161 162 palette.base: _hostName.text.length 163 ? ( acceptableInput 164 ? ( _hostName.text === "localhost" 165 ? negativeFieldColor : positiveFieldColor ) 166 : negativeFieldColor) 167 : unfilledFieldColor 168 palette.highlight : _hostName.text.length 169 ? ( acceptableInput 170 ? ( _hostName.text === "localhost" 171 ? negativeFieldOutlineColor : positiveFieldOutlineColor ) 172 : negativeFieldOutlineColor) 173 : unfilledFieldOutlineColor 174 } 175 176 Label { 177 width: parent.width 178 text: qsTr("This name will be used if you make the computer visible to others on a network.") 179 font.weight: Font.Thin 180 font.pointSize: 8 181 color: commentsColor 182 } 183 } 184 185 Kirigami.InlineMessage { 186 id: hostMessage 187 Layout.fillWidth: true 188 visible: false 189 type: Kirigami.MessageType.Error 190 text: qsTr("Only letters, numbers, underscore and hyphen are allowed, minimal of two characters.") 191 } 192 193 Kirigami.InlineMessage { 194 id: forbiddenHost 195 Layout.fillWidth: true 196 visible: false 197 type: Kirigami.MessageType.Error 198 text: qsTr("localhost is not allowed as hostname.") 199 } 200 201 Column { 202 Layout.fillWidth: true 203 spacing: Kirigami.Units.smallSpacing 204 205 Label { 206 width: parent.width 207 text: qsTr("Choose a password to keep your account safe.") 208 } 209 210 Row { 211 width: parent.width 212 spacing: 20 213 214 TextField { 215 id: _passwordField 216 width: parent.width / 2 - 10 217 placeholderText: qsTr("Password") 218 text: config.userPassword 219 onTextChanged: config.setUserPassword(text) 220 221 palette.base: _passwordField.text.length 222 ? positiveFieldColor : unfilledFieldColor 223 palette.highlight : _passwordField.text.length 224 ? positiveFieldOutlineColor : unfilledFieldOutlineColor 225 226 echoMode: TextInput.Password 227 passwordMaskDelay: 300 228 inputMethodHints: Qt.ImhNoAutoUppercase 229 } 230 231 TextField { 232 id: _verificationPasswordField 233 width: parent.width / 2 - 10 234 placeholderText: qsTr("Repeat Password") 235 text: config.userPasswordSecondary 236 237 onTextChanged: _passwordField.text === _verificationPasswordField.text 238 ? ( config.setUserPasswordSecondary(text), 239 passMessage.visible = false, 240 validityMessage.visible = true ) 241 : ( passMessage.visible = true, 242 validityMessage.visible = false ) 243 244 palette.base: _verificationPasswordField.text.length 245 ? ( _passwordField.text === _verificationPasswordField.text 246 ? positiveFieldColor : negativeFieldColor ) 247 : unfilledFieldColor 248 palette.highlight : _verificationPasswordField.text.length 249 ? ( _passwordField.text === _verificationPasswordField.text 250 ? positiveFieldOutlineColor : negativeFieldOutlineColor ) 251 : unfilledFieldOutlineColor 252 253 echoMode: TextInput.Password 254 passwordMaskDelay: 300 255 inputMethodHints: Qt.ImhNoAutoUppercase 256 } 257 } 258 259 Label { 260 width: parent.width 261 text: qsTr("Enter the same password twice, so that it can be checked for typing errors. A good password will contain a mixture of letters, numbers and punctuation, should be at least eight characters long, and should be changed at regular intervals.") 262 font.weight: Font.Thin 263 font.pointSize: 8 264 wrapMode: Text.WordWrap 265 color: commentsColor 266 } 267 } 268 269 Kirigami.InlineMessage { 270 id: passMessage 271 Layout.fillWidth: true 272 showCloseButton: true 273 visible: false 274 type: Kirigami.MessageType.Error 275 text: config.userPasswordMessage 276 } 277 278 Kirigami.InlineMessage { 279 id: validityMessage 280 Layout.fillWidth: true 281 showCloseButton: true 282 visible: false 283 type: config.userPasswordValidity 284 ? ( config.requireStrongPasswords 285 ? Kirigami.MessageType.Error : Kirigami.MessageType.Warning ) 286 : Kirigami.MessageType.Positive 287 text: config.userPasswordMessage 288 } 289 290 CheckBox { 291 id: root 292 visible: config.writeRootPassword 293 text: qsTr("Reuse user password as root password") 294 checked: config.reuseUserPasswordForRoot 295 onCheckedChanged: config.setReuseUserPasswordForRoot(checked) 296 } 297 298 Label { 299 visible: root.checked 300 width: parent.width 301 text: qsTr("Use the same password for the administrator account.") 302 font.weight: Font.Thin 303 font.pointSize: 8 304 color: commentsColor 305 } 306 307 Column { 308 visible: ! root.checked 309 Layout.fillWidth: true 310 spacing: Kirigami.Units.smallSpacing 311 312 Label { 313 width: parent.width 314 text: qsTr("Choose a root password to keep your account safe.") 315 } 316 317 Row { 318 width: parent.width 319 spacing: 20 320 321 TextField { 322 id: _rootPasswordField 323 width: parent.width / 2 -10 324 placeholderText: qsTr("Root Password") 325 text: config.rootPassword 326 327 onTextChanged: config.setRootPassword(text) 328 329 palette.base: _rootPasswordField.text.length 330 ? positiveFieldColor : unfilledFieldColor 331 palette.highlight : _rootPasswordField.text.length 332 ? positiveFieldOutlineColor : unfilledFieldOutlineColor 333 334 echoMode: TextInput.Password 335 passwordMaskDelay: 300 336 inputMethodHints: Qt.ImhNoAutoUppercase 337 } 338 339 TextField { 340 id: _verificationRootPasswordField 341 width: parent.width / 2 -10 342 placeholderText: qsTr("Repeat Root Password") 343 text: config.rootPasswordSecondary 344 345 onTextChanged: _rootPasswordField.text === _verificationRootPasswordField.text 346 ? ( config.setRootPasswordSecondary(text), 347 rootPassMessage.visible = false,rootValidityMessage.visible = true ) 348 : ( rootPassMessage.visible = true,rootValidityMessage.visible = false ) 349 350 palette.base: _verificationRootPasswordField.text.length 351 ? ( _rootPasswordField.text === _verificationRootPasswordField.text 352 ? positiveFieldColor : negativeFieldColor) 353 : unfilledFieldColor 354 palette.highlight : _verificationRootPasswordField.text.length 355 ? ( _rootPasswordField.text === _verificationRootPasswordField.text 356 ? positiveFieldOutlineColor : negativeFieldOutlineColor) 357 : unfilledFieldOutlineColor 358 359 echoMode: TextInput.Password 360 passwordMaskDelay: 300 361 inputMethodHints: Qt.ImhNoAutoUppercase 362 } 363 } 364 365 Label { 366 visible: ! root.checked 367 width: parent.width 368 text: qsTr("Enter the same password twice, so that it can be checked for typing errors.") 369 font.weight: Font.Thin 370 font.pointSize: 8 371 color: commentsColor 372 } 373 } 374 375 Kirigami.InlineMessage { 376 id: rootPassMessage 377 Layout.fillWidth: true 378 showCloseButton: true 379 visible: false 380 type: Kirigami.MessageType.Error 381 text: config.rootPasswordMessage 382 } 383 384 Kirigami.InlineMessage { 385 id: rootValidityMessage 386 Layout.fillWidth: true 387 showCloseButton: true 388 visible: false 389 type: config.rootPasswordValidity 390 ? ( config.requireStrongPasswords 391 ? Kirigami.MessageType.Error : Kirigami.MessageType.Warning ) 392 : Kirigami.MessageType.Positive 393 text: config.rootPasswordMessage 394 } 395 396 CheckBox { 397 Layout.alignment: Qt.AlignCenter 398 text: qsTr("Log in automatically without asking for the password") 399 checked: config.doAutoLogin 400 onCheckedChanged: config.setAutoLogin(checked) 401 } 402 403 CheckBox { 404 visible: config.permitWeakPasswords 405 Layout.alignment: Qt.AlignCenter 406 text: qsTr("Validate passwords quality") 407 checked: config.requireStrongPasswords 408 onCheckedChanged: config.setRequireStrongPasswords(checked), 409 rootPassMessage.visible = false 410 } 411 412 Label { 413 visible: config.permitWeakPasswords 414 width: parent.width 415 Layout.alignment: Qt.AlignCenter 416 text: qsTr("When this box is checked, password-strength checking is done and you will not be able to use a weak password.") 417 font.weight: Font.Thin 418 font.pointSize: 8 419 color: commentsColor 420 } 421 } 422} 423