Warning, /system/mycroft-gui/application/main.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 QtQuick.Window 2.15 0021 import QtQuick.Layouts 1.15 0022 import QtQuick.Controls 2.15 0023 import QtQuick.Controls.Material 2.15 0024 import org.kde.kirigami 2.19 as Kirigami 0025 import Mycroft 1.0 as Mycroft 0026 import org.kde.private.mycroftgui 1.0 as MycroftGui 0027 import Qt5Compat.GraphicalEffects 0028 0029 Kirigami.ApplicationWindow { 0030 id: root 0031 visible: true 0032 0033 minimumHeight : deviceHeight || undefined 0034 maximumHeight : deviceHeight || undefined 0035 minimumWidth : deviceWidth || undefined 0036 maximumWidth : deviceWidth || undefined 0037 x: deviceWidth ? Screen.desktopAvailableHeight - width : undefined 0038 y: deviceHeight ? Screen.desktopAvailableHeight - height : undefined 0039 0040 color: "black" 0041 //HACK!! needs proper api in kirigami 0042 Component.onCompleted: { 0043 globalDrawer.handle.handleAnchor = handleAnchor; 0044 0045 // Maximize and auto connect if set 0046 if (deviceMaximized) { 0047 showMaximized() 0048 } 0049 0050 if (singleSkillHome.length > 0 && Mycroft.MycroftController.status === Mycroft.MycroftController.Open) { 0051 Mycroft.MycroftController.sendRequest(singleSkillHome, {}); 0052 } 0053 0054 if(!isAndroid && Kirigami.Settings.isMobile){ 0055 applicationSettings.usesRemoteSTT = true 0056 Mycroft.GlobalSettings.usesRemoteTTS = true 0057 } 0058 } 0059 0060 Connections { 0061 target: Mycroft.MycroftController 0062 function onStatusChanged(status) { 0063 if (singleSkillHome.length > 0 && Mycroft.MycroftController.status === Mycroft.MycroftController.Open) { 0064 Mycroft.MycroftController.sendRequest(singleSkillHome, {}); 0065 } 0066 } 0067 0068 function onSpeechRequestedChanged(expectingResponse) { 0069 if(expectingResponse) { 0070 micButton.clicked() 0071 } 0072 } 0073 0074 function onSkillTimeoutReceived(skillidleid) { 0075 if(mainView.currentItem.contentItem.skillId() == skillidleid) { 0076 root.close() 0077 } 0078 } 0079 } 0080 0081 Connections { 0082 target: keyFilter 0083 function onGlobalBackReceived() { 0084 mainView.currentItem.backRequested() 0085 } 0086 } 0087 0088 // Uses Android's voice popup for speech recognition 0089 MycroftGui.SpeechIntent { 0090 id: speechIntent 0091 title: "Say something to Mycroft" // TODO i18n 0092 onSpeechRecognized: (text)=> { 0093 Mycroft.MycroftController.sendText(text) 0094 } 0095 //onRecognitionFailed: console.log("SPEECH FAILED") 0096 //onRecognitionCanceled: console.log("SPEECH CANCELED") 0097 //onNothingRecognized: console.log("SPEECH NOTHING") 0098 } 0099 0100 //HACK 0101 Connections { 0102 target: root.pageStack.layers 0103 onDepthChanged: { 0104 if (root.pageStack.layers.depth == 1) { 0105 globalDrawer.handle.handleAnchor = handleAnchor; 0106 } else { 0107 globalDrawer.handle.handleAnchor = null; 0108 } 0109 } 0110 } 0111 0112 globalDrawer: Kirigami.GlobalDrawer { 0113 bannerImageSource: "banner.png" 0114 handleVisible: !hideTextInput 0115 Kirigami.Theme.inherit: false 0116 Kirigami.Theme.colorSet: applicationSettings.darkMode ? Kirigami.Theme.Complementary : Kirigami.Theme.View 0117 0118 actions: [ 0119 Kirigami.Action { 0120 text: "Hints" 0121 iconName: "help-hint" 0122 visible: !Kirigami.Settings.isMobile 0123 checked: pageStack.layers.currentItem.objectName == "hints" 0124 onTriggered: { 0125 if (checked) { 0126 pageStack.layers.pop(pageStack.layers.initialItem); 0127 } else if (pageStack.layers.depth > 1) { 0128 pageStack.layers.replace(Qt.resolvedUrl("HintsPage.qml")); 0129 } else { 0130 pageStack.layers.push(Qt.resolvedUrl("HintsPage.qml")); 0131 } 0132 } 0133 }, 0134 Kirigami.Action { 0135 text: "Settings" 0136 iconName: "configure" 0137 checked: pageStack.layers.currentItem.objectName == "Settings" 0138 onTriggered: { 0139 if (checked) { 0140 pageStack.layers.pop(pageStack.layers.initialItem); 0141 } else if (pageStack.layers.depth > 1) { 0142 pageStack.layers.replace(Qt.resolvedUrl("SettingsPage.qml")); 0143 } else { 0144 pageStack.layers.push(Qt.resolvedUrl("SettingsPage.qml")); 0145 } 0146 } 0147 }, 0148 Kirigami.Action { 0149 text: "About" 0150 iconName: "help-about" 0151 checked: pageStack.layers.currentItem.objectName == "About" 0152 onTriggered: { 0153 if (checked) { 0154 pageStack.layers.pop(pageStack.layers.initialItem); 0155 } else if (pageStack.layers.depth > 1) { 0156 pageStack.layers.replace(Qt.resolvedUrl("AboutPage.qml")); 0157 } else { 0158 pageStack.layers.push(Qt.resolvedUrl("AboutPage.qml")); 0159 } 0160 } 0161 } 0162 ] 0163 0164 Switch { 0165 id: nightSwitch 0166 visible: !Kirigami.Settings.isMobile 0167 text: "Dark Mode" 0168 checked: applicationSettings.darkMode 0169 onCheckedChanged: applicationSettings.darkMode = checked 0170 } 0171 } 0172 0173 Timer { 0174 interval: 20000 0175 running: Mycroft.GlobalSettings.autoConnect && Mycroft.MycroftController.status != Mycroft.MycroftController.Open 0176 triggeredOnStart: true 0177 onTriggered: { 0178 print("Trying to connect to Mycroft"); 0179 Mycroft.MycroftController.start(); 0180 } 0181 } 0182 0183 pageStack.globalToolBar.style: pageStack.layers.depth == 1 ? Kirigami.ApplicationHeaderStyle.None : Kirigami.ApplicationHeaderStyle.Auto 0184 0185 pageStack.initialPage: Kirigami.Page { 0186 leftPadding: 0 0187 rightPadding: 0 0188 topPadding: 0 0189 bottomPadding: 0 0190 onBackRequested: { 0191 if (mainView.active) { 0192 event.accepted = true; 0193 mainView.goBack(); 0194 } 0195 } 0196 Rectangle { 0197 color: nightSwitch.checked ? "black" : Kirigami.Theme.backgroundColor 0198 rotation: globalScreenRotation || 0 0199 anchors.fill: parent 0200 Image { 0201 visible: singleSkill.length === 0 0202 source: "background.png" 0203 fillMode: Image.PreserveAspectFit 0204 anchors.fill: parent 0205 opacity: !mainView.currentItem 0206 Behavior on opacity { 0207 OpacityAnimator { 0208 duration: Kirigami.Units.longDuration 0209 easing.type: Easing.InQuad 0210 } 0211 } 0212 } 0213 0214 Popup { 0215 id: audioRecorder 0216 width: root.width - (Kirigami.Units.largeSpacing * 2) 0217 height: root.height / 2 0218 closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent 0219 Kirigami.Theme.colorSet: nightSwitch.checked ? Kirigami.Theme.Complementary : Kirigami.Theme.View 0220 parent: root 0221 x: (root.width - width) / 2 0222 y: (root.height - height) / 2 0223 0224 background: Rectangle { 0225 color: Kirigami.Theme.backgroundColor 0226 radius: Kirigami.Units.smallSpacing * 0.25 0227 border.width: 1 0228 Kirigami.Theme.colorSet: nightSwitch.checked ? Kirigami.Theme.Complementary : Kirigami.Theme.View 0229 border.color: Qt.rgba(Kirigami.Theme.disabledTextColor.r, Kirigami.Theme.disabledTextColor.g, Kirigami.Theme.disabledTextColor.b, 0.7) 0230 } 0231 0232 RemoteStt { 0233 id: remoteSttInstance 0234 } 0235 0236 onOpenedChanged: { 0237 if(audioRecorder.opened){ 0238 remoteSttInstance.record = true; 0239 } else { 0240 remoteSttInstance.record = false; 0241 } 0242 } 0243 } 0244 0245 Mycroft.SkillView { 0246 id: mainView 0247 activeSkills.whiteList: singleSkill.length > 0 ? singleSkill : null 0248 Kirigami.Theme.colorSet: nightSwitch.checked ? Kirigami.Theme.Complementary : Kirigami.Theme.View 0249 anchors.fill: parent 0250 } 0251 0252 Button { 0253 anchors.centerIn: parent 0254 text: "start" 0255 visible: Mycroft.MycroftController.status == Mycroft.MycroftController.Closed 0256 onClicked: (mouse)=> { 0257 Mycroft.MycroftController.start(); 0258 } 0259 } 0260 0261 Mycroft.StatusIndicator { 0262 id: si 0263 //visible: false 0264 anchors { 0265 top: parent.top 0266 right: parent.right 0267 margins: Kirigami.Units.largeSpacing 0268 } 0269 z: 999 0270 } 0271 0272 Kirigami.Heading { 0273 id: inputQuery 0274 Kirigami.Theme.colorSet: mainView.Kirigami.Theme.colorSet 0275 anchors.right: si.left 0276 anchors.rightMargin: Kirigami.Units.largeSpacing 0277 anchors.verticalCenter: si.verticalCenter 0278 level: 3 0279 opacity: 0 0280 onTextChanged: { 0281 opacity = 1; 0282 utteranceTimer.restart(); 0283 } 0284 Timer { 0285 id: utteranceTimer 0286 interval: 8000 0287 onTriggered: { 0288 inputQuery.text = ""; 0289 inputQuery.opacity = 0 0290 } 0291 } 0292 Behavior on opacity { 0293 OpacityAnimator { 0294 duration: Kirigami.units.longDuration 0295 easing.type: Easing.InOutQuad 0296 } 0297 } 0298 0299 Connections { 0300 target: Mycroft.MycroftController 0301 function onIntentRecevied(type, data) { 0302 if(type == "recognizer_loop:utterance") { 0303 inputQuery.text = data.utterances[0] 0304 } 0305 } 0306 } 0307 } 0308 } 0309 0310 //Note: a custom control as ToolBar on Android has a funny color 0311 footer: Control { 0312 Kirigami.Theme.colorSet: nightSwitch.checked ? Kirigami.Theme.Complementary : Kirigami.Theme.Window 0313 visible: !hideTextInput 0314 height: hideTextInput ? 0 : implicitHeight 0315 implicitHeight: contentItem.implicitHeight + topPadding + bottomPadding 0316 contentItem: RowLayout { 0317 Item { 0318 id: handleAnchor 0319 Layout.fillHeight: true 0320 Layout.preferredWidth: height 0321 } 0322 0323 ToolButton { 0324 id: backButton 0325 Kirigami.Theme.colorSet: nightSwitch.checked ? Kirigami.Theme.Complementary : Kirigami.Theme.Window 0326 Layout.preferredWidth: handleAnchor.width 0327 Layout.fillHeight: true 0328 Layout.rightMargin: Kirigami.Units.smallSpacing 0329 enabled: !isAndroid && Kirigami.Settings.isMobile ? 1 : 0 0330 icon.name: "go-previous" 0331 0332 onClicked:(mouse)=> { 0333 mainView.currentItem.backRequested() 0334 } 0335 visible: !isAndroid && Kirigami.Settings.isMobile ? 1 : 0 0336 } 0337 0338 0339 TextField { 0340 id: qinput 0341 Layout.fillWidth: true 0342 0343 placeholderText: "Ask Mycroft..." 0344 onAccepted: { 0345 Mycroft.MycroftController.sendText(qinput.text) 0346 } 0347 focus: false 0348 Connections { 0349 target: speechIntent 0350 function onSpeechRecognized(text){ 0351 qinput.text = text 0352 } 0353 } 0354 onFocusChanged: { 0355 if (focus) { 0356 selectAll(); 0357 } 0358 } 0359 } 0360 0361 ToolButton { 0362 id: micButton 0363 Kirigami.Theme.colorSet: nightSwitch.checked ? Kirigami.Theme.Complementary : Kirigami.Theme.Window 0364 Layout.preferredWidth: handleAnchor.width 0365 Layout.fillHeight: true 0366 Layout.rightMargin: Kirigami.Units.smallSpacing 0367 icon.name: "audio-input-microphone" 0368 0369 onClicked: (mouse)=> { 0370 if(applicationSettings.usesRemoteSTT){ 0371 audioRecorder.open() 0372 } else { 0373 speechIntent.start() 0374 } 0375 } 0376 visible: speechIntent.supported || applicationSettings.usesRemoteSTT 0377 } 0378 } 0379 background: Rectangle { 0380 color: Kirigami.Theme.backgroundColor 0381 LinearGradient { 0382 anchors { 0383 left: parent.left 0384 right: parent.right 0385 bottom: parent.top 0386 } 0387 implicitHeight: Kirigami.Units.gridUnit/2 0388 0389 start: Qt.point(0, height) 0390 end: Qt.point(0, 0) 0391 gradient: Gradient { 0392 GradientStop { 0393 position: 0.0 0394 color: Qt.rgba(0, 0, 0, 0.2) 0395 } 0396 GradientStop { 0397 position: 0.3 0398 color: Qt.rgba(0, 0, 0, 0.1) 0399 } 0400 GradientStop { 0401 position: 1.0 0402 color: "transparent" 0403 } 0404 } 0405 } 0406 } 0407 } 0408 } 0409 }