diff --git a/sddm-theme/BreezeMenuStyle.qml b/sddm-theme/BreezeMenuStyle.qml new file mode 100644 index 000000000..7d56c1499 --- /dev/null +++ b/sddm-theme/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/sddm-theme/KeyboardButton.qml b/sddm-theme/KeyboardButton.qml index 611758cec..9989d93ef 100644 --- a/sddm-theme/KeyboardButton.qml +++ b/sddm-theme/KeyboardButton.qml @@ -1,114 +1,38 @@ -import QtQuick 2.6 +import QtQuick 2.2 import org.kde.plasma.core 2.0 as PlasmaCore -import org.kde.plasma.components 3.0 as PlasmaComponents +import org.kde.plasma.components 2.0 as PlasmaComponents -import QtQuick.Controls 2.5 as QQC2 -import QtGraphicalEffects 1.0 +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 font.pointSize: config.fontSize - visible: keyboardMenu.count > 1 + visible: menu.items.length > 1 Component.onCompleted: currentIndex = Qt.binding(function() {return keyboard.currentLayout}); - onClicked: { - keyboardMenu.popup(x, y) - } - - QQC2.Menu { + menu: QQC.Menu { id: keyboardMenu - - property int largestWidth: 9999 - - Component.onCompleted: { - var trueWidth = 0; - for (var i = 0; i < keyboardMenu.count; i++) { - trueWidth = Math.max(trueWidth, keyboardMenu.itemAt(i).textWidth) - } - keyboardMenu.largestWidth = trueWidth - } - - background: Rectangle { - implicitHeight: 40 - implicitWidth: keyboardMenu.largestWidth > keyboardButton.implicitWidth ? keyboardMenu.largestWidth : keyboardButton.implicitWidth - color: PlasmaCore.ColorScope.backgroundColor - property color borderColor: PlasmaCore.Colorscope.textColor - border.color: Qt.rgba(borderColor.r, borderColor.g, borderColor.b, 0.3) - border.width: 1 - layer.enabled: true - layer.effect: DropShadow { - transparentBorder: true - radius: 8 - samples: 8 - horizontalOffset: 0 - verticalOffset: 2 - color: Qt.rgba(0, 0, 0, 0.3) - } - } - + style: BreezeMenuStyle {} Instantiator { id: instantiator model: keyboard.layouts - onObjectAdded: keyboardMenu.addItem( object ) + onObjectAdded: keyboardMenu.insertItem(index, object) onObjectRemoved: keyboardMenu.removeItem( object ) - delegate: QQC2.MenuItem { - id: menuItem - property string name: modelData.longName + delegate: QQC.MenuItem { + text: modelData.longName property string shortName: modelData.shortName - - property real textWidth: text.contentWidth + 20 - implicitWidth: text.contentWidth + 20 - implicitHeight: Math.round(text.contentHeight * 1.6) - - contentItem: QQC2.Label { - id: text - font.pointSize: config.fontSize - text: modelData.longName - color: menuItem.highlighted ? PlasmaCore.ColorScope.highlightedTextColor : PlasmaCore.ColorScope.textColor - horizontalAlignment: Text.AlignLeft - verticalAlignment: Text.AlignVCenter - elide: Text.ElideRight - } - - background: Rectangle { - color: PlasmaCore.ColorScope.highlightColor - opacity: menuItem.highlighted ? 1 : 0 - MouseArea { - anchors.fill: parent - hoverEnabled: true - onContainsMouseChanged: menuItem.highlighted = containsMouse - onClicked: { - keyboardMenu.dismiss() - keyboard.currentLayout = model.index - } - } + onTriggered: { + keyboard.currentLayout = model.index } } } - - enter: Transition { - NumberAnimation { - property: "opacity" - from: 0 - to: 1 - duration: 150 - } - } - exit: Transition { - NumberAnimation { - property: "opacity" - from: 1 - to: 0 - duration: 150 - } - } } } diff --git a/sddm-theme/Main.qml b/sddm-theme/Main.qml index 550ed6be9..6746238fc 100644 --- a/sddm-theme/Main.qml +++ b/sddm-theme/Main.qml @@ -1,521 +1,521 @@ /* * Copyright 2016 David Edmundson * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 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 Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import QtQuick 2.8 import QtQuick.Layouts 1.1 -import QtQuick.Controls 2.0 +import QtQuick.Controls 1.1 import QtGraphicalEffects 1.0 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.plasma.extras 2.0 as PlasmaExtras import "components" PlasmaCore.ColorScope { id: root // 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 colorGroup: PlasmaCore.Theme.ComplementaryColorGroup readonly property bool lightBackground: Math.max(PlasmaCore.ColorScope.backgroundColor.r, PlasmaCore.ColorScope.backgroundColor.g, PlasmaCore.ColorScope.backgroundColor.b) > 0.5 width: 1600 height: 900 property string notificationMessage LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft LayoutMirroring.childrenInherit: true PlasmaCore.DataSource { id: keystateSource engine: "keystate" connectedSources: "Caps Lock" } Item { id: wallpaper anchors.fill: parent Repeater { model: screenModel Background { x: geometry.x; y: geometry.y; width: geometry.width; height: geometry.height sceneBackgroundType: config.type sceneBackgroundColor: config.color sceneBackgroundImage: config.background } } } 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; } } } WallpaperFader { visible: config.type === "image" anchors.fill: parent state: loginScreenRoot.uiVisible ? "on" : "off" source: wallpaper mainStack: mainStack footer: footer clock: clock } DropShadow { id: clockShadow anchors.fill: clock source: clock visible: !softwareRendering horizontalOffset: 1 verticalOffset: 1 radius: 6 samples: 14 spread: 0.3 color: root.lightBackground ? PlasmaCore.ColorScope.backgroundColor : "black" // black matches Breeze window decoration and desktopcontainment Behavior on opacity { OpacityAnimator { duration: 1000 easing.type: Easing.InOutQuad } } } Clock { id: clock visible: y > 0 property Item shadow: clockShadow y: (userListComponent.userList.y + mainStack.y)/2 - height/2 anchors.horizontalCenter: parent.horizontalCenter } StackView { id: mainStack anchors { left: parent.left right: parent.right } height: root.height + units.gridUnit * 3 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") onClicked: sddm.suspend() enabled: sddm.canSuspend visible: !inputPanel.keyboardActive }, ActionButton { iconSource: "system-reboot" text: i18nd("plasma_lookandfeel_org.kde.lookandfeel","Restart") onClicked: sddm.reboot() enabled: sddm.canReboot visible: !inputPanel.keyboardActive }, ActionButton { iconSource: "system-shutdown" text: i18nd("plasma_lookandfeel_org.kde.lookandfeel","Shut Down") 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...") 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: units.longDuration } } } Loader { id: inputPanel state: "hidden" property bool keyboardActive: item ? item.active : false onKeyboardActiveChanged: { if (keyboardActive) { state = "visible" } else { state = "hidden"; } } source: "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: units.longDuration easing.type: Easing.InOutQuad } NumberAnimation { target: inputPanel property: "y" duration: units.longDuration easing.type: Easing.OutQuad } OpacityAnimator { target: inputPanel duration: units.longDuration easing.type: Easing.OutQuad } } } }, Transition { from: "visible" to: "hidden" SequentialAnimation { ParallelAnimation { NumberAnimation { target: mainStack property: "y" duration: units.longDuration easing.type: Easing.InOutQuad } NumberAnimation { target: inputPanel property: "y" duration: units.longDuration easing.type: Easing.InQuad } OpacityAnimator { target: inputPanel duration: units.longDuration easing.type: Easing.InQuad } } ScriptAction { script: { Qt.inputMethod.hide(); } } } } ] } Component { id: userPromptComponent Login { showUsernamePrompt: true notificationMessage: root.notificationMessage loginScreenUiVisible: loginScreenRoot.uiVisible // 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") onClicked: sddm.suspend() enabled: sddm.canSuspend visible: !inputPanel.keyboardActive }, ActionButton { iconSource: "system-reboot" text: i18nd("plasma_lookandfeel_org.kde.lookandfeel","Restart") onClicked: sddm.reboot() enabled: sddm.canReboot visible: !inputPanel.keyboardActive }, ActionButton { iconSource: "system-shutdown" text: i18nd("plasma_lookandfeel_org.kde.lookandfeel","Shut Down") onClicked: sddm.powerOff() enabled: sddm.canPowerOff visible: !inputPanel.keyboardActive }, ActionButton { iconSource: "system-user-list" text: i18nd("plasma_lookandfeel_org.kde.lookandfeel","List Users") onClicked: mainStack.pop() visible: !inputPanel.keyboardActive } ] } } Image { id: logo visible: config.showlogo == "shown" source: config.logo anchors.horizontalCenter: parent.horizontalCenter anchors.bottom: footer.top anchors.bottomMargin: units.largeSpacing asynchronous: true sourceSize.height: height opacity: loginScreenRoot.uiVisible ? 0 : 1 fillMode: Image.PreserveAspectFit height: Math.round(units.gridUnit * 3.5) Behavior on opacity { OpacityAnimator { duration: units.longDuration easing.type: Easing.InOutQuad } } } 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" // matches Breeze window decoration and desktopcontainment opacity: loginScreenRoot.uiVisible ? 0 : 1 Behavior on opacity { OpacityAnimator { duration: units.longDuration easing.type: Easing.InOutQuad } } } //Footer RowLayout { id: footer anchors { bottom: parent.bottom left: parent.left right: parent.right margins: units.smallSpacing } Behavior on opacity { OpacityAnimator { duration: units.longDuration } } PlasmaComponents.ToolButton { text: i18ndc("plasma_lookandfeel_org.kde.lookandfeel", "Button to show/hide virtual keyboard", "Virtual Keyboard") font.pointSize: config.fontSize iconName: inputPanel.keyboardActive ? "input-keyboard-virtual-on" : "input-keyboard-virtual-off" onClicked: inputPanel.showHide() visible: inputPanel.status == Loader.Ready } KeyboardButton { } SessionButton { id: sessionButton } Item { Layout.fillWidth: true } Battery { } } } Connections { target: sddm onLoginFailed: { notificationMessage = i18nd("plasma_lookandfeel_org.kde.lookandfeel", "Login Failed") footer.enabled = true mainStack.enabled = true userListComponent.userList.opacity = 1 } onLoginSucceeded: { //note SDDM will kill the greeter at some random point after this //there is no certainty any transition will finish, it depends on the time it //takes to complete the init mainStack.opacity = 0 footer.opacity = 0 } } onNotificationMessageChanged: { if (notificationMessage) { notificationResetTimer.start(); } } Timer { id: notificationResetTimer interval: 3000 onTriggered: notificationMessage = "" } } diff --git a/sddm-theme/SessionButton.qml b/sddm-theme/SessionButton.qml index be84d3a5f..58590c835 100644 --- a/sddm-theme/SessionButton.qml +++ b/sddm-theme/SessionButton.qml @@ -1,133 +1,59 @@ /* -* Copyright 2016 David Edmundson -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU Library General Public License as -* published by the Free Software Foundation; either version 2 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 Library General Public -* License along with this program; if not, write to the -* Free Software Foundation, Inc., -* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -import QtQuick 2.6 + * Copyright 2016 David Edmundson + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 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 Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +import QtQuick 2.2 import org.kde.plasma.core 2.0 as PlasmaCore -import org.kde.plasma.components 3.0 as PlasmaComponents +import org.kde.plasma.components 2.0 as PlasmaComponents -import QtQuick.Controls 2.5 as QQC2 -import QtGraphicalEffects 1.0 +import QtQuick.Controls 1.3 as QQC PlasmaComponents.ToolButton { - id: sessionButton + id: root property int currentIndex: -1 - visible: sessionMenu.count > 1 + implicitWidth: minimumWidth + + visible: menu.items.length > 1 - text: i18nd("plasma_lookandfeel_org.kde.lookandfeel", "Desktop Session: %1", instantiator.objectAt(currentIndex).name || "Error") + text: i18nd("plasma_lookandfeel_org.kde.lookandfeel", "Desktop Session: %1", instantiator.objectAt(currentIndex).text || "") font.pointSize: config.fontSize Component.onCompleted: { currentIndex = sessionModel.lastIndex } - onClicked: { - sessionMenu.popup(x, y) - } - - QQC2.Menu { - id: sessionMenu - - property int largestWidth: 9999 - - Component.onCompleted: { - var trueWidth = 0; - for (var i = 0; i < sessionMenu.count; i++) { - trueWidth = Math.max(trueWidth, sessionMenu.itemAt(i).textWidth) - } - sessionMenu.largestWidth = trueWidth - } - - background: Rectangle { - implicitHeight: 40 - implicitWidth: sessionMenu.largestWidth > sessionButton.implicitWidth ? sessionMenu.largestWidth : sessionButton.implicitWidth - color: PlasmaCore.ColorScope.backgroundColor - property color borderColor: PlasmaCore.Colorscope.textColor - border.color: Qt.rgba(borderColor.r, borderColor.g, borderColor.b, 0.3) - border.width: 1 - layer.enabled: true - layer.effect: DropShadow { - transparentBorder: true - radius: 8 - samples: 8 - horizontalOffset: 0 - verticalOffset: 2 - color: Qt.rgba(0, 0, 0, 0.3) - } - } - + menu: QQC.Menu { + id: menu + style: BreezeMenuStyle {} Instantiator { id: instantiator model: sessionModel - onObjectAdded: sessionMenu.addItem( object ) - onObjectRemoved: sessionMenu.removeItem( object ) - delegate: QQC2.MenuItem { - id: menuItem - property string name: model.name - - property real textWidth: text.contentWidth + 20 - implicitWidth: text.contentWidth + 20 - implicitHeight: Math.round(text.contentHeight * 1.6) - - contentItem: QQC2.Label { - id: text - font.pointSize: config.fontSize - text: model.name - color: menuItem.highlighted ? PlasmaCore.ColorScope.highlightedTextColor : PlasmaCore.ColorScope.textColor - horizontalAlignment: Text.AlignLeft - verticalAlignment: Text.AlignVCenter - elide: Text.ElideRight - } - - background: Rectangle { - color: PlasmaCore.ColorScope.highlightColor - opacity: menuItem.highlighted ? 1 : 0 - MouseArea { - anchors.fill: parent - hoverEnabled: true - onContainsMouseChanged: menuItem.highlighted = containsMouse - onClicked: { - sessionMenu.dismiss() - sessionButton.currentIndex = model.index - } - } + onObjectAdded: menu.insertItem(index, object) + onObjectRemoved: menu.removeItem( object ) + delegate: QQC.MenuItem { + text: model.name + onTriggered: { + root.currentIndex = model.index } } } - - enter: Transition { - NumberAnimation { - property: "opacity" - from: 0 - to: 1 - duration: 150 - } - } - exit: Transition { - NumberAnimation { - property: "opacity" - from: 1 - to: 0 - duration: 150 - } - } } }