Warning, /plasma/plasma-workspace/kcms/users/src/ui/FingerprintDialog.qml is written in an unsupported language. File is not indexed.

0001 /*
0002     Copyright 2020  Devin Lin <espidev@gmail.com>
0003 
0004     This library is free software; you can redistribute it and/or
0005     modify it under the terms of the GNU Lesser General Public
0006     License as published by the Free Software Foundation; either
0007     version 2.1 of the License, or (at your option) version 3, or any
0008     later version accepted by the membership of KDE e.V. (or its
0009     successor approved by the membership of KDE e.V.), which shall
0010     act as a proxy defined in Section 6 of version 3 of the license.
0011 
0012     This library is distributed in the hope that it will be useful,
0013     but WITHOUT ANY WARRANTY; without even the implied warranty of
0014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0015     Lesser General Public License for more details.
0016 
0017     You should have received a copy of the GNU Lesser General Public
0018     License along with this library.  If not, see <http://www.gnu.org/licenses/>.
0019 */
0020 
0021 import QtQuick 2.12
0022 import QtQuick.Layouts 1.3
0023 import QtQuick.Shapes 1.12
0024 import QtQuick.Controls 2.5 as QQC2
0025 
0026 import org.kde.kirigami 2.12 as Kirigami
0027 import org.kde.plasma.kcm.users 1.0 as UsersKCM
0028 import FingerprintModel 1.0
0029 
0030 Kirigami.OverlaySheet {
0031     id: fingerprintRoot
0032 
0033     property var fingerprintModel: kcm.fingerprintModel
0034     property string currentFinger
0035 
0036     enum DialogState {
0037         FingerprintList,
0038         PickFinger,
0039         Enrolling,
0040         EnrollComplete
0041     }
0042 
0043     title: i18n("Configure Fingerprints")
0044 
0045     footer: Kirigami.ActionToolBar {
0046         flat: false
0047         alignment: Qt.AlignRight
0048 
0049         actions: [
0050             // FingerprintList State
0051             Kirigami.Action {
0052                 text: i18nc("@action:button 'all' refers to fingerprints", "Clear All")
0053                 visible: fingerprintModel.dialogState === FingerprintDialog.DialogState.FingerprintList
0054                 enabled: fingerprintModel.enrolledFingerprints.length !== 0
0055                 icon.name: "delete"
0056                 onTriggered: fingerprintModel.clearFingerprints();
0057             },
0058             Kirigami.Action {
0059                 text: i18n("Add")
0060                 visible: fingerprintModel.dialogState === FingerprintDialog.DialogState.FingerprintList
0061                 enabled: fingerprintModel.availableFingersToEnroll.length !== 0
0062                 icon.name: "list-add"
0063                 onTriggered: fingerprintModel.dialogState = FingerprintDialog.DialogState.PickFinger
0064             },
0065 
0066             // Enrolling State
0067             Kirigami.Action {
0068                 text: i18n("Cancel")
0069                 visible: fingerprintModel.dialogState === FingerprintDialog.DialogState.Enrolling
0070                 icon.name: "dialog-cancel"
0071                 onTriggered: fingerprintModel.stopEnrolling();
0072             },
0073 
0074             // EnrollComplete State
0075             Kirigami.Action {
0076                 text: i18n("Done")
0077                 visible: fingerprintModel.dialogState === FingerprintDialog.DialogState.EnrollComplete
0078                 icon.name: "dialog-ok"
0079                 onTriggered: fingerprintModel.stopEnrolling();
0080             }
0081         ]
0082     }
0083 
0084     Item {
0085         id: rootPanel
0086         implicitWidth: Kirigami.Units.gridUnit * 20
0087         Layout.maximumWidth: Kirigami.Units.gridUnit * 24
0088         Layout.leftMargin: Kirigami.Units.smallSpacing
0089         Layout.rightMargin: Kirigami.Units.smallSpacing
0090         height: Kirigami.Units.gridUnit * 18
0091 
0092         ColumnLayout {
0093             id: enrollFeedback
0094             spacing: Kirigami.Units.largeSpacing * 2
0095             visible: fingerprintModel.dialogState === FingerprintDialog.DialogState.Enrolling || fingerprintModel.dialogState === FingerprintDialog.DialogState.EnrollComplete
0096             anchors.fill: parent
0097 
0098             Kirigami.Heading {
0099                 level: 2
0100                 text: i18n("Enrolling Fingerprint")
0101                 textFormat: Text.PlainText
0102                 Layout.alignment: Qt.AlignHCenter
0103                 visible: fingerprintModel.dialogState === FingerprintDialog.DialogState.Enrolling
0104             }
0105 
0106             QQC2.Label {
0107                 text: {
0108                     if (fingerprintModel.scanType == FprintDevice.Press) {
0109                         if (fingerprintRoot.currentFinger == "right-index-finger") {
0110                             return i18n("Please repeatedly press your right index finger on the fingerprint sensor.")
0111                         } else if (fingerprintRoot.currentFinger == "right-middle-finger") {
0112                             return i18n("Please repeatedly press your right middle finger on the fingerprint sensor.")
0113                         } else if (fingerprintRoot.currentFinger == "right-ring-finger") {
0114                             return i18n("Please repeatedly press your right ring finger on the fingerprint sensor.")
0115                         } else if (fingerprintRoot.currentFinger == "right-little-finger") {
0116                             return i18n("Please repeatedly press your right little finger on the fingerprint sensor.")
0117                         } else if (fingerprintRoot.currentFinger == "right-thumb") {
0118                             return i18n("Please repeatedly press your right thumb on the fingerprint sensor.")
0119                         } else if (fingerprintRoot.currentFinger == "left-index-finger") {
0120                             return i18n("Please repeatedly press your left index finger on the fingerprint sensor.")
0121                         } else if (fingerprintRoot.currentFinger == "left-middle-finger") {
0122                             return i18n("Please repeatedly press your left middle finger on the fingerprint sensor.")
0123                         } else if (fingerprintRoot.currentFinger == "left-ring-finger") {
0124                             return i18n("Please repeatedly press your left ring finger on the fingerprint sensor.")
0125                         } else if (fingerprintRoot.currentFinger == "left-little-finger") {
0126                             return i18n("Please repeatedly press your left little finger on the fingerprint sensor.")
0127                         } else if (fingerprintRoot.currentFinger == "left-thumb") {
0128                             return i18n("Please repeatedly press your left thumb on the fingerprint sensor.")
0129                         }
0130                     } else if (fingerprintModel.scanType == FprintDevice.Swipe) {
0131                         if (fingerprintRoot.currentFinger == "right-index-finger") {
0132                             return i18n("Please repeatedly swipe your right index finger on the fingerprint sensor.")
0133                         } else if (fingerprintRoot.currentFinger == "right-middle-finger") {
0134                             return i18n("Please repeatedly swipe your right middle finger on the fingerprint sensor.")
0135                         } else if (fingerprintRoot.currentFinger == "right-ring-finger") {
0136                             return i18n("Please repeatedly swipe your right ring finger on the fingerprint sensor.")
0137                         } else if (fingerprintRoot.currentFinger == "right-little-finger") {
0138                             return i18n("Please repeatedly swipe your right little finger on the fingerprint sensor.")
0139                         } else if (fingerprintRoot.currentFinger == "right-thumb") {
0140                             return i18n("Please repeatedly swipe your right thumb on the fingerprint sensor.")
0141                         } else if (fingerprintRoot.currentFinger == "left-index-finger") {
0142                             return i18n("Please repeatedly swipe your left index finger on the fingerprint sensor.")
0143                         } else if (fingerprintRoot.currentFinger == "left-middle-finger") {
0144                             return i18n("Please repeatedly swipe your left middle finger on the fingerprint sensor.")
0145                         } else if (fingerprintRoot.currentFinger == "left-ring-finger") {
0146                             return i18n("Please repeatedly swipe your left ring finger on the fingerprint sensor.")
0147                         } else if (fingerprintRoot.currentFinger == "left-little-finger") {
0148                             return i18n("Please repeatedly swipe your left little finger on the fingerprint sensor.")
0149                         } else if (fingerprintRoot.currentFinger == "left-thumb") {
0150                             return i18n("Please repeatedly swipe your left thumb on the fingerprint sensor.")
0151                         }
0152                     }
0153                     return ""
0154                 }
0155                 textFormat: Text.PlainText
0156 
0157                 Layout.alignment: Qt.AlignHCenter
0158                 wrapMode: Text.Wrap
0159                 horizontalAlignment: Text.AlignHCenter
0160                 Layout.maximumWidth: parent.width
0161                 visible: fingerprintModel.dialogState === FingerprintDialog.DialogState.Enrolling
0162             }
0163 
0164             Kirigami.Heading {
0165                 level: 2
0166                 text: i18n("Finger Enrolled")
0167                 textFormat: Text.PlainText
0168                 Layout.alignment: Qt.AlignHCenter
0169                 visible: fingerprintModel.dialogState === FingerprintDialog.DialogState.EnrollComplete
0170             }
0171 
0172             // reset from back from whatever color was used before
0173             onVisibleChanged: progressCircle.colorTimer.restart();
0174 
0175             // progress circle
0176             FingerprintProgressCircle {
0177                 id: progressCircle
0178             }
0179 
0180             QQC2.Label {
0181                 text: fingerprintModel.enrollFeedback
0182                 textFormat: Text.PlainText
0183                 wrapMode: Text.Wrap
0184                 Layout.maximumWidth: parent.width
0185                 Layout.alignment: Qt.AlignVCenter | Qt.AlignHCenter
0186             }
0187         }
0188 
0189         ColumnLayout {
0190             id: pickFinger
0191             visible: fingerprintModel.dialogState === FingerprintDialog.DialogState.PickFinger
0192             anchors.centerIn: parent
0193             spacing: Kirigami.Units.largeSpacing
0194             width: parent.width
0195 
0196             Kirigami.Heading {
0197                 level: 2
0198                 text: i18n("Pick a finger to enroll")
0199                 textFormat: Text.PlainText
0200                 Layout.alignment: Qt.AlignHCenter
0201             }
0202 
0203             Item {
0204                 id: handContainer
0205                 implicitHeight: basePalm.height
0206                 Layout.fillWidth: true
0207 
0208                 property string currentFinger: ""
0209                 property string currentFingerData: ""
0210 
0211                 Image {
0212                     id: basePalm
0213                     source: kcm.recolorSVG(Qt.resolvedUrl("hand-images/palm.svg"), Kirigami.Theme.textColor)
0214                     fillMode: Image.PreserveAspectFit
0215                     width: handContainer.width
0216                     opacity: 0.25
0217                 }
0218 
0219                 Repeater {
0220                     model: fingerprintModel.availableFingersToEnroll
0221                     delegate: Image {
0222                         id: img
0223                         activeFocusOnTab: true
0224                         source: kcm.recolorSVG(Qt.resolvedUrl(`hand-images/${modelData.internalName}.svg`), color)
0225                         readonly property color color: focus ?
0226                             Kirigami.Theme.focusColor :
0227                             (maskArea.hovered ? Kirigami.Theme.hoverColor : Kirigami.Theme.textColor)
0228 
0229                         fillMode: Image.PreserveAspectFit
0230                         anchors.fill: parent
0231                         Accessible.name: modelData.friendlyName
0232                         Accessible.focusable: true
0233                         Accessible.role: Accessible.RadioButton
0234                         Accessible.onPressAction: {
0235                             img.activate()
0236                         }
0237                         Keys.onEnterPressed: {
0238                             img.activate()
0239                         }
0240                         function activate() {
0241                             fingerprintRoot.currentFinger = modelData.internalName;
0242                             fingerprintModel.startEnrolling(modelData.internalName);
0243                         }
0244                         UsersKCM.MaskMouseArea {
0245                             id: maskArea
0246                             anchors.fill: parent
0247                             onTapped: {
0248                                 img.activate()
0249                             }
0250                         }
0251                     }
0252                 }
0253 
0254                 Repeater {
0255                     model: fingerprintModel.unavailableFingersToEnroll
0256                     delegate: Image {
0257                         source: kcm.recolorSVG(Qt.resolvedUrl(`hand-images/${modelData.internalName}.svg`), Kirigami.Theme.textColor)
0258                         fillMode: Image.PreserveAspectFit
0259                         anchors.fill: parent
0260                         opacity: 0.25
0261                     }
0262                 }
0263             }
0264         }
0265 
0266         ColumnLayout {
0267             id: fingerprints
0268             spacing: Kirigami.Units.smallSpacing
0269             visible: fingerprintModel.dialogState === FingerprintDialog.DialogState.FingerprintList
0270             anchors.fill: parent
0271 
0272             Kirigami.InlineMessage {
0273                 id: errorMessage
0274                 type: Kirigami.MessageType.Error
0275                 visible: fingerprintModel.currentError !== ""
0276                 text: fingerprintModel.currentError
0277                 Layout.fillWidth: true
0278                 actions: [
0279                     Kirigami.Action {
0280                         icon.name: "dialog-close"
0281                         onTriggered: fingerprintModel.currentError = ""
0282                     }
0283                 ]
0284             }
0285 
0286             ListView {
0287                 id: fingerprintsList
0288                 model: kcm.fingerprintModel.deviceFound ? fingerprintModel.enrolledFingerprints : 0
0289                 Layout.fillWidth: true
0290                 Layout.fillHeight: true
0291                 QQC2.ScrollBar.vertical: QQC2.ScrollBar {}
0292 
0293                 delegate: Kirigami.SwipeListItem {
0294                     property Finger finger: modelData
0295                     // Don't need a background or hover effect for this use case
0296                     hoverEnabled: false
0297                     backgroundColor: "transparent"
0298                     contentItem: RowLayout {
0299                         Kirigami.Icon {
0300                             source: "fingerprint"
0301                             height: Kirigami.Units.iconSizes.medium
0302                             width: Kirigami.Units.iconSizes.medium
0303                         }
0304                         QQC2.Label {
0305                             Layout.fillWidth: true
0306                             elide: Text.ElideRight
0307                             text: finger.friendlyName
0308                             textFormat: Text.PlainText
0309                         }
0310                     }
0311                     actions: [
0312                         Kirigami.Action {
0313                             icon.name: "edit-entry"
0314                             onTriggered: {
0315                                 fingerprintRoot.currentFinger = finger.internalName;
0316                                 fingerprintModel.startEnrolling(finger.internalName);
0317                             }
0318                             tooltip: i18n("Re-enroll finger")
0319                         },
0320                         Kirigami.Action {
0321                             icon.name: "entry-delete"
0322                             onTriggered: {
0323                                 fingerprintModel.deleteFingerprint(finger.internalName);
0324                             }
0325                             tooltip: i18n("Delete fingerprint")
0326                         }
0327                     ]
0328                 }
0329 
0330                 Kirigami.PlaceholderMessage {
0331                     anchors.centerIn: parent
0332                     width: parent.width - (Kirigami.Units.largeSpacing * 4)
0333                     visible: fingerprintsList.count == 0
0334                     text: i18n("No fingerprints added")
0335                     icon.name: "fingerprint"
0336                 }
0337             }
0338         }
0339     }
0340 
0341     Component.onCompleted: {
0342         fingerprintButton.dialog = this;
0343         open();
0344     }
0345 }