This repository has been archived on 2026-05-31. You can view files and clone it, but cannot push or open issues or pull requests.

361 lines
12 KiB
QML

import QtQuick 2.8
import QtQuick.Controls 2.1
import QtQuick.Controls.Material 2.1
import QtQuick.Layouts 1.2
import Qt.labs.settings 1.0
import QtQuick.Window 2.3
import Nymea 1.0
ApplicationWindow {
id: app
visible: true
width: 360
height: 580
visibility: ApplicationWindow.AutomaticVisibility
font: Qt.application.font
title: appName
property int margins: 14
property int bigMargins: 20
property int extraSmallFont: 10
property int smallFont: 13
property int mediumFont: 16
property int largeFont: 20
property int iconSize: 30
property int delegateHeight: 60
property bool landscape: app.width > app.height
property var settings: Settings {
property string lastConnectedHost: ""
property alias viewMode: app.visibility
property bool returnToHome: false
property bool darkTheme: false
property string graphStyle: "bars"
property string style: "light"
property int currentMainViewIndex: 0
}
Component.onCompleted: {
pageStack.push(Qt.resolvedUrl("ConnectPage.qml"))
}
Connections {
target: Engine.jsonRpcClient
onConnectedChanged: {
print("json client connected changed", Engine.jsonRpcClient.connected)
if (Engine.jsonRpcClient.connected) {
settings.lastConnectedHost = Engine.connection.url
}
init();
}
onAuthenticationRequiredChanged: {
print("auth required changed")
init();
}
onInitialSetupRequiredChanged: {
print("setup required changed")
init();
}
onInvalidProtocolVersion: {
var popup = invalidVersionComponent.createObject(app.contentItem);
popup.actualVersion = actualVersion;
popup.minimumVersion = minimumVersion
popup.open()
settings.lastConnectedHost = ""
}
}
function init() {
print("calling init. Auth required:", Engine.jsonRpcClient.authenticationRequired, "initial setup required:", Engine.jsonRpcClient.initialSetupRequired, "jsonrpc connected:", Engine.jsonRpcClient.connected)
pageStack.clear()
if (!Engine.connection.connected) {
pageStack.push(Qt.resolvedUrl("ConnectPage.qml"))
return;
}
if (Engine.jsonRpcClient.authenticationRequired || Engine.jsonRpcClient.initialSetupRequired) {
if (Engine.jsonRpcClient.pushButtonAuthAvailable) {
print("opening push button auth")
var page = pageStack.push(Qt.resolvedUrl("PushButtonAuthPage.qml"))
page.backPressed.connect(function() {
settings.lastConnectedHost = "";
Engine.connection.disconnect();
init();
})
} else {
var page = pageStack.push(Qt.resolvedUrl("LoginPage.qml"));
page.backPressed.connect(function() {
settings.lastConnectedHost = "";
Engine.connection.disconnect()
init();
})
}
} else if (Engine.jsonRpcClient.connected) {
pageStack.push(Qt.resolvedUrl("MainPage.qml"))
} else {
pageStack.push(Qt.resolvedUrl("ConnectPage.qml"))
}
}
// Workaround flickering on pageStack animations when the white background shines through
Rectangle {
anchors.fill: parent
color: Material.background
}
StackView {
id: pageStack
objectName: "pageStack"
anchors.fill: parent
initialItem: Page {}
onDepthChanged: {
print("stackview depth changed", pageStack.depth)
}
}
onClosing: {
if (Qt.platform.os == "android") {
// If we're connected, allow going back up to MainPage
if ((Engine.jsonRpcClient.connected && pageStack.depth > 1)
// if we're not connected, only allow using the back button in wizards
|| (!Engine.jsonRpcClient.connected && pageStack.depth > 3)) {
close.accepted = false;
pageStack.pop();
}
}
}
Connections {
target: Qt.application
enabled: Engine.jsonRpcClient.connected && settings.returnToHome
onStateChanged: {
print("App active state changed:", state)
if (state !== Qt.ApplicationActive) {
init();
}
}
}
property var supportedInterfaces: ["light", "weather", "sensor", "media", "garagegate", "extendedawning", "extendedshutter", "extendedblind", "button", "notifications", "inputtrigger", "outputtrigger", "gateway"]
function interfaceToString(name) {
switch(name) {
case "light":
return qsTr("Lighting")
case "weather":
return qsTr("Weather")
case "sensor":
return qsTr("Sensors")
case "media":
return qsTr("Media")
case "button":
return qsTr("Switches")
case "gateway":
return qsTr("Gateways")
case "notifications":
return qsTr("Notifications")
case "temperaturesensor":
return qsTr("Temperature");
case "humiditysensor":
return qsTr("Humidity");
case "pressuresensor":
return qsTr("Pressure");
case "inputtrigger":
return qsTr("Incoming Events");
case "outputtrigger":
return qsTr("Events");
case "shutter":
case "extendedshutter":
return qsTr("Shutters");
case "blind":
case "extendedblind":
return qsTr("Blinds");
case "awning":
case "extendedawning":
return qsTr("Awnings");
case "garagegate":
return qsTr("Garage gates");
case "uncategorized":
return qsTr("Uncategorized")
}
}
function interfacesToIcon(interfaces) {
for (var i = 0; i < interfaces.length; i++) {
var icon = interfaceToIcon(interfaces[i]);
if (icon !== "") {
return icon;
}
}
return Qt.resolvedUrl("images/select-none.svg")
}
function interfaceToIcon(name) {
switch (name) {
case "light":
case "colorlight":
case "dimmablelight":
return Qt.resolvedUrl("images/light-on.svg")
case "sensor":
return Qt.resolvedUrl("images/sensors.svg")
case "temperaturesensor":
return Qt.resolvedUrl("images/sensors/temperature.svg")
case "humiditysensor":
return Qt.resolvedUrl("images/sensors/humidity.svg")
case "moisturesensor":
return Qt.resolvedUrl("images/sensors/moisture.svg")
case "lightsensor":
return Qt.resolvedUrl("images/sensors/light.svg")
case "conductivitysensor":
return Qt.resolvedUrl("images/sensors/conductivity.svg")
case "pressuresensor":
return Qt.resolvedUrl("images/sensors/pressure.svg")
case "media":
case "mediacontroller":
return Qt.resolvedUrl("images/mediaplayer-app-symbolic.svg")
case "button":
case "longpressbutton":
case "simplemultibutton":
case "longpressmultibutton":
return Qt.resolvedUrl("images/system-shutdown.svg")
case "weather":
return Qt.resolvedUrl("images/weather-app-symbolic.svg")
case "temperaturesensor":
return Qt.resolvedUrl("images/sensors/temperature.svg")
case "humiditysensor":
return Qt.resolvedUrl("images/sensors/humidity.svg")
case "gateway":
return Qt.resolvedUrl("images/network-wired-symbolic.svg")
case "notifications":
return Qt.resolvedUrl("images/notification.svg")
case "connectable":
return Qt.resolvedUrl("images/stock_link.svg")
case "inputtrigger":
return Qt.resolvedUrl("images/attention.svg")
case "outputtrigger":
return Qt.resolvedUrl("images/send.svg")
case "shutter":
case "extendedshutter":
return Qt.resolvedUrl("images/DeviceIconRollerShutter.svg")
case "blind":
case "extendedblind":
return Qt.resolvedUrl("images/DeviceIconBlind.svg")
case "garagegate":
return Qt.resolvedUrl("images/shutter/shutter-100.svg")
case "extendedawning":
return Qt.resolvedUrl("images/awning/awning-100.svg")
case "battery":
return Qt.resolvedUrl("images/battery/battery-050.svg")
case "uncategorized":
return Qt.resolvedUrl("images/select-none.svg")
case "simpleclosable":
return Qt.resolvedUrl("images/sort-listitem.svg")
default:
console.warn("InterfaceToIcon: Unhandled interface", name)
}
return "";
}
function interfaceToColor(name) {
switch (name) {
case "temperaturesensor":
return "red";
case "humiditysensor":
return "deepskyblue";
case "moisturesensor":
return "blue";
case "lightsensor":
return "orange";
case "conductivitysensor":
return "green";
case "pressuresensor":
return "grey";
}
return "grey";
}
function interfaceToDisplayName(name) {
switch (name) {
case "light":
return qsTr("light")
case "button":
return "button";
case "sensor":
return qsTr("sensor")
}
}
function interfaceListToDevicePage(interfaceList) {
var page;
if (interfaceList.indexOf("media") >= 0) {
page = "MediaDevicePage.qml";
} else if (interfaceList.indexOf("button") >= 0) {
page = "ButtonDevicePage.qml";
} else if (interfaceList.indexOf("weather") >= 0) {
page = "WeatherDevicePage.qml";
} else if (interfaceList.indexOf("sensor") >= 0) {
page = "SensorDevicePage.qml";
} else if (interfaceList.indexOf("inputtrigger") >= 0) {
page = "InputTriggerDevicePage.qml";
} else if (interfaceList.indexOf("garagegate") >= 0 ) {
page = "GarageGateDevicePage.qml";
} else if (interfaceList.indexOf("light") >= 0) {
page = "ColorLightDevicePage.qml";
} else if (interfaceList.indexOf("extendedshutter") >= 0 ) {
page = "ShutterDevicePage.qml";
} else if (interfaceList.indexOf("extendedawning") >= 0) {
page = "AwningDevicePage.qml";
} else {
page = "GenericDevicePage.qml";
}
print("Selecting page", page, "for interface list:", interfaceList)
return page;
}
function pad(num, size) {
var s = "000000000" + num;
return s.substr(s.length-size);
}
Component {
id: invalidVersionComponent
Popup {
id: popup
property string actualVersion: "0.0"
property string minimumVersion: "1.0"
width: app.width * .8
height: col.childrenRect.height + app.margins * 2
x: (app.width - width) / 2
y: (app.height - height) / 2
visible: false
ColumnLayout {
id: col
anchors { left: parent.left; right: parent.right }
spacing: app.margins
Label {
text: qsTr("Connection error")
Layout.fillWidth: true
font.pixelSize: app.largeFont
}
Label {
text: qsTr("Sorry, the version of the %1 box you are trying to connect to is too old. This app requires at least version %2 but the %1 box only supports %3").arg(app.systemName).arg(popup.minimumVersion).arg(popup.actualVersion)
wrapMode: Text.WordWrap
Layout.fillWidth: true
}
Button {
Layout.fillWidth: true
text: qsTr("OK")
onClicked: {
Engine.connection.disconnect();
popup.close()
}
}
}
}
}
}