Warning, /system/mycroft-gui/import/qml/StatusIndicator.qml is written in an unsupported language. File is not indexed.

0001 /*
0002  * Copyright 2018 by Marco Martin <mart@kde.org>
0003  * Copyright 2018 David Edmundson <davidedmundson@kde.org>
0004  *
0005  * Licensed under the Apache License, Version 2.0 (the "License");
0006  * you may not use this file except in compliance with the License.
0007  * You may obtain a copy of the License at
0008  *
0009  *    http://www.apache.org/licenses/LICENSE-2.0
0010  *
0011  * Unless required by applicable law or agreed to in writing, software
0012  * distributed under the License is distributed on an "AS IS" BASIS,
0013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014  * See the License for the specific language governing permissions and
0015  * limitations under the License.
0016  *
0017  */
0018 
0019 import QtQuick 2.15
0020 import org.kde.kirigami 2.19 as Kirigami
0021 import Mycroft 1.0 as Mycroft
0022 import Qt5Compat.GraphicalEffects
0023 
0024 Item {
0025     id: root
0026     implicitWidth: Kirigami.Units.gridUnit * 5
0027     implicitHeight: width
0028     
0029     property bool hasShadow: true
0030 
0031     state: "idle"
0032     states: [
0033         State {
0034             name: "idle"
0035             PropertyChanges {
0036                 target: innerCircle
0037                 graphicsColor: "white"
0038                 backgroundColor: "deepskyblue"
0039             }
0040             PropertyChanges {
0041                 target: root
0042                 opacity: 0
0043             }
0044             StateChangeScript {
0045                 script: {
0046                     innerCircleRotation.running = false;
0047                     innerCircleRotation.to = 0;
0048                     innerCircleRotation.loops = 1;
0049                     innerCircleRotation.running = true;
0050 
0051                     outerCircleRotation.loops = 1;
0052                     outerCircleRotation.restart();
0053 
0054                     fadeTimer.running = false;
0055                 }
0056             }
0057         },
0058         State {
0059             name: "waiting"
0060             PropertyChanges {
0061                 target: innerCircle
0062                 graphicsColor: "white"
0063                 backgroundColor: "deepskyblue"
0064             }
0065             PropertyChanges {
0066                 target: root
0067                 opacity: 1
0068             }
0069             StateChangeScript {
0070                 script: {
0071                     innerCircleRotation.running = false;
0072                     innerCircleRotation.to = -360;
0073                     innerCircleRotation.loops = 1;
0074                     innerCircleRotation.running = true;
0075 
0076                     outerCircleRotation.loops = 1;
0077                     outerCircleRotation.restart();
0078 
0079                     fadeTimer.running = false;
0080                 }
0081             }
0082         },
0083         State {
0084             name: "loading"
0085             PropertyChanges {
0086                 target: innerCircle
0087                 targetRotation: 0
0088                 graphicsColor: "white"
0089                 backgroundColor: "deepskyblue"
0090             }
0091             PropertyChanges {
0092                 target: root
0093                 opacity: 1
0094             }
0095 
0096             StateChangeScript {
0097                 script: {
0098                     innerCircleRotation.running = false;
0099                     innerCircleRotation.to = innerCircle.rotation - 360;
0100                     innerCircleRotation.loops = Animation.Infinite;
0101                     innerCircleRotation.running = true;
0102 
0103                     outerCircleRotation.loops = Animation.Infinite;
0104                     outerCircleRotation.restart();
0105 
0106                     fadeTimer.running = false;
0107                 }
0108             }
0109         },
0110         State {
0111             name: "ok"
0112             PropertyChanges {
0113                 target: innerCircle
0114                 explicit: true
0115                 targetRotation: -90
0116                 graphicsColor: Kirigami.Theme.positiveTextColor
0117                 backgroundColor: Qt.tint(Kirigami.Theme.backgroundColor, Qt.rgba(Kirigami.Theme.positiveTextColor.r, Kirigami.Theme.positiveTextColor.g, Kirigami.Theme.positiveTextColor.b, 0.4))
0118             }
0119             PropertyChanges {
0120                 target: root
0121                 opacity: 1
0122             }
0123             StateChangeScript {
0124                 script: {
0125                     innerCircleRotation.running = false;
0126                     innerCircleRotation.to = -90;
0127                     innerCircleRotation.loops = 1;
0128                     innerCircleRotation.running = true;
0129 
0130                     outerCircleRotation.loops = 1;
0131                     outerCircleRotation.restart();
0132 
0133                     fadeTimer.restart();
0134                 }
0135             }
0136         },
0137         State {
0138             name: "error"
0139             PropertyChanges {
0140                 target: innerCircle
0141                 explicit: true
0142                 graphicsColor: Kirigami.Theme.negativeTextColor
0143                 backgroundColor: Qt.tint(Kirigami.Theme.backgroundColor, Qt.rgba(Kirigami.Theme.negativeTextColor.r, Kirigami.Theme.negativeTextColor.g, Kirigami.Theme.negativeTextColor.b, 0.4))
0144             }
0145             PropertyChanges {
0146                 target: root
0147                 opacity: 1
0148             }
0149             StateChangeScript {
0150                 script: {
0151                     innerCircleRotation.running = false;
0152                     innerCircleRotation.to = 90;
0153                     innerCircleRotation.loops = 1;
0154                     innerCircleRotation.running = true;
0155 
0156                     outerCircleRotation.loops = 1;
0157                     outerCircleRotation.restart();
0158 
0159                     fadeTimer.restart();
0160                 }
0161             }
0162         }
0163     ]
0164 
0165     Connections {
0166         target: Mycroft.MycroftController
0167         function onListeningChanged() {
0168             if (Mycroft.MycroftController.listening) {
0169                 root.state = "waiting";
0170             } else {
0171                 fadeTimer.restart();
0172             }
0173         }
0174         function onNotUnderstood() {
0175             root.state = "idle"
0176             root.state = "error";
0177         }
0178         function onFallbackTextRecieved(skill, data){
0179             if (skill.length > 0) {
0180                 root.state = "ok";
0181             }
0182         }
0183         function onServerReadyChanged() {
0184             if (Mycroft.MycroftController.serverReady) {
0185                 root.state = "ok";
0186             }
0187         }
0188         function onStatusChanged(status) {
0189             switch (Mycroft.MycroftController.status) {
0190             case Mycroft.MycroftController.Open:
0191                 root.state = Mycroft.MycroftController.serverReady ? "ok" : "loading";
0192                 break;
0193             case Mycroft.MycroftController.Connecting:
0194                 root.state = "loading";
0195                 break;
0196             case Mycroft.MycroftController.Error:
0197             default:
0198                 root.state = "error";
0199                 break;
0200             }
0201         }
0202         function onCurrentIntentChanged() {
0203             if (Mycroft.MycroftController.currentIntent.length == 0) {
0204                 if (root.state == "loading") {
0205                     root.state = "idle";
0206                 }
0207             } else {
0208                 root.state = "loading";
0209             }
0210         }
0211     }
0212 
0213     Rectangle {
0214         id: background
0215         anchors.centerIn: parent
0216         width: Math.min(parent.width, parent.height)
0217         height: width
0218         color: innerCircle.backgroundColor
0219         radius: height
0220         layer.enabled: hasShadow
0221         layer.effect: DropShadow {
0222             cached: true
0223             transparentBorder: true
0224             horizontalOffset: 0
0225             verticalOffset: 2
0226         }
0227     }
0228     Behavior on opacity {
0229         OpacityAnimator {
0230             duration: innerCircle.animationLength
0231             easing.type: Easing.InOutCubic
0232         }
0233     }
0234 
0235     Rectangle {
0236         id: innerCircleGraphics
0237         anchors {
0238             fill: outerCircle
0239             margins: innerCircle.unit * 5
0240         }
0241         visible: false
0242 
0243         color: innerCircle.graphicsColor
0244         radius: width
0245     }
0246     Item {
0247         id: innerCircleMask
0248         visible: false
0249         anchors.fill: innerCircleGraphics
0250 
0251         Rectangle {
0252             anchors {
0253                 left: parent.left
0254                 right: parent.horizontalCenter
0255                 top: parent.top
0256                 bottom: parent.bottom
0257             }
0258             color: "white"
0259         }
0260     }
0261     OpacityMask {
0262         id: innerCircle
0263         property int unit: Math.max(1, background.width/20)
0264         property color graphicsColor
0265         property color backgroundColor
0266         property int animationLength: 1000
0267         property int targetRotation: 0
0268         Behavior on graphicsColor {
0269             ColorAnimation {
0270                 duration: innerCircle.animationLength
0271                 easing.type: Easing.InOutCubic
0272             }
0273         }
0274         Behavior on backgroundColor {
0275             ColorAnimation {
0276                 duration: innerCircle.animationLength
0277                 easing.type: Easing.InOutCubic
0278             }
0279         }
0280         anchors.fill: innerCircleGraphics
0281         source: innerCircleGraphics
0282         maskSource: innerCircleMask
0283 
0284         RotationAnimator {
0285             id: innerCircleRotation
0286             target: innerCircle
0287             from: innerCircle.rotation
0288             to: 0
0289             direction: RotationAnimator.Counterclockwise
0290             duration: innerCircle.animationLength
0291             easing.type: Easing.InOutCubic
0292         }
0293     }
0294 
0295     Item {
0296         id: outerCircle
0297 
0298         anchors {
0299             fill: background
0300             margins: innerCircle.unit * 3
0301         }
0302 
0303         // the little dot
0304         Rectangle {
0305             width: innerCircle.unit * 2
0306             height: width
0307             radius: width
0308             color: innerCircle.graphicsColor
0309             anchors.horizontalCenter : parent.horizontalCenter
0310         }
0311         //the circle
0312         Rectangle {
0313             anchors {
0314                 fill: parent
0315                 margins: innerCircle.unit * 3
0316             }
0317             radius: width
0318             color: "transparent"
0319             border.width: innerCircle.unit 
0320             border.color: innerCircle.graphicsColor
0321         }
0322         RotationAnimator {
0323             id: outerCircleRotation
0324             target: outerCircle
0325             from: outerCircle.rotation
0326             to: outerCircle.rotation + 360 - (outerCircle.rotation + 360) % 360
0327             direction: RotationAnimator.Clockwise
0328             duration: innerCircle.animationLength
0329             easing.type: Easing.InOutCubic
0330         }
0331     }
0332     Timer {
0333         id: fadeTimer
0334         interval: 3000
0335         repeat: false
0336         onTriggered: root.state = "idle"
0337     }
0338 }