diff --git a/.gitignore b/.gitignore index 4f0ebbb..f09bef4 100644 --- a/.gitignore +++ b/.gitignore @@ -231,3 +231,6 @@ cython_debug/ # option (not recommended) you can uncomment the following to ignore the entire idea folder. #.idea/ +# User-specific stuff +.idea + diff --git a/BreezeMenuStyle.qml b/BreezeMenuStyle.qml new file mode 100644 index 0000000..7d56c14 --- /dev/null +++ b/BreezeMenuStyle.qml @@ -0,0 +1,25 @@ +import QtQuick 2.2 + +import org.kde.plasma.core 2.0 as PlasmaCore + +import QtQuick.Controls.Styles 1.4 as QQCS +import QtQuick.Controls 1.3 as QQC + +QQCS.MenuStyle { + frame: Rectangle { + color: PlasmaCore.ColorScope.backgroundColor + border.color: Qt.tint(PlasmaCore.ColorScope.textColor, Qt.rgba(color.r, color.g, color.b, 0.7)) + border.width: 1 + } + itemDelegate.label: QQC.Label { + height: contentHeight * 1.2 + verticalAlignment: Text.AlignVCenter + color: styleData.selected ? PlasmaCore.ColorScope.highlightedTextColor : PlasmaCore.ColorScope.textColor + font.pointSize: config.fontSize + text: styleData.text + } + itemDelegate.background: Rectangle { + visible: styleData.selected + color: PlasmaCore.ColorScope.highlightColor + } +} diff --git a/KeyboardButton.qml b/KeyboardButton.qml new file mode 100644 index 0000000..d5d5a44 --- /dev/null +++ b/KeyboardButton.qml @@ -0,0 +1,37 @@ +import QtQuick 2.2 + +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.components 2.0 as PlasmaComponents // Because PC3 ToolButton can't take a menu + +import QtQuick.Controls 1.3 as QQC + +PlasmaComponents.ToolButton { + id: keyboardButton + + property int currentIndex: -1 + + text: i18nd("plasma_lookandfeel_org.kde.lookandfeel", "Keyboard Layout: %1", instantiator.objectAt(currentIndex).shortName) + implicitWidth: minimumWidth + + visible: menu.items.length > 1 + + Component.onCompleted: currentIndex = Qt.binding(function() {return keyboard.currentLayout}); + + menu: QQC.Menu { + id: keyboardMenu + style: BreezeMenuStyle {} + Instantiator { + id: instantiator + model: keyboard.layouts + onObjectAdded: keyboardMenu.insertItem(index, object) + onObjectRemoved: keyboardMenu.removeItem( object ) + delegate: QQC.MenuItem { + text: modelData.longName + property string shortName: modelData.shortName + onTriggered: { + keyboard.currentLayout = model.index + } + } + } + } +} diff --git a/Login.qml b/Login.qml new file mode 100644 index 0000000..5dc3f6a --- /dev/null +++ b/Login.qml @@ -0,0 +1,126 @@ +import "components" + +import QtQuick 2.0 +import QtQuick.Layouts 1.2 + +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.components 3.0 as PlasmaComponents3 + +SessionManagementScreen { + id: root + property Item mainPasswordBox: passwordBox + + property bool showUsernamePrompt: !showUserList + + property string lastUserName + property bool loginScreenUiVisible: false + + //the y position that should be ensured visible when the on screen keyboard is visible + property int visibleBoundary: mapFromItem(loginButton, 0, 0).y + onHeightChanged: visibleBoundary = mapFromItem(loginButton, 0, 0).y + loginButton.height + PlasmaCore.Units.smallSpacing + + property int fontSize: parseInt(config.fontSize) + 2 + + signal loginRequest(string username, string password) + + onShowUsernamePromptChanged: { + if (!showUsernamePrompt) { + lastUserName = "" + } + } + + /* + * Login has been requested with the following username and password + * If username field is visible, it will be taken from that, otherwise from the "name" property of the currentIndex + */ + function startLogin() { + var username = showUsernamePrompt ? userNameInput.text : userList.selectedUser + var password = passwordBox.text + + footer.enabled = false + mainStack.enabled = false + userListComponent.userList.opacity = 0.5 + + //this is partly because it looks nicer + //but more importantly it works round a Qt bug that can trigger if the app is closed with a TextField focused + //DAVE REPORT THE FRICKING THING AND PUT A LINK + loginButton.forceActiveFocus(); + loginRequest(username, password); + } + + PlasmaComponents3.TextField { + id: userNameInput + font.pointSize: fontSize + 1 + Layout.fillWidth: true + + text: lastUserName + visible: showUsernamePrompt + focus: showUsernamePrompt && !lastUserName //if there's a username prompt it gets focus first, otherwise password does + placeholderText: i18nd("plasma_lookandfeel_org.kde.lookandfeel", "Username") + + onAccepted: + if (root.loginScreenUiVisible) { + passwordBox.forceActiveFocus() + } + } + + RowLayout { + Layout.fillWidth: true + + PlasmaComponents3.TextField { + id: passwordBox + font.pointSize: fontSize + 1 + Layout.fillWidth: true + + placeholderText: i18nd("plasma_lookandfeel_org.kde.lookandfeel", "Password") + focus: !showUsernamePrompt || lastUserName + echoMode: TextInput.Password + revealPasswordButtonShown: false // Disabled whilst SDDM does not have the breeze icon set loaded + + onAccepted: { + if (root.loginScreenUiVisible) { + startLogin(); + } + } + + visible: root.showUsernamePrompt || userList.currentItem.needsPassword + + Keys.onEscapePressed: { + mainStack.currentItem.forceActiveFocus(); + } + + //if empty and left or right is pressed change selection in user switch + //this cannot be in keys.onLeftPressed as then it doesn't reach the password box + Keys.onPressed: { + if (event.key === Qt.Key_Left && !text) { + userList.decrementCurrentIndex(); + event.accepted = true + } + if (event.key === Qt.Key_Right && !text) { + userList.incrementCurrentIndex(); + event.accepted = true + } + } + + Connections { + target: sddm + function onLoginFailed() { + passwordBox.selectAll() + passwordBox.forceActiveFocus() + } + } + } + + PlasmaComponents3.Button { + id: loginButton + Accessible.name: i18nd("plasma_lookandfeel_org.kde.lookandfeel", "Log In") + Layout.preferredHeight: passwordBox.implicitHeight + Layout.preferredWidth: text.length == 0 ? loginButton.Layout.preferredHeight : -1 + + icon.name: text.length == 0 ? (root.LayoutMirroring.enabled ? "go-previous" : "go-next") : "" + + text: root.showUsernamePrompt || userList.currentItem.needsPassword ? "" : i18n("Log In") + onClicked: startLogin(); + } + } +} diff --git a/Main.qml b/Main.qml new file mode 100644 index 0000000..ac7e6b6 --- /dev/null +++ b/Main.qml @@ -0,0 +1,1011 @@ +import QtQuick.Controls 1.1 +import QtQuick.Controls 2.12 as QQC2 +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.components 3.0 as PlasmaComponents3 +import org.kde.plasma.extras 2.0 as PlasmaExtras +import QtGraphicalEffects 1.0 +import QtQuick.Layouts 1.1 + +import QtQuick 2.8 +import SddmComponents 2.0 +import QtMultimedia 5.7 + + +import "components" + +Rectangle { + // Main Container + id: container + + LayoutMirroring.enabled: Qt.locale().textDirection == Qt.RightToLeft + LayoutMirroring.childrenInherit: true + + property int sessionIndex: session.index + + // Inherited from SDDMComponents + TextConstants { + id: textConstants + } + + // Set SDDM actions + Connections { + target: sddm + onLoginSucceeded: { + } + + onLoginFailed: { + error_message.color = "#dc322f" + error_message.text = textConstants.loginFailed + } + } + + // Set Font + FontLoader { + id: textFont; name: config.displayFont + } + + // Background Fill + Rectangle { + anchors.fill: parent + color: "black" + } + + // Set Background Image + Image { + id: image1 + anchors.fill: parent + //source: config.background + fillMode: Image.PreserveAspectCrop + } + + // Set Background Video1 + MediaPlayer { + id: mediaplayer1 + autoPlay: true; muted: true + playlist: Playlist { + id: playlist1 + playbackMode: Playlist.Random + onLoaded: { mediaplayer1.play() } + } + } + + VideoOutput { + id: video1 + fillMode: VideoOutput.PreserveAspectCrop + anchors.fill: parent; source: mediaplayer1 + MouseArea { + id: mouseArea1 + anchors.fill: parent; + //onPressed: {playlist1.shuffle(); playlist1.next();} + onPressed: { + fader1.state = fader1.state == "off" ? "on" : "off" ; + if (config.autofocusInput == "true") { + if (username_input_box.text == "") + username_input_box.focus = true + else + password_input_box.focus = true + } + } + } + Keys.onPressed: { + fader1.state = "on"; + if (username_input_box.text == "") + username_input_box.focus = true + else + password_input_box.focus = true + } + } + WallpaperFader { + id: fader1 + visible: true + anchors.fill: parent + state: "off" + source: video1 + mainStack: login_container + footer: login_container + } + + // Set Background Video2 + MediaPlayer { + id: mediaplayer2 + autoPlay: true; muted: true + playlist: Playlist { + id: playlist2; playbackMode: Playlist.Random + //onLoaded: { mediaplayer2.play() } + } + } + + VideoOutput { + id: video2 + fillMode: VideoOutput.PreserveAspectCrop + anchors.fill: parent; source: mediaplayer2 + opacity: 0 + MouseArea { + id: mouseArea2 + enabled: false + anchors.fill: parent; + onPressed: { + fader1.state = fader1.state == "off" ? "on" : "off" ; + if (config.autofocusInput == "true") { + if (username_input_box.text == "") + username_input_box.focus = true + else + password_input_box.focus = true + } + } + } + Behavior on opacity { + enabled: true + NumberAnimation { easing.type: Easing.InOutQuad; duration: 3000 } + } + Keys.onPressed: { + fader2.state = "on"; + if (username_input_box.text == "") + username_input_box.focus = true + else + password_input_box.focus = true + } + } + + WallpaperFader { + id: fader2 + visible: true + anchors.fill: parent + state: "off" + source: video2 + mainStack: login_container + footer: login_container + } + + property MediaPlayer currentPlayer: mediaplayer1 + + // Timer event to handle fade between videos + Timer { + interval: 1000; + running: true; repeat: true + onTriggered: { + if (currentPlayer.duration != -1 && currentPlayer.position > currentPlayer.duration - 10000) { // pre load the 2nd player + if (video2.opacity == 0) { // toogle opacity + mediaplayer2.play() + } else + mediaplayer1.play() + } + if (currentPlayer.duration != -1 && currentPlayer.position > currentPlayer.duration - 3000) { // initiate transition + if (video2.opacity == 0) { // toogle opacity + mouseArea1.enabled = false + currentPlayer = mediaplayer2 + video2.opacity = 1 + triggerTimer.start() + mouseArea2.enabled = true + } else { + mouseArea2.enabled = false + currentPlayer = mediaplayer1 + video2.opacity = 0 + triggerTimer.start() + mouseArea1.enabled = true + } + } + } + } + + Timer { // this timer waits for fade to stop and stops the video + id: triggerTimer + interval: 4000; running: false; repeat: false + onTriggered: { + if (video2.opacity == 1) + mediaplayer1.stop() + else + mediaplayer2.stop() + } + } + + + + // Clock and Login Area + Rectangle { + id: rectangle + anchors.fill: parent + color: "transparent" + + MouseArea { + id: loginScreenRoot + anchors.fill: parent + + property bool uiVisible: true + property bool blockUI: mainStack.depth > 1 || userListComponent.mainPasswordBox.text.length > 0 || inputPanel.keyboardActive || config.type !== "image" + + hoverEnabled: true + drag.filterChildren: true + onPressed: uiVisible = true; + onPositionChanged: uiVisible = true; + onUiVisibleChanged: { + if (blockUI) { + fadeoutTimer.running = false; + } else if (uiVisible) { + fadeoutTimer.restart(); + } + } + onBlockUIChanged: { + if (blockUI) { + fadeoutTimer.running = false; + uiVisible = true; + } else { + fadeoutTimer.restart(); + } + } + + Keys.onPressed: { + uiVisible = true; + event.accepted = false; + } + + //takes one full minute for the ui to disappear + Timer { + id: fadeoutTimer + running: true + interval: 60000 + onTriggered: { + if (!loginScreenRoot.blockUI) { + loginScreenRoot.uiVisible = false; + } + } + } + + QQC2.StackView { + id: mainStack + anchors.fill: parent + height: root.height + PlasmaCore.Units.gridUnit * 3 + + // If true (depends on the style and environment variables), hover events are always accepted + // and propagation stopped. This means the parent MouseArea won't get them and the UI won't be shown. + // Disable capturing those events while the UI is hidden to avoid that, while still passing events otherwise. + // One issue is that while the UI is visible, mouse activity won't keep resetting the timer, but when it + // finally expires, the next event should immediately set uiVisible = true again. + hoverEnabled: loginScreenRoot.uiVisible ? undefined : false + + focus: true //StackView is an implicit focus scope, so we need to give this focus so the item inside will have it + + Timer { + //SDDM has a bug in 0.13 where even though we set the focus on the right item within the window, the window doesn't have focus + //it is fixed in 6d5b36b28907b16280ff78995fef764bb0c573db which will be 0.14 + //we need to call "window->activate()" *After* it's been shown. We can't control that in QML so we use a shoddy timer + //it's been this way for all Plasma 5.x without a huge problem + running: true + repeat: false + interval: 200 + onTriggered: mainStack.forceActiveFocus() + } + + initialItem: Login { + id: userListComponent + userListModel: userModel + loginScreenUiVisible: loginScreenRoot.uiVisible + userListCurrentIndex: userModel.lastIndex >= 0 ? userModel.lastIndex : 0 + lastUserName: userModel.lastUser + showUserList: { + if ( !userListModel.hasOwnProperty("count") + || !userListModel.hasOwnProperty("disableAvatarsThreshold")) + return (userList.y + mainStack.y) > 0 + + if ( userListModel.count === 0 ) return false + + if ( userListModel.hasOwnProperty("containsAllUsers") && !userListModel.containsAllUsers ) return false + + return userListModel.count <= userListModel.disableAvatarsThreshold && (userList.y + mainStack.y) > 0 + } + + notificationMessage: { + var text = "" + if (keystateSource.data["Caps Lock"]["Locked"]) { + text += i18nd("plasma_lookandfeel_org.kde.lookandfeel","Caps Lock is on") + if (root.notificationMessage) { + text += " • " + } + } + text += root.notificationMessage + return text + } + + actionItems: [ + ActionButton { + iconSource: "system-suspend" + text: i18ndc("plasma_lookandfeel_org.kde.lookandfeel","Suspend to RAM","Sleep") + fontSize: parseInt(config.fontSize) + 1 + onClicked: sddm.suspend() + enabled: sddm.canSuspend + visible: !inputPanel.keyboardActive + }, + ActionButton { + iconSource: "system-reboot" + text: i18nd("plasma_lookandfeel_org.kde.lookandfeel","Restart") + fontSize: parseInt(config.fontSize) + 1 + onClicked: sddm.reboot() + enabled: sddm.canReboot + visible: !inputPanel.keyboardActive + }, + ActionButton { + iconSource: "system-shutdown" + text: i18nd("plasma_lookandfeel_org.kde.lookandfeel","Shut Down") + fontSize: parseInt(config.fontSize) + 1 + onClicked: sddm.powerOff() + enabled: sddm.canPowerOff + visible: !inputPanel.keyboardActive + }, + ActionButton { + iconSource: "system-user-prompt" + text: i18ndc("plasma_lookandfeel_org.kde.lookandfeel", "For switching to a username and password prompt", "Other…") + fontSize: parseInt(config.fontSize) + 1 + onClicked: mainStack.push(userPromptComponent) + enabled: true + visible: !userListComponent.showUsernamePrompt && !inputPanel.keyboardActive + }] + + onLoginRequest: { + root.notificationMessage = "" + sddm.login(username, password, sessionButton.currentIndex) + } + } + + Behavior on opacity { + OpacityAnimator { + duration: PlasmaCore.Units.longDuration + } + } + + readonly property real zoomFactor: 3 + + popEnter: Transition { + ScaleAnimator { + from: mainStack.zoomFactor + to: 1 + duration: PlasmaCore.Units.longDuration * (mainStack.zoomFactor / 2) + easing.type: Easing.OutCubic + } + OpacityAnimator { + from: 0 + to: 1 + duration: PlasmaCore.Units.longDuration * (mainStack.zoomFactor / 2) + easing.type: Easing.OutCubic + } + } + + popExit: Transition { + ScaleAnimator { + from: 1 + to: 0 + duration: PlasmaCore.Units.longDuration * (mainStack.zoomFactor / 2) + easing.type: Easing.OutCubic + } + OpacityAnimator { + from: 1 + to: 0 + duration: PlasmaCore.Units.longDuration * (mainStack.zoomFactor / 2) + easing.type: Easing.OutCubic + } + } + + pushEnter: Transition { + ScaleAnimator { + from: 0 + to: 1 + duration: PlasmaCore.Units.longDuration * (mainStack.zoomFactor / 2) + easing.type: Easing.OutCubic + } + OpacityAnimator { + from: 0 + to: 1 + duration: PlasmaCore.Units.longDuration * (mainStack.zoomFactor / 2) + easing.type: Easing.OutCubic + } + } + + pushExit: Transition { + ScaleAnimator { + from: 1 + to: mainStack.zoomFactor + duration: PlasmaCore.Units.longDuration * (mainStack.zoomFactor / 2) + easing.type: Easing.OutCubic + } + OpacityAnimator { + from: 1 + to: 0 + duration: PlasmaCore.Units.longDuration * (mainStack.zoomFactor / 2) + easing.type: Easing.OutCubic + } + } + } + + Loader { + id: inputPanel + state: "hidden" + property bool keyboardActive: item ? item.active : false + onKeyboardActiveChanged: { + if (keyboardActive) { + state = "visible" + // Otherwise the password field loses focus and virtual keyboard + // keystrokes get eaten + userListComponent.mainPasswordBox.forceActiveFocus(); + } else { + state = "hidden"; + } + } + + source: Qt.platform.pluginName.includes("wayland") ? "components/VirtualKeyboard_wayland.qml" : "components/VirtualKeyboard.qml" + anchors { + left: parent.left + right: parent.right + } + + function showHide() { + state = state == "hidden" ? "visible" : "hidden"; + } + + states: [ + State { + name: "visible" + PropertyChanges { + target: mainStack + y: Math.min(0, root.height - inputPanel.height - userListComponent.visibleBoundary) + } + PropertyChanges { + target: inputPanel + y: root.height - inputPanel.height + opacity: 1 + } + }, + State { + name: "hidden" + PropertyChanges { + target: mainStack + y: 0 + } + PropertyChanges { + target: inputPanel + y: root.height - root.height/4 + opacity: 0 + } + } + ] + transitions: [ + Transition { + from: "hidden" + to: "visible" + SequentialAnimation { + ScriptAction { + script: { + inputPanel.item.activated = true; + Qt.inputMethod.show(); + } + } + ParallelAnimation { + NumberAnimation { + target: mainStack + property: "y" + duration: PlasmaCore.Units.longDuration + easing.type: Easing.InOutQuad + } + NumberAnimation { + target: inputPanel + property: "y" + duration: PlasmaCore.Units.longDuration + easing.type: Easing.OutQuad + } + OpacityAnimator { + target: inputPanel + duration: PlasmaCore.Units.longDuration + easing.type: Easing.OutQuad + } + } + } + }, + Transition { + from: "visible" + to: "hidden" + SequentialAnimation { + ParallelAnimation { + NumberAnimation { + target: mainStack + property: "y" + duration: PlasmaCore.Units.longDuration + easing.type: Easing.InOutQuad + } + NumberAnimation { + target: inputPanel + property: "y" + duration: PlasmaCore.Units.longDuration + easing.type: Easing.InQuad + } + OpacityAnimator { + target: inputPanel + duration: PlasmaCore.Units.longDuration + easing.type: Easing.InQuad + } + } + ScriptAction { + script: { + inputPanel.item.activated = false; + Qt.inputMethod.hide(); + } + } + } + } + ] + } + + + Component { + id: userPromptComponent + Login { + showUsernamePrompt: true + notificationMessage: root.notificationMessage + loginScreenUiVisible: loginScreenRoot.uiVisible + fontSize: parseInt(config.fontSize) + 2 + + // using a model rather than a QObject list to avoid QTBUG-75900 + userListModel: ListModel { + ListElement { + name: "" + iconSource: "" + } + Component.onCompleted: { + // as we can't bind inside ListElement + setProperty(0, "name", i18nd("plasma_lookandfeel_org.kde.lookandfeel", "Type in Username and Password")); + } + } + + onLoginRequest: { + root.notificationMessage = "" + sddm.login(username, password, sessionButton.currentIndex) + } + + actionItems: [ + ActionButton { + iconSource: "system-suspend" + text: i18ndc("plasma_lookandfeel_org.kde.lookandfeel","Suspend to RAM","Sleep") + fontSize: parseInt(config.fontSize) + 1 + onClicked: sddm.suspend() + enabled: sddm.canSuspend + visible: !inputPanel.keyboardActive + }, + ActionButton { + iconSource: "system-reboot" + text: i18nd("plasma_lookandfeel_org.kde.lookandfeel","Restart") + fontSize: parseInt(config.fontSize) + 1 + onClicked: sddm.reboot() + enabled: sddm.canReboot + visible: !inputPanel.keyboardActive + }, + ActionButton { + iconSource: "system-shutdown" + text: i18nd("plasma_lookandfeel_org.kde.lookandfeel","Shut Down") + fontSize: parseInt(config.fontSize) + 1 + onClicked: sddm.powerOff() + enabled: sddm.canPowerOff + visible: !inputPanel.keyboardActive + }, + ActionButton { + iconSource: "system-user-list" + text: i18nd("plasma_lookandfeel_org.kde.lookandfeel","List Users") + fontSize: parseInt(config.fontSize) + 1 + onClicked: mainStack.pop() + visible: !inputPanel.keyboardActive + } + ] + } + } + + DropShadow { + id: logoShadow + anchors.fill: logo + source: logo + visible: !softwareRendering && config.showlogo == "shown" + horizontalOffset: 1 + verticalOffset: 1 + radius: 6 + samples: 14 + spread: 0.3 + color : "black" // shadows should always be black + opacity: loginScreenRoot.uiVisible ? 0 : 1 + Behavior on opacity { + //OpacityAnimator when starting from 0 is buggy (it shows one frame with opacity 1)" + NumberAnimation { + duration: PlasmaCore.Units.longDuration + easing.type: Easing.InOutQuad + } + } + } + + Image { + id: logo + visible: config.showlogo == "shown" + source: config.logo + anchors.horizontalCenter: parent.horizontalCenter + anchors.bottom: footer.top + anchors.bottomMargin: PlasmaCore.Units.largeSpacing + asynchronous: true + sourceSize.height: height + opacity: loginScreenRoot.uiVisible ? 0 : 1 + fillMode: Image.PreserveAspectFit + height: Math.round(PlasmaCore.Units.gridUnit * 3.5) + Behavior on opacity { + // OpacityAnimator when starting from 0 is buggy (it shows one frame with opacity 1)" + NumberAnimation { + duration: PlasmaCore.Units.longDuration + easing.type: Easing.InOutQuad + } + } + } + + //Footer + RowLayout { + id: footer + anchors { + bottom: parent.bottom + left: parent.left + right: parent.right + margins: PlasmaCore.Units.smallSpacing + } + + Behavior on opacity { + OpacityAnimator { + duration: PlasmaCore.Units.longDuration + } + } + + PlasmaComponents3.ToolButton { + text: i18ndc("plasma_lookandfeel_org.kde.lookandfeel", "Button to show/hide virtual keyboard", "Virtual Keyboard") + font.pointSize: config.fontSize + icon.name: inputPanel.keyboardActive ? "input-keyboard-virtual-on" : "input-keyboard-virtual-off" + onClicked: inputPanel.showHide() + visible: inputPanel.status == Loader.Ready + } + + KeyboardButton { + font.pointSize: config.fontSize + } + + SessionButton { + id: sessionButton + font.pointSize: config.fontSize + } + + Item { + Layout.fillWidth: true + } + + Battery { + fontSize: config.fontSize + } + } + } + + Clock { + id: clock + y: parent.height * config.relativePositionY - clock.height / 2 + x: parent.width * config.relativePositionX - clock.width / 2 + color: "white" + timeFont.family: textFont.name + dateFont.family: textFont.name + } + + Rectangle { + id: login_container + + //y: parent.height * 0.8 + y: clock.y + clock.height + 30 + width: clock.width + height: parent.height * 0.08 + color: "transparent" + anchors.left: clock.left + + Rectangle { + id: username_row + height: parent.height * 0.36 + color: "transparent" + anchors.left: parent.left + anchors.leftMargin: 0 + anchors.right: parent.right + anchors.rightMargin: 0 + transformOrigin: Item.Center + anchors.margins: 10 + + Text { + id: username_label + width: parent.width * 0.27 + height: parent.height * 0.66 + horizontalAlignment: Text.AlignLeft + font.family: textFont.name + font.bold: true + font.pixelSize: 16 + color: "white" + text: "Username" + anchors.verticalCenter: parent.verticalCenter + } + + TextBox { + id: username_input_box + height: parent.height + text: userModel.lastUser + anchors.verticalCenter: parent.verticalCenter + anchors.left: username_label.right + anchors.leftMargin: config.usernameLeftMargin + anchors.right: parent.right + anchors.rightMargin: 0 + font: textFont.name + color: "#25000000" + borderColor: "transparent" + textColor: "white" + + Keys.onPressed: { + if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) { + sddm.login(username_input_box.text, password_input_box.text, session.index) + event.accepted = true + } + } + + KeyNavigation.backtab: password_input_box + KeyNavigation.tab: password_input_box + } + } + + Rectangle { + id: password_row + y: username_row.height + 10 + height: parent.height * 0.36 + color: "transparent" + anchors.right: parent.right + anchors.rightMargin: 0 + anchors.left: parent.left + anchors.leftMargin: 0 + + Text { + id: password_label + width: parent.width * 0.27 + text: textConstants.password + anchors.verticalCenter: parent.verticalCenter + horizontalAlignment: Text.AlignLeft + font.family: textFont.name + font.bold: true + font.pixelSize: 16 + color: "white" + } + + PasswordBox { + id: password_input_box + height: parent.height + font: textFont.name + color: "#25000000" + anchors.verticalCenter: parent.verticalCenter + anchors.right: parent.right + anchors.rightMargin: parent.height // this sets button width, this way its a square + anchors.left: password_label.right + anchors.leftMargin: config.passwordLeftMargin + borderColor: "transparent" + textColor: "white" + tooltipBG: "#25000000" + tooltipFG: "#dc322f" + image: "components/resources/warning_red.png" + onTextChanged: { + if (password_input_box.text == "") { + clear_passwd_button.visible = false + } + if (password_input_box.text != "" && config.showClearPasswordButton != "false") { + clear_passwd_button.visible = true + } + } + + Keys.onPressed: { + if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) { + sddm.login(username_input_box.text, password_input_box.text, session.index) + event.accepted = true + } + } + + KeyNavigation.backtab: username_input_box + KeyNavigation.tab: login_button + } + + Button { + id: clear_passwd_button + height: parent.height + width: parent.height + color: "transparent" + text: "x" + font: textFont.name + + border.color: "transparent" + border.width: 0 + anchors.verticalCenter: parent.verticalCenter + anchors.right: parent.right + anchors.leftMargin: 0 + anchors.rightMargin: parent.height + + disabledColor: "#dc322f" + activeColor: "#393939" + pressedColor: "#2aa198" + + onClicked: { + password_input_box.text='' + password_input_box.focus = true + } + } + + Button { + id: login_button + height: parent.height + color: "#393939" + text: ">" + border.color: "#00000000" + anchors.verticalCenter: parent.verticalCenter + anchors.left: password_input_box.right + anchors.right: parent.right + disabledColor: "#dc322f" + activeColor: "#268bd2" + pressedColor: "#2aa198" + textColor: "white" + font: textFont.name + + onClicked: sddm.login(username_input_box.text, password_input_box.text, session.index) + + KeyNavigation.backtab: password_input_box + KeyNavigation.tab: reboot_button + } + + Text { + id: error_message + height: parent.height + font.family: textFont.name + font.pixelSize: 12 + color: "white" + anchors.top: password_input_box.bottom + anchors.left: password_input_box.left + anchors.leftMargin: 0 + } + } + + } + } + + // Top Bar + Rectangle { + id: actionBar + width: parent.width + height: parent.height * 0.04 + anchors.top: parent.top; + anchors.horizontalCenter: parent.horizontalCenter + color: "transparent" + visible: config.showTopBar != "false" + + Row { + id: row_left + anchors.left: parent.left + anchors.margins: 5 + height: parent.height + spacing: 10 + + ComboBox { + id: session + width: 145 + height: 20 + anchors.verticalCenter: parent.verticalCenter + color: "transparent" + arrowColor: "transparent" + textColor: "#505050" + borderColor: "transparent" + hoverColor: "#5692c4" + + model: sessionModel + index: sessionModel.lastIndex + + KeyNavigation.backtab: shutdown_button + KeyNavigation.tab: password_input_box + } + + ComboBox { + id: language + + model: keyboard.layouts + index: keyboard.currentLayout + width: 50 + height: 20 + anchors.verticalCenter: parent.verticalCenter + color: "transparent" + arrowColor: "transparent" + textColor: "white" + borderColor: "transparent" + hoverColor: "#5692c4" + + onValueChanged: keyboard.currentLayout = id + + Connections { + target: keyboard + + onCurrentLayoutChanged: combo.index = keyboard.currentLayout + } + + rowDelegate: Rectangle { + color: "transparent" + + Text { + anchors.margins: 4 + anchors.top: parent.top + anchors.bottom: parent.bottom + + verticalAlignment: Text.AlignVCenter + + text: modelItem ? modelItem.modelData.shortName : "zz" + font.family: textFont.name + font.pixelSize: 14 + //color: "white" + color: "#505050" + } + } + KeyNavigation.backtab: session + KeyNavigation.tab: username_input_box + } + } + + Row { + id: row_right + height: parent.height + anchors.right: parent.right + anchors.margins: 5 + spacing: 10 + + ImageButton { + id: reboot_button + height: parent.height + source: "components/resources/reboot.svg" + + visible: sddm.canReboot + onClicked: sddm.reboot() + KeyNavigation.backtab: login_button + KeyNavigation.tab: shutdown_button + } + + ImageButton { + id: shutdown_button + height: parent.height + source: "components/resources/shutdown.svg" + visible: sddm.canPowerOff + onClicked: sddm.powerOff() + KeyNavigation.backtab: reboot_button + KeyNavigation.tab: session + } + } + } + + Component.onCompleted: { + // Set Focus + /* if (username_input_box.text == "") */ + /* username_input_box.focus = true */ + /* else */ + /* password_input_box.focus = true */ + + video1.focus = true + + // load and randomize playlist + var time = parseInt(new Date().toLocaleTimeString(Qt.locale(),'h')) + if ( time >= 5 && time <= 17 ) { + playlist1.load(Qt.resolvedUrl(config.background_vid_day), 'm3u') + playlist2.load(Qt.resolvedUrl(config.background_vid_day), 'm3u') + image1.source = config.background_img_day + } else { + playlist1.load(Qt.resolvedUrl(config.background_vid_night), 'm3u') + playlist2.load(Qt.resolvedUrl(config.background_vid_night), 'm3u') + image1.source = config.background_img_night + } + + for (var k = 0; k < Math.ceil(Math.random() * 10) ; k++) { + playlist1.shuffle() + playlist2.shuffle() + } + + if (config.showLoginButton == "false") { + login_button.visible = false + password_input_box.anchors.rightMargin = 0 + clear_passwd_button.anchors.rightMargin = 0 + } + clear_passwd_button.visible = false + } +} diff --git a/SessionButton.qml b/SessionButton.qml new file mode 100644 index 0000000..8cb56ba --- /dev/null +++ b/SessionButton.qml @@ -0,0 +1,44 @@ +/* + SPDX-FileCopyrightText: 2016 David Edmundson + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ + +import QtQuick 2.2 + +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.components 2.0 as PlasmaComponents // Because PC3 ToolButton can't take a menu + +import QtQuick.Controls 1.3 as QQC + +PlasmaComponents.ToolButton { + id: root + property int currentIndex: -1 + + implicitWidth: minimumWidth + + visible: menu.items.length > 1 + + text: i18nd("plasma_lookandfeel_org.kde.lookandfeel", "Desktop Session: %1", instantiator.objectAt(currentIndex).text || "") + + Component.onCompleted: { + currentIndex = sessionModel.lastIndex + } + + menu: QQC.Menu { + id: menu + style: BreezeMenuStyle {} + Instantiator { + id: instantiator + model: sessionModel + onObjectAdded: menu.insertItem(index, object) + onObjectRemoved: menu.removeItem( object ) + delegate: QQC.MenuItem { + text: model.name + onTriggered: { + root.currentIndex = model.index + } + } + } + } +} diff --git a/background.jpg b/background.jpg new file mode 100644 index 0000000..14d36e8 Binary files /dev/null and b/background.jpg differ diff --git a/components/ActionButton.qml b/components/ActionButton.qml new file mode 100644 index 0000000..af278f6 --- /dev/null +++ b/components/ActionButton.qml @@ -0,0 +1,115 @@ +/* + SPDX-FileCopyrightText: 2016 David Edmundson + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ + +import QtQuick 2.8 +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.components 3.0 as PlasmaComponents3 + +Item { + id: root + property alias text: label.text + property alias iconSource: icon.source + property alias containsMouse: mouseArea.containsMouse + property alias font: label.font + property alias labelRendering: label.renderType + property alias circleOpacity: iconCircle.opacity + property alias circleVisiblity: iconCircle.visible + property int fontSize: PlasmaCore.Theme.defaultFont.pointSize + 1 + readonly property bool softwareRendering: GraphicsInfo.api === GraphicsInfo.Software + signal clicked + + activeFocusOnTab: true + + property int iconSize: PlasmaCore.Units.gridUnit * 3 + + implicitWidth: Math.max(iconSize + PlasmaCore.Units.largeSpacing * 2, label.contentWidth) + implicitHeight: iconSize + PlasmaCore.Units.smallSpacing + label.implicitHeight + + opacity: activeFocus || containsMouse ? 1 : 0.85 + Behavior on opacity { + PropertyAnimation { // OpacityAnimator makes it turn black at random intervals + duration: PlasmaCore.Units.longDuration + easing.type: Easing.InOutQuad + } + } + + Rectangle { + id: iconCircle + anchors.centerIn: icon + width: iconSize + PlasmaCore.Units.smallSpacing + height: width + radius: width / 2 + color: softwareRendering ? PlasmaCore.ColorScope.backgroundColor : PlasmaCore.ColorScope.textColor + opacity: root.activeFocus || containsMouse ? (softwareRendering ? 0.8 : 0.15) : (softwareRendering ? 0.6 : 0) + Behavior on opacity { + PropertyAnimation { // OpacityAnimator makes it turn black at random intervals + duration: PlasmaCore.Units.longDuration + easing.type: Easing.InOutQuad + } + } + } + + Rectangle { + anchors.centerIn: iconCircle + width: iconCircle.width + height: width + radius: width / 2 + scale: mouseArea.containsPress ? 1 : 0 + color: PlasmaCore.ColorScope.textColor + opacity: 0.15 + Behavior on scale { + PropertyAnimation { + duration: PlasmaCore.Units.shortDuration + easing.type: Easing.InOutQuart + } + } + } + + PlasmaCore.IconItem { + id: icon + anchors { + top: parent.top + horizontalCenter: parent.horizontalCenter + } + width: iconSize + height: iconSize + + colorGroup: PlasmaCore.ColorScope.colorGroup + active: mouseArea.containsMouse || root.activeFocus + } + + PlasmaComponents3.Label { + id: label + font.pointSize: root.fontSize + anchors { + top: icon.bottom + topMargin: (softwareRendering ? 1.5 : 1) * PlasmaCore.Units.smallSpacing + left: parent.left + right: parent.right + } + style: softwareRendering ? Text.Outline : Text.Normal + styleColor: softwareRendering ? PlasmaCore.ColorScope.backgroundColor : "transparent" //no outline, doesn't matter + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignTop + wrapMode: Text.WordWrap + font.underline: root.activeFocus + } + + MouseArea { + id: mouseArea + hoverEnabled: true + onClicked: root.clicked() + anchors.fill: parent + } + + Keys.onEnterPressed: clicked() + Keys.onReturnPressed: clicked() + Keys.onSpacePressed: clicked() + + Accessible.onPressAction: clicked() + Accessible.role: Accessible.Button + Accessible.name: label.text +} diff --git a/components/Battery.qml b/components/Battery.qml new file mode 100644 index 0000000..05be535 --- /dev/null +++ b/components/Battery.qml @@ -0,0 +1,43 @@ +/* + SPDX-FileCopyrightText: 2016 Kai Uwe Broulik + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ + +import QtQuick 2.2 + +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.components 3.0 as PlasmaComponents3 +import org.kde.plasma.workspace.components 2.0 as PW + +Row { + id: row + + property int fontSize: PlasmaCore.Theme.defaultFont.pointSize + + spacing: PlasmaCore.Units.smallSpacing + visible: pmSource.data["Battery"]["Has Cumulative"] + + PlasmaCore.DataSource { + id: pmSource + engine: "powermanagement" + connectedSources: ["Battery", "AC Adapter"] + } + + PW.BatteryIcon { + id: battery + hasBattery: pmSource.data["Battery"]["Has Battery"] || false + percent: pmSource.data["Battery"]["Percent"] || 0 + pluggedIn: pmSource.data["AC Adapter"] ? pmSource.data["AC Adapter"]["Plugged in"] : false + + height: batteryLabel.height + width: height + } + + PlasmaComponents3.Label { + id: batteryLabel + font.pointSize: row.fontSize + text: i18nd("plasma_lookandfeel_org.kde.lookandfeel","%1%", battery.percent) + Accessible.name: i18nd("plasma_lookandfeel_org.kde.lookandfeel","Battery at %1%", battery.percent) + } +} diff --git a/components/SessionManagementScreen.qml b/components/SessionManagementScreen.qml new file mode 100644 index 0000000..ac4baaf --- /dev/null +++ b/components/SessionManagementScreen.qml @@ -0,0 +1,109 @@ +/* + SPDX-FileCopyrightText: 2016 David Edmundson + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ + +import QtQuick 2.2 + +import QtQuick.Layouts 1.1 +import QtQuick.Controls 1.1 + +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.components 3.0 as PlasmaComponents3 + +FocusScope { + id: root + + /* + * Any message to be displayed to the user, visible above the text fields + */ + property alias notificationMessage: notificationsLabel.text + + /* + * A list of Items (typically ActionButtons) to be shown in a Row beneath the prompts + */ + property alias actionItems: actionItemsLayout.children + + /* + * A model with a list of users to show in the view + * The following roles should exist: + * - name + * - iconSource + * + * The following are also handled: + * - vtNumber + * - displayNumber + * - session + * - isTty + */ + property alias userListModel: userListView.model + + /* + * Self explanatory + */ + property alias userListCurrentIndex: userListView.currentIndex + property alias userListCurrentItem: userListView.currentItem + property bool showUserList: true + + property alias userList: userListView + + property int fontSize: PlasmaCore.Theme.defaultFont.pointSize + 2 + + default property alias _children: innerLayout.children + + UserList { + id: userListView + visible: showUserList && y > 0 + anchors { + bottom: parent.verticalCenter + left: parent.left + right: parent.right + } + fontSize: root.fontSize + } + + //goal is to show the prompts, in ~16 grid units high, then the action buttons + //but collapse the space between the prompts and actions if there's no room + //ui is constrained to 16 grid units wide, or the screen + ColumnLayout { + id: prompts + anchors.top: parent.verticalCenter + anchors.topMargin: PlasmaCore.Units.gridUnit * 0.5 + anchors.left: parent.left + anchors.right: parent.right + anchors.bottom: parent.bottom + PlasmaComponents3.Label { + id: notificationsLabel + font.pointSize: root.fontSize + Layout.maximumWidth: PlasmaCore.Units.gridUnit * 16 + Layout.alignment: Qt.AlignHCenter + Layout.fillWidth: true + horizontalAlignment: Text.AlignHCenter + wrapMode: Text.WordWrap + font.italic: true + } + ColumnLayout { + Layout.minimumHeight: implicitHeight + Layout.maximumHeight: PlasmaCore.Units.gridUnit * 10 + Layout.maximumWidth: PlasmaCore.Units.gridUnit * 16 + Layout.alignment: Qt.AlignHCenter + ColumnLayout { + id: innerLayout + Layout.alignment: Qt.AlignHCenter + Layout.fillWidth: true + } + Item { + Layout.fillHeight: true + } + } + Row { //deliberately not rowlayout as I'm not trying to resize child items + id: actionItemsLayout + spacing: PlasmaCore.Units.largeSpacing / 2 + Layout.alignment: Qt.AlignHCenter | Qt.AlignTop + } + Item { + Layout.fillHeight: true + } + } +} diff --git a/components/UserDelegate.qml b/components/UserDelegate.qml new file mode 100644 index 0000000..9a823a2 --- /dev/null +++ b/components/UserDelegate.qml @@ -0,0 +1,180 @@ +/* + SPDX-FileCopyrightText: 2014 David Edmundson + SPDX-FileCopyrightText: 2014 Aleix Pol Gonzalez + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ + +import QtQuick 2.8 +import QtQuick.Window 2.15 +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.components 3.0 as PlasmaComponents3 + +Item { + id: wrapper + + // If we're using software rendering, draw outlines instead of shadows + // See https://bugs.kde.org/show_bug.cgi?id=398317 + readonly property bool softwareRendering: GraphicsInfo.api === GraphicsInfo.Software + + property bool isCurrent: true + + property string name + property string userName + property string avatarPath + property string iconSource + property bool needsPassword + property var vtNumber + property bool constrainText: true + property alias nameFontSize: usernameDelegate.font.pointSize + property int fontSize: PlasmaCore.Theme.defaultFont.pointSize + 2 + signal clicked() + + property real faceSize: PlasmaCore.Units.gridUnit * 7 + + opacity: isCurrent ? 1.0 : 0.5 + + Behavior on opacity { + OpacityAnimator { + duration: PlasmaCore.Units.longDuration + } + } + + // Draw a translucent background circle under the user picture + Rectangle { + anchors.centerIn: imageSource + width: imageSource.width - 2 // Subtract to prevent fringing + height: width + radius: width / 2 + + color: PlasmaCore.ColorScope.backgroundColor + opacity: 0.6 + } + + Item { + id: imageSource + anchors { + bottom: usernameDelegate.top + bottomMargin: PlasmaCore.Units.largeSpacing + horizontalCenter: parent.horizontalCenter + } + Behavior on width { + PropertyAnimation { + from: faceSize + duration: PlasmaCore.Units.longDuration; + } + } + width: isCurrent ? faceSize : faceSize - PlasmaCore.Units.largeSpacing + height: width + + //Image takes priority, taking a full path to a file, if that doesn't exist we show an icon + Image { + id: face + source: wrapper.avatarPath + sourceSize: Qt.size(faceSize * Screen.devicePixelRatio, faceSize * Screen.devicePixelRatio) + fillMode: Image.PreserveAspectCrop + anchors.fill: parent + } + + PlasmaCore.IconItem { + id: faceIcon + source: iconSource + visible: (face.status == Image.Error || face.status == Image.Null) + anchors.fill: parent + anchors.margins: PlasmaCore.Units.gridUnit * 0.5 // because mockup says so... + colorGroup: PlasmaCore.ColorScope.colorGroup + } + } + + ShaderEffect { + anchors { + bottom: usernameDelegate.top + bottomMargin: PlasmaCore.Units.largeSpacing + horizontalCenter: parent.horizontalCenter + } + + width: imageSource.width + height: imageSource.height + + supportsAtlasTextures: true + + property var source: ShaderEffectSource { + sourceItem: imageSource + // software rendering is just a fallback so we can accept not having a rounded avatar here + hideSource: wrapper.GraphicsInfo.api !== GraphicsInfo.Software + live: true // otherwise the user in focus will show a blurred avatar + } + + property var colorBorder: PlasmaCore.ColorScope.textColor + + //draw a circle with an antialiased border + //innerRadius = size of the inner circle with contents + //outerRadius = size of the border + //blend = area to blend between two colours + //all sizes are normalised so 0.5 == half the width of the texture + + //if copying into another project don't forget to connect themeChanged to update() + //but in SDDM that's a bit pointless + fragmentShader: " + varying highp vec2 qt_TexCoord0; + uniform highp float qt_Opacity; + uniform lowp sampler2D source; + + uniform lowp vec4 colorBorder; + highp float blend = 0.01; + highp float innerRadius = 0.47; + highp float outerRadius = 0.49; + lowp vec4 colorEmpty = vec4(0.0, 0.0, 0.0, 0.0); + + void main() { + lowp vec4 colorSource = texture2D(source, qt_TexCoord0.st); + + highp vec2 m = qt_TexCoord0 - vec2(0.5, 0.5); + highp float dist = sqrt(m.x * m.x + m.y * m.y); + + if (dist < innerRadius) + gl_FragColor = colorSource; + else if (dist < innerRadius + blend) + gl_FragColor = mix(colorSource, colorBorder, ((dist - innerRadius) / blend)); + else if (dist < outerRadius) + gl_FragColor = colorBorder; + else if (dist < outerRadius + blend) + gl_FragColor = mix(colorBorder, colorEmpty, ((dist - outerRadius) / blend)); + else + gl_FragColor = colorEmpty ; + + gl_FragColor = gl_FragColor * qt_Opacity; + } + " + } + + PlasmaComponents3.Label { + id: usernameDelegate + + // Make it bigger than other fonts to match the scale of the avatar better + font.pointSize: wrapper.fontSize + 4 + anchors { + bottom: parent.bottom + horizontalCenter: parent.horizontalCenter + } + width: constrainText ? parent.width : implicitWidth + text: wrapper.name + style: softwareRendering ? Text.Outline : Text.Normal + styleColor: softwareRendering ? PlasmaCore.ColorScope.backgroundColor : "transparent" //no outline, doesn't matter + elide: Text.ElideRight + horizontalAlignment: Text.AlignHCenter + //make an indication that this has active focus, this only happens when reached with keyboard navigation + font.underline: wrapper.activeFocus + } + + MouseArea { + anchors.fill: parent + hoverEnabled: true + + onClicked: wrapper.clicked(); + } + + Accessible.name: name + Accessible.role: Accessible.Button + function accessiblePressAction() { wrapper.clicked() } +} diff --git a/components/UserList.qml b/components/UserList.qml new file mode 100644 index 0000000..49f38eb --- /dev/null +++ b/components/UserList.qml @@ -0,0 +1,88 @@ +/* + SPDX-FileCopyrightText: 2014 David Edmundson + + SPDX-License-Identifier: LGPL-2.0-or-later +*/ + +import QtQuick 2.2 +import org.kde.plasma.core 2.0 as PlasmaCore + +ListView { + id: view + readonly property string selectedUser: currentItem ? currentItem.userName : "" + readonly property int userItemWidth: PlasmaCore.Units.gridUnit * 8 + readonly property int userItemHeight: PlasmaCore.Units.gridUnit * 8 + property int fontSize: PlasmaCore.Theme.defaultFont.pointSize + 2 + + implicitHeight: userItemHeight + + activeFocusOnTab : true + + /* + * Signals that a user was explicitly selected + */ + signal userSelected; + + orientation: ListView.Horizontal + highlightRangeMode: ListView.StrictlyEnforceRange + + //centre align selected item (which implicitly centre aligns the rest + preferredHighlightBegin: width/2 - userItemWidth/2 + preferredHighlightEnd: preferredHighlightBegin + + // Disable flicking if we only have on user (like on the lockscreen) + interactive: count > 1 + + delegate: UserDelegate { + avatarPath: model.icon || "" + iconSource: model.iconName || "user-identity" + fontSize: view.fontSize + vtNumber: model.vtNumber + needsPassword: model.needsPassword + + name: { + var displayName = model.realName || model.name + + if (model.vtNumber === undefined || model.vtNumber < 0) { + return displayName + } + + if (!model.session) { + return i18ndc("plasma_lookandfeel_org.kde.lookandfeel", "Nobody logged in on that session", "Unused") + } + + + var location = "" + if (model.isTty) { + location = i18ndc("plasma_lookandfeel_org.kde.lookandfeel", "User logged in on console number", "TTY %1", model.vtNumber) + } else if (model.displayNumber) { + location = i18ndc("plasma_lookandfeel_org.kde.lookandfeel", "User logged in on console (X display number)", "on TTY %1 (Display %2)", model.vtNumber, model.displayNumber) + } + + if (location) { + return i18ndc("plasma_lookandfeel_org.kde.lookandfeel", "Username (location)", "%1 (%2)", displayName, location) + } + + return displayName + } + + userName: model.name + + width: userItemWidth + height: userItemHeight + + //if we only have one delegate, we don't need to clip the text as it won't be overlapping with anything + constrainText: ListView.view.count > 1 + + isCurrent: ListView.isCurrentItem + + onClicked: { + ListView.view.currentIndex = index; + ListView.view.userSelected(); + } + } + + Keys.onEscapePressed: view.userSelected() + Keys.onEnterPressed: view.userSelected() + Keys.onReturnPressed: view.userSelected() +} diff --git a/components/VirtualKeyboard.qml b/components/VirtualKeyboard.qml new file mode 100644 index 0000000..503a35b --- /dev/null +++ b/components/VirtualKeyboard.qml @@ -0,0 +1,70 @@ +/* + SPDX-FileCopyrightText: 2017 Martin Gräßlin + + SPDX-License-Identifier: GPL-2.0-or-later +*/ + +import QtQuick 2.5 +import QtQuick.VirtualKeyboard 2.1 +import org.kde.plasma.core 2.0 as PlasmaCore + +InputPanel { + id: inputPanel + property bool activated: false + active: activated && Qt.inputMethod.visible + width: parent.width + + states: [ + State { + name: "visible" + when: inputPanel.active + PropertyChanges { + target: inputPanel + y: inputPanel.parent.height - inputPanel.height + opacity: 1 + visible: true + } + }, + State { + name: "hidden" + when: !inputPanel.active + PropertyChanges { + target: inputPanel + y: inputPanel.parent.height + opacity: 0 + visible:false + } + } + ] + + transitions: [ + Transition { + to: "visible" + ParallelAnimation { + YAnimator { + // NOTE this is necessary as otherwise the keyboard always starts the transition with Y as 0, due to the internal reparenting happening when becomes active + from: inputPanel.parent.height + duration: PlasmaCore.Units.longDuration + easing.type: Easing.OutQuad + } + OpacityAnimator { + duration: PlasmaCore.Units.longDuration + easing.type: Easing.OutQuad + } + } + }, + Transition { + to: "hidden" + ParallelAnimation { + YAnimator { + duration: PlasmaCore.Units.longDuration + easing.type: Easing.InQuad + } + OpacityAnimator { + duration: PlasmaCore.Units.longDuration + easing.type: Easing.InQuad + } + } + } + ] +} diff --git a/components/WallpaperFader.qml b/components/WallpaperFader.qml new file mode 100644 index 0000000..7369c49 --- /dev/null +++ b/components/WallpaperFader.qml @@ -0,0 +1,161 @@ +/******************************************************************** + This file is part of the KDE project. + +Copyright (C) 2014 Aleix Pol Gonzalez + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ + +import QtQuick 2.6 +import QtQuick.Controls 1.1 +import QtQuick.Layouts 1.1 +import QtGraphicalEffects 1.0 + +Item { + id: wallpaperFader + property Item mainStack + property Item footer + property alias source: wallpaperBlur.source + state: lockScreenRoot.uiVisible ? "on" : "off" + property real factor: 20 + + Behavior on factor { + NumberAnimation { + target: wallpaperFader + property: "factor" + duration: 1000 + easing.type: Easing.InOutQuad + } + } + FastBlur { + id: wallpaperBlur + anchors.fill: parent + radius: 50 * wallpaperFader.factor + } + ShaderEffect { + id: wallpaperShader + anchors.fill: parent + supportsAtlasTextures: true + property var source: ShaderEffectSource { + sourceItem: wallpaperBlur + live: true + hideSource: true + textureMirroring: ShaderEffectSource.NoMirroring + } + + readonly property real contrast: 0.45 * wallpaperFader.factor + (1 - wallpaperFader.factor) + readonly property real saturation: 1.7 * wallpaperFader.factor + (1 - wallpaperFader.factor) + readonly property real intensity: wallpaperFader.factor + (1 - wallpaperFader.factor) + + property var colorMatrix: Qt.matrix4x4( + contrast, 0, 0, 0.0, + 0, contrast, 0, 0.0, + 0, 0, contrast, 0.0, + 0, 0, 0, 1.0).times(Qt.matrix4x4( + saturation, 0.0, 0.0, 0.0, + 0, saturation, 0, 0.0, + 0, 0, saturation, 0.0, + 0, 0, 0, 1.0)).times(Qt.matrix4x4( + intensity, 0, 0, 0, + 0, intensity, 0, 0, + 0, 0, intensity, 0, + 0, 0, 0, 1 + )); + + + fragmentShader: " + uniform mediump mat4 colorMatrix; + uniform mediump sampler2D source; + varying mediump vec2 qt_TexCoord0; + uniform lowp float qt_Opacity; + + void main(void) + { + mediump vec4 tex = texture2D(source, qt_TexCoord0); + gl_FragColor = tex * colorMatrix * qt_Opacity; + }" + } + + states: [ + State { + name: "on" + PropertyChanges { + target: mainStack + opacity: 1 + } + PropertyChanges { + target: footer + opacity: 1 + } + PropertyChanges { + target: wallpaperFader + factor: 1 + } + }, + State { + name: "off" + PropertyChanges { + target: mainStack + opacity: 0 + } + PropertyChanges { + target: footer + opacity: 0 + } + PropertyChanges { + target: wallpaperFader + factor: 0 + } + } + ] + transitions: [ + Transition { + from: "off" + to: "on" + //Note: can't use animators as they don't play well with parallelanimations + ParallelAnimation { + NumberAnimation { + target: mainStack + property: "opacity" + duration: units.longDuration + easing.type: Easing.InOutQuad + } + NumberAnimation { + target: footer + property: "opacity" + duration: units.longDuration + easing.type: Easing.InOutQuad + } + } + }, + Transition { + from: "on" + to: "off" + ParallelAnimation { + NumberAnimation { + target: mainStack + property: "opacity" + duration: 500 + easing.type: Easing.InOutQuad + } + NumberAnimation { + target: footer + property: "opacity" + duration: 500 + easing.type: Easing.InOutQuad + } + } + } + ] +} diff --git a/components/resources/reboot.svg b/components/resources/reboot.svg new file mode 100644 index 0000000..f04eb1f --- /dev/null +++ b/components/resources/reboot.svg @@ -0,0 +1,117 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + diff --git a/components/resources/shutdown.svg b/components/resources/shutdown.svg new file mode 100644 index 0000000..a62781c --- /dev/null +++ b/components/resources/shutdown.svg @@ -0,0 +1,75 @@ + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/components/resources/warning_red.png b/components/resources/warning_red.png new file mode 100644 index 0000000..2dde516 Binary files /dev/null and b/components/resources/warning_red.png differ diff --git a/metadata.desktop b/metadata.desktop new file mode 100644 index 0000000..40de80a --- /dev/null +++ b/metadata.desktop @@ -0,0 +1,16 @@ +[SddmGreeterTheme] +Name=Aerial HD Video +Description=Aerial HD Video Stream +Author=Fabio Almeida +Copyright=(c) 2016, Fabio Almeida +License=CC-BY-SA +Type=sddm-theme +Version=0.1 +Website=https://github.com/3ximus/aerial-sddm-theme +Screenshot=screens/screenshot.png +MainScript=Main.qml +ConfigFile=theme.conf +Email=fabio_r11@hotmail.com +Theme-Id=aerial-sddm +Theme-API=2.0 + diff --git a/playlists/4k.m3u b/playlists/4k.m3u new file mode 100644 index 0000000..a153ef2 --- /dev/null +++ b/playlists/4k.m3u @@ -0,0 +1,36 @@ +/usr/share/sddm/themes/_shared/assets/comp_CH_C007_C011_PSNK_v02_SDR_PS_FINAL_20180709_SDR_4K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/comp_CH_C002_C005_PSNK_v05_SDR_PS_FINAL_20180709_SDR_4K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/comp_CH_C007_C004_PSNK_v02_SDR_PS_FINAL_20180709_SDR_4K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/DB_D008_C010_4K_SDR_HEVC.mov +/usr/share/sddm/themes/_shared/assets/DB_D001_C001_4K_SDR_HEVC.mov +/usr/share/sddm/themes/_shared/assets/DB_D011_C010_4K_SDR_HEVC.mov +/usr/share/sddm/themes/_shared/assets/DB_D002_C003_4K_SDR_HEVC.mov +/usr/share/sddm/themes/_shared/assets/DB_D001_C005_4K_SDR_HEVC.mov +/usr/share/sddm/themes/_shared/assets/DB_D011_C009_4K_SDR_HEVC.mov +/usr/share/sddm/themes/_shared/assets/GL_G004_C010_4K_SDR_HEVC.mov +/usr/share/sddm/themes/_shared/assets/GL_G002_C002_4K_SDR_HEVC.mov +/usr/share/sddm/themes/_shared/assets/HK_B005_C011_4K_SDR_HEVC.mov +/usr/share/sddm/themes/_shared/assets/HK_H004_C010_4K_SDR_HEVC.mov +/usr/share/sddm/themes/_shared/assets/HK_H004_C013_4K_SDR_HEVC.mov +/usr/share/sddm/themes/_shared/assets/HK_H004_C001_4K_SDR_HEVC.mov +/usr/share/sddm/themes/_shared/assets/HK_H004_C008_4K_SDR_HEVC.mov +/usr/share/sddm/themes/_shared/assets/comp_GMT312_162NC_139M_1041_AFRICA_NIGHT_v14_SDR_FINAL_20180706_SDR_4K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/comp_A103_C002_0205DG_v12_SDR_FINAL_20180706_SDR_4K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/comp_GMT306_139NC_139J_3066_CALI_TO_VEGAS_v07_SDR_FINAL_22062018_SDR_4K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/comp_A108_C001_v09_SDR_FINAL_22062018_SDR_4K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/comp_GMT308_139K_142NC_CARIBBEAN_DAY_v09_SDR_FINAL_22062018_SDR_4K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/comp_GMT329_113NC_396B_1105_CHINA_v04_SDR_FINAL_20180706_F900F2700_SDR_4K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/comp_A083_C002_1130KZ_v04_SDR_PS_FINAL_20180725_SDR_4K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/comp_GMT329_117NC_401C_1037_IRELAND_TO_ASIA_v48_SDR_PS_FINAL_20180725_F0F6300_SDR_4K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/comp_GMT026_363A_103NC_E1027_KOREA_JAPAN_NIGHT_v17_SDR_FINAL_25062018_SDR_4K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/comp_A105_C003_0212CT_FLARE_v10_SDR_PS_FINAL_20180711_SDR_4K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/comp_A009_C001_010181A_v09_SDR_PS_FINAL_20180725_SDR_4K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/comp_A114_C001_0305OT_v10_SDR_FINAL_22062018_SDR_4K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/comp_A001_C004_1207W5_v23_SDR_FINAL_20180706_SDR_4K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/LW_L001_C006_4K_SDR_HEVC.mov +/usr/share/sddm/themes/_shared/assets/LA_A006_C008_4K_SDR_HEVC.mov +/usr/share/sddm/themes/_shared/assets/LA_A009_C009_4K_SDR_HEVC.mov +/usr/share/sddm/themes/_shared/assets/LA_A008_C004_4K_SDR_HEVC.mov +/usr/share/sddm/themes/_shared/assets/comp_LA_A006_C004_v01_SDR_FINAL_PS_20180730_SDR_4K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/LA_A005_C009_4K_SDR_HEVC.mov +/usr/share/sddm/themes/_shared/assets/LA_A011_C003_4K_SDR_HEVC.mov diff --git a/playlists/all_sd.m3u b/playlists/all_sd.m3u new file mode 100644 index 0000000..d44d745 --- /dev/null +++ b/playlists/all_sd.m3u @@ -0,0 +1,89 @@ +/usr/share/sddm/themes/_shared/assets/comp_LA_A006_C004_v01_SDR_FINAL_PS_20180730_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/comp_A083_C002_1130KZ_v04_SDR_PS_FINAL_20180725_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/b4-3.mov +/usr/share/sddm/themes/_shared/assets/BO_A014_C023_SDR_20190717_F240F3709_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/g201_WH_D004_L014_SDR_20191031_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/LA_A011_C003_2K_SDR_HEVC.mov +/usr/share/sddm/themes/_shared/assets/CR_A009_C007_SDR_20191113_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/g201_AK_A003_C014_SDR_20191113_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/b1-4.mov +/usr/share/sddm/themes/_shared/assets/LA_A005_C009_2K_SDR_HEVC.mov +/usr/share/sddm/themes/_shared/assets/HK_H004_C013_2K_SDR_HEVC.mov +/usr/share/sddm/themes/_shared/assets/LA_A006_C008_2K_SDR_HEVC.mov +/usr/share/sddm/themes/_shared/assets/comp_A001_C004_1207W5_v23_SDR_FINAL_20180706_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/b10-3.mov +/usr/share/sddm/themes/_shared/assets/comp_GMT329_113NC_396B_1105_CHINA_v04_SDR_FINAL_20180706_F900F2700_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/HK_H004_C010_2K_SDR_HEVC.mov +/usr/share/sddm/themes/_shared/assets/HK_H004_C008_2K_SDR_HEVC.mov +/usr/share/sddm/themes/_shared/assets/comp_CH_C007_C004_PSNK_v02_SDR_PS_FINAL_20180709_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/HK_H004_C001_2K_SDR_HEVC.mov +/usr/share/sddm/themes/_shared/assets/GL_G004_C010_2K_SDR_HEVC.mov +/usr/share/sddm/themes/_shared/assets/comp_A103_C002_0205DG_v12_SDR_FINAL_20180706_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/DB_D001_C001_2K_SDR_HEVC.mov +/usr/share/sddm/themes/_shared/assets/b1-3.mov +/usr/share/sddm/themes/_shared/assets/DB_D002_C003_2K_SDR_HEVC.mov +/usr/share/sddm/themes/_shared/assets/comp_A114_C001_0305OT_v10_SDR_FINAL_22062018_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/comp_A009_C001_010181A_v09_SDR_PS_FINAL_20180725_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/DB_D011_C009_2K_SDR_HEVC.mov +/usr/share/sddm/themes/_shared/assets/BO_A012_C031_SDR_20190726_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/comp_A105_C003_0212CT_FLARE_v10_SDR_PS_FINAL_20180711_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/b7-3.mov +/usr/share/sddm/themes/_shared/assets/comp_GMT312_162NC_139M_1041_AFRICA_NIGHT_v14_SDR_FINAL_20180706_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/comp_GMT329_117NC_401C_1037_IRELAND_TO_ASIA_v48_SDR_PS_FINAL_20180725_F0F6300_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/b3-1.mov +/usr/share/sddm/themes/_shared/assets/b6-2.mov +/usr/share/sddm/themes/_shared/assets/b3-2.mov +/usr/share/sddm/themes/_shared/assets/PA_A004_C003_SDR_20190719_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/b9-3.mov +/usr/share/sddm/themes/_shared/assets/b6-3.mov +/usr/share/sddm/themes/_shared/assets/b2-3.mov +/usr/share/sddm/themes/_shared/assets/g201_CA_A016_C002_SDR_20191114_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/FK_U009_C004_SDR_20191220_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/HK_B005_C011_2K_SDR_HEVC.mov +/usr/share/sddm/themes/_shared/assets/comp_GMT026_363A_103NC_E1027_KOREA_JAPAN_NIGHT_v17_SDR_FINAL_25062018_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/b5-2.mov +/usr/share/sddm/themes/_shared/assets/b4-2.mov +/usr/share/sddm/themes/_shared/assets/DB_D001_C005_2K_SDR_HEVC.mov +/usr/share/sddm/themes/_shared/assets/LA_A008_C004_2K_SDR_HEVC.mov +/usr/share/sddm/themes/_shared/assets/MEX_A006_C008_SDR_20190923_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/b5-3.mov +/usr/share/sddm/themes/_shared/assets/comp_GMT306_139NC_139J_3066_CALI_TO_VEGAS_v07_SDR_FINAL_22062018_SDR_4K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/KP_A010_C002_SDR_20190717_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/PA_A001_C007_SDR_20190717_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/DB_D011_C010_2K_SDR_HEVC.mov +/usr/share/sddm/themes/_shared/assets/AK_A004_C012_SDR_20191217_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/b2-2.mov +/usr/share/sddm/themes/_shared/assets/SE_A016_C009_SDR_20190717_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/comp_GMT308_139K_142NC_CARIBBEAN_DAY_v09_SDR_FINAL_22062018_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/b2-1.mov.1 +/usr/share/sddm/themes/_shared/assets/b6-1.mov +/usr/share/sddm/themes/_shared/assets/g201_TH_803_A001_8_SDR_20191031_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/b5-1.mov +/usr/share/sddm/themes/_shared/assets/b9-2.mov +/usr/share/sddm/themes/_shared/assets/comp_A108_C001_v09_SDR_FINAL_22062018_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/DL_B002_C011_SDR_20191122_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/b8-2.mov +/usr/share/sddm/themes/_shared/assets/b1-2.mov +/usr/share/sddm/themes/_shared/assets/b8-1.mov +/usr/share/sddm/themes/_shared/assets/b4-1.mov +/usr/share/sddm/themes/_shared/assets/b1-1.mov +/usr/share/sddm/themes/_shared/assets/b3-3.mov +/usr/share/sddm/themes/_shared/assets/b2-4.mov +/usr/share/sddm/themes/_shared/assets/comp_CH_C007_C011_PSNK_v02_SDR_PS_FINAL_20180709_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/comp_CH_C002_C005_PSNK_v05_SDR_PS_FINAL_20180709_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/g201_TH_804_A001_8_SDR_20191031_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/PA_A002_C009_SDR_20190730_ALT01_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/GL_G002_C002_2K_SDR_HEVC.mov +/usr/share/sddm/themes/_shared/assets/PA_A010_C007_SDR_20190717_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/b8-3.mov +/usr/share/sddm/themes/_shared/assets/comp_GL_G010_C006_v08_6Mbps.mov +/usr/share/sddm/themes/_shared/assets/b6-4.mov +/usr/share/sddm/themes/_shared/assets/b7-1.mov +/usr/share/sddm/themes/_shared/assets/BO_A018_C029_SDR_20190812_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/b7-2.mov +/usr/share/sddm/themes/_shared/assets/DB_D008_C010_2K_SDR_HEVC.mov +/usr/share/sddm/themes/_shared/assets/LA_A009_C009_2K_SDR_HEVC.mov +/usr/share/sddm/themes/_shared/assets/RS_A008_C010_SDR_20191218_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/b2-1.mov +/usr/share/sddm/themes/_shared/assets/BO_A014_C008_SDR_20190719_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/b2-1.mov.2 diff --git a/playlists/day.m3u b/playlists/day.m3u new file mode 100644 index 0000000..c49d40f --- /dev/null +++ b/playlists/day.m3u @@ -0,0 +1,36 @@ +/usr/share/sddm/themes/_shared/assets/b2-1.mov +/usr/share/sddm/themes/_shared/assets/b6-1.mov +/usr/share/sddm/themes/_shared/assets/b1-1.mov +/usr/share/sddm/themes/_shared/assets/b2-2.mov +/usr/share/sddm/themes/_shared/assets/b4-1.mov +/usr/share/sddm/themes/_shared/assets/b7-1.mov +/usr/share/sddm/themes/_shared/assets/b5-2.mov +/usr/share/sddm/themes/_shared/assets/b1-3.mov +/usr/share/sddm/themes/_shared/assets/b3-2.mov +/usr/share/sddm/themes/_shared/assets/b7-2.mov +/usr/share/sddm/themes/_shared/assets/b8-2.mov +/usr/share/sddm/themes/_shared/assets/b4-3.mov +/usr/share/sddm/themes/_shared/assets/b8-3.mov +/usr/share/sddm/themes/_shared/assets/b9-3.mov +/usr/share/sddm/themes/_shared/assets/comp_CH_C007_C011_PSNK_v02_SDR_PS_FINAL_20180709_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/comp_CH_C002_C005_PSNK_v05_SDR_PS_FINAL_20180709_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/comp_CH_C007_C004_PSNK_v02_SDR_PS_FINAL_20180709_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/DB_D008_C010_2K_SDR_HEVC.mov +/usr/share/sddm/themes/_shared/assets/DB_D001_C001_2K_SDR_HEVC.mov +/usr/share/sddm/themes/_shared/assets/DB_D002_C003_2K_SDR_HEVC.mov +/usr/share/sddm/themes/_shared/assets/DB_D001_C005_2K_SDR_HEVC.mov +/usr/share/sddm/themes/_shared/assets/GL_G004_C010_2K_SDR_HEVC.mov +/usr/share/sddm/themes/_shared/assets/GL_G002_C002_2K_SDR_HEVC.mov +/usr/share/sddm/themes/_shared/assets/HK_H004_C010_2K_SDR_HEVC.mov +/usr/share/sddm/themes/_shared/assets/HK_H004_C013_2K_SDR_HEVC.mov +/usr/share/sddm/themes/_shared/assets/HK_H004_C008_2K_SDR_HEVC.mov +/usr/share/sddm/themes/_shared/assets/comp_A103_C002_0205DG_v12_SDR_FINAL_20180706_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/comp_A108_C001_v09_SDR_FINAL_22062018_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/comp_GMT308_139K_142NC_CARIBBEAN_DAY_v09_SDR_FINAL_22062018_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/comp_A105_C003_0212CT_FLARE_v10_SDR_PS_FINAL_20180711_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/comp_A009_C001_010181A_v09_SDR_PS_FINAL_20180725_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/comp_A114_C001_0305OT_v10_SDR_FINAL_22062018_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/comp_A001_C004_1207W5_v23_SDR_FINAL_20180706_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/LA_A006_C008_2K_SDR_HEVC.mov +/usr/share/sddm/themes/_shared/assets/LA_A008_C004_2K_SDR_HEVC.mov +/usr/share/sddm/themes/_shared/assets/LA_A005_C009_2K_SDR_HEVC.mov diff --git a/playlists/night.m3u b/playlists/night.m3u new file mode 100644 index 0000000..d0a96ad --- /dev/null +++ b/playlists/night.m3u @@ -0,0 +1,30 @@ +/usr/share/sddm/themes/_shared/assets/b5-1.mov +/usr/share/sddm/themes/_shared/assets/comp_GL_G010_C006_v08_6Mbps.mov +/usr/share/sddm/themes/_shared/assets/b6-2.mov +/usr/share/sddm/themes/_shared/assets/b8-1.mov +/usr/share/sddm/themes/_shared/assets/b1-2.mov +/usr/share/sddm/themes/_shared/assets/b3-1.mov +/usr/share/sddm/themes/_shared/assets/b6-3.mov +/usr/share/sddm/themes/_shared/assets/b2-3.mov +/usr/share/sddm/themes/_shared/assets/b4-2.mov +/usr/share/sddm/themes/_shared/assets/b1-4.mov +/usr/share/sddm/themes/_shared/assets/b2-4.mov +/usr/share/sddm/themes/_shared/assets/b3-3.mov +/usr/share/sddm/themes/_shared/assets/b5-3.mov +/usr/share/sddm/themes/_shared/assets/b6-4.mov +/usr/share/sddm/themes/_shared/assets/b7-3.mov +/usr/share/sddm/themes/_shared/assets/b9-2.mov +/usr/share/sddm/themes/_shared/assets/b10-3.mov +/usr/share/sddm/themes/_shared/assets/DB_D011_C010_2K_SDR_HEVC.mov +/usr/share/sddm/themes/_shared/assets/DB_D011_C009_2K_SDR_HEVC.mov +/usr/share/sddm/themes/_shared/assets/HK_B005_C011_2K_SDR_HEVC.mov +/usr/share/sddm/themes/_shared/assets/HK_H004_C001_2K_SDR_HEVC.mov +/usr/share/sddm/themes/_shared/assets/comp_GMT312_162NC_139M_1041_AFRICA_NIGHT_v14_SDR_FINAL_20180706_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/comp_GMT306_139NC_139J_3066_CALI_TO_VEGAS_v07_SDR_FINAL_22062018_SDR_4K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/comp_GMT329_113NC_396B_1105_CHINA_v04_SDR_FINAL_20180706_F900F2700_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/comp_A083_C002_1130KZ_v04_SDR_PS_FINAL_20180725_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/comp_GMT329_117NC_401C_1037_IRELAND_TO_ASIA_v48_SDR_PS_FINAL_20180725_F0F6300_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/comp_GMT026_363A_103NC_E1027_KOREA_JAPAN_NIGHT_v17_SDR_FINAL_25062018_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/LA_A009_C009_2K_SDR_HEVC.mov +/usr/share/sddm/themes/_shared/assets/comp_LA_A006_C004_v01_SDR_FINAL_PS_20180730_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/LA_A011_C003_2K_SDR_HEVC.mov diff --git a/playlists/undersea.m3u b/playlists/undersea.m3u new file mode 100644 index 0000000..a3c75d1 --- /dev/null +++ b/playlists/undersea.m3u @@ -0,0 +1,21 @@ +/usr/share/sddm/themes/_shared/assets/AK_A004_C012_SDR_20191217_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/g201_AK_A003_C014_SDR_20191113_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/BO_A018_C029_SDR_20190812_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/BO_A014_C008_SDR_20190719_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/DL_B002_C011_SDR_20191122_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/g201_CA_A016_C002_SDR_20191114_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/CR_A009_C007_SDR_20191113_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/MEX_A006_C008_SDR_20190923_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/FK_U009_C004_SDR_20191220_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/g201_WH_D004_L014_SDR_20191031_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/BO_A014_C023_SDR_20190717_F240F3709_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/KP_A010_C002_SDR_20190717_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/PA_A004_C003_SDR_20190719_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/PA_A001_C007_SDR_20190717_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/PA_A002_C009_SDR_20190730_ALT01_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/PA_A010_C007_SDR_20190717_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/RS_A008_C010_SDR_20191218_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/BO_A012_C031_SDR_20190726_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/SE_A016_C009_SDR_20190717_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/g201_TH_804_A001_8_SDR_20191031_SDR_2K_HEVC.mov +/usr/share/sddm/themes/_shared/assets/g201_TH_803_A001_8_SDR_20191031_SDR_2K_HEVC.mov diff --git a/screens/custom.gif b/screens/custom.gif new file mode 100644 index 0000000..bbb9679 Binary files /dev/null and b/screens/custom.gif differ diff --git a/screens/preview1.gif b/screens/preview1.gif new file mode 100644 index 0000000..d722fa2 Binary files /dev/null and b/screens/preview1.gif differ diff --git a/screens/preview2.gif b/screens/preview2.gif new file mode 100644 index 0000000..05a3119 Binary files /dev/null and b/screens/preview2.gif differ diff --git a/screens/preview3.gif b/screens/preview3.gif new file mode 100644 index 0000000..1210741 Binary files /dev/null and b/screens/preview3.gif differ diff --git a/screens/screenshot.png b/screens/screenshot.png new file mode 100644 index 0000000..1f0bdf1 Binary files /dev/null and b/screens/screenshot.png differ diff --git a/theme.conf b/theme.conf new file mode 100644 index 0000000..7882e7c --- /dev/null +++ b/theme.conf @@ -0,0 +1,21 @@ +[General] +showlogo=hidden +logo=/usr/share/sddm/themes/breeze/default-logo.svg +type=image +color=#1d99f3 +fontSize=10 +background=/usr/share/wallpapers/Next/contents/images/5120x2880.jpg +needsFullUserModel=false + +background_img_day=background.jpg +background_img_night=background.jpg +background_vid_day=playlists/day.m3u +background_vid_night=playlists/night.m3u +displayFont="Droid Sans Mono for Powerline" +showLoginButton=true +passwordLeftMargin=15 +usernameLeftMargin=15 +relativePositionX=0.3 +relativePositionY=0.7 +showTopBar=true +autofocusInput=true diff --git a/theme.conf.user b/theme.conf.user new file mode 100644 index 0000000..156cc82 --- /dev/null +++ b/theme.conf.user @@ -0,0 +1,11 @@ +[General] +background_vid_day=playlists/day.m3u +background_vid_night=playlists/night.m3u +passwordLeftMargin=15 +relativePositionX=0.5 +relativePositionY=0.75 +showLoginButton=false +type=color +usernameLeftMargin=15 +showTopBar=true +autofocusInput=true