diff --git a/CMakeLists.txt b/CMakeLists.txt
index c605502..fd6938a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,59 +1,82 @@
# Set minimum CMake version (required for CMake 3.0 or later)
cmake_minimum_required(VERSION 2.8.12)
option(BUILD_GUI_DEPS "Build Mycroft-GUI Dependencies" OFF)
set(QT_MIN_VERSION "5.9.0")
set(KF5_MIN_VERSION "5.0.0")
# Use Extra CMake Modules (ECM) for common functionality.
# See http://api.kde.org/ecm/manual/ecm.7.html
# and http://api.kde.org/ecm/manual/ecm-kde-modules.7.html
find_package(ECM REQUIRED NO_MODULE)
set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR} ${CMAKE_MODULE_PATH})
set(VERSION 2.1.0)
include(KDEInstallDirs)
include(KDECMakeSettings)
include(KDECompilerSettings NO_POLICY_SCOPE)
include(ECMInstallIcons)
include(ExternalProject)
# Locate plasma_install_package macro.
find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS
Plasma
I18n
Notifications
)
find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS
Quick
Core
Qml
DBus
Network
WebSockets
)
add_subdirectory(icons)
add_subdirectory(plugin)
+find_program(MycroftGUI mycroft-gui-app)
+
+if(NOT MycroftGUI)
+ message(STATUS "MYCROFT GUI DEPENDENCY NOT FOUND, ADDING AND BUILDING DEPENDENCIES")
+
+ExternalProject_Add(mycroft-gui
+ GIT_REPOSITORY https://github.com/MycroftAI/Mycroft-Gui
+ CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Release -DKDE_INSTALL_LIBDIR=lib -DKDE_INSTALL_USE_QT_SYS_PATHS=ON -DBUILD_REMOTE_TTS=ON
+ BUILD_COMMAND make
+ INSTALL_COMMAND sudo make install
+)
+
+ExternalProject_Add(lottie-qml
+ GIT_REPOSITORY https://github.com/kbroulik/lottie-qml
+ CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Release -DKDE_INSTALL_LIBDIR=lib -DKDE_INSTALL_USE_QT_SYS_PATHS=ON
+ BUILD_COMMAND make
+ INSTALL_COMMAND sudo make install
+)
+endif()
+
+if(MycroftGUI)
+ message(STATUS "MYCROFT GUI DEPENDENCY FOUND, SKIPPING BUILDING DEPENDENCIES")
+endif()
if(BUILD_GUI_DEPS)
ExternalProject_Add(mycroft-gui
GIT_REPOSITORY https://github.com/MycroftAI/Mycroft-Gui
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Release -DKDE_INSTALL_LIBDIR=lib -DKDE_INSTALL_USE_QT_SYS_PATHS=ON -DBUILD_REMOTE_TTS=ON
BUILD_COMMAND make
INSTALL_COMMAND sudo make install
)
ExternalProject_Add(lottie-qml
GIT_REPOSITORY https://github.com/kbroulik/lottie-qml
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Release -DKDE_INSTALL_LIBDIR=lib -DKDE_INSTALL_USE_QT_SYS_PATHS=ON
BUILD_COMMAND make
INSTALL_COMMAND sudo make install
)
endif()
plasma_install_package(plasmoid org.kde.plasma.mycroftplasmoid)
install( DIRECTORY mycroft DESTINATION ${SYSCONF_INSTALL_DIR})
diff --git a/plasmoid/contents/config/main.xml b/plasmoid/contents/config/main.xml
index 28bac85..c8704f6 100644
--- a/plasmoid/contents/config/main.xml
+++ b/plasmoid/contents/config/main.xml
@@ -1,22 +1,28 @@
true
false
true
-
+
+
+
+
+
+ false
+
diff --git a/plasmoid/contents/ui/BottomBarViewComponent.qml b/plasmoid/contents/ui/BottomBarViewComponent.qml
index 6762eb4..288e34d 100644
--- a/plasmoid/contents/ui/BottomBarViewComponent.qml
+++ b/plasmoid/contents/ui/BottomBarViewComponent.qml
@@ -1,105 +1,119 @@
/* Copyright 2016 Aditya Mehra
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) version 3, or any
later version accepted by the membership of KDE e.V. (or its
successor approved by the membership of KDE e.V.), which shall
act as a proxy defined in Section 6 of version 3 of the license.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library. If not, see .
*/
import QtQuick 2.9
import QtQml.Models 2.2
import QtQuick.Controls 2.2 as Controls
import QtQuick.Layouts 1.3
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.plasmoid 2.0
import org.kde.plasma.components 2.0 as PlasmaComponents
import org.kde.plasma.extras 2.0 as PlasmaExtras
import org.kde.kirigami 2.5 as Kirigami
import QtGraphicalEffects 1.0
import Mycroft 1.0 as Mycroft
Item {
id: appletBottomBarComponent
anchors.fill: parent
property alias autoCompModel: completionItems
property alias queryInput: qinput
property var lastMessage
function autoAppend(model, getinputstring, setinputstring) {
for(var i = 0; i < model.count; ++i)
if (getinputstring(model.get(i))){
return true
}
return null
}
function evalAutoLogic() {
if (suggestionsBox.currentIndex === -1) {
} else {
suggestionsBox.complete(suggestionsBox.currentItem)
}
}
ListModel {
id: completionItems
}
ColumnLayout {
anchors.fill: parent
- PlasmaComponents.TextField {
- id: qinput
+
+ RowLayout{
Layout.fillWidth: true
- Layout.preferredHeight: Kirigami.Units.gridUnit * 2
- placeholderText: i18n("Enter Query or Say 'Hey Mycroft'")
- clearButtonShown: true
+ Layout.fillHeight: true
+
+ PlasmaComponents.TextField {
+ id: qinput
+ Layout.fillWidth: true
+ Layout.preferredHeight: Kirigami.Units.gridUnit * 2
+ placeholderText: i18n("Enter Query or Say 'Hey Mycroft'")
+ clearButtonShown: true
- onAccepted: {
- if(qinput.text !== ""){
- lastMessage = qinput.text
+ onAccepted: {
+ if(qinput.text !== ""){
+ lastMessage = qinput.text
+ }
+ var doesExist = appletBottomBarComponent.autoAppend(autoCompModel, function(item) { return item.name === qinput.text }, qinput.text)
+ var evaluateExist = doesExist
+ if(evaluateExist === null){
+ autoCompModel.append({"name": qinput.text});
+ }
+ Mycroft.MycroftController.sendText(qinput.text);
+ Mycroft.MycroftController.sendRequest('mycroft.qinput.text', {"inputQuery": qinput.Text})
+ qinput.text = "";
}
- var doesExist = appletBottomBarComponent.autoAppend(autoCompModel, function(item) { return item.name === qinput.text }, qinput.text)
- var evaluateExist = doesExist
- if(evaluateExist === null){
- autoCompModel.append({"name": qinput.text});
- }
- Mycroft.MycroftController.sendText(qinput.text);
- Mycroft.MycroftController.sendRequest('mycroft.qinput.text', {"inputQuery": qinput.Text})
- qinput.text = "";
- }
- onTextChanged: {
- appletBottomBarComponent.evalAutoLogic();
- }
+ onTextChanged: {
+ appletBottomBarComponent.evalAutoLogic();
+ }
- AutocompleteBox {
- id: suggestionsBox
- model: completionItems
- width: parent.width
- anchors.bottom: parent.top
- anchors.left: parent.left
- anchors.right: parent.right
- filter: qinput.text
- property: "name"
- onItemSelected: complete(item)
+ AutocompleteBox {
+ id: suggestionsBox
+ model: completionItems
+ width: parent.width
+ anchors.bottom: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ filter: qinput.text
+ property: "name"
+ onItemSelected: complete(item)
- function complete(item) {
- if (item !== undefined)
- qinput.text = item.name
+ function complete(item) {
+ if (item !== undefined)
+ qinput.text = item.name
+ }
+ }
+ }
+
+ Controls.Button {
+ text: "Speak" // TODO generic microphone icon
+ onClicked: {
+ audioRecorder.open()
}
+ visible: plasmoid.configuration.enableRemoteSTT
}
}
}
}
diff --git a/plasmoid/contents/ui/FullRepresentation.qml b/plasmoid/contents/ui/FullRepresentation.qml
index daeb2bd..aabf650 100644
--- a/plasmoid/contents/ui/FullRepresentation.qml
+++ b/plasmoid/contents/ui/FullRepresentation.qml
@@ -1,207 +1,228 @@
/* Copyright 2016 Aditya Mehra
Copyright 2018 Marco Martin
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) version 3, or any
later version accepted by the membership of KDE e.V. (or its
successor approved by the membership of KDE e.V.), which shall
act as a proxy defined in Section 6 of version 3 of the license.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library. If not, see .
*/
import QtQuick 2.9
import QtQml.Models 2.2
import QtQuick.Controls 2.2 as Controls
import QtQuick.Layouts 1.3
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 2.0 as PlasmaComponents
import org.kde.plasma.extras 2.0 as PlasmaExtras
import org.kde.plasma.plasmoid 2.0
import org.kde.kirigami 2.5 as Kirigami
import org.kde.private.mycroftplasmoid 1.0 as MycroftPlasmoid
import Mycroft 1.0 as Mycroft
Item {
id: root
implicitWidth: Kirigami.Units.gridUnit * 20
implicitHeight: Kirigami.Units.gridUnit * 32
property bool cfg_notifications: plasmoid.configuration.notifications
Item {
id: topBar
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
height: Kirigami.Units.gridUnit * 4
ColumnLayout{
anchors.fill: parent
TopBarViewComponent {
id: topBarView
Layout.fillWidth: true
Layout.preferredHeight: Kirigami.Units.gridUnit * 2
}
PlasmaCore.SvgItem {
Layout.fillWidth: true
Layout.preferredHeight: horlineSvg.elementSize("horizontal-line").height
elementId: "horizontal-line"
svg: PlasmaCore.Svg {
id: horlineSvg2;
imagePath: "widgets/line"
}
}
PlasmaComponents.TabBar {
id: tabBar
visible: true
Layout.fillWidth: true
Layout.preferredHeight: Kirigami.Units.gridUnit * 1.5
PlasmaComponents.TabButton {
id: mycroftTab
iconSource: "go-home"
text: "Conversation"
}
PlasmaComponents.TabButton {
id: mycroftSkillsTab
iconSource: "games-hint"
text: "Hints & Tips"
}
PlasmaComponents.TabButton {
id: mycroftMSMinstTab
iconSource: "kmouth-phresebook-new"
text: "Skill Browser"
}
}
PlasmaCore.SvgItem {
Layout.fillWidth: true
Layout.preferredHeight: horlineSvg.elementSize("horizontal-line").height
elementId: "horizontal-line"
svg: PlasmaCore.Svg {
id: horlineSvg;
imagePath: "widgets/line"
}
}
}
}
ColumnLayout {
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: bottomBar.top
anchors.top: topBar.bottom
anchors.topMargin: Kirigami.Units.largeSpacing + Kirigami.Units.smallSpacing
opacity: Mycroft.MycroftController.status == Mycroft.MycroftController.Open
visible: tabBar.currentTab == mycroftTab;
Behavior on opacity {
OpacityAnimator {
duration: Kirigami.Units.longDuration
easing.type: Easing.InOutCubic
}
}
Item {
id: delegateItem
Layout.fillWidth: true
Layout.fillHeight: true
+ Controls.Popup {
+ id: audioRecorder
+ width: 300
+ height: 125
+ closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent
+ x: (root.width - width) / 2
+ y: (root.height - height) / 2
+
+ RemoteStt {
+ id: remoteSttInstance
+ }
+
+ onOpenedChanged: {
+ if(audioRecorder.opened){
+ remoteSttInstance.record = true;
+ } else {
+ remoteSttInstance.record = false;
+ }
+ }
+ }
+
Mycroft.SkillView {
id: skillView
anchors.fill: parent
Kirigami.Theme.colorSet: Kirigami.Theme.View
anchors.margins: Kirigami.Units.largeSpacing
clip: true
onCurrentItemChanged: {
backgroundVisible = false
}
Connections {
id: mycroftConnection
target: Mycroft.MycroftController
onFallbackTextRecieved: {
Mycroft.MycroftController.sendRequest("mycroft.desktop.applet.show_conversationview", {})
if (!plasmoid.expanded && cfg_notifications == true) {
var post = data.utterance;
var title = "Mycroft's Reply:"
var notiftext = " " + post;
MycroftPlasmoid.Notify.mycroftResponse(title, notiftext);
}
}
}
}
}
}
Item {
id: bottomBar
anchors.bottom: root.bottom
anchors.left: root.left
anchors.right: root.right
height: Kirigami.Units.gridUnit * 2
BottomBarViewComponent {
id: bottomBarView
}
}
Image {
anchors.centerIn: parent
opacity: Mycroft.MycroftController.status != Mycroft.MycroftController.Open
source: "../images/logo.png"
Behavior on opacity {
OpacityAnimator {
duration: Kirigami.Units.longDuration
easing.type: Easing.InOutCubic
}
}
}
ColumnLayout {
id: mycroftSkillscolumntab
visible: tabBar.currentTab == mycroftSkillsTab;
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: bottomBar.top
anchors.top: topBar.bottom
anchors.topMargin: Kirigami.Units.largeSpacing + Kirigami.Units.smallSpacing
anchors.bottomMargin: Kirigami.Units.smallSpacing
HintsViewComponent {
id: hintsView
}
}
ColumnLayout {
id: mycroftMsmColumn
visible: tabBar.currentTab == mycroftMSMinstTab;
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: bottomBar.top
anchors.top: topBar.bottom
anchors.topMargin: Kirigami.Units.largeSpacing + Kirigami.Units.smallSpacing
anchors.bottomMargin: Kirigami.Units.smallSpacing
SkillsInstallerComponent{
id: skillsInstallerView
}
}
}
diff --git a/plasmoid/contents/ui/RemoteStt.qml b/plasmoid/contents/ui/RemoteStt.qml
new file mode 100644
index 0000000..04eb8cf
--- /dev/null
+++ b/plasmoid/contents/ui/RemoteStt.qml
@@ -0,0 +1,135 @@
+import QtQuick 2.9
+import QtQuick.Layouts 1.3
+import QtQuick.Controls 2.2
+import org.kde.kirigami 2.4 as Kirigami
+import Mycroft 1.0 as Mycroft
+
+Item {
+ id: root
+ anchors.fill: parent
+ property alias record: audrectimer.running
+
+ Mycroft.AudioRec {
+ id: audioRec
+ }
+
+ Timer {
+ id: audrectimer
+ interval: 10000
+ running: false
+ onRunningChanged: {
+ if(running){
+ audioRec.recordTStart()
+ numAnim.start()
+ } else {
+ audioRec.recordTStop()
+ }
+ }
+ }
+
+ function sendAudioClip() {
+ audioRec.returnStream()
+ }
+
+ Connections {
+ target: audioRec
+ onRecordTStatus: {
+ console.log(recStatus)
+ switch(recStatus){
+ case "Completed":
+ console.log("In Completed")
+ audioRec.readStream()
+ sendAudioClip()
+ audioRecorder.close()
+ break;
+ case "Error":
+ console.log("inError")
+ break;
+ }
+ }
+ }
+
+ ColumnLayout {
+ id: closebar
+ anchors.fill: parent
+ spacing: 0
+
+ Kirigami.Heading {
+ id: lbl1
+ text: "Listening"
+ level: 2
+ font.bold: true
+ Layout.alignment: Qt.AlignTop | Qt.AlignHCenter
+ }
+
+ Kirigami.Separator {
+ Layout.fillWidth: true
+ Layout.preferredHeight: 1
+ }
+
+ Item {
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+ ProgressBar {
+ id: bar
+ to: 100
+ from: 0
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.leftMargin: Kirigami.Units.largeSpacing
+ anchors.rightMargin: Kirigami.Units.largeSpacing
+ anchors.verticalCenter: parent.verticalCenter
+
+ contentItem: Item {
+ implicitWidth: parent.width
+ implicitHeight: parent.height
+
+ Rectangle {
+ width: bar.visualPosition * parent.width
+ height: parent.height
+ radius: 2
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: Kirigami.Theme.linkColor }
+ GradientStop { position: 0.3; color: Qt.lighter(Kirigami.Theme.linkColor, 1.5)}
+ GradientStop { position: 0.6; color: Qt.lighter(Kirigami.Theme.linkColor, 1.5)}
+ GradientStop { position: 1.0; color: Kirigami.Theme.linkColor }
+ }
+ }
+ }
+
+ NumberAnimation {
+ id: numAnim
+ target: bar
+ property: "value"
+ from: 0
+ to: 100
+ duration: 10000
+ }
+ }
+ }
+
+ Kirigami.Separator {
+ Layout.fillWidth: true
+ Layout.preferredHeight: 1
+ }
+
+ Rectangle {
+ color: Kirigami.Theme.hoverColor
+ Layout.fillWidth: true
+ Layout.preferredHeight: Kirigami.Units.gridUnit * 1.5
+
+ Kirigami.Heading {
+ level: 2
+ text: "Close"
+ anchors.centerIn: parent
+ anchors.margins: Kirigami.Units.largeSpacing
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: audioRecorder.close()
+ }
+ }
+ }
+}
+
diff --git a/plasmoid/contents/ui/config/configGeneral.qml b/plasmoid/contents/ui/config/configGeneral.qml
index d196ca6..2fe8e5c 100644
--- a/plasmoid/contents/ui/config/configGeneral.qml
+++ b/plasmoid/contents/ui/config/configGeneral.qml
@@ -1,63 +1,61 @@
import QtQuick 2.9
import QtQml.Models 2.2
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.3
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.plasmoid 2.0
import org.kde.plasma.components 2.0 as PlasmaComponents
import org.kde.plasma.extras 2.0 as PlasmaExtras
import org.kde.kirigami 2.5 as Kirigami
import Mycroft 1.0 as Mycroft
Item {
id: page
property alias cfg_websocketAddress: websocketAddress.text
property alias cfg_notificationSwitch: notificationSwitch.checked
property alias cfg_selectView: selectView.currentIndex
+ property alias cfg_enableRemoteTTS: enableRemoteTTS.checked
+ property alias cfg_enableRemoteSTT: enableRemoteSTT.checked
- GridLayout {
- Layout.fillWidth: true
- columns: 2
-
- PlasmaComponents.Label {
- id: websocketLabel
- text: "Websocket Address"
- }
-
+ Kirigami.FormLayout {
+ anchors.left: parent.left
+ anchors.right: parent.right
+
PlasmaComponents.TextField {
- id: websocketAddress
- Layout.fillWidth: true
-
- Component.onCompleted: {
- websocketAddress.text = Mycroft.GlobalSettings.webSocketAddress
- }
+ id: websocketAddress
+ Layout.fillWidth: true
+ Kirigami.FormData.label: i18n("Websocket Address:")
+ Component.onCompleted: {
+ websocketAddress.text = Mycroft.GlobalSettings.webSocketAddress
}
+ }
- ColumnLayout{
- Layout.fillWidth: true
+ CheckBox {
+ id: notificationSwitch
+ Kirigami.FormData.label: i18n ("Additional Settings:")
+ text: i18n("Enable Notifications")
+ checked: true
+ }
- PlasmaComponents.Switch {
- id: notificationSwitch
- Layout.fillWidth: true
- text: i18n("Enable Notifications")
- checked: true
- }
-
- RowLayout {
- Layout.fillWidth: true
-
- PlasmaComponents.Label {
- id: selectViewLabel
- Layout.fillWidth: true
- text: "Select Default View:"
- }
-
- PlasmaComponents.ComboBox{
- id: selectView
- Layout.fillWidth: true
- model: ["Conversation View", "Dashboard View"]
- }
- }
+ CheckBox {
+ id: enableRemoteTTS
+ text: i18n("Enable Remote TTS")
+ checked: Mycroft.GlobalSettings.usesRemoteTTS
+ onCheckedChanged: Mycroft.GlobalSettings.usesRemoteTTS = checked
+ }
+
+ CheckBox {
+ id: enableRemoteSTT
+ text: i18n("Enable Remote STT")
+ checked: false
+ }
+
+ PlasmaComponents.ComboBox{
+ id: selectView
+ Layout.fillWidth: true
+ Kirigami.FormData.label: i18n ("Default View:")
+ model: ["Conversation View", "Dashboard View"]
}
}
}
+