update
This commit is contained in:
379
themes/sm1tee/components/LoginScreen.qml
Normal file
379
themes/sm1tee/components/LoginScreen.qml
Normal file
@@ -0,0 +1,379 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import SddmComponents
|
||||
|
||||
Item {
|
||||
id: loginScreen
|
||||
signal close
|
||||
signal toggleLayoutPopup
|
||||
|
||||
state: "normal"
|
||||
property bool stateChanging: false
|
||||
function safeStateChange(newState) { // This is probably overkill, but whatever
|
||||
if (!stateChanging) {
|
||||
stateChanging = true;
|
||||
state = newState;
|
||||
stateChanging = false;
|
||||
}
|
||||
}
|
||||
onStateChanged: {
|
||||
if (state === "normal") {
|
||||
resetFocus();
|
||||
}
|
||||
}
|
||||
|
||||
readonly property alias password: password
|
||||
readonly property alias loginButton: loginButton
|
||||
readonly property alias loginContainer: loginContainer
|
||||
|
||||
property bool showKeyboard: !Config.virtualKeyboardStartHidden
|
||||
|
||||
// Login info
|
||||
property int sessionIndex: 0
|
||||
property int userIndex: 0
|
||||
property string userName: ""
|
||||
property string userRealName: ""
|
||||
property string userIcon: ""
|
||||
property bool userNeedsPassword: false
|
||||
|
||||
function login() {
|
||||
if (password.text.length > 0 || !userNeedsPassword) {
|
||||
safeStateChange("authenticating");
|
||||
sddm.login(userName, password.text, sessionIndex);
|
||||
}
|
||||
}
|
||||
Connections {
|
||||
function onLoginSucceeded() {
|
||||
loginContainer.scale = 0.0;
|
||||
}
|
||||
function onLoginFailed() {
|
||||
safeStateChange("normal");
|
||||
loginMessage.warn(textConstants.loginFailed || "Login failed", "error");
|
||||
password.text = "";
|
||||
}
|
||||
function onInformationMessage(message) {
|
||||
loginMessage.warn(message, "error");
|
||||
}
|
||||
target: sddm
|
||||
}
|
||||
|
||||
// FIX: Critical connections memory leak prevention?
|
||||
Component.onDestruction: {
|
||||
if (typeof connections !== 'undefined') {
|
||||
connections.target = null;
|
||||
}
|
||||
}
|
||||
|
||||
function updateCapsLock() {
|
||||
if (root.capsLockOn && loginScreen.state !== "authenticating") {
|
||||
loginMessage.warn(textConstants.capslockWarning || "Caps Lock is on", "warning");
|
||||
} else {
|
||||
loginMessage.clear();
|
||||
}
|
||||
}
|
||||
|
||||
function resetFocus() {
|
||||
if (loginScreen.userNeedsPassword) {
|
||||
password.input.forceActiveFocus();
|
||||
} else {
|
||||
loginButton.forceActiveFocus();
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: loginContainer
|
||||
width: Config.loginAreaPosition === "left" || Config.loginAreaPosition === "right" ? (Config.avatarActiveSize + Config.usernameMargin + loginArea.width) : userSelector.width
|
||||
height: childrenRect.height
|
||||
scale: 0.5 // Initial animation
|
||||
|
||||
Behavior on scale {
|
||||
enabled: Config.enableAnimations
|
||||
NumberAnimation {
|
||||
duration: 200
|
||||
}
|
||||
}
|
||||
|
||||
// LoginArea position
|
||||
Component.onCompleted: {
|
||||
if (Config.loginAreaPosition === "left") {
|
||||
anchors.verticalCenter = parent.verticalCenter;
|
||||
if (Config.loginAreaMargin === -1) {
|
||||
anchors.horizontalCenter = parent.horizontalCenter;
|
||||
} else {
|
||||
anchors.left = parent.left;
|
||||
anchors.leftMargin = Config.loginAreaMargin;
|
||||
}
|
||||
} else if (Config.loginAreaPosition === "right") {
|
||||
anchors.verticalCenter = parent.verticalCenter;
|
||||
if (Config.loginAreaMargin === -1) {
|
||||
anchors.horizontalCenter = parent.horizontalCenter;
|
||||
} else {
|
||||
anchors.right = parent.right;
|
||||
anchors.rightMargin = Config.loginAreaMargin;
|
||||
}
|
||||
} else {
|
||||
anchors.horizontalCenter = parent.horizontalCenter;
|
||||
if (Config.loginAreaMargin === -1) {
|
||||
anchors.verticalCenter = parent.verticalCenter;
|
||||
} else {
|
||||
anchors.top = parent.top;
|
||||
anchors.topMargin = Config.loginAreaMargin;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UserSelector {
|
||||
id: userSelector
|
||||
listUsers: loginScreen.state === "selectingUser"
|
||||
enabled: loginScreen.state !== "authenticating"
|
||||
activeFocusOnTab: true
|
||||
orientation: Config.loginAreaPosition === "left" || Config.loginAreaPosition === "right" ? "vertical" : "horizontal"
|
||||
width: orientation === "horizontal" ? loginScreen.width - Config.loginAreaMargin * 2 : Config.avatarActiveSize
|
||||
height: orientation === "horizontal" ? Config.avatarActiveSize : loginScreen.height - Config.loginAreaMargin * 2
|
||||
onOpenUserList: {
|
||||
safeStateChange("selectingUser");
|
||||
}
|
||||
onCloseUserList: {
|
||||
safeStateChange("normal");
|
||||
loginScreen.resetFocus(); // resetFocus with escape even if the selector is not open
|
||||
}
|
||||
onUserChanged: (index, name, realName, icon, needsPassword) => {
|
||||
loginScreen.userIndex = index;
|
||||
loginScreen.userName = name;
|
||||
loginScreen.userRealName = realName;
|
||||
loginScreen.userIcon = icon;
|
||||
loginScreen.userNeedsPassword = needsPassword;
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
anchors.top = parent.top;
|
||||
if (Config.loginAreaPosition === "left") {
|
||||
anchors.left = parent.left;
|
||||
} else if (Config.loginAreaPosition === "right") {
|
||||
anchors.right = parent.right;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: loginLayout
|
||||
height: activeUserName.height + Config.passwordInputMarginTop + loginArea.height
|
||||
width: loginArea.width > activeUserName.width ? loginArea.width : activeUserName.width
|
||||
|
||||
// LoginArea alignment
|
||||
Component.onCompleted: {
|
||||
if (Config.loginAreaPosition === "left") {
|
||||
anchors.verticalCenter = parent.verticalCenter;
|
||||
anchors.left = userSelector.right;
|
||||
anchors.leftMargin = Config.usernameMargin;
|
||||
} else if (Config.loginAreaPosition === "right") {
|
||||
anchors.verticalCenter = parent.verticalCenter;
|
||||
anchors.right = userSelector.left;
|
||||
anchors.rightMargin = Config.usernameMargin;
|
||||
} else {
|
||||
anchors.top = userSelector.bottom;
|
||||
anchors.topMargin = Config.usernameMargin;
|
||||
anchors.horizontalCenter = parent.horizontalCenter;
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
id: activeUserName
|
||||
font.family: Config.usernameFontFamily
|
||||
font.weight: Config.usernameFontWeight
|
||||
font.pixelSize: Config.usernameFontSize
|
||||
color: Config.usernameColor
|
||||
text: loginScreen.userRealName || loginScreen.userName || ""
|
||||
|
||||
Component.onCompleted: {
|
||||
anchors.top = parent.top;
|
||||
if (Config.loginAreaPosition === "left") {
|
||||
anchors.left = parent.left;
|
||||
} else if (Config.loginAreaPosition === "right") {
|
||||
anchors.right = parent.right;
|
||||
} else {
|
||||
anchors.horizontalCenter = parent.horizontalCenter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: loginArea
|
||||
height: Config.passwordInputHeight
|
||||
spacing: Config.loginButtonMarginLeft
|
||||
visible: loginScreen.state !== "authenticating"
|
||||
|
||||
Component.onCompleted: {
|
||||
anchors.top = activeUserName.bottom;
|
||||
anchors.topMargin = Config.passwordInputMarginTop;
|
||||
if (Config.loginAreaPosition === "left") {
|
||||
anchors.left = parent.left;
|
||||
} else if (Config.loginAreaPosition === "right") {
|
||||
anchors.right = parent.right;
|
||||
} else {
|
||||
anchors.horizontalCenter = parent.horizontalCenter;
|
||||
}
|
||||
}
|
||||
|
||||
PasswordInput {
|
||||
id: password
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
enabled: loginScreen.state !== "selectingUser" && loginScreen.state !== "authenticating" && loginScreen.state === "normal"
|
||||
visible: loginScreen.userNeedsPassword
|
||||
onAccepted: {
|
||||
loginScreen.login();
|
||||
}
|
||||
}
|
||||
|
||||
IconButton {
|
||||
id: loginButton
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.preferredWidth: width // Fix button not resizing when label updates
|
||||
height: password.height
|
||||
visible: !Config.loginButtonHideIfNotNeeded || !loginScreen.userNeedsPassword
|
||||
enabled: loginScreen.state !== "selectingUser" && loginScreen.state !== "authenticating"
|
||||
activeFocusOnTab: true
|
||||
icon: Config.getIcon(Config.loginButtonIcon)
|
||||
label: textConstants.login ? textConstants.login.toUpperCase() : "LOGIN"
|
||||
showLabel: Config.loginButtonShowTextIfNoPassword && !loginScreen.userNeedsPassword
|
||||
tooltipText: !Config.tooltipsDisableLoginButton && (!Config.loginButtonShowTextIfNoPassword || loginScreen.userNeedsPassword) ? (textConstants.login || "Login") : ""
|
||||
iconSize: Config.loginButtonIconSize
|
||||
fontFamily: Config.loginButtonFontFamily
|
||||
fontSize: Config.loginButtonFontSize
|
||||
fontWeight: Config.loginButtonFontWeight
|
||||
contentColor: Config.loginButtonContentColor
|
||||
activeContentColor: Config.loginButtonActiveContentColor
|
||||
backgroundColor: Config.loginButtonBackgroundColor
|
||||
backgroundOpacity: Config.loginButtonBackgroundOpacity
|
||||
activeBackgroundColor: Config.loginButtonActiveBackgroundColor
|
||||
activeBackgroundOpacity: Config.loginButtonActiveBackgroundOpacity
|
||||
borderSize: Config.loginButtonBorderSize
|
||||
borderColor: Config.loginButtonBorderColor
|
||||
borderRadiusLeft: password.visible ? Config.loginButtonBorderRadiusLeft : Config.loginButtonBorderRadiusRight
|
||||
borderRadiusRight: Config.loginButtonBorderRadiusRight
|
||||
onClicked: {
|
||||
loginScreen.login();
|
||||
}
|
||||
|
||||
Behavior on x {
|
||||
enabled: Config.enableAnimations
|
||||
NumberAnimation {
|
||||
duration: 150
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Spinner {
|
||||
id: spinner
|
||||
visible: loginScreen.state === "authenticating"
|
||||
opacity: visible ? 1.0 : 0.0
|
||||
|
||||
Component.onCompleted: {
|
||||
anchors.top = activeUserName.bottom;
|
||||
anchors.topMargin = Config.passwordInputMarginTop;
|
||||
if (Config.loginAreaPosition === "left") {
|
||||
anchors.left = parent.left;
|
||||
} else if (Config.loginAreaPosition === "right") {
|
||||
anchors.right = parent.right;
|
||||
} else {
|
||||
anchors.horizontalCenter = parent.horizontalCenter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
id: loginMessage
|
||||
property bool capslockWarning: false
|
||||
font.pixelSize: Config.warningMessageFontSize
|
||||
font.family: Config.warningMessageFontFamily
|
||||
font.weight: Config.warningMessageFontWeight
|
||||
color: Config.warningMessageNormalColor
|
||||
visible: text !== "" && loginScreen.state !== "authenticating" && (capslockWarning ? loginScreen.userNeedsPassword : true)
|
||||
opacity: visible ? 1.0 : 0.0
|
||||
anchors.top: loginArea.bottom
|
||||
anchors.topMargin: visible ? Config.warningMessageMarginTop : 0
|
||||
|
||||
Component.onCompleted: {
|
||||
if (root.capsLockOn)
|
||||
loginMessage.warn(textConstants.capslockWarning || "Caps Lock is on", "warning");
|
||||
|
||||
if (Config.loginAreaPosition === "left") {
|
||||
anchors.left = parent.left;
|
||||
} else if (Config.loginAreaPosition === "right") {
|
||||
anchors.right = parent.right;
|
||||
} else {
|
||||
anchors.horizontalCenter = parent.horizontalCenter;
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on anchors.topMargin {
|
||||
enabled: Config.enableAnimations
|
||||
NumberAnimation {
|
||||
duration: 150
|
||||
}
|
||||
}
|
||||
Behavior on opacity {
|
||||
enabled: Config.enableAnimations
|
||||
NumberAnimation {
|
||||
duration: 150
|
||||
}
|
||||
}
|
||||
|
||||
function warn(message, type) {
|
||||
clear();
|
||||
text = message;
|
||||
color = type === "error" ? Config.warningMessageErrorColor : (type === "warning" ? Config.warningMessageWarningColor : Config.warningMessageNormalColor);
|
||||
if (message === (textConstants.capslockWarning || "Caps Lock is on"))
|
||||
capslockWarning = true;
|
||||
}
|
||||
|
||||
function clear() {
|
||||
text = "";
|
||||
capslockWarning = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MenuArea {}
|
||||
VirtualKeyboard {}
|
||||
|
||||
Keys.onPressed: function (event) {
|
||||
if (event.key === Qt.Key_Escape) {
|
||||
if (loginScreen.state === "authenticating") {
|
||||
event.accepted = false;
|
||||
return;
|
||||
}
|
||||
if (Config.lockScreenDisplay) {
|
||||
loginScreen.close();
|
||||
}
|
||||
password.text = "";
|
||||
} else if (event.key === Qt.Key_CapsLock) {
|
||||
root.capsLockOn = !root.capsLockOn;
|
||||
}
|
||||
event.accepted = true;
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: closeUserSelectorMouseArea
|
||||
z: -1
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onClicked: {
|
||||
if (loginScreen.state === "selectingUser") {
|
||||
safeStateChange("normal");
|
||||
}
|
||||
}
|
||||
onWheel: event => {
|
||||
if (loginScreen.state === "selectingUser") {
|
||||
if (event.angleDelta.y < 0) {
|
||||
userSelector.nextUser();
|
||||
} else {
|
||||
userSelector.prevUser();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user