summaryrefslogtreecommitdiff
path: root/raveos-sddm-theme/sddm-rave-theme/Components/Input.qml
diff options
context:
space:
mode:
Diffstat (limited to 'raveos-sddm-theme/sddm-rave-theme/Components/Input.qml')
-rw-r--r--raveos-sddm-theme/sddm-rave-theme/Components/Input.qml923
1 files changed, 615 insertions, 308 deletions
diff --git a/raveos-sddm-theme/sddm-rave-theme/Components/Input.qml b/raveos-sddm-theme/sddm-rave-theme/Components/Input.qml
index 47e6598..daf3ba0 100644
--- a/raveos-sddm-theme/sddm-rave-theme/Components/Input.qml
+++ b/raveos-sddm-theme/sddm-rave-theme/Components/Input.qml
@@ -4,14 +4,16 @@
// Distributed under the GPLv3+ License https://www.gnu.org/licenses/gpl-3.0.html
import QtQuick 2.15
-import QtQuick.Layouts 1.15
+import QtQuick.Layouts 6.5
import QtQuick.Controls 2.15
-import QtQuick.Effects
+import QtQuick.Effects 6.5
Column {
id: inputContainer
+ width: parent.width
Layout.fillWidth: true
+ clip: true
property ComboBox exposeSession: sessionSelect.exposeSession
property bool failed
@@ -21,7 +23,7 @@ Column {
// change also in selectSession
height: root.font.pointSize * 2
- width: parent.width / 2
+ width: parent.width
anchors.horizontalCenter: parent.horizontalCenter
Label {
@@ -65,43 +67,176 @@ Column {
}
}
- // Profilkép + felhasználóváltó
+ // Profilkép
Item {
id: avatarField
- height: root.font.pointSize * 12
- width: parent.width / 2
+ height: Math.min(root.font.pointSize * 6.5, parent.width * 0.35)
+ width: parent.width
anchors.horizontalCenter: parent.horizontalCenter
- property string userIconPath: {
- var icon = userModel.data(userModel.index(selectUser.currentIndex, 0), Qt.UserRole + 4)
- return (icon && icon !== "") ? icon : ""
+ property int currentAttempt: 0
+ property var candidateIcons: []
+
+ function resolveIconCandidates(idx, name) {
+ var list = []
+ var count = (typeof userModel !== "undefined" && userModel) ? userModel.count : 0
+
+ var uIndex = -1
+ if (name && name !== "" && count > 0) {
+ for (var i = 0; i < count; i++) {
+ var qIdx = userModel.index(i, 0)
+ var uName = userModel.data(qIdx, Qt.UserRole + 1)
+ if (uName === name) {
+ uIndex = i
+ break
+ }
+ }
+ }
+ if (uIndex === -1) {
+ uIndex = (idx >= 0 && idx < count) ? idx : (userModel && userModel.lastIndex >= 0 ? userModel.lastIndex : 0)
+ }
+
+ var directIcon = ""
+ var home = ""
+ var uName = name || ""
+
+ if (count > 0 && uIndex >= 0 && uIndex < count) {
+ var qIdx = userModel.index(uIndex, 0)
+ directIcon = userModel.data(qIdx, Qt.UserRole + 4) || ""
+ home = userModel.data(qIdx, Qt.UserRole + 3) || ""
+ if (!uName || uName === "") {
+ uName = userModel.data(qIdx, Qt.UserRole + 1) || ""
+ }
+ }
+
+ function addCandidate(p) {
+ if (!p || p === "") return
+ var s = p.toString().trim()
+ if (s === "") return
+ // Ignore generic silhouette icon installed in SDDM faces directory
+ if (s === "/usr/share/sddm/faces/.face.icon" || s === "file:///usr/share/sddm/faces/.face.icon") return
+ var url = (s.startsWith("file://") || s.startsWith("image://") || s.startsWith("qrc://") || s.startsWith("http")) ? s : ("file://" + s)
+ if (list.indexOf(url) === -1) {
+ list.push(url)
+ }
+ }
+
+ // 1. Direct icon reported by SDDM (AccountsService or explicit face config)
+ if (directIcon !== "") {
+ addCandidate(directIcon)
+ }
+
+ // 2. AccountsService system icons (standard across Linux - world-readable 644)
+ if (uName !== "") {
+ addCandidate("/var/lib/AccountsService/icons/" + uName)
+ addCandidate("/var/lib/AccountsService/icons/" + uName + ".png")
+ addCandidate("/var/lib/AccountsService/icons/" + uName + ".jpg")
+ addCandidate("/var/lib/AccountsService/icons/" + uName + ".jpeg")
+ addCandidate("/var/lib/AccountsService/icons/" + uName + ".svg")
+ }
+
+ // 3. User's home directory faces
+ if (home !== "") {
+ addCandidate(home + "/.face")
+ addCandidate(home + "/.face.icon")
+ addCandidate(home + "/.face.png")
+ addCandidate(home + "/.face.jpg")
+ addCandidate(home + "/.face.jpeg")
+ addCandidate(home + "/.icon")
+ addCandidate(home + "/.avatar")
+ }
+ if (uName !== "") {
+ addCandidate("/home/" + uName + "/.face")
+ addCandidate("/home/" + uName + "/.face.icon")
+ addCandidate("/home/" + uName + "/.face.png")
+ addCandidate("/home/" + uName + "/.face.jpg")
+ addCandidate("/home/" + uName + "/.face.jpeg")
+ addCandidate("/home/" + uName + "/.icon")
+ addCandidate("/home/" + uName + "/.avatar")
+ }
+
+ // 4. System SDDM faces directory
+ if (uName !== "") {
+ addCandidate("/usr/share/sddm/faces/" + uName + ".face.icon")
+ addCandidate("/usr/share/sddm/faces/" + uName + ".png")
+ addCandidate("/usr/share/sddm/faces/" + uName + ".jpg")
+ addCandidate("/usr/share/sddm/faces/" + uName)
+ addCandidate("/var/lib/sddm/faces/" + uName + ".face.icon")
+ addCandidate("/var/lib/sddm/faces/" + uName + ".png")
+ addCandidate("/var/lib/sddm/faces/" + uName + ".jpg")
+ addCandidate("/var/lib/sddm/faces/" + uName)
+ }
+
+ // 5. Configured theme avatar
+ if (config.UserAvatar && config.UserAvatar !== "") {
+ addCandidate(config.UserAvatar)
+ }
+ if (config.DefaultAvatar && config.DefaultAvatar !== "") {
+ addCandidate(config.DefaultAvatar)
+ }
+
+ return list
+ }
+
+ function tryNextCandidate() {
+ if (currentAttempt < candidateIcons.length) {
+ var nextUrl = candidateIcons[currentAttempt]
+ currentAttempt++
+ avatarPhoto.source = nextUrl
+ } else {
+ avatarPhoto.source = ""
+ }
+ }
+
+ function updateAvatarSource() {
+ var targetUser = usernameField.selectedUsername
+ if (!targetUser && typeof userModel !== "undefined" && userModel && userModel.count > 0) {
+ targetUser = usernameField.getInitialUsername()
+ }
+ candidateIcons = resolveIconCandidates(usernameField.selectedUserIndex, targetUser)
+ currentAttempt = 0
+ avatarPhoto.source = ""
+ if (candidateIcons.length > 0) {
+ tryNextCandidate()
+ }
+ }
+
+ Component.onCompleted: updateAvatarSource()
+
+ Connections {
+ target: usernameField
+ function onSelectedUsernameChanged() { avatarField.updateAvatarSource() }
+ function onSelectedUserIndexChanged() { avatarField.updateAvatarSource() }
}
- Column {
+ Connections {
+ target: (typeof userModel !== "undefined") ? userModel : null
+ function onRowsInserted() { avatarField.updateAvatarSource() }
+ function onModelReset() { avatarField.updateAvatarSource() }
+ function onDataChanged() { avatarField.updateAvatarSource() }
+ }
+
+ // Avatar kör
+ Item {
anchors.centerIn: parent
- spacing: root.font.pointSize * 0.8
+ width: root.font.pointSize * 5.2
+ height: root.font.pointSize * 5.2
+
+ // Avatar drop shadow
+ Rectangle {
+ anchors.fill: parent
+ anchors.topMargin: root.font.pointSize * 0.15
+ radius: width / 2
+ color: Qt.rgba(0, 0, 0, 0.30)
+ }
- // Avatar kör
Rectangle {
id: avatarCircle
- anchors.horizontalCenter: parent.horizontalCenter
- width: root.font.pointSize * 7
- height: root.font.pointSize * 7
+ anchors.fill: parent
radius: width / 2
clip: true
- color: Qt.rgba(0.10, 0.10, 0.15, 0.65)
-
- // The source image (invisible)
- Image {
- id: avatarPhoto
- anchors.fill: parent
- source: avatarField.userIconPath !== "" ? avatarField.userIconPath : ""
- fillMode: Image.PreserveAspectCrop
- smooth: true
- mipmap: true
- visible: false
- }
+ color: Qt.rgba(1, 1, 1, 0.15)
// The mask source
Item {
@@ -116,15 +251,23 @@ Column {
}
}
- // Apply MultiEffect to mask the avatarPhoto
- MultiEffect {
+ Image {
+ id: avatarPhoto
anchors.fill: parent
- source: avatarPhoto
- visible: avatarPhoto.status === Image.Ready && avatarField.userIconPath !== ""
- maskEnabled: true
- maskSource: avatarMask
- maskThresholdMin: 0.5
- maskSpreadAtMin: 1.0
+ fillMode: Image.PreserveAspectCrop
+ smooth: true
+ mipmap: true
+ visible: status === Image.Ready
+ layer.enabled: true
+ layer.effect: MultiEffect {
+ maskEnabled: true
+ maskSource: avatarMask
+ }
+ onStatusChanged: {
+ if (status === Image.Error) {
+ avatarField.tryNextCandidate()
+ }
+ }
}
Image {
@@ -135,8 +278,8 @@ Column {
source: Qt.resolvedUrl("../Assets/User.svg")
fillMode: Image.PreserveAspectFit
smooth: true
- visible: avatarField.userIconPath === "" || avatarPhoto.status !== Image.Ready
- opacity: 0.75
+ visible: avatarPhoto.status !== Image.Ready
+ opacity: 0.85
}
// Draw the border on top of everything!
@@ -144,271 +287,391 @@ Column {
anchors.fill: parent
radius: parent.width / 2
color: "transparent"
- border.color: Qt.rgba(1, 1, 1, 0.30)
- border.width: 2
- }
- }
-
- // Felhasználóváltó gomb (csak ha több user van)
- UserSwitcher {
- id: userSwitcher
- anchors.horizontalCenter: parent.horizontalCenter
- selectedIndex: selectUser.currentIndex
-
- onUserSwitched: function(idx, name) {
- selectUser.currentIndex = idx
- username.text = name
+ border.color: Qt.rgba(1, 1, 1, 0.40)
+ border.width: root.font.pointSize * 0.12
}
}
}
}
-
Item {
id: usernameField
- height: root.font.pointSize * 4.5
- width: parent.width / 2
+ height: root.font.pointSize * 3.8
+ width: parent.width
anchors.horizontalCenter: parent.horizontalCenter
- Button {
- id: staticUserIcon
-
- width: parent.height
- height: parent.height
- anchors.left: parent.left
- z: 2
- visible: userModel.count <= 1
- enabled: false
-
- icon.height: parent.height * 0.25
- icon.width: parent.height * 0.25
- icon.color: config.UserIconColor
- icon.source: Qt.resolvedUrl("../Assets/User.svg")
+ property int selectedUserIndex: (typeof userModel !== "undefined" && userModel && userModel.lastIndex >= 0) ? userModel.lastIndex : 0
+ property string selectedUsername: getInitialUsername()
- background: Rectangle {
- color: "transparent"
- border.color: "transparent"
- }
+ function getInitialUsername() {
+ if (typeof userModel === "undefined" || !userModel || userModel.count === 0) return ""
+ var idx = (userModel.lastIndex >= 0 && userModel.lastIndex < userModel.count) ? userModel.lastIndex : 0
+ var name = userModel.data(userModel.index(idx, 0), Qt.UserRole + 1)
+ return (name !== undefined && name !== null) ? name.toString() : ""
}
- ComboBox {
- id: selectUser
-
- width: parent.height
- height: parent.height
- anchors.left: parent.left
- z: 2
- visible: userModel.count > 1
+ function selectUserAt(idx) {
+ if (typeof userModel === "undefined" || !userModel || idx < 0 || idx >= userModel.count) return
+ selectedUserIndex = idx
+ selectedUsername = userModel.data(userModel.index(idx, 0), Qt.UserRole + 1) || ""
+ avatarField.updateAvatarSource()
+ userDropdownPopup.close()
+ password.forceActiveFocus()
+ }
- model: userModel
- currentIndex: model.lastIndex
- textRole: "name"
- hoverEnabled: true
- onActivated: {
- username.text = currentText;
+ Connections {
+ target: (typeof userModel !== "undefined") ? userModel : null
+ function onRowsInserted() {
+ if (usernameField.selectedUsername === "" || usernameField.selectedUserIndex >= userModel.count) {
+ usernameField.selectedUserIndex = (userModel.lastIndex >= 0 && userModel.lastIndex < userModel.count) ? userModel.lastIndex : 0
+ usernameField.selectedUsername = usernameField.getInitialUsername()
+ }
+ avatarField.updateAvatarSource()
}
-
- property var popkey: config.RightToLeftLayout == "true" ? Qt.Key_Right : Qt.Key_Left
- Keys.onPressed: function (event) {
- if (event.key == Qt.Key_Down && !popup.opened)
- username.forceActiveFocus();
- if ((event.key == Qt.Key_Up || event.key == popkey) && !popup.opened)
- popup.open();
+ function onModelReset() {
+ usernameField.selectedUserIndex = (userModel.lastIndex >= 0 && userModel.lastIndex < userModel.count) ? userModel.lastIndex : 0
+ usernameField.selectedUsername = usernameField.getInitialUsername()
+ avatarField.updateAvatarSource()
}
- KeyNavigation.down: username
- KeyNavigation.right: username
+ function onDataChanged() {
+ usernameField.selectedUsername = usernameField.getInitialUsername()
+ avatarField.updateAvatarSource()
+ }
+ }
- delegate: ItemDelegate {
- // minus padding
- width: popupHandler.width - 20
- anchors.horizontalCenter: popupHandler.horizontalCenter
+ // Container button / click area
+ Item {
+ id: userSelectorButton
+ anchors.centerIn: parent
+ height: root.font.pointSize * 2.8
+ width: parent.width
+ activeFocusOnTab: true
- contentItem: Text {
- verticalAlignment: Text.AlignVCenter
- horizontalAlignment: Text.AlignHCenter
+ Keys.onReturnPressed: userDropdownPopup.visible ? userDropdownPopup.close() : userDropdownPopup.open()
+ Keys.onEnterPressed: userDropdownPopup.visible ? userDropdownPopup.close() : userDropdownPopup.open()
+ Keys.onSpacePressed: userDropdownPopup.visible ? userDropdownPopup.close() : userDropdownPopup.open()
+ Keys.onDownPressed: {
+ if (!userDropdownPopup.visible) {
+ password.forceActiveFocus()
+ }
+ }
+ KeyNavigation.down: password
- text: model.name
- font.pointSize: root.font.pointSize * 0.8
- font.capitalization: Font.AllLowercase
- font.family: root.font.family
- color: config.DropdownTextColor
+ // Background with drop shadow and frosted glass
+ Item {
+ anchors.fill: parent
+ Rectangle {
+ anchors.fill: parent
+ anchors.topMargin: root.font.pointSize * 0.12
+ radius: config.RoundCorners !== "" ? parseInt(config.RoundCorners) : root.font.pointSize * 0.8
+ color: Qt.rgba(0, 0, 0, 0.20)
}
- background: Rectangle {
- color: selectUser.highlightedIndex === index ? Qt.rgba(1, 1, 1, 0.15) : "transparent"
- radius: config.RoundCorners !== "" ? parseInt(config.RoundCorners) / 4 : 5
+ Rectangle {
+ anchors.fill: parent
+ color: userSelectorMouseArea.pressed ? Qt.rgba(1, 1, 1, 0.25) : (userSelectorMouseArea.containsMouse || userSelectorButton.activeFocus ? Qt.rgba(1, 1, 1, 0.20) : Qt.rgba(1, 1, 1, 0.14))
+ border.color: userSelectorButton.activeFocus ? Qt.rgba(255, 255, 255, 0.75) : (userSelectorMouseArea.containsMouse ? Qt.rgba(255, 255, 255, 0.45) : Qt.rgba(255, 255, 255, 0.25))
+ border.width: userSelectorButton.activeFocus ? root.font.pointSize * 0.12 : root.font.pointSize * 0.08
+ radius: config.RoundCorners !== "" ? parseInt(config.RoundCorners) : root.font.pointSize * 0.8
+ Behavior on color { ColorAnimation { duration: 150 } }
+ Behavior on border.color { ColorAnimation { duration: 150 } }
}
}
- indicator: Button {
- id: usernameIcon
-
- width: selectUser.height * 1
+ // Left Icon (User icon)
+ Button {
+ id: userFieldLeftIcon
+ width: parent.height
height: parent.height
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
- anchors.leftMargin: selectUser.height * 0
-
- icon.height: parent.height * 0.25
- icon.width: parent.height * 0.25
enabled: false
- icon.color: config.UserIconColor
+
icon.source: Qt.resolvedUrl("../Assets/User.svg")
+ icon.width: parent.height * 0.38
+ icon.height: parent.height * 0.38
+ icon.color: "#ffffff"
- background: Rectangle {
- color: "transparent"
- border.color: "transparent"
- }
+ background: Rectangle { color: "transparent" }
}
- background: Rectangle {
- color: "transparent"
- border.color: "transparent"
- }
+ // Username display in the middle (Non-editable, clean text)
+ Text {
+ id: username
+ anchors.centerIn: parent
+ width: parent.width - userFieldLeftIcon.width * 2.2
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ elide: Text.ElideRight
- popup: Popup {
- id: popupHandler
+ text: usernameField.selectedUsername
+ color: config.LoginFieldTextColor
+ font.bold: true
+ font.pointSize: root.font.pointSize * 0.95
+ font.family: root.font.family
+ style: Text.Raised
+ styleColor: Qt.rgba(0, 0, 0, 0.40)
+ }
- implicitHeight: contentItem.implicitHeight
- width: usernameField.width
- y: parent.height - username.height / 3
- x: config.RightToLeftLayout == "true" ? -loginButton.width + selectUser.width : 0
- rightMargin: config.RightToLeftLayout == "true" ? root.padding + usernameField.width / 2 : undefined
- padding: 10
+ // Dropdown Arrow Button on Right
+ Item {
+ id: userDropdownBtn
+ width: parent.height
+ height: parent.height
+ anchors.right: parent.right
+ anchors.verticalCenter: parent.verticalCenter
- contentItem: ListView {
- implicitHeight: contentHeight + 20
+ Canvas {
+ id: chevronCanvas
+ width: root.font.pointSize * 0.85
+ height: root.font.pointSize * 0.50
+ anchors.centerIn: parent
+ rotation: userDropdownPopup.visible ? 180 : 0
+ Behavior on rotation { NumberAnimation { duration: 200; easing.type: Easing.OutCubic } }
- clip: true
- model: selectUser.popup.visible ? selectUser.delegateModel : null
- currentIndex: selectUser.highlightedIndex
- ScrollIndicator.vertical: ScrollIndicator {}
- }
+ onPaint: {
+ var ctx = getContext("2d");
+ ctx.reset();
+ ctx.clearRect(0, 0, width, height);
+ ctx.strokeStyle = userSelectorMouseArea.containsMouse ? "#ffffff" : "rgba(255, 255, 255, 0.85)";
+ ctx.lineWidth = Math.max(1.5, root.font.pointSize * 0.12);
+ ctx.lineCap = "round";
+ ctx.lineJoin = "round";
- background: Rectangle {
- radius: config.RoundCorners !== "" ? parseInt(config.RoundCorners) / 2 : 10
- color: Qt.rgba(1, 1, 1, 0.08)
- border.color: Qt.rgba(1, 1, 1, 0.18)
- border.width: 1
- layer.enabled: true
- }
+ ctx.beginPath();
+ ctx.moveTo(1.5, 1.5);
+ ctx.lineTo(width / 2, height - 1.5);
+ ctx.lineTo(width - 1.5, 1.5);
+ ctx.stroke();
+ }
- enter: Transition {
- NumberAnimation {
- property: "opacity"
- from: 0
- to: 1
+ Connections {
+ target: userSelectorMouseArea
+ function onContainsMouseChanged() { chevronCanvas.requestPaint(); }
}
}
}
- states: [
- State {
- name: "pressed"
- when: selectUser.down
- PropertyChanges {
- target: usernameIcon
- icon.color: Qt.lighter(config.HoverUserIconColor, 1.1)
- }
- },
- State {
- name: "hovered"
- when: selectUser.hovered
- PropertyChanges {
- target: usernameIcon
- icon.color: Qt.lighter(config.HoverUserIconColor, 1.2)
- }
- },
- State {
- name: "focused"
- when: selectUser.activeFocus
- PropertyChanges {
- target: usernameIcon
- icon.color: config.HoverUserIconColor
- }
- }
- ]
- transitions: [
- Transition {
- PropertyAnimation {
- properties: "color, border.color, icon.color"
- duration: 150
+ // Whole field click area
+ MouseArea {
+ id: userSelectorMouseArea
+ anchors.fill: parent
+ hoverEnabled: true
+ cursorShape: Qt.PointingHandCursor
+ onClicked: {
+ if (userDropdownPopup.visible) {
+ userDropdownPopup.close();
+ } else {
+ userDropdownPopup.open();
}
}
- ]
+ }
}
- TextField {
- id: username
+ // Dropdown Popup
+ Popup {
+ id: userDropdownPopup
- anchors.centerIn: parent
- height: root.font.pointSize * 3
width: parent.width
- horizontalAlignment: TextInput.AlignHCenter
- z: 1
+ y: parent.height + root.font.pointSize * 0.4
+ x: 0
+ padding: root.font.pointSize * 0.5
+ dim: false
+ closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent
+ z: 100
- text: config.ForceLastUser == "true" ? selectUser.currentText : null
- color: config.LoginFieldTextColor
- font.bold: true
- font.capitalization: config.AllowUppercaseLettersInUsernames == "false" ? Font.AllLowercase : Font.MixedCase
- placeholderText: config.TranslatePlaceholderUsername || textConstants.userName
- placeholderTextColor: config.PlaceholderTextColor
- selectByMouse: true
- renderType: Text.QtRendering
+ background: Item {
+ // Drop shadow underlay
+ Rectangle {
+ anchors.fill: parent
+ anchors.topMargin: root.font.pointSize * 0.15
+ radius: config.RoundCorners !== "" ? parseInt(config.RoundCorners) : root.font.pointSize * 0.8
+ color: Qt.rgba(0, 0, 0, 0.40)
+ }
- onFocusChanged: {
- if (focus)
- selectAll();
- }
+ // Frosted Glass body (minimally translucent)
+ Rectangle {
+ anchors.fill: parent
+ radius: config.RoundCorners !== "" ? parseInt(config.RoundCorners) : root.font.pointSize * 0.8
+ border.color: Qt.rgba(1, 1, 1, 0.40)
+ border.width: 1
+ clip: true
- background: Rectangle {
- color: username.activeFocus ? Qt.rgba(0, 0, 0, 0.35) : Qt.rgba(0, 0, 0, 0.2)
- border.color: username.activeFocus ? Qt.rgba(255, 255, 255, 0.3) : Qt.rgba(255, 255, 255, 0.12)
- border.width: username.activeFocus ? 1.5 : 1
- radius: config.RoundCorners !== "" ? parseInt(config.RoundCorners) : 10
- Behavior on color {
- ColorAnimation {
- duration: 150
- }
- }
- Behavior on border.color {
- ColorAnimation {
- duration: 150
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: Qt.rgba(0.18, 0.20, 0.28, 0.92) }
+ GradientStop { position: 0.5; color: Qt.rgba(0.14, 0.16, 0.24, 0.94) }
+ GradientStop { position: 1.0; color: Qt.rgba(0.11, 0.13, 0.20, 0.96) }
}
}
}
- onAccepted: config.AllowUppercaseLettersInUsernames == "false" ? sddm.login(username.text.toLowerCase(), password.text, sessionSelect.selectedSession) : sddm.login(username.text, password.text, sessionSelect.selectedSession)
- KeyNavigation.down: passwordIcon
+ contentItem: ListView {
+ id: userDropdownList
+ implicitHeight: Math.min(contentHeight, root.font.pointSize * 16)
+ clip: true
+ model: userModel
+ spacing: root.font.pointSize * 0.25
+ boundsBehavior: Flickable.StopAtBounds
- states: [
- State {
- name: "focused"
- when: username.activeFocus
- PropertyChanges {
- target: username
- color: Qt.lighter(config.LoginFieldTextColor, 1.15)
+ delegate: Item {
+ id: userDelegateItem
+ width: userDropdownList.width
+ height: root.font.pointSize * 3.4
+
+ property var itemCandidates: avatarField.resolveIconCandidates(index, model.name)
+ property int itemAttempt: 0
+ property bool isSelected: index === usernameField.selectedUserIndex
+
+ function tryNextItemCandidate() {
+ if (itemAttempt < itemCandidates.length) {
+ var nextUrl = itemCandidates[itemAttempt]
+ itemAttempt++
+ dPhoto.source = nextUrl
+ } else {
+ dPhoto.source = ""
+ }
+ }
+
+ Component.onCompleted: {
+ itemAttempt = 0
+ dPhoto.source = ""
+ if (itemCandidates.length > 0) {
+ tryNextItemCandidate()
+ }
+ }
+
+ Rectangle {
+ anchors.fill: parent
+ radius: root.font.pointSize * 0.6
+ color: userDelegateMouse.pressed
+ ? Qt.rgba(1, 1, 1, 0.24)
+ : userDelegateMouse.containsMouse
+ ? Qt.rgba(1, 1, 1, 0.16)
+ : (userDelegateItem.isSelected ? Qt.rgba(1, 1, 1, 0.10) : "transparent")
+ border.color: userDelegateItem.isSelected ? Qt.rgba(1, 1, 1, 0.45) : (userDelegateMouse.containsMouse ? Qt.rgba(1, 1, 1, 0.25) : "transparent")
+ border.width: 1
+ Behavior on color { ColorAnimation { duration: 100 } }
+ Behavior on border.color { ColorAnimation { duration: 100 } }
+ }
+
+ Row {
+ anchors.fill: parent
+ anchors.leftMargin: root.font.pointSize * 0.8
+ anchors.rightMargin: root.font.pointSize * 0.8
+ spacing: root.font.pointSize * 0.8
+
+ // Mini avatar in dropdown row
+ Item {
+ width: root.font.pointSize * 2.4
+ height: root.font.pointSize * 2.4
+ anchors.verticalCenter: parent.verticalCenter
+
+ Rectangle {
+ anchors.fill: parent
+ radius: width / 2
+ clip: true
+ color: Qt.rgba(1, 1, 1, 0.15)
+ border.color: Qt.rgba(1, 1, 1, 0.35)
+ border.width: 1
+
+ Item {
+ id: dMask
+ anchors.fill: parent
+ visible: false
+ layer.enabled: true
+ Rectangle {
+ anchors.fill: parent
+ radius: parent.width / 2
+ color: "black"
+ }
+ }
+
+ Image {
+ id: dPhoto
+ anchors.fill: parent
+ fillMode: Image.PreserveAspectCrop
+ smooth: true
+ visible: status === Image.Ready
+ layer.enabled: true
+ layer.effect: MultiEffect {
+ maskEnabled: true
+ maskSource: dMask
+ }
+ onStatusChanged: {
+ if (status === Image.Error) {
+ userDelegateItem.tryNextItemCandidate()
+ }
+ }
+ }
+
+ Button {
+ anchors.centerIn: parent
+ width: parent.width * 0.65
+ height: parent.height * 0.65
+ enabled: false
+ icon.source: Qt.resolvedUrl("../Assets/User.svg")
+ icon.width: parent.width * 0.65
+ icon.height: parent.height * 0.65
+ icon.color: "#ffffff"
+ visible: dPhoto.status !== Image.Ready
+ background: Rectangle { color: "transparent" }
+ }
+ }
+ }
+
+ // Username & realName
+ Column {
+ anchors.verticalCenter: parent.verticalCenter
+ spacing: 2
+
+ Text {
+ text: model.name || ""
+ color: "#ffffff"
+ font.bold: true
+ font.pointSize: root.font.pointSize * 0.85
+ font.family: root.font.family
+ style: Text.Raised
+ styleColor: Qt.rgba(0, 0, 0, 0.40)
+ }
+
+ Text {
+ text: (model.realName && model.realName !== model.name) ? model.realName : ""
+ color: Qt.rgba(1, 1, 1, 0.65)
+ font.pointSize: root.font.pointSize * 0.70
+ font.family: root.font.family
+ visible: text !== ""
+ }
+ }
+ }
+
+ MouseArea {
+ id: userDelegateMouse
+ anchors.fill: parent
+ hoverEnabled: true
+ cursorShape: Qt.PointingHandCursor
+ onClicked: {
+ usernameField.selectUserAt(index)
+ }
}
}
- ]
+ }
}
}
Item {
id: passwordField
- height: root.font.pointSize * 4.5
- width: parent.width / 2
+ height: root.font.pointSize * 3.8
+ width: parent.width
anchors.horizontalCenter: parent.horizontalCenter
Button {
id: passwordIcon
height: parent.height
- width: selectUser.height * 1
+ width: parent.height
anchors.left: parent.left
- anchors.leftMargin: selectUser.height * 0
anchors.verticalCenter: parent.verticalCenter
z: 2
@@ -478,7 +741,7 @@ Column {
TextField {
id: password
- height: root.font.pointSize * 3
+ height: root.font.pointSize * 2.8
width: parent.width
anchors.centerIn: parent
horizontalAlignment: TextInput.AlignHCenter
@@ -494,19 +757,29 @@ Column {
renderType: Text.QtRendering
selectByMouse: true
- background: Rectangle {
- color: password.activeFocus ? Qt.rgba(0, 0, 0, 0.35) : Qt.rgba(0, 0, 0, 0.2)
- border.color: password.activeFocus ? Qt.rgba(255, 255, 255, 0.3) : Qt.rgba(255, 255, 255, 0.12)
- border.width: password.activeFocus ? 1.5 : 1
- radius: config.RoundCorners !== "" ? parseInt(config.RoundCorners) : 10
- Behavior on color {
- ColorAnimation {
- duration: 150
- }
+ background: Item {
+ Rectangle {
+ anchors.fill: parent
+ anchors.topMargin: root.font.pointSize * 0.12
+ radius: config.RoundCorners !== "" ? parseInt(config.RoundCorners) : root.font.pointSize * 0.8
+ color: Qt.rgba(0, 0, 0, 0.20)
}
- Behavior on border.color {
- ColorAnimation {
- duration: 150
+
+ Rectangle {
+ anchors.fill: parent
+ color: password.activeFocus ? Qt.rgba(1, 1, 1, 0.25) : Qt.rgba(1, 1, 1, 0.14)
+ border.color: password.activeFocus ? Qt.rgba(255, 255, 255, 0.65) : Qt.rgba(255, 255, 255, 0.25)
+ border.width: password.activeFocus ? root.font.pointSize * 0.12 : root.font.pointSize * 0.08
+ radius: config.RoundCorners !== "" ? parseInt(config.RoundCorners) : root.font.pointSize * 0.8
+ Behavior on color {
+ ColorAnimation {
+ duration: 150
+ }
+ }
+ Behavior on border.color {
+ ColorAnimation {
+ duration: 150
+ }
}
}
}
@@ -537,10 +810,8 @@ Column {
Item {
id: login
- // important
- // try 4 or 9 ...
- height: root.font.pointSize * 9
- width: parent.width / 2
+ height: root.font.pointSize * 4.2
+ width: parent.width
anchors.horizontalCenter: parent.horizontalCenter
visible: config.HideLoginButton == "true" ? false : true
@@ -548,7 +819,7 @@ Column {
Item {
id: loginButton
- height: root.font.pointSize * 3
+ height: root.font.pointSize * 2.8
width: parent.width
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
@@ -568,12 +839,20 @@ Column {
KeyNavigation.down: rebootBtn
+ // Drop shadow
+ Rectangle {
+ anchors.fill: parent
+ anchors.topMargin: root.font.pointSize * 0.12
+ radius: config.RoundCorners !== "" ? parseInt(config.RoundCorners) : root.font.pointSize * 0.8
+ color: Qt.rgba(0, 0, 0, 0.25)
+ }
+
Rectangle {
id: buttonBackground
anchors.fill: parent
- radius: config.RoundCorners !== "" ? parseInt(config.RoundCorners) : 10
- border.width: loginButton.activeFocus ? 1.5 : 1
+ radius: config.RoundCorners !== "" ? parseInt(config.RoundCorners) : root.font.pointSize * 0.8
+ border.width: loginButton.activeFocus ? root.font.pointSize * 0.12 : root.font.pointSize * 0.08
border.color: loginButton.down ? Qt.rgba(21/255, 128/255, 61/255, 0.95) : (loginButton.hovered ? Qt.rgba(34/255, 197/255, 94/255, 0.85) : Qt.rgba(74/255, 222/255, 128/255, 0.65))
@@ -600,6 +879,8 @@ Column {
font.pointSize: root.font.pointSize
font.family: root.font.family
color: "#ffffff"
+ style: Text.Raised
+ styleColor: Qt.rgba(0, 0, 0, 0.45)
text: config.TranslateLogin || textConstants.login
opacity: 1.0
@@ -622,58 +903,71 @@ Column {
Item {
id: powerButtonsRow
- height: root.font.pointSize * 10
- width: parent.width / 2
+ height: root.font.pointSize * 5.5
+ width: parent.width
anchors.horizontalCenter: parent.horizontalCenter
Row {
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
- spacing: root.font.pointSize * 3
+ spacing: root.font.pointSize * 1.5
// Reboot gomb
Column {
- spacing: root.font.pointSize * 0.6
+ spacing: root.font.pointSize * 0.45
- RoundButton {
- id: rebootBtn
+ Item {
+ width: root.font.pointSize * 4.2
+ height: root.font.pointSize * 4.2
- width: root.font.pointSize * 6
- height: root.font.pointSize * 6
+ // Button shadow
+ Rectangle {
+ anchors.fill: parent
+ anchors.topMargin: root.font.pointSize * 0.12
+ radius: width / 2
+ color: Qt.rgba(0, 0, 0, 0.30)
+ }
- activeFocusOnTab: true
- Keys.onReturnPressed: sddm.reboot()
- Keys.onEnterPressed: sddm.reboot()
- KeyNavigation.right: shutdownBtn
- hoverEnabled: true
+ RoundButton {
+ id: rebootBtn
+ anchors.fill: parent
- icon.source: Qt.resolvedUrl("../Assets/Reboot.svg")
- icon.width: root.font.pointSize * 3
- icon.height: root.font.pointSize * 3
- icon.color: "#ffffff"
+ activeFocusOnTab: true
+ Keys.onReturnPressed: sddm.reboot()
+ Keys.onEnterPressed: sddm.reboot()
+ KeyNavigation.right: shutdownBtn
+ hoverEnabled: true
- opacity: rebootBtn.hovered || rebootBtn.activeFocus ? 1.0 : 0.75
- Behavior on opacity { NumberAnimation { duration: 150 } }
+ icon.source: Qt.resolvedUrl("../Assets/Reboot.svg")
+ icon.width: root.font.pointSize * 2.1
+ icon.height: root.font.pointSize * 2.1
+ icon.color: "#ffffff"
- scale: rebootBtn.pressed ? 0.88 : 1.0
- Behavior on scale { NumberAnimation { duration: 100 } }
+ opacity: rebootBtn.hovered || rebootBtn.activeFocus ? 1.0 : 0.75
+ Behavior on opacity { NumberAnimation { duration: 150 } }
- background: Rectangle {
- anchors.fill: parent
- radius: width / 2
- color: rebootBtn.pressed ? Qt.rgba(1, 0.45, 0.0, 0.35) : (rebootBtn.hovered ? Qt.rgba(1, 0.55, 0.0, 0.22) : "transparent")
- border.color: "transparent"
- border.width: 0
- Behavior on color { ColorAnimation { duration: 150 } }
- }
+ scale: rebootBtn.pressed ? 0.88 : 1.0
+ Behavior on scale { NumberAnimation { duration: 100 } }
- onClicked: sddm.reboot()
+ background: Rectangle {
+ anchors.fill: parent
+ radius: width / 2
+ color: rebootBtn.pressed ? Qt.rgba(1, 0.45, 0.0, 0.35) : (rebootBtn.hovered ? Qt.rgba(1, 0.55, 0.0, 0.22) : "transparent")
+ border.color: "transparent"
+ border.width: 0
+ Behavior on color { ColorAnimation { duration: 150 } }
+ }
+
+ onClicked: sddm.reboot()
+ }
}
Text {
anchors.horizontalCenter: parent.children[0].horizontalCenter
text: config.TranslateReboot || textConstants.reboot
color: "#ffffff"
+ style: Text.Raised
+ styleColor: Qt.rgba(0, 0, 0, 0.50)
font.pointSize: root.font.pointSize * 0.8
font.family: root.font.family
horizontalAlignment: Text.AlignHCenter
@@ -684,47 +978,60 @@ Column {
// Shutdown gomb
Column {
- spacing: root.font.pointSize * 0.6
+ spacing: root.font.pointSize * 0.45
- RoundButton {
- id: shutdownBtn
+ Item {
+ width: root.font.pointSize * 4.2
+ height: root.font.pointSize * 4.2
- width: root.font.pointSize * 6
- height: root.font.pointSize * 6
+ // Button shadow
+ Rectangle {
+ anchors.fill: parent
+ anchors.topMargin: root.font.pointSize * 0.12
+ radius: width / 2
+ color: Qt.rgba(0, 0, 0, 0.30)
+ }
- activeFocusOnTab: true
- Keys.onReturnPressed: sddm.powerOff()
- Keys.onEnterPressed: sddm.powerOff()
- KeyNavigation.left: rebootBtn
- hoverEnabled: true
+ RoundButton {
+ id: shutdownBtn
+ anchors.fill: parent
- icon.source: Qt.resolvedUrl("../Assets/Shutdown.svg")
- icon.width: root.font.pointSize * 3
- icon.height: root.font.pointSize * 3
- icon.color: "#ffffff"
+ activeFocusOnTab: true
+ Keys.onReturnPressed: sddm.powerOff()
+ Keys.onEnterPressed: sddm.powerOff()
+ KeyNavigation.left: rebootBtn
+ hoverEnabled: true
- opacity: shutdownBtn.hovered || shutdownBtn.activeFocus ? 1.0 : 0.75
- Behavior on opacity { NumberAnimation { duration: 150 } }
+ icon.source: Qt.resolvedUrl("../Assets/Shutdown.svg")
+ icon.width: root.font.pointSize * 2.1
+ icon.height: root.font.pointSize * 2.1
+ icon.color: "#ffffff"
- scale: shutdownBtn.pressed ? 0.88 : 1.0
- Behavior on scale { NumberAnimation { duration: 100 } }
+ opacity: shutdownBtn.hovered || shutdownBtn.activeFocus ? 1.0 : 0.75
+ Behavior on opacity { NumberAnimation { duration: 150 } }
- background: Rectangle {
- anchors.fill: parent
- radius: width / 2
- color: shutdownBtn.pressed ? Qt.rgba(0.8, 0.1, 0.1, 0.40) : (shutdownBtn.hovered ? Qt.rgba(0.8, 0.1, 0.1, 0.25) : "transparent")
- border.color: "transparent"
- border.width: 0
- Behavior on color { ColorAnimation { duration: 150 } }
- }
+ scale: shutdownBtn.pressed ? 0.88 : 1.0
+ Behavior on scale { NumberAnimation { duration: 100 } }
+
+ background: Rectangle {
+ anchors.fill: parent
+ radius: width / 2
+ color: shutdownBtn.pressed ? Qt.rgba(0.8, 0.1, 0.1, 0.40) : (shutdownBtn.hovered ? Qt.rgba(0.8, 0.1, 0.1, 0.25) : "transparent")
+ border.color: "transparent"
+ border.width: 0
+ Behavior on color { ColorAnimation { duration: 150 } }
+ }
- onClicked: sddm.powerOff()
+ onClicked: sddm.powerOff()
+ }
}
Text {
anchors.horizontalCenter: parent.children[0].horizontalCenter
text: config.TranslateShutdown || textConstants.shutdown
color: "#ffffff"
+ style: Text.Raised
+ styleColor: Qt.rgba(0, 0, 0, 0.50)
font.pointSize: root.font.pointSize * 0.8
font.family: root.font.family
horizontalAlignment: Text.AlignHCenter