Untitled diff

Created Diff never expires
10 removals
458 lines
0 additions
448 lines
/********************************************************************
/********************************************************************
This file is part of the KDE project.
This file is part of the KDE project.


Copyright (C) 2014 Aleix Pol Gonzalez <aleixpol@blue-systems.com>
Copyright (C) 2014 Aleix Pol Gonzalez <aleixpol@blue-systems.com>


This program is free software; you can redistribute it and/or modify
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
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
(at your option) any later version.


This program is distributed in the hope that it will be useful,
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
GNU General Public License for more details.


You should have received a copy of the GNU General Public License
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
*********************************************************************/


import QtQuick 2.6
import QtQuick 2.6
import QtQuick.Controls 1.1
import QtQuick.Controls 1.1
import QtQuick.Layouts 1.1
import QtQuick.Layouts 1.1
import QtGraphicalEffects 1.0
import QtGraphicalEffects 1.0


import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 2.0 as PlasmaComponents
import org.kde.plasma.components 2.0 as PlasmaComponents


import org.kde.plasma.private.sessions 2.0
import org.kde.plasma.private.sessions 2.0
import "../components"
import "../components"


PlasmaCore.ColorScope {
PlasmaCore.ColorScope {


colorGroup: PlasmaCore.Theme.ComplementaryColorGroup
colorGroup: PlasmaCore.Theme.ComplementaryColorGroup


Connections {
Connections {
target: authenticator
target: authenticator
onFailed: {
onFailed: {
root.notification = i18nd("plasma_lookandfeel_org.kde.lookandfeel","Unlocking failed");
root.notification = i18nd("plasma_lookandfeel_org.kde.lookandfeel","Unlocking failed");
}
}
onGraceLockedChanged: {
onGraceLockedChanged: {
if (!authenticator.graceLocked) {
if (!authenticator.graceLocked) {
root.notification = "";
root.notification = "";
root.clearPassword();
root.clearPassword();
}
}
}
}
onMessage: {
onMessage: {
root.notification = msg;
root.notification = msg;
}
}
onError: {
onError: {
root.notification = err;
root.notification = err;
}
}
}
}


SessionsModel {
SessionsModel {
id: sessionsModel
id: sessionsModel
showNewSessionEntry: true
showNewSessionEntry: true
}
}


PlasmaCore.DataSource {
PlasmaCore.DataSource {
id: keystateSource
id: keystateSource
engine: "keystate"
engine: "keystate"
connectedSources: "Caps Lock"
connectedSources: "Caps Lock"
}
}


Loader {
Loader {
id: changeSessionComponent
id: changeSessionComponent
active: false
active: false
source: "ChangeSession.qml"
source: "ChangeSession.qml"
visible: false
visible: false
}
}


MouseArea {
MouseArea {
id: lockScreenRoot
id: lockScreenRoot


property bool uiVisible: false
property bool uiVisible: false
property bool blockUI: mainStack.depth > 1 || mainBlock.mainPasswordBox.text.length > 0 || inputPanel.keyboardActive
property bool blockUI: mainStack.depth > 1 || mainBlock.mainPasswordBox.text.length > 0 || inputPanel.keyboardActive


x: parent.x
x: parent.x
y: parent.y
y: parent.y
width: parent.width
width: parent.width
height: parent.height
height: parent.height
hoverEnabled: true
hoverEnabled: true
drag.filterChildren: true
drag.filterChildren: true
onPressed: uiVisible = true;
onPressed: uiVisible = true;
onPositionChanged: uiVisible = true;
onPositionChanged: uiVisible = true;
onUiVisibleChanged: {
onUiVisibleChanged: {
if (blockUI) {
if (blockUI) {
fadeoutTimer.running = false;
fadeoutTimer.running = false;
} else if (uiVisible) {
} else if (uiVisible) {
fadeoutTimer.restart();
fadeoutTimer.restart();
}
}
}
}
onBlockUIChanged: {
onBlockUIChanged: {
if (blockUI) {
if (blockUI) {
fadeoutTimer.running = false;
fadeoutTimer.running = false;
uiVisible = true;
uiVisible = true;
} else {
} else {
fadeoutTimer.restart();
fadeoutTimer.restart();
}
}
}
}
Keys.onEscapePressed: {
Keys.onEscapePressed: {
uiVisible = !uiVisible;
uiVisible = !uiVisible;
if (inputPanel.keyboardActive) {
if (inputPanel.keyboardActive) {
inputPanel.showHide();
inputPanel.showHide();
}
}
if (!uiVisible) {
if (!uiVisible) {
mainBlock.mainPasswordBox.text = "";
mainBlock.mainPasswordBox.text = "";
}
}
}
}
Keys.onPressed: {
Keys.onPressed: {
uiVisible = true;
uiVisible = true;
event.accepted = false;
event.accepted = false;
}
}
Timer {
Timer {
id: fadeoutTimer
id: fadeoutTimer
interval: 10000
interval: 10000
onTriggered: {
onTriggered: {
if (!lockScreenRoot.blockUI) {
if (!lockScreenRoot.blockUI) {
lockScreenRoot.uiVisible = false;
lockScreenRoot.uiVisible = false;
}
}
}
}
}
}


Component.onCompleted: PropertyAnimation { id: launchAnimation; target: lockScreenRoot; property: "opacity"; from: 0; to: 1; duration: 1000 }
Component.onCompleted: PropertyAnimation { id: launchAnimation; target: lockScreenRoot; property: "opacity"; from: 0; to: 1; duration: 1000 }


states: [
states: [
State {
State {
name: "onOtherSession"
name: "onOtherSession"
// for slide out animation
// for slide out animation
PropertyChanges { target: lockScreenRoot; y: lockScreenRoot.height }
PropertyChanges { target: lockScreenRoot; y: lockScreenRoot.height }
// we also change the opacity just to be sure it's not visible even on unexpected screen dimension changes with possible race conditions
// we also change the opacity just to be sure it's not visible even on unexpected screen dimension changes with possible race conditions
PropertyChanges { target: lockScreenRoot; opacity: 0 }
PropertyChanges { target: lockScreenRoot; opacity: 0 }
}
}
]
]


transitions:
transitions:
Transition {
Transition {
// we only animate switchting to another session, because kscreenlocker doesn't get notified when
// we only animate switchting to another session, because kscreenlocker doesn't get notified when
// coming from another session back and so we wouldn't know when to trigger the animation exactly
// coming from another session back and so we wouldn't know when to trigger the animation exactly
from: ""
from: ""
to: "onOtherSession"
to: "onOtherSession"


PropertyAnimation { id: stateChangeAnimation; properties: "y"; duration: 300; easing.type: Easing.InQuad}
PropertyAnimation { id: stateChangeAnimation; properties: "y"; duration: 300; easing.type: Easing.InQuad}
PropertyAnimation { properties: "opacity"; duration: 300}
PropertyAnimation { properties: "opacity"; duration: 300}


onRunningChanged: {
onRunningChanged: {
// after the animation has finished switch session: since we only animate the transition TO state "onOtherSession"
// after the animation has finished switch session: since we only animate the transition TO state "onOtherSession"
// and not the other way around, we don't have to check the state we transitioned into
// and not the other way around, we don't have to check the state we transitioned into
if (/* lockScreenRoot.state == "onOtherSession" && */ !running) {
if (/* lockScreenRoot.state == "onOtherSession" && */ !running) {
mainStack.currentItem.switchSession()
mainStack.currentItem.switchSession()
}
}
}
}
}
}


WallpaperFader {
WallpaperFader {
anchors.fill: parent
anchors.fill: parent
state: lockScreenRoot.uiVisible ? "on" : "off"
state: lockScreenRoot.uiVisible ? "on" : "off"
source: wallpaper
source: wallpaper
mainStack: mainStack
mainStack: mainStack
footer: footer
footer: footer
clock: clock
}

Clock {
id: clock
property Item shadow: clockShadow
anchors.horizontalCenter: parent.horizontalCenter
y: (mainBlock.userList.y + mainStack.y)/2 - height/2
visible: y > 0
Layout.alignment: Qt.AlignBaseline
}
}


ListModel {
ListModel {
id: users
id: users


Component.onCompleted: {
Component.onCompleted: {
users.append({name: kscreenlocker_userName,
users.append({name: kscreenlocker_userName,
realName: kscreenlocker_userName,
realName: kscreenlocker_userName,
icon: kscreenlocker_userImage,
icon: kscreenlocker_userImage,


})
})
}
}
}
}


StackView {
StackView {
id: mainStack
id: mainStack
anchors {
anchors {
left: parent.left
left: parent.left
right: parent.right
right: parent.right
}
}
height: lockScreenRoot.height
height: lockScreenRoot.height
focus: true //StackView is an implicit focus scope, so we need to give this focus so the item inside will have it
focus: true //StackView is an implicit focus scope, so we need to give this focus so the item inside will have it


initialItem: MainBlock {
initialItem: MainBlock {
id: mainBlock
id: mainBlock
lockScreenUiVisible: lockScreenRoot.uiVisible
lockScreenUiVisible: lockScreenRoot.uiVisible


showUserList: userList.y + mainStack.y > 0
showUserList: userList.y + mainStack.y > 0


Stack.onStatusChanged: {
Stack.onStatusChanged: {
// prepare for presenting again to the user
// prepare for presenting again to the user
if (Stack.status == Stack.Activating) {
if (Stack.status == Stack.Activating) {
mainPasswordBox.remove(0, mainPasswordBox.length)
mainPasswordBox.remove(0, mainPasswordBox.length)
mainPasswordBox.focus = true
mainPasswordBox.focus = true
}
}
}
}
userListModel: users
userListModel: users
notificationMessage: {
notificationMessage: {
var text = ""
var text = ""
if (keystateSource.data["Caps Lock"]["Locked"]) {
if (keystateSource.data["Caps Lock"]["Locked"]) {
text += i18nd("plasma_lookandfeel_org.kde.lookandfeel","Caps Lock is on")
text += i18nd("plasma_lookandfeel_org.kde.lookandfeel","Caps Lock is on")
if (root.notification) {
if (root.notification) {
text += " • "
text += " • "
}
}
}
}
text += root.notification
text += root.notification
return text
return text
}
}


onLoginRequest: {
onLoginRequest: {
root.notification = ""
root.notification = ""
authenticator.tryUnlock(password)
authenticator.tryUnlock(password)
}
}


actionItems: [
actionItems: [
ActionButton {
ActionButton {
text: i18nd("plasma_lookandfeel_org.kde.lookandfeel", "Switch User")
text: i18nd("plasma_lookandfeel_org.kde.lookandfeel", "Switch User")
iconSource: "system-switch-user"
iconSource: "system-switch-user"
onClicked: mainStack.push(switchSessionPage)
onClicked: mainStack.push(switchSessionPage)
// the current session isn't listed in the model, hence a check for greater than zero, not one
// the current session isn't listed in the model, hence a check for greater than zero, not one
visible: (sessionsModel.count > 0 || sessionsModel.canStartNewSession) && sessionsModel.canSwitchUser
visible: (sessionsModel.count > 0 || sessionsModel.canStartNewSession) && sessionsModel.canSwitchUser
}
}
]
]


Loader {
Loader {
Layout.fillWidth: true
Layout.fillWidth: true
Layout.preferredHeight: item ? item.implicitHeight : 0
Layout.preferredHeight: item ? item.implicitHeight : 0
active: config.showMediaControls
active: config.showMediaControls
source: "MediaControls.qml"
source: "MediaControls.qml"
}
}
}
}


Component.onCompleted: {
Component.onCompleted: {
if (defaultToSwitchUser) { //context property
if (defaultToSwitchUser) { //context property
mainStack.push({
mainStack.push({
item: switchSessionPage,
item: switchSessionPage,
immediate: true});
immediate: true});
}
}
}
}
}
}


Loader {
Loader {
id: inputPanel
id: inputPanel
state: "hidden"
state: "hidden"
readonly property bool keyboardActive: item ? item.active : false
readonly property bool keyboardActive: item ? item.active : false
anchors {
anchors {
left: parent.left
left: parent.left
right: parent.right
right: parent.right
}
}
function showHide() {
function showHide() {
state = state == "hidden" ? "visible" : "hidden";
state = state == "hidden" ? "visible" : "hidden";
}
}
Component.onCompleted: inputPanel.source = "../components/VirtualKeyboard.qml"
Component.onCompleted: inputPanel.source = "../components/VirtualKeyboard.qml"


onKeyboardActiveChanged: {
onKeyboardActiveChanged: {
if (keyboardActive) {
if (keyboardActive) {
state = "visible";
state = "visible";
} else {
} else {
state = "hidden";
state = "hidden";
}
}
}
}
states: [
states: [
State {
State {
name: "visible"
name: "visible"
PropertyChanges {
PropertyChanges {
target: mainStack
target: mainStack
y: Math.min(0, lockScreenRoot.height - inputPanel.height - mainBlock.visibleBoundary)
y: Math.min(0, lockScreenRoot.height - inputPanel.height - mainBlock.visibleBoundary)
}
}
PropertyChanges {
PropertyChanges {
target: inputPanel
target: inputPanel
y: lockScreenRoot.height - inputPanel.height
y: lockScreenRoot.height - inputPanel.height
opacity: 1
opacity: 1
}
}
},
},
State {
State {
name: "hidden"
name: "hidden"
PropertyChanges {
PropertyChanges {
target: mainStack
target: mainStack
y: 0
y: 0
}
}
PropertyChanges {
PropertyChanges {
target: inputPanel
target: inputPanel
y: lockScreenRoot.height - lockScreenRoot.height/4
y: lockScreenRoot.height - lockScreenRoot.height/4
opacity: 0
opacity: 0
}
}
}
}
]
]
transitions: [
transitions: [
Transition {
Transition {
from: "hidden"
from: "hidden"
to: "visible"
to: "visible"
SequentialAnimation {
SequentialAnimation {
ScriptAction {
ScriptAction {
script: {
script: {
inputPanel.item.activated = true;
inputPanel.item.activated = true;
Qt.inputMethod.show();
Qt.inputMethod.show();
}
}
}
}
ParallelAnimation {
ParallelAnimation {
NumberAnimation {
NumberAnimation {
target: mainStack
target: mainStack
property: "y"
property: "y"
duration: units.longDuration
duration: units.longDuration
easing.type: Easing.InOutQuad
easing.type: Easing.InOutQuad
}
}
NumberAnimation {
NumberAnimation {
target: inputPanel
target: inputPanel
property: "y"
property: "y"
duration: units.longDuration
duration: units.longDuration
easing.type: Easing.OutQuad
easing.type: Easing.OutQuad
}
}
OpacityAnimator {
OpacityAnimator {
target: inputPanel
target: inputPanel
duration: units.longDuration
duration: units.longDuration
easing.type: Easing.OutQuad
easing.type: Easing.OutQuad
}
}
}
}
}
}
},
},
Transition {
Transition {
from: "visible"
from: "visible"
to: "hidden"
to: "hidden"
SequentialAnimation {
SequentialAnimation {
ParallelAnimation {
ParallelAnimation {
NumberAnimation {
NumberAnimation {
target: mainStack
target: mainStack
property: "y"
property: "y"
duration: units.longDuration
duration: units.longDuration
easing.type: Easing.InOutQuad
easing.type: Easing.InOutQuad
}
}
NumberAnimation {
NumberAnimation {
target: inputPanel
target: inputPanel
property: "y"
property: "y"
duration: units.longDuration
duration: units.longDuration
easing.type: Easing.InQuad
easing.type: Easing.InQuad
}
}
OpacityAnimator {
OpacityAnimator {
target: inputPanel
target: inputPanel
duration: units.longDuration
duration: units.longDuration
easing.type: Easing.InQuad
easing.type: Easing.InQuad
}
}
}
}
ScriptAction {
ScriptAction {
script: {
script: {
Qt.inputMethod.hide();
Qt.inputMethod.hide();
}
}
}
}
}
}
}
}
]
]
}
}


Component {
Component {
id: switchSessionPage
id: switchSessionPage
SessionManagementScreen {
SessionManagementScreen {
property var switchSession: finalSwitchSession
property var switchSession: finalSwitchSession


Stack.onStatusChanged: {
Stack.onStatusChanged: {
if (Stack.status == Stack.Activating) {
if (Stack.status == Stack.Activating) {
focus = true
focus = true
}
}
}
}


userListModel: sessionsModel
userListModel: sessionsModel


// initiating animation of lockscreen for session switch
// initiating animation of lockscreen for session switch
function initSwitchSession() {
function initSwitchSession() {
lockScreenRoot.state = 'onOtherSession'
lockScreenRoot.state = 'onOtherSession'
}
}


// initiating session switch and preparing lockscreen for possible return of user
// initiating session switch and preparing lockscreen for possible return of user
function finalSwitchSession() {
function finalSwitchSession() {
mainStack.pop({immediate:true})
mainStack.pop({immediate:true})
sessionsModel.switchUser(userListCurrentModelData.vtNumber)
sessionsModel.switchUser(userListCurrentModelData.vtNumber)
lockScreenRoot.state = ''
lockScreenRoot.state = ''
}
}


Keys.onLeftPressed: userList.decrementCurrentIndex()
Keys.onLeftPressed: userList.decrementCurrentIndex()
Keys.onRightPressed: userList.incrementCurrentIndex()
Keys.onRightPressed: userList.incrementCurrentIndex()
Keys.onEnterPressed: initSwitchSession()
Keys.onEnterPressed: initSwitchSession()
Keys.onReturnPressed: initSwitchSession()
Keys.onReturnPressed: initSwitchSession()
Keys.onEscapePressed: mainStack.pop()
Keys.onEscapePressed: mainStack.pop()


PlasmaComponents.Button {
PlasmaComponents.Button {
Layout.fillWidth: true
Layout.fillWidth: true
// the magic "-1" vtNumber indicates the "New Session" entry
// the magic "-1" vtNumber indicates the "New Session" entry
text: userListCurrentModelData.vtNumber === -1 ? i18nd("plasma_lookandfeel_org.kde.lookandfeel", "Start New Session") : i18nd("plasma_lookandfeel_org.kde.lookandfeel", "Switch Session")
text: userListCurrentModelData.vtNumber === -1 ? i18nd("plasma_lookandfeel_org.kde.lookandfeel", "Start New Session") : i18nd("plasma_lookandfeel_org.kde.lookandfeel", "Switch Session")
onClicked: initSwitchSession()
onClicked: initSwitchSession()
}
}


actionItems: [
actionItems: [
ActionButton {
ActionButton {
iconSource: "go-previous"
iconSource: "go-previous"
text: i18nd("plasma_lookandfeel_org.kde.lookandfeel","Back")
text: i18nd("plasma_lookandfeel_org.kde.lookandfeel","Back")
onClicked: mainStack.pop()
onClicked: mainStack.pop()
}
}
]
]
}
}
}
}


Loader {
Loader {
active: root.viewVisible
active: root.viewVisible
source: "LockOsd.qml"
source: "LockOsd.qml"
anchors {
anchors {
horizontalCenter: parent.horizontalCenter
horizontalCenter: parent.horizontalCenter
bottom: parent.bottom
bottom: parent.bottom
bottomMargin: units.largeSpacing
bottomMargin: units.largeSpacing
}
}
}
}


RowLayout {
RowLayout {
id: footer
id: footer
anchors {
anchors {
bottom: parent.bottom
bottom: parent.bottom
left: parent.left
left: parent.left
right: parent.right
right: parent.right
margins: units.smallSpacing
margins: units.smallSpacing
}
}


PlasmaComponents.ToolButton {
PlasmaComponents.ToolButton {
text: i18ndc("plasma_lookandfeel_org.kde.lookandfeel", "Button to show/hide virtual keyboard", "Virtual Keyboard")
text: i18ndc("plasma_lookandfeel_org.kde.lookandfeel", "Button to show/hide virtual keyboard", "Virtual Keyboard")
iconName: inputPanel.keyboardActive ? "input-keyboard-virtual-on" : "input-keyboard-virtual-off"
iconName: inputPanel.keyboardActive ? "input-keyboard-virtual-on" : "input-keyboard-virtual-off"
onClicked: inputPanel.showHide()
onClicked: inputPanel.showHide()


visible: inputPanel.status == Loader.Ready
visible: inputPanel.status == Loader.Ready
}
}


KeyboardLayoutButton {
KeyboardLayoutButton {
}
}


Item {
Item {
Layout.fillWidth: true
Layout.fillWidth: true
}
}


Battery {}
Battery {}
}
}
}
}


Component.onCompleted: {
Component.onCompleted: {
// version support checks
// version support checks
if (root.interfaceVersion < 1) {
if (root.interfaceVersion < 1) {
// ksmserver of 5.4, with greeter of 5.5
// ksmserver of 5.4, with greeter of 5.5
root.viewVisible = true;
root.viewVisible = true;
}
}
}
}
}
}