diff --git a/lookandfeel/contents/components/KeyboardLayoutButton.qml b/lookandfeel/contents/components/KeyboardLayoutButton.qml index 4fd402d49..fd4c896ef 100644 --- a/lookandfeel/contents/components/KeyboardLayoutButton.qml +++ b/lookandfeel/contents/components/KeyboardLayoutButton.qml @@ -1,53 +1,47 @@ /*************************************************************************** * Copyright (C) 2014 by Daniel Vrátil * * * * 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . * ***************************************************************************/ import QtQuick 2.1 +import QtQuick.Controls 1.1 as QQC import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.plasma.workspace.keyboardlayout 1.0 -PlasmaComponents.Button { +PlasmaComponents.ToolButton { id: kbLayoutButton - property bool hidden : false - implicitWidth: minimumWidth text: layout.currentLayoutDisplayName Accessible.name: i18ndc("plasma_lookandfeel_org.kde.lookandfeel", "Button to change keyboard layout", "Switch layout") - onClicked: { - layout.nextLayout(); - } - - visible: !hidden && layout.layouts.length > 1 + visible: layout.layouts.length > 1 + onClicked: layout.nextLayout() KeyboardLayout { id: layout - - function nextLayout() { + function nextLayout() { var layouts = layout.layouts; var index = (layouts.indexOf(layout.currentLayout)+1) % layouts.length; - layout.currentLayout = layouts[index]; } } } diff --git a/lookandfeel/contents/components/Login.qml b/lookandfeel/contents/components/SessionManagementScreen.qml similarity index 53% rename from lookandfeel/contents/components/Login.qml rename to lookandfeel/contents/components/SessionManagementScreen.qml index c56637e02..52871c1fe 100644 --- a/lookandfeel/contents/components/Login.qml +++ b/lookandfeel/contents/components/SessionManagementScreen.qml @@ -1,159 +1,115 @@ /* * 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 QtQuick.Layouts 1.1 import QtQuick.Controls 1.1 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents Item { id: root - /* - * Whether a text box for the user to type a username should be visible - */ - property bool showUsernamePrompt: false /* * 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: userList.model + property alias userListModel: userListView.model /* * Self explanatory */ - property alias userListCurrentIndex: userList.currentIndex + property alias userListCurrentIndex: userListView.currentIndex + property var userListCurrentModelData: userListView.currentItem === null ? [] : userListView.currentItem.m + property alias userList: userListView - /* - * 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 - */ - signal loginRequest(string username, string password) + default property alias _children: innerLayout.children - function startLogin() { - var username = showUsernamePrompt ? userNameInput.text : userList.selectedUser - var password = passwordBox.text - loginRequest(username, password); - } UserList { - id: userList + id: userListView anchors { bottom: parent.verticalCenter left: parent.left right: parent.right } - onUserSelected: passwordBox.forceActiveFocus() } ColumnLayout { id: prompts anchors.top: parent.verticalCenter anchors.topMargin: units.gridUnit * 0.5 anchors.horizontalCenter: parent.horizontalCenter height: Math.max(implicitHeight, units.gridUnit * 10) width: Math.max(implicitWidth, units.gridUnit * 16) PlasmaComponents.Label { id: notificationsLabel Layout.fillWidth: true horizontalAlignment: Text.AlignHCenter wrapMode: Text.WordWrap font.italic: true } - PlasmaComponents.TextField { - id: userNameInput - Layout.fillWidth: true - - visible: showUsernamePrompt - focus: showUsernamePrompt //if there's a username prompt it gets focus first, otherwise password does - placeholderText: i18nd("plasma_lookandfeel_org.kde.lookandfeel", "Username"); - } - - PlasmaComponents.TextField { - id: passwordBox + ColumnLayout { Layout.fillWidth: true - - placeholderText: i18nd("plasma_lookandfeel_org.kde.lookandfeel", "Password"); - focus: !showUsernamePrompt - echoMode: TextInput.Password - - onAccepted: startLogin() - - 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 - } - } + id: innerLayout } - PlasmaComponents.Button { - id: loginButton - Layout.fillWidth: true - text: i18nd("plasma_lookandfeel_org.kde.lookandfeel", "Login") - onClicked: startLogin(); - } Item { Layout.fillHeight: true } } Row { //deliberately not rowlayout as I'm not trying to resize child items id: actionItemsLayout spacing: units.smallSpacing //align centre, but cap to the width of the screen anchors { top: prompts.bottom topMargin: units.smallSpacing horizontalCenter: parent.horizontalCenter } } } diff --git a/lookandfeel/contents/components/UserDelegate.qml b/lookandfeel/contents/components/UserDelegate.qml index 85b65e61b..a12d577db 100644 --- a/lookandfeel/contents/components/UserDelegate.qml +++ b/lookandfeel/contents/components/UserDelegate.qml @@ -1,156 +1,157 @@ /* * Copyright 2014 David Edmundson * Copyright 2014 Aleix Pol Gonzalez * * 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.4 import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.components 2.0 as PlasmaComponents Item { id: wrapper property bool isCurrent: true + readonly property var m: model property string name property string userName property string iconSource signal clicked() property real faceSize: Math.min(width, height - usernameDelegate.height - units.largeSpacing) opacity: isCurrent ? 1.0 : 0.5 Behavior on opacity { OpacityAnimator { duration: units.longDuration } } Item { id: imageSource width: faceSize height: faceSize //we sometimes have a path to an image sometimes an icon //IconItem tries to load a full path as an icon which is rubbish //we try loading it as a normal image, if that fails we fall back to IconItem Image { id: face source: wrapper.iconSource fillMode: Image.PreserveAspectCrop anchors.fill: parent } PlasmaCore.IconItem { id: faceIcon source: visible ? "user-identity" : undefined visible: (face.status == Image.Error || face.status == Image.Null) anchors.fill: parent anchors.margins: units.gridUnit * 0.5 // because mockup says so... colorGroup: PlasmaCore.ColorScope.colorGroup } } ShaderEffect { anchors.top: parent.top anchors.horizontalCenter: parent.horizontalCenter width: imageSource.width height: imageSource.height supportsAtlasTextures: true property var source: ShaderEffectSource { sourceItem: imageSource hideSource: true live: false } property var colorBorder: PlasmaCore.ColorScope.textColor //draw a circle with an antialised 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 vec4 colorBorder; float blend = 0.01; float innerRadius = 0.47; float outerRadius = innerRadius + 0.02; vec4 colorEmpty = vec4(0.0, 0.0, 0.0, 0.0); void main() { vec4 colorSource = texture2D(source, qt_TexCoord0.st); vec2 m = qt_TexCoord0 - vec2(0.5, 0.5); 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; } " } PlasmaComponents.Label { id: usernameDelegate anchors { bottom: parent.bottom left: parent.left right: parent.right } height: implicitHeight // work around stupid bug in Plasma Components that sets the height text: wrapper.name 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/lookandfeel/contents/components/UserList.qml b/lookandfeel/contents/components/UserList.qml index 1bf3f1f44..9f03446e8 100644 --- a/lookandfeel/contents/components/UserList.qml +++ b/lookandfeel/contents/components/UserList.qml @@ -1,63 +1,86 @@ /* * Copyright 2014 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 ListView { id: view readonly property string selectedUser: currentItem ? currentItem.userName : "" readonly property int userItemWidth: units.gridUnit * 8 readonly property int userItemHeight: units.gridUnit * 8 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 delegate: UserDelegate { - name: model.realName || model.name - userName: model.name iconSource: model.icon || "" + name: { + var displayName = model.realName || model.name + + if (model.vtNumber === undefined) { + 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) + } + } + + userName: model.name width: userItemWidth height: userItemHeight 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/lookandfeel/contents/lockscreen/ChangeSession.qml b/lookandfeel/contents/lockscreen/ChangeSession.qml deleted file mode 100644 index 95a3619ae..000000000 --- a/lookandfeel/contents/lockscreen/ChangeSession.qml +++ /dev/null @@ -1,92 +0,0 @@ -/******************************************************************** - 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.0 -import QtQuick.Layouts 1.1 -import QtQuick.Controls 1.1 -import org.kde.plasma.components 2.0 as PlasmaComponents -import "../components" - -BreezeBlock { - id: selectSessionBlock - - Action { - onTriggered: stackView.pop() - shortcut: "Escape" - } - - main: UserSelect { - id: sessionSelect - - model: sessionsModel - delegate: UserDelegate { - // so the button can access it from outside through currentItem - readonly property int userVt: model.vtNumber - - name: { - if (!model.session) { - return i18ndc("plasma_lookandfeel_org.kde.lookandfeel", "Nobody logged in on that session", "Unused") - } - - var displayName = model.realName || model.name - - 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 - iconSource: model.icon || "user-identity" - width: ListView.view.userItemWidth - height: ListView.view.userItemHeight - faceSize: ListView.view.userFaceSize - - onClicked: { - ListView.view.currentIndex = index; - ListView.view.forceActiveFocus(); - } - } - } - - controls: Item { - height: childrenRect.height - RowLayout { - anchors.centerIn: parent - PlasmaComponents.Button { - text: i18nd("plasma_lookandfeel_org.kde.lookandfeel","Cancel") - onClicked: stackView.pop() - } - PlasmaComponents.Button { - text: i18nd("plasma_lookandfeel_org.kde.lookandfeel","Change Session") - onClicked: { - sessionsModel.switchUser(selectSessionBlock.mainItem.selectedItem.userVt) - stackView.pop() - userSelect.selectedIndex = 0 - } - } - } - } -} diff --git a/lookandfeel/contents/lockscreen/LockScreenUi.qml b/lookandfeel/contents/lockscreen/LockScreenUi.qml index 4caeef032..ed099e444 100644 --- a/lookandfeel/contents/lockscreen/LockScreenUi.qml +++ b/lookandfeel/contents/lockscreen/LockScreenUi.qml @@ -1,96 +1,190 @@ /******************************************************************** 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.5 import QtQuick.Controls 1.1 +import QtQuick.Layouts 1.1 + import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.components 2.0 as PlasmaComponents + import org.kde.plasma.private.sessions 2.0 import "../components" -Item { +PlasmaCore.ColorScope { id: lockScreenRoot + colorGroup: PlasmaCore.Theme.ComplementaryColorGroup + Connections { target: authenticator onFailed: { root.notification = i18nd("plasma_lookandfeel_org.kde.lookandfeel","Unlocking failed"); } onGraceLockedChanged: { if (!authenticator.graceLocked) { root.notification = ""; root.clearPassword(); } } onMessage: { root.notification = msg; } onError: { root.notification = err; } } SessionsModel { id: sessionsModel } PlasmaCore.DataSource { id: keystateSource engine: "keystate" connectedSources: "Caps Lock" } Loader { id: changeSessionComponent active: false source: "ChangeSession.qml" visible: false } + Clock { + anchors.bottom: parent.verticalCenter + anchors.bottomMargin: units.gridUnit * 13 + anchors.horizontalCenter: parent.horizontalCenter + } + + ListModel { + id: users + + Component.onCompleted: { + users.append({name: kscreenlocker_userName, + realName: kscreenlocker_userName, + icon: kscreenlocker_userImage, + + }) + if (sessionsModel.canStartNewSession) { + users.append({realName: i18nd("plasma_lookandfeel_org.kde.lookandfeel", "New Session"), + name: "__new_session", + icon: "system-log-out", //TODO Need an icon for new session + }) + } + } + } + StackView { - id: stackView - height: units.largeSpacing * 14 - anchors { - verticalCenter: parent.verticalCenter - left: parent.left - right: parent.right + id: mainStack + anchors.fill: parent + focus: true //StackView is an implicit focus scope, so we need to give this focus so the item inside will have it + initialItem: MainBlock { + userListModel: users + notificationMessage: { + var text = "" + if (keystateSource.data["Caps Lock"]["Locked"]) { + text += i18nd("plasma_lookandfeel_org.kde.lookandfeel","Caps Lock is on") + if (root.notification) { + text += " • " + } + } + text += root.notification + return text + } + + onNewSession: { + sessionsModel.startNewSession(false); + } + + onLoginRequest: { + root.notification = "" + authenticator.tryUnlock(password) + } + + actionItems: [ + ActionButton { + text: i18nd("org.kde.plasma_lookandfeel_org.kde.lookandfeel", "Switch User") + iconSource: "system-switch-user" + onClicked: mainStack.push(switchSessionPage) + visible: sessionsModel.count > 1 && sessionsModel.canSwitchUser + } + ] } + } - initialItem: Loader { - active: root.viewVisible - source: "MainBlock.qml" + Component { + id: switchSessionPage + SessionManagementScreen { + userListModel: sessionsModel + + PlasmaComponents.Button { + Layout.fillWidth: true + text: "Switch Session" + onClicked: { + sessionsModel.switchUser(userListCurrentModelData.vtNumber) + } + } + + actionItems: [ + ActionButton { + iconSource: "go-previous" + text: i18nd("plasma_lookandfeel_org.kde.lookandfeel","Back") + onClicked: mainStack.pop() + } + ] } } Loader { active: root.viewVisible source: "LockOsd.qml" anchors { horizontalCenter: parent.horizontalCenter bottom: parent.bottom } } + RowLayout { + id: footer + anchors { + bottom: parent.bottom + left: parent.left + right: parent.right + margins: units.smallSpacing + } + + KeyboardLayoutButton { + } + + Item { + Layout.fillWidth: true + } + } + + Component.onCompleted: { // version support checks if (root.interfaceVersion < 1) { // ksmserver of 5.4, with greeter of 5.5 root.viewVisible = true; } } } diff --git a/lookandfeel/contents/lockscreen/Login.qml b/lookandfeel/contents/lockscreen/Login.qml deleted file mode 100644 index 252fb8442..000000000 --- a/lookandfeel/contents/lockscreen/Login.qml +++ /dev/null @@ -1,167 +0,0 @@ -/* - * 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 QtQuick.Layouts 1.1 -import QtQuick.Controls 1.1 - -import org.kde.plasma.core 2.0 as PlasmaCore -import org.kde.plasma.components 2.0 as PlasmaComponents - -Item { - id: root - - /* - * Whether a text box for the user to type a username should be visible - */ - property bool showUsernamePrompt: false - /* - * 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 - */ - property alias userListModel: userList.model - - /* - * Self explanatory - */ - property alias userListCurrentIndex: userList.currentIndex - - - /* - * 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 - */ - signal loginRequest(string username, string password) - - function startLogin() { - var username = showUsernamePrompt ? userNameInput.text : userList.selectedUser - var password = passwordBox.text - loginRequest(username, password); - - //work around a bug in TextHandle in QQC - //for some reason, it changes the parent if activeFocus is set - //this means if we close the window when the control is activeFocus - //however on app shutdown this leads us to reparent whilst the parent item (the TextInputWithHandles object) is destroying it's children - //this leads to a nasty crash -// passwordBox.focus = false; - } - - UserList { - id: userList - anchors { - bottom: parent.verticalCenter - left: parent.left - right: parent.right - } - onUserSelected: passwordBox.forceActiveFocus() - } - - ColumnLayout { - id: prompts - anchors.top: parent.verticalCenter - anchors.topMargin: units.gridUnit * 0.5 - anchors.horizontalCenter: parent.horizontalCenter - - height: Math.max(implicitHeight, units.gridUnit * 10) - width: Math.max(implicitWidth, units.gridUnit * 16) - - PlasmaComponents.Label { - id: notificationsLabel - - Layout.fillWidth: true - - horizontalAlignment: Text.AlignHCenter - wrapMode: Text.WordWrap - font.italic: true - } - - PlasmaComponents.TextField { - id: userNameInput - Layout.fillWidth: true - - visible: showUsernamePrompt - focus: showUsernamePrompt //if there's a username prompt it gets focus first, otherwise password does - placeholderText: i18nd("plasma_lookandfeel_org.kde.lookandfeel", "Username"); - } - - PlasmaComponents.TextField { - id: passwordBox - Layout.fillWidth: true - - placeholderText: "Password" - focus: !showUsernamePrompt - echoMode: TextInput.Password - - onAccepted: startLogin() - - 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 - } - } - } - - PlasmaComponents.Button { - id: loginButton - Layout.fillWidth: true - - text: i18nd("plasma_lookandfeel_org.kde.lookandfeel", "Login") - onClicked: startLogin(); - } - Item { - Layout.fillHeight: true - } - } - - Row { //deliberately not rowlayout as I'm not trying to resize child items - id: actionItemsLayout - spacing: units.smallSpacing - - //align centre, but cap to the width of the screen - anchors { - top: prompts.bottom - topMargin: units.gridUnit * 0.25 - horizontalCenter: parent.horizontalCenter - } - } -} diff --git a/lookandfeel/contents/lockscreen/MainBlock.qml b/lookandfeel/contents/lockscreen/MainBlock.qml index e754c2016..05ad49480 100644 --- a/lookandfeel/contents/lockscreen/MainBlock.qml +++ b/lookandfeel/contents/lockscreen/MainBlock.qml @@ -1,191 +1,96 @@ -/******************************************************************** - This file is part of the KDE project. +/* + * 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 -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.0 import QtQuick.Layouts 1.1 import QtQuick.Controls 1.1 -import org.kde.plasma.components 2.0 as PlasmaComponents + import org.kde.plasma.core 2.0 as PlasmaCore -import org.kde.plasma.workspace.keyboardlayout 1.0 +import org.kde.plasma.components 2.0 as PlasmaComponents + import "../components" -BreezeBlock { - id: block - main: UserSelect { - id: usersSelection +SessionManagementScreen { + id: root + /* + * 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 + */ + signal loginRequest(string password) - onVisibleChanged: { - if(visible) { - selectedIndex = 0; - } - } - Component.onCompleted: root.userSelect = usersSelection - - notification: { - var text = "" - if (keystateSource.data["Caps Lock"]["Locked"]) { - text += i18nd("plasma_lookandfeel_org.kde.lookandfeel","Caps Lock is on") - if (root.notification) { - text += " • " - } - } - text += root.notification - return text - } + /* + */ + signal newSession() - model: ListModel { - id: users - - Component.onCompleted: { - users.append({name: kscreenlocker_userName, - realName: kscreenlocker_userName, - icon: kscreenlocker_userImage, - showPassword: true, - ButtonLabel: i18nd("plasma_lookandfeel_org.kde.lookandfeel", "Unlock"), - ButtonAction: "unlock" - }) - if (sessionsModel.canStartNewSession) { - users.append({realName: i18nd("plasma_lookandfeel_org.kde.lookandfeel", "New Session"), - icon: "system-log-out", //TODO Need an icon for new session - ButtonLabel: i18nd("plasma_lookandfeel_org.kde.lookandfeel", "Create Session"), - ButtonAction: "newSession" - }) - } - if (sessionsModel.canSwitchUser && sessionsModel.count > 0) { - users.append({realName: i18nd("plasma_lookandfeel_org.kde.lookandfeel", "Change Session"), - icon: "system-switch-user", - ButtonLabel: i18nd("plasma_lookandfeel_org.kde.lookandfeel", "Change Session..."), - ButtonAction: "changeSession" - }) - } - } - } + function startLogin() { + var password = passwordBox.text + + //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 focussed + //See https://bugreports.qt.io/browse/QTBUG-55460 + loginButton.forceActiveFocus(); + + loginRequest(password); } - controls: Item { - height: childrenRect.height + PlasmaComponents.Label { + id: notificationsLabel + Layout.fillWidth: true - function unlockFunction() { - authenticator.tryUnlock(passwordInput.text); - } - ColumnLayout { - anchors.horizontalCenter: parent.horizontalCenter - RowLayout { - anchors.horizontalCenter: parent.horizontalCenter - - KeyboardLayoutButton { - id: kbdLayoutButton - hidden: !passwordInput.visible - KeyNavigation.tab: block.mainItem - } - - PlasmaComponents.TextField { - id: passwordInput - placeholderText: i18nd("plasma_lookandfeel_org.kde.lookandfeel","Password") - echoMode: TextInput.Password - enabled: !authenticator.graceLocked - onAccepted: actionButton.clicked(null) - focus: true - //HACK: Similar hack is needed in sddm loginscreen - //TODO: investigate - Timer { - interval: 200 - running: true - repeat: false - onTriggered: passwordInput.forceActiveFocus() - } - visible: block.mainItem.model.get(block.mainItem.selectedIndex) ? !!block.mainItem.model.get(block.mainItem.selectedIndex).showPassword : false - onVisibleChanged: { - if (visible) { - forceActiveFocus(); - } - text = ""; - } - onTextChanged: { - if (text == "") { - clearTimer.stop(); - } else { - clearTimer.restart(); - } - } - - Keys.onLeftPressed: { - if (text == "") { - root.userSelect.decrementCurrentIndex(); - } else { - event.accepted = false; - } - } - Keys.onRightPressed: { - if (text == "") { - root.userSelect.incrementCurrentIndex(); - } else { - event.accepted = false; - } - } - Timer { - id: clearTimer - interval: 30000 - repeat: false - onTriggered: { - passwordInput.text = ""; - } - } - KeyNavigation.backtab: block.mainItem - } - - PlasmaComponents.Button { - id: actionButton - Layout.minimumWidth: passwordInput.width - text: block.mainItem.model.get(block.mainItem.selectedIndex) ? block.mainItem.model.get(block.mainItem.selectedIndex).ButtonLabel : "" - enabled: !authenticator.graceLocked - onClicked: switch(block.mainItem.model.get(block.mainItem.selectedIndex)["ButtonAction"]) { - case "unlock": - unlockFunction(); - break; - case "newSession": - // false means don't lock, we're the lock screen - sessionsModel.startNewSession(false); - break; - case "changeSession": - changeSessionComponent.active = true - stackView.push(changeSessionComponent.item) - break; - } - KeyNavigation.tab: kbdLayoutButton - } - - Connections { - target: root - onClearPassword: { - passwordInput.selectAll(); - passwordInput.forceActiveFocus(); - } - } - Keys.onLeftPressed: { - root.userSelect.decrementCurrentIndex(); - } - Keys.onRightPressed: { - root.userSelect.incrementCurrentIndex(); - } + horizontalAlignment: Text.AlignHCenter + wrapMode: Text.WordWrap + font.italic: true + } + + PlasmaComponents.TextField { + id: passwordBox + Layout.fillWidth: true + + placeholderText: i18nd("plasma_lookandfeel_org", "Password") + focus: true + echoMode: TextInput.Password + + onAccepted: startLogin() + + visible: userListCurrentIndex == 0 + + //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 } } } + + PlasmaComponents.Button { + id: loginButton + Layout.fillWidth: true + + text: userListCurrentIndex == 0 ? i18nd("plasma_lookandfeel_org", "Unlock") : i18nd("plasma_lookandfeel_org", "Start New Session") + onClicked: userListCurrentIndex == 0 ? startLogin(passwordBox.text) : newSession() + } } diff --git a/sddm-theme/Login.qml b/sddm-theme/Login.qml new file mode 100644 index 000000000..86b9311ab --- /dev/null +++ b/sddm-theme/Login.qml @@ -0,0 +1,74 @@ +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 2.0 as PlasmaComponents + +SessionManagementScreen { + + property bool showUsernamePrompt: false + + signal loginRequest(string username, string password) + + /* + * 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 + + //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 focussed + //DAVE REPORT THE FRICKING THING AND PUT A LINK + loginButton.forceActiveFocus(); + loginRequest(username, password); + } + + PlasmaComponents.TextField { + id: userNameInput + Layout.fillWidth: true + + visible: showUsernamePrompt + focus: showUsernamePrompt //if there's a username prompt it gets focus first, otherwise password does + placeholderText: i18nd("plasma_lookandfeel_org.kde.lookandfeel", "Username") + } + + PlasmaComponents.TextField { + id: passwordBox + Layout.fillWidth: true + + placeholderText: i18nd("plasma_lookandfeel_org.kde.lookandfeel", "Password") + focus: !showUsernamePrompt + echoMode: TextInput.Password + + onAccepted: startLogin() + + 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 + } + } + } + PlasmaComponents.Button { + id: loginButton + Layout.fillWidth: true + + text: i18nd("plasma_lookandfeel_org.kde.lookandfeel", "Login") + onClicked: startLogin(); + } + +}