4.8 KiB · text History e74691a
// Only QtQuick itself is imported: the greeter always has it, whereas
// QtQuick.Controls ships in a differently named package on every
// distribution and would make this package's dependencies guesswork.
import QtQuick 2.15

Rectangle {
    id: root

    readonly property color bg: config.background || "#651d1d"
    readonly property color fg: config.foreground || "#fef3c7"
    readonly property real unit: Math.max(12, height / 60)

    color: bg

    // Same choice the plymouth script makes: match the aspect ratio
    // first, then need the least scaling, preferring to shrink.
    function pickBackground() {
        var names = String(config.backgrounds || "").split(",")
        var best = ""
        var bestScore = Infinity
        for (var i = 0; i < names.length; i++) {
            var dims = names[i].trim().split("x")
            var w = Number(dims[0]), h = Number(dims[1])
            if (!(w > 0 && h > 0))
                continue
            var aspectErr = Math.abs(w / h - root.width / root.height)
            var scale = Math.max(root.width / w, root.height / h)
            var fit = scale > 1 ? (scale - 1) * 4 : 1 / scale - 1
            var score = aspectErr * 100 + fit
            if (score < bestScore) {
                best = names[i].trim()
                bestScore = score
            }
        }
        return best === "" ? "" : "backgrounds/" + best + ".png"
    }

    Image {
        anchors.fill: parent
        source: root.width > 0 && root.height > 0 ? root.pickBackground() : ""
        fillMode: Image.PreserveAspectCrop
        asynchronous: true
    }

    // Model data is only reachable through delegates, so session names
    // are mirrored here for the selector to read by index.
    Repeater {
        id: sessions
        model: sessionModel
        delegate: Item { property string sessionName: model.name }
    }

    property int sessionIndex: sessionModel.lastIndex >= 0 ? sessionModel.lastIndex : 0

    Connections {
        target: sddm
        function onLoginFailed() {
            password.text = ""
            error.text = "Login failed"
            password.forceActiveFocus()
        }
        function onLoginSucceeded() {
            error.text = ""
        }
    }

    function login() {
        error.text = ""
        sddm.login(user.text, password.text, root.sessionIndex)
    }

    Text {
        id: clock
        anchors { top: parent.top; right: parent.right; margins: root.unit * 2 }
        color: root.fg
        font.pixelSize: root.unit * 1.6
        text: Qt.formatTime(new Date(), "hh:mm")

        Timer {
            interval: 1000; running: true; repeat: true
            onTriggered: clock.text = Qt.formatTime(new Date(), "hh:mm")
        }
    }

    Column {
        anchors.centerIn: parent
        width: root.unit * 18
        spacing: root.unit

        Text {
            width: parent.width
            horizontalAlignment: Text.AlignHCenter
            color: root.fg
            font.pixelSize: root.unit * 1.4
            text: sddm.hostName
        }

        Field {
            id: user
            width: parent.width
            unit: root.unit
            fg: root.fg
            placeholder: "user"
            text: userModel.lastUser
            KeyNavigation.tab: password
            onAccepted: password.forceActiveFocus()
        }

        Field {
            id: password
            width: parent.width
            unit: root.unit
            fg: root.fg
            placeholder: "password"
            echoMode: TextInput.Password
            focus: true
            KeyNavigation.backtab: user
            onAccepted: root.login()
        }

        Text {
            id: error
            width: parent.width
            height: root.unit * 1.2
            horizontalAlignment: Text.AlignHCenter
            color: root.fg
            font.pixelSize: root.unit
        }
    }

    Row {
        anchors { bottom: parent.bottom; left: parent.left; right: parent.right; margins: root.unit * 2 }
        spacing: root.unit * 2
        layoutDirection: Qt.RightToLeft

        Action { label: "Power off"; unit: root.unit; fg: root.fg; visible: sddm.canPowerOff; onClicked: sddm.powerOff() }
        Action { label: "Reboot"; unit: root.unit; fg: root.fg; visible: sddm.canReboot; onClicked: sddm.reboot() }
        Action { label: "Suspend"; unit: root.unit; fg: root.fg; visible: sddm.canSuspend; onClicked: sddm.suspend() }
    }

    // Clicking cycles through sessions; there are rarely more than a few.
    Action {
        anchors { bottom: parent.bottom; left: parent.left; margins: root.unit * 2 }
        unit: root.unit
        fg: root.fg
        visible: sessions.count > 1
        label: sessions.count > 0 && sessions.itemAt(root.sessionIndex)
               ? sessions.itemAt(root.sessionIndex).sessionName : ""
        onClicked: root.sessionIndex = (root.sessionIndex + 1) % sessions.count
    }
}