summaryrefslogtreecommitdiffstats
path: root/Main.qml
diff options
context:
space:
mode:
Diffstat (limited to 'Main.qml')
-rw-r--r--Main.qml541
1 files changed, 541 insertions, 0 deletions
diff --git a/Main.qml b/Main.qml
new file mode 100644
index 0000000..43e444e
--- /dev/null
+++ b/Main.qml
@@ -0,0 +1,541 @@
+/*
+ * Copyright 2016 David Edmundson <davidedmundson@kde.org>
+ *
+ * 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 1.1
+import QtGraphicalEffects 1.0
+
+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 "components"
+
+// TODO: Once SDDM 0.19 is released and we are setting the font size using the
+// SDDM KCM's syncing feature, remove the `config.fontSize` overrides here and
+// the fontSize properties in various components, because the theme's default
+// font size will be correctly propagated to the login screen
+
+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")
+ 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: 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
+ 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" // matches Breeze window decoration and desktopcontainment
+ opacity: loginScreenRoot.uiVisible ? 0 : 1
+ Behavior on opacity {
+ //OpacityAnimator when starting from 0 is buggy (it shows one frame with opacity 1)"
+ NumberAnimation {
+ duration: 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: 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 when starting from 0 is buggy (it shows one frame with opacity 1)"
+ NumberAnimation {
+ duration: 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: 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
+ }
+ }
+ }
+
+ Connections {
+ target: sddm
+ function onLoginFailed() {
+ notificationMessage = i18nd("plasma_lookandfeel_org.kde.lookandfeel", "Login Failed")
+ footer.enabled = true
+ mainStack.enabled = true
+ userListComponent.userList.opacity = 1
+ }
+ function 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 = ""
+ }
+}