feat: add custom SDDM login theme
This commit is contained in:
parent
3f0609bcfc
commit
7ae4243548
4 changed files with 241 additions and 0 deletions
205
sddm/Main.qml
Normal file
205
sddm/Main.qml
Normal file
|
|
@ -0,0 +1,205 @@
|
|||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Effects
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
width: 1920
|
||||
height: 1080
|
||||
color: "#223638"
|
||||
property date now: new Date()
|
||||
property bool busy: false
|
||||
property string message: ""
|
||||
readonly property color cream: "#eee8dd"
|
||||
readonly property color muted: "#bcb5ab"
|
||||
readonly property color red: "#bc3b3b"
|
||||
readonly property color dark: "#1c1717"
|
||||
|
||||
FontLoader { id: face; source: "font.ttf" }
|
||||
Timer { interval: 1000; running: true; repeat: true; onTriggered: root.now = new Date() }
|
||||
|
||||
function login() {
|
||||
if (busy) return
|
||||
if (!username.text.trim() || session.count === 0) {
|
||||
message = "Enter a username and select a session."
|
||||
return
|
||||
}
|
||||
message = ""
|
||||
busy = true
|
||||
sddm.login(username.text.trim(), password.text, session.currentIndex)
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: sddm
|
||||
function onLoginFailed() {
|
||||
root.busy = false
|
||||
root.message = "Login failed. Please try again."
|
||||
password.clear()
|
||||
password.forceActiveFocus()
|
||||
}
|
||||
function onLoginSucceeded() { root.message = "Welcome back!" }
|
||||
function onInformationMessage(message) { root.message = message }
|
||||
}
|
||||
|
||||
Image {
|
||||
id: wallpaper
|
||||
anchors.fill: parent
|
||||
source: "background.jpg"
|
||||
fillMode: Image.PreserveAspectCrop
|
||||
visible: false
|
||||
}
|
||||
MultiEffect {
|
||||
anchors.fill: parent
|
||||
source: wallpaper
|
||||
blurEnabled: true
|
||||
blurMax: 64
|
||||
blur: 1.0
|
||||
brightness: -0.2
|
||||
}
|
||||
Rectangle { anchors.fill: parent; color: "#30223638" }
|
||||
|
||||
component Card: Rectangle {
|
||||
radius: 25
|
||||
color: "#991c2827"
|
||||
}
|
||||
component LabelText: Text {
|
||||
color: root.cream
|
||||
font.family: face.name
|
||||
font.pixelSize: 20
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
component Action: Button {
|
||||
id: action
|
||||
property color fill: "#cda67d"
|
||||
font.family: face.name
|
||||
font.pixelSize: 18
|
||||
background: Rectangle {
|
||||
radius: 20
|
||||
color: action.down ? Qt.darker(action.fill, 1.2) : action.fill
|
||||
border.width: action.activeFocus ? 2 : 0
|
||||
border.color: root.cream
|
||||
opacity: action.enabled ? 1 : 0.5
|
||||
}
|
||||
contentItem: Text {
|
||||
text: action.text
|
||||
font: action.font
|
||||
color: root.dark
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
width: 760
|
||||
height: 650
|
||||
anchors.centerIn: parent
|
||||
scale: Math.min(1, root.width / 900, root.height / 780)
|
||||
|
||||
Card {
|
||||
width: 360; height: 380
|
||||
LabelText { x: 20; y: 32; width: 320; text: "NixOS · " + sddm.hostName; color: root.muted }
|
||||
LabelText { x: 20; y: 76; width: 320; text: "Log in"; font.pixelSize: 56 }
|
||||
|
||||
Rectangle {
|
||||
x: 20; y: 185; width: 320; height: 70; radius: 20; color: root.red
|
||||
LabelText { x: 18; y: 6; text: "Username"; color: root.dark; font.pixelSize: 14 }
|
||||
TextField {
|
||||
id: username
|
||||
x: 10; y: 25; width: 300; height: 40
|
||||
text: userModel.lastUser
|
||||
color: root.dark
|
||||
font.family: face.name; font.pixelSize: 28
|
||||
selectByMouse: true
|
||||
enabled: !root.busy
|
||||
background: Item {}
|
||||
onAccepted: password.forceActiveFocus()
|
||||
KeyNavigation.tab: password
|
||||
}
|
||||
}
|
||||
Rectangle {
|
||||
x: 20; y: 275; width: 320; height: 70; radius: 20; color: root.red
|
||||
LabelText { x: 18; y: 6; text: "Password"; color: root.dark; font.pixelSize: 14 }
|
||||
TextField {
|
||||
id: password
|
||||
x: 10; y: 25; width: 300; height: 40
|
||||
color: root.dark
|
||||
font.family: face.name; font.pixelSize: 28
|
||||
echoMode: TextInput.Password
|
||||
selectByMouse: true
|
||||
enabled: !root.busy
|
||||
background: Item {}
|
||||
onAccepted: root.login()
|
||||
KeyNavigation.tab: session
|
||||
KeyNavigation.backtab: username
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Card {
|
||||
y: 410; width: 360; height: 160
|
||||
LabelText { y: 4; width: 360; height: 116; text: Qt.formatDateTime(root.now, "HH:mm"); font.pixelSize: 96 }
|
||||
LabelText { y: 122; width: 360; text: "Welcome back"; color: root.muted; font.pixelSize: 18 }
|
||||
}
|
||||
|
||||
Card {
|
||||
x: 400; width: 360; height: 650
|
||||
Rectangle {
|
||||
x: 116; y: 26; width: 128; height: 128
|
||||
radius: 24; color: root.cream; border.width: 4; border.color: root.red
|
||||
Image { anchors.fill: parent; anchors.margins: 6; source: "avatar.png"; fillMode: Image.PreserveAspectFit }
|
||||
}
|
||||
LabelText { y: 168; width: 360; text: Qt.formatDateTime(root.now, "ddd").toUpperCase(); font.pixelSize: 56; font.bold: true }
|
||||
LabelText { y: 236; width: 360; text: Qt.formatDateTime(root.now, "dd MMMM, yyyy"); color: root.muted }
|
||||
}
|
||||
|
||||
Card {
|
||||
x: 400; y: 330; width: 360; height: 320; color: "#f01c1717"
|
||||
LabelText { y: 16; width: 360; text: "Desktop session"; color: root.muted; font.pixelSize: 16 }
|
||||
ComboBox {
|
||||
id: session
|
||||
x: 20; y: 48; width: 320; height: 42
|
||||
model: sessionModel
|
||||
textRole: "name"
|
||||
currentIndex: Math.max(0, sessionModel.lastIndex)
|
||||
enabled: !root.busy
|
||||
font.family: face.name; font.pixelSize: 18
|
||||
palette.button: "#332a29"
|
||||
palette.buttonText: root.cream
|
||||
palette.text: root.cream
|
||||
palette.base: root.dark
|
||||
palette.highlight: root.red
|
||||
KeyNavigation.tab: loginButton
|
||||
KeyNavigation.backtab: password
|
||||
}
|
||||
Row {
|
||||
x: 20; y: 112; spacing: 20
|
||||
Action { width: 150; height: 75; text: "Restart"; enabled: sddm.canReboot && !root.busy; onClicked: sddm.reboot() }
|
||||
Action { width: 150; height: 75; text: "Power off"; enabled: sddm.canPowerOff && !root.busy; onClicked: sddm.powerOff() }
|
||||
}
|
||||
Action {
|
||||
id: loginButton
|
||||
x: 20; y: 205; width: 320; height: 70
|
||||
fill: root.red
|
||||
text: root.busy ? "Logging in…" : "Log in"
|
||||
font.pixelSize: 30
|
||||
enabled: !root.busy && session.count > 0
|
||||
onClicked: root.login()
|
||||
KeyNavigation.tab: username
|
||||
KeyNavigation.backtab: session
|
||||
}
|
||||
LabelText {
|
||||
x: 12; y: 282; width: 336; height: 32
|
||||
text: root.message
|
||||
font.pixelSize: 12
|
||||
color: root.cream
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
if (username.text) password.forceActiveFocus()
|
||||
else username.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
9
sddm/metadata.desktop
Normal file
9
sddm/metadata.desktop
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
[SddmGreeterTheme]
|
||||
Name=Custom environment
|
||||
Description=Two-column login screen with ProFont and translucent cards
|
||||
Type=sddm-theme
|
||||
Version=1.0
|
||||
MainScript=Main.qml
|
||||
Theme-Id=custom-environment
|
||||
Theme-API=2.0
|
||||
QtVersion=6
|
||||
Loading…
Add table
Add a link
Reference in a new issue